XJC does not generate enum inside xs:union

最后都变了- 提交于 2021-02-07 13:14:02

问题


I have several XSD files containing structures like the following:

<xs:complexType name="SomeThing" abstract="false">
    <xs:sequence>
        <xs:element name="id" type="schema2:SomeIdTypeClass" minOccurs="1" maxOccurs="1"/>
        <xs:element name="myType" type="schema1:MyType" minOccurs="1" maxOccurs="1"/>
    </xs:sequence>
</xs:complexType>

<xs:simpleType name="MyType">
    <xs:union>
        <xs:simpleType>
            <xs:restriction base="xs:string">
                    <xs:enumeration value="APPLE"/>
                    <xs:enumeration value="ORANGE"/>
                    <xs:enumeration value="BANANA"/>
                </xs:restriction>
            </xs:simpleType>
            <xs:simpleType>
                <xs:restriction base="xs:string">
                <xs:pattern value="OTHER:[a-zA-Z_][a-zA-Z0-9_]*"/>
            </xs:restriction>
        </xs:simpleType>
    </xs:union>
</xs:simpleType>

I am using the XJC command to generate the Java classes on the console, not maven or ant or any other build tool.

All Classes seem to be generated fine except these kind of enums. The Classes that are using the enum Type are only referecning it as String, e.g. the Something class contains MyType only as a String, and not as an ENUM, as I would expect it.

In another file I have something like this, where the Enums are generated without problems and referencing classes are using it as Enums as they should.

<xs:simpleType name="SizeType">
<xs:restriction base="xs:string">
        <xs:enumeration value="SMALL"/>
        <xs:enumeration value="MEDIUM"/>
        <xs:enumeration value="LARGE"/>
</xs:restriction>

I do not want to alternate the XSD files since they are not generated by myself and I have a few files with many of those elements.

I came to the conclusion that i need to use some kind of XJB binding file, but I cannot figure out, what exactly i need to write there:

The following gives me only the error "results in too many target nodes"

<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
jaxb:extensionBindingPrefixes="xjc">
    <jaxb:bindings schemaLocation="MySchema.xsd" node="/xs:schema">
        <jaxb:bindings node="//xs:simpleType[@name='MyType']/xs:union/xs:simpleType">
            <jaxb:typesafeEnumClass name="MyType"/>
        </jaxb:bindings>    
    </jaxb:bindings>
</jaxb:bindings>

Adding multiple="true" solves that but still does not give me the Enums that I want.

Edit: When i remove the xs:union so that i have a normal xs:simpleType like this:

<xs:simpleType name="MyType">
    <xs:restriction base="xs:string">
    <xs:pattern value="OTHER:[a-zA-Z_][a-zA-Z0-9_]*"/>
    <xs:enumeration value="APPLE"/>
    <xs:enumeration value="ORANGE"/>
    <xs:enumeration value="BANANA"/>
    </xs:restriction>             
</xs:simpleType>

Then it works as intended. I still dont want to go down that route and edit the schemas if I dont have to. There must be some way around.


回答1:


Ok I have been spending some time on the subject, I googled a lot and made some tests.

Short answer : it's not possible

Detailled answer :

This question on SO is about a guy having the same issue but simpler : he had an union containing a single simpleType (a restriction with some enumeration), which is weird because the union is pointless but anyway.

So the guy is stuck and this answer was quite interesting :

It looks like unions are not well supported https://jaxb.java.net/tutorial/section_2_2_10-Defining-a-Type-Union.html

If you could modify the schema you could extract the enumerated anonymous simple type to a named type and then use in your code the Java enum generated for this new type....

Not well supported... But not well as in "not at all" or as in "in some case" ?

Unfortunalely the link is broken but thanks to our friend The Internet Archive, I pulled out the information I needed :

In Java, there is no convenient way of expressing unions of simple types. The JAXB compiler simply inserts Java's String type wherever the union type is used and leaves it up to the application programmer to handle the rest. Try to avoid xsd:union.

So that's the end of the road, you are stuck. As long as union are present in your schema, no emum class will be generated and String will always be picked as default type.

Moreover, I found this article, Extend enumerated lists in XML schema. In some solutions, the author advocates to use union but ultimately say :

Requires <xsd:union> tag support, which is sometimes not implemented in tools

Finally, the best solution is maybe the first one in the article : Edit the original schema to include the new enumerated values




回答2:


You need to use the following binding.

<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
jaxb:extensionBindingPrefixes="xjc">
<jaxb:bindings schemaLocation="MySchema.xsd" node="/xs:schema">
<jxb:bindings node="//xs:element[@name='MyType']">
            <jxb:property >
                <jxb:baseType name="java.lang.String"></jxb:baseType>
            </jxb:property>
        </jxb:bindings>
        </jxb:bindings>


来源:https://stackoverflow.com/questions/37281539/xjc-does-not-generate-enum-inside-xsunion

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!