AweSIM
AweSIM

Reputation: 1703

Moxy Xpath :: "Lifting" attributes

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

Answers (1)

3Fish
3Fish

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

Related Questions