开发者

JAXB enumeration with numeric values

I want to restrict input values like this

<simpleType name="SomeCode">
  <restriction base="string">
    <enumeration value="036222B"/>
    <enumeration value="036111C"/>
  </restriction>
</simpleType>

But this does not generate an Enum. I suspect it is because the values start with numbers and this is not allowed for Enum values开发者_如何学编程.

Is there any solution or workaround?


Here is my answer to a similar question that may help (see issue 2):

  • Enums don't match schema: problem with jaxb or xsd?

There are a couple of enumeration values that are causing this issue. These issues can be overcome through the use of a JAXB external binding file (see below).

Enum Issue #1 - Empty String

Some of your enum values are empty string (""), which is causing a String rather than an enum property to be generated:

<xs:enumeration value="">
    <xs:annotation>
        <xs:documentation>Blank</xs:documentation> 
    </xs:annotation>
</xs:enumeration>

Enum Issue #2 - Numeric String

Some of the enum values are numbers which is causing a String rather than an enum property to be generated:

<xs:enumeration value="6">
    <xs:annotation>
        <xs:documentation>6th grade</xs:documentation> 
   </xs:annotation>
</xs:enumeration>

Bindings File (bindings.xml)

The following bindings file can be used to address the issues with the educationLevelType, the concepts here can be applied to all the problematic types:

<jxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1">
    <jxb:bindings schemaLocation="http://www.acf.hhs.gov/programs/cb/systems/nytd/nytd_data_file_format.xsd">
        <jxb:bindings node="//xs:simpleType[@name='educationLevelType']/xs:restriction/xs:enumeration[@value='6']">
            <jxb:typesafeEnumMember name="SIX"/>
        </jxb:bindings>
        <jxb:bindings node="//xs:simpleType[@name='educationLevelType']/xs:restriction/xs:enumeration[@value='7']">
            <jxb:typesafeEnumMember name="SEVEN"/>
        </jxb:bindings>
        <jxb:bindings node="//xs:simpleType[@name='educationLevelType']/xs:restriction/xs:enumeration[@value='8']">
            <jxb:typesafeEnumMember name="EIGHT"/>
        </jxb:bindings>
        <jxb:bindings node="//xs:simpleType[@name='educationLevelType']/xs:restriction/xs:enumeration[@value='9']">
            <jxb:typesafeEnumMember name="NINE"/>
        </jxb:bindings>
        <jxb:bindings node="//xs:simpleType[@name='educationLevelType']/xs:restriction/xs:enumeration[@value='10']">
            <jxb:typesafeEnumMember name="TEN"/>
        </jxb:bindings>
        <jxb:bindings node="//xs:simpleType[@name='educationLevelType']/xs:restriction/xs:enumeration[@value='11']">
            <jxb:typesafeEnumMember name="ELEVEN"/>
        </jxb:bindings>
        <jxb:bindings node="//xs:simpleType[@name='educationLevelType']/xs:restriction/xs:enumeration[@value='12']">
            <jxb:typesafeEnumMember name="TWELVE"/>
        </jxb:bindings>
        <jxb:bindings node="//xs:simpleType[@name='educationLevelType']/xs:restriction/xs:enumeration[@value='']">
            <jxb:typesafeEnumMember name="BLANK"/>
        </jxb:bindings>
    </jxb:bindings>
</jxb:bindings>

The XJC call can be made as follows (the -nv flag is described below):

xjc -nv -b bindings.xml -d out http://www.acf.hhs.gov/programs/cb/systems/nytd/nytd_data_file_format.xsd

This will cause the following Enum to be generated:

package gov.hhs.acf.nytd;

import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlType;

@XmlType(name = "educationLevelType")
@XmlEnum
public enum EducationLevelType {

    @XmlEnumValue("under 6")
    UNDER_6("under 6"),

    @XmlEnumValue("6")
    SIX("6"),

    @XmlEnumValue("7")
    SEVEN("7"),

    @XmlEnumValue("8")
    EIGHT("8"),

    @XmlEnumValue("9")
    NINE("9"),

    @XmlEnumValue("10")
    TEN("10"),

    @XmlEnumValue("11")
    ELEVEN("11"),

    @XmlEnumValue("12")
    TWELVE("12"),

    @XmlEnumValue("post secondary")
    POST_SECONDARY("post secondary"),

    @XmlEnumValue("college")
    COLLEGE("college"),
    @XmlEnumValue("")

    BLANK("");
    private final String value;

    EducationLevelType(String v) {
        value = v;
    }

    public String value() {
        return value;
    }

    public static EducationLevelType fromValue(String v) {
        for (EducationLevelType c: EducationLevelType.values()) {
            if (c.value.equals(v)) {
                return c;
            }
        }
        throw new IllegalArgumentException(v);
    }

}

maxOccurs Issue

For the maxOccurs issue, the following command line with the no verify (-nv) flag can be used to parse the XML schema:

xjc -nv -d out http://www.acf.hhs.gov/programs/cb/systems/nytd/nytd_data_file_format.xsd

This will get you past the following error without having to modify the XML schema:

parsing a schema... [ERROR] Current configuration of the parser doesn't allow a maxOccurs attribute value to be set greater than the value 5,000.
line 41 of http://www.acf.hhs.gov/programs/cb/systems/nytd/nytd_data_file_format.xsd

Failed to parse a schema.

For More Information

  • http://blog.bdoughan.com/2011/08/jaxb-and-enums.html


Yes. You could define the enum yourself instead of having XJC generate it. Then you could instruct XJC to use that enum. You'll need an adapter class, though.

import acme.MyEnum;

public class MyEnumadapter {

    public static MyEnum unmarshal(final String value) {
        if(value == null)
            return null;
        //use some method to identify the enum by the value and return
    }

    public static String marshal(final MyEnum value) {
        if (value == null)
            return null;
        //use some method to get the value for the enum
    }

}

Either in a bindings file or embedded in the schema, customize the bindings like this:

<bindings node="//xs:simpleType[@name='SomeCode']">
    <javaType name="acme.MyEnum"
        parseMethod="MyEnumAdapter.unmarshal"
        printMethod="MyEnumAdapter.marshal"/>
</bindings>

MyEnumAdapter is in the default package here, so make sure you use the fully qualified names when doing this yourself.


This code is more simpler way, works for me.

@XmlEnum(value = Integer.class)
public enum SomeEnum {
  @XmlEnumValue("0")
  Value1,
  @XmlEnumValue("1")
  Value2,
  @XmlEnumValue("2")
  Value3;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜