Reputation: 1703
I have an XML representing a hierarchical DOM where each element is an <element ...>
with zero or more children each. Each <element>
has a ton of attributes and I don't want to litter the Element
class with all those attributes, given it has a bunch of its own methods too.
The first draft of Element
class was as follows. This works flawlessly:
class Element {
@XmlAttribute private String name;
@XmlAttribute private String bounds;
// A whole bunch of other attributes
@XmlElement(name = "element") List<Element> children;
// A whole bunch of other methods
}
I tried to improve this by:
class Element {
@XmlPath(".") private Attributes attributes;
@XmlElement(name = "element") List<Element> children;
// A whole bunch of other methods
}
class Attributes {
@XmlAttribute private String name;
@XmlAttribute private String bounds;
// A whole bunch of other attributes
}
This seems to work fine, however, it actually messes up data upon closer inspection. If I input the following XML:
<element name="Hello" bounds="[0,0][1,1]">
<element name="World" bounds="[1,1][2,2]">
<element name="Testing" bounds="[2,2][3,3]">
<element name="One two three" bounds="[3,3][4,4]" />
</element>
</element>
</element>
The unmarshalled object has the following structure/properties:
+ [Element]
- name = "World"
- bounds = "[1,1][2,2]"
+ children[0]
- name = "Testing"
- bounds = "[2,2][3,3]"
+ children[0]
- name = "One two three"
- bounds = "[3,3][4,4]"
+ children[0]
- name = "One two three"
- bounds = "[3,3][4,4]"
- children = null
My assumption was that XPath(".")
would "lift" the attributes of the Attributes
class to the parent Element
class. But in fact it is lifting those attributes two levels upwards.
When I construct the Element
hierarchy manually, then try to marshall it, the resulting XML is just fine. It is just the unmarshalling that is producing the incorrect object.
Am I using XPath
incorrectly here? I have a working solution by including all attributes directly within the Element
class, but I just wanted to group those attributes into a separate class and marshall/unmarshall them to the container Element
class.
Thanks! Asim
Upvotes: 4
Views: 80
Reputation: 688
How about using @XmlAnyAttribute
with a Map<String,Object>. That should put all attributes that are not accounted for into the map.
class Element {
@XmlAnyAttribute private Map<String,String> attributes;
@XmlElement(name = "element") List<Element> children;
}
Using it like element.attributes.get("name)
Alternatively, you could extend a common Attributes
class.
These would look in the XML just as if they are in the Element class.
public class Attributes {
@XmlAttribute
private String name;
@XmlAttribute
private String bounds;
}
and
class Element extends Attributes {
@XmlElement(name = "element")
List<Element> children;
}
Upvotes: 1