问题
I'm starting with JAXB and im trying to read the following xml to map it to a classe:
<element id="0">
<type>1</type>
<color>0</color>
<size>1</size>
<location>
<absolute>
<absolute-item>top</absolute-item>
<absolute-item>left</absolute-item>
</absolute>
<relative>
<right>0</right>
<left>0</left>
</relative>
</location>
</element>
My porblem comes when I try to map the nested elements like abslute, wich can contain any number of elements. I'm trying this right now:
public class Element {
@XmlAttribute
private int id;
@XmlElement
private int type;
@XmlElement
private int color;
@XmlElement
private int size;
@XmlElementWrapper(name="absolute")
@XmlElement(name="absolute-item")
private ArrayList<String> absoluteItems;
@Override
public String toString() {
return "Element "+id+" {" +
"type=" + type +
", color=" + color +
", size=" + size +
", Location Relative: "+ absoluteItems
+"}";
}
}
I got the simple elements but not the nested one. Apparently I can't annotate to wrappers together, so I don't know how to fix it.
UPDATE:
I'm trying this as suggested. I'm getting an IllegalAnnotationExceptions
because Element$Location.right is not a compilation property, but i don't know what it means. Should I create one more class for the element?
public class Element {
@XmlAttribute
private int id;
@XmlElement
private int type;
@XmlElement
private int color;
@XmlElement
private int size;
@XmlElement(name="location")
private Location location;
public static class Location {
@XmlElementWrapper(name="absolute")
@XmlElement(name="absolute-item")
private ArrayList<String> absoluteItems;
@XmlElementWrapper(name="relative")
@XmlElement(name="right")
private int right;
@XmlElement(name="left")
private int left;
@Override
public String toString() {
return "Location{" +
"Absolute=" + absoluteItems +
", relative {right=" + right +
", left=" + left +
"}}";
}
}
回答1:
JAXB processing assumes a separate element definition for each complex element. A complex element means an element containing other elements.
The error you mention, referring to Element$Location, probably indicates the jaxb routines have found the annotation for the field "right" in the nested Location class; at runtime, nested classes have the name of the containing class, in this case Element, as a prefix separated from the nested class by a dollar sign.
To unmarshall (translate from xml text to Java code) the data structure you provide above, the JAXB routines would expect to find the following public class definitions:
Absolute Element Location ObjectFactory Relative
In the java code the jaxb compiler produces, the main element definition has its own class, and the following annotations:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"type",
"color",
"size",
"location"
})
@XmlRootElement(name = "element")
public class Element
{
@XmlElement(required = true)
protected BigInteger type;
.
. additional element definitions go here
.
// note: location here is a public class
@XmlElement(required = true)
protected Location location;
// the attribute is defined thus:
@XmlAttribute(name = "id")
protected BigInteger id;
/**
* Gets the value of the type property.
* @return BigInteger type code
*/
public BigInteger getType() { return type; }
/**
* Sets the value of the type property.
* @param value BigInteger type code to set
*/
public void setType(BigInteger value) { this.type = value; }
.
. all other getters and setters defined here
.
}
The element contained, in this case Location, has its own class with the following annotations:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Location", propOrder = {
"absolute",
"relative"
})
public class Location
{
protected Absolute absolute;
protected Relative relative;
.
. getters and setters go here: note these fields have no
. annotations
}
Again, jaxb expects to find public Absolute and Relative classes. Since the absolute-item element can be repeated indefinitely, jaxb expects to find it defined as a collection (List), thus:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Absolute", propOrder = {
"absoluteItem"
})
public class Absolute
{
@XmlElement(name = "absolute-item", required = true)
protected List<String> absoluteItem;
/**
* Gets the value of the absoluteItem property.
*
* <p>This accessor returns a reference to the live list; any
* modification to the returned list will be reflected in the
* JAXB object.
* This is why there is not a setter for absoluteItem.
*
* To add a new item, do as follows:
* getAbsoluteItem().add(newItem)
*/
public List<String> getAbsoluteItem()
{
if (absoluteItem == null)
absoluteItem = new ArrayList <> ();
return this.absoluteItem;
}
}
In my experience, jaxb schema compiler, xjc, provides the easiest way, by far, to generate classes or use with jaxb. xjc takes an XML schema definition, and translates it into java code for you; you then have only to include the resulting java files in your project. Most Java development tools will handle this for you automatically. To generate the code I used as a source for the examples above (I did some condensing, I wrote the following schema:
<?xml version="1.0" encoding="UTF-8"?>
<!--
Component ==> example for stack overflow
Purpose: show how the jaxb compiler works
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:desc = "http://sox.org/element"
targetNamespace = "http://sox.org/element"
jxb:version="2.0">
<xs:element name="element">
<xs:complexType>
<xs:sequence>
<xs:element name = "type" type = "xs:integer" />
<xs:element name = "color" type = "xs:integer" />
<xs:element name = "size" type = "xs:integer" />
<xs:element name = "location" type = "desc:Location" />
</xs:sequence>
<xs:attribute name="id" type="xs:integer" use="optional"
default="0" />
</xs:complexType>
</xs:element>
<xs:complexType name="Location">
<xs:sequence>
<xs:element name = "absolute" type = "desc:Absolute"
minOccurs="0" />
<xs:element name = "relative" type = "desc:Relative"
minOccurs="0" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Absolute">
<xs:sequence>
<xs:element name="absolute-item" type="xs:string"
maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Relative">
<xs:sequence>
<xs:element name="right" type="xs:string" />
<xs:element name="left" type="xs:string" />
</xs:sequence>
</xs:complexType>
来源:https://stackoverflow.com/questions/49181125/unmarshal-nested-xml-elements-with-jaxb