问题
I have an xsd that looks like this (snippet):
<xs:complexType name="IDType">
<xs:choice minOccurs="1" maxOccurs="2">
<xs:element name="FileID" minOccurs="0" maxOccurs="1" type="an..35" />
<xs:element name="IDNumber1" minOccurs="0" maxOccurs="1" type="an..35" />
<xs:element name="Number" minOccurs="0" maxOccurs="1" type="an..35" />
<xs:element name="PNumber" minOccurs="0" maxOccurs="1" type="an..35" />
<xs:element name="SS" minOccurs="0" maxOccurs="1" type="an..35" />
<xs:element name="Player" minOccurs="0" maxOccurs="1" type="an..35" />
<xs:element name="Prior" minOccurs="0" maxOccurs="1" type="an..35" />
<xs:element name="BIN" minOccurs="0" maxOccurs="1" type="an..35" />
<xs:element name="Mutual" minOccurs="0" maxOccurs="1" type="an..35" />
</xs:choice>
</xs:complexType>
<xs:simpleType name="an..35">
<xs:restriction base="an">
<xs:maxLength value="35" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="an">
<xs:restriction base="xs:string">
<xs:pattern value="[ !-~]*" />
</xs:restriction>
</xs:simpleType>
For some reason this is the Java code that gets generated:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "IDType", propOrder = {
"fileID"
})
public class PatientIDType {
@XmlElementRefs({
@XmlElementRef(name = "FileED", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
@XmlElementRef(name = "IDNumber1", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
@XmlElementRef(name = "Number", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
@XmlElementRef(name = "PNumber", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
@XmlElementRef(name = "SS", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
@XmlElementRef(name = "Plaer", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
@XmlElementRef(name = "Prior", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
@XmlElementRef(name = "BIN", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
@XmlElementRef(name = "Mutual", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class)
})
protected List<JAXBElement<String>> fileID;
/**
* Gets the value of the fileID property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the fileID property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getFileID().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link JAXBElement }{@code <}{@link String }{@code >}
* {@link JAXBElement }{@code <}{@link String }{@code >}
* {@link JAXBElement }{@code <}{@link String }{@code >}
* {@link JAXBElement }{@code <}{@link String }{@code >}
* {@link JAXBElement }{@code <}{@link String }{@code >}
* {@link JAXBElement }{@code <}{@link String }{@code >}
* {@link JAXBElement }{@code <}{@link String }{@code >}
* {@link JAXBElement }{@code <}{@link String }{@code >}
* {@link JAXBElement }{@code <}{@link String }{@code >}
*/
public List<JAXBElement<String>> getFileID() {
if (fileID == null) {
fileID = new ArrayList<JAXBElement<String>>();
}
return this.fileID;
}
Why is the class generated like this and simply not some kind of string array? I really don't want to have to create JAXBElements every time I want to create something?
How can I have it generate classes for each of the types that simply represent string or something like that?
Thanks in advance,
Ian
回答1:
This code is generated because your complex type, IDType, contains a choice with a maxOccurrence greater than one, here:
<xs:choice minOccurs="1" maxOccurs="2">
The contents of this lists are elements with different names but the same type. This has no equivalent in standard object-oriented models. JAXB then uses the JAXBElement class to work around this: a JAXBElement wraps a simple object that contains the data and assigns it a QName.
Thus you can read from this list and write to the list unambiguously by providing:
- The data object (in your case a String since all restrictions from String are represented as a Java String)
- A
JAXBElementwhosegetValue()method returns the string
The JAXB specification contains fairly detailed and reasonably complex explanations of how to deal with repeating choices and repeating sequences. Note that if your sequence contained objects of different types as well as different names, you would end up with List<Object>.
That was the long explanation, now here are some options:
- If you can modify the schema, put a wrapper element around the 8 items, say, "Wrapper". Wrapper will contain a single choice of the elements; Then make IDType contain a sequence of Wrapper elements with minOccurs = 1 and maxOccurs = 2.
- Create yourself some helper functions to quickly create the JAXBElements. JAXB puts a Factory class in your target package that can help you - for example, it contains references to the Schema namespace, etc.
回答2:
Your ObejctFActory class should have the createMethod for thosr values, somthing like
@XmlElementDecl(namespace = "http://www.surescripts.com/messaging", name = "SocialSecurity", scope = PatientIDType.class)
public JAXBElement<String> createPatientIDTypeSocialSecurity(String value) {
return new JAXBElement<String>(_PayerIDTypeSocialSecurity_QNAME, String.class, PatientIDType.class, value);
}
回答3:
If you're using the Sun JAXB implementation, you could try compiling with the xjc:simple mode enabled. See the documentation on simplified binding for an example. It should turn
public class PatientIDType {
protected List<JAXBElement<String>> fileID;
}
in to
public class PatientIDType {
String fileID;
...
}
You'll need to compile your schema with a binding customisation file. See Kohsuke's blog for an example of how to do it.
来源:https://stackoverflow.com/questions/790118/jaxb-types-problem