0

Disclaimer: This is just a very simple example. My scenario is much more complex than this.

Scenario:

My input XML:

<root>
  ...
  <element>
    Hello <name type="first">John</name>. Your policy number <policy number=1234/> has arrived.
    Please contact <contact brand="XPTO">999-9999</contact> for more information.
  </element>
  ...
</root>

My models: Root.java

@XmlRootElement(name = "root")
public class Root {
  @XmlElement
  protected Element element;

  ... (many other elements)
  //gets and sets
}

Element.java

@XmlRootElement(name = "element")
public class Element {

  @XmlElementRefs({
    @XmlElementRef(name = "name", type = Name.class, required = false),
    @XmlElementRef(name = "policy", type = Policy.class, required = false),
    @XmlElementRef(name = "contact", type = Contact.class, required = false),
  })
  @XmlJavaTypeAdapter(CommonElementAdapter.class)
  protected List<CommonElement> content;

  @XmlAnyElement
  @XmlMixed
  protected List<String> value;
  //gets and sets
}

Name/Policy/Contact.class (All of them has the very similar style)

@XmlRootElement(name = "name")
public class Name extends CommonElement {

  @XmlValue
  protected String value;

  @XmlAttribute
  protected String type;
  //gets and sets

  @Override
  public CommonElement unmarshal(CommonElement content) {
    //Do some stuff here with content. E.g.:
    content.setValue(content.getValue().toUpperCase());
    return content;
  }
}

CommonElement.java

@XmlTransient
public abstract class CommonElement {

    public CommonElement unmarshal (CommonElement value) {
        return value;
    }
}

CommonElementAdapter.java

public class CommonElementAdapter extends XmlAdapter<CommonElement, CommonElement> {

  @Override
  public CommonElement unmarshal(CommonElement content) throws Exception {
      return content.unmarshal(content); //Call the unmarshal for each element
  }

  @Override
  public CommonElement marshal(CommonElement content) throws Exception {
      return content;
  }
}

Expected result:

<root>
  ...
  <element>
    Hello <name type="first">JOHN</name>. Your policy number <policy number=1234/> has arrived.
    Please contact <contact brand="XPTO">999-9999</contact> for more information.
  </element>
  ...
</root>

Requirements:

  • The final text must be exactly as in the input XML, keeping the order as received.
  • The elements inside the tag must have it's on adapter. As my solution, it's inside the element itself, being called by CommonElementAdapter.
  • I CAN'T use MOXy or any other custom implementation.

My issue:

This way I put here, I can make all the text and elements appear in the result, but the order isn't correct. I'm getting something like this:

<element>
  <name type="first">JOHN</name>
  <policy number=1234/>
  <contact brand="XPTO">999-9999</contact>
  Hello . Your policy number has arrived.
  Please contact for more information.
</element>

I can change this removing the List<String> value from Element.java and changing the List<CommonElement> to List<Object>, so the value would be included at the content variable, keeping the order. But, this way, I couldn't make the Adapter work.

Adriano
  • 1
  • 2

0 Answers0