问题
<ProductInformation Context="GL">
<Assets>
<Asset ID="assetID" UserTypeID="ID">
<Name>name</Name>
<Reference ClassificationID="id"/>
<Values>
<Value AttributeID="ID">Value1</Value>
<Value AttributeID="ID">Value2</Value>
<MultiValue AttributeID="attributeID">
<Value>value3a</Value>
<Value>value3b</Value>
</MultiValue>
</Values>
</Asset>
</Assets>
<Products>....</Products>
</ProductInformation>
I used this xml->xsd and xjc to create classes from it.
Now I want to create my ProductInformation object,and marshall it.
My problem is xjc create 3 classes and a objectfactory, and some nested classes inside ProductInformation. When I look at the avaliable methods I mostly see getters instead of setters.
"Asset" class has no such methods like;
asset.setValues(List<Value> values)
Also I ended up writing funny code like this;
ProductInformation.Assets.Asset.Values.MultiValue multivalue=new ProductInformation.Assets.Asset.Values.MultiValue();
Is this normal with Jaxb?
回答1:
The way JAXB normally handles multi valued properties is to provide just a getter and no setter for the List<Whatever>
, which returns a mutable list - you're supposed to call the getter to retrieve an initially-empty list and then create the member objects for this list using new
in the normal way and add
them directly to the list. You can new
a static nested class in exactly the same way as a top-level one.
Single-valued properties (not lists) should have been generated with both getter and setter.
回答2:
The answer given by Ian Roberts is the correct one. I am giving this one to provide some additional information for those people interested in not having inner classes.
XML Schema (schema.xsd)
If JAXB classes are generated from the following XML schema, both the resulting Customer
and Employee
classes will contain a static nested class called Address
(because each contains their own definition of an address). This is in fact why static nested classes are used to avoid name conflict problems.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
targetNamespace="http://www.example.org/company"
xmlns="http://www.example.org/company"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:element name="customer">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="address">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="street" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="employee">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="address">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="road" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
JAXB Binding File (binding.xml)
A bindings file is used to customize the schema to Java generation. You can specify that everything should be a top level class with localScoping="top-level"
. When you do this you must make sure to resolve any potential name conflicts.
<jaxb:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="company.xsd">
<jaxb:bindings node="//xsd:element[@name='employee']/xsd:complexType/xsd:sequence/xsd:element[@name='address']/xsd:complexType">
<jaxb:class name="EmployeeAddress"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
XJC Call
Below is an example of specifying a bindings file when using the XJC command to generate Java classes from an XML schema.
xjc -b binding.xml schema.xsd
For More Information
- http://blog.bdoughan.com/2011/07/jaxb-xjc-and-nested-classes.html
回答3:
This is actually just a comment to Blaise Doughan's answer but I want to post the xml.
If you work with a more complex xsd and the path in the node
attribute is getting too long, you can:
<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="company.xsd">
<jaxb:bindings node="//xsd:element[@name='employee']">
....
<jaxb:bindings node=".//xsd:element[@name='address']/xsd:complexType">
<jaxb:class name="EmployeeAddress"/>
</jaxb:bindings>
....
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
来源:https://stackoverflow.com/questions/13414407/marshall-with-xjc-created-nested-classes