Marvin
Marvin

Reputation: 658

Java JAXB marshall into DOM Document

I have JAXB annotations:

@XmlElement(name="String")
private String string = "one";

@XmlElement(name="ArrayOne")
private ArrayList<String> array1 = new ArrayList<String>();

and marshalling:

array.add("Just one");
JAXBContext jc1 = JAXBContext.newInstance( getClass() );
Marshaller marshaller = jc1.createMarshaller();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance() ; 
Document doc = factory.newDocumentBuilder().newDocument();
marshaller.marshal(this, doc);

If I dig into document nodes, I cannot see any difference between node elements. My question is, if there is any trick how to marshall into DOM document, that node elements will be somehow distinct, whether is simple object(String), or array object. Marshaller of course is aware of field types, so I wonder, if it puts some flag in Element data.

DOM structure is

NodeName:String     NodeContent:one
NodeName:ArrayOne   NodeContent:Just one

but I would like to have like:

NodeName:String     NodeContent:one
NodeName:ArrayOne
    Children:
    NodeName:ArrayOne   NodeContent:Just one

so I know, ArrayOne is array, no matter of just one object.

Note, that I cannot change annotations, since there is not always source available.

Upvotes: 0

Views: 1605

Answers (1)

kaos
kaos

Reputation: 1608

You can create wrapper element for collections using @XmlElementWrapper:

@XmlElement(name="String")
private String string = "one";

@XmlElementWrapper(name="ArrayOne")
private ArrayList<String> array1 = new ArrayList<String>();

XML output for this mapping looks like this:

<testElement>
    <String>one</String>
    <ArrayOne>
        <array1>one</array1>
    </ArrayOne>
</testElement>

Update for comment: Adding wrapper on DOM Document manually (probably there is an easier way, maybe by using a Transformer):

TestElement te = new TestElement();

JAXBContext jc1 = JAXBContext.newInstance(TestElement.class);
Marshaller marshaller = jc1.createMarshaller();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance() ;
Document doc = factory.newDocumentBuilder().newDocument();
marshaller.marshal(te, doc);

NodeList nodeList = doc.getDocumentElement().getChildNodes();
Node newNode = doc.createElement("ArrayOneWrapper");
List<Node> arrayOneElements = new ArrayList<>();

for (int i = 0; i < nodeList.getLength(); i++) {
    Node n = nodeList.item(i);

    if (n.getNodeName().equals("ArrayOne")) {
        arrayOneElements.add(n);
    }
}
for (Node n : arrayOneElements) {
    newNode.appendChild(n);
}

XML output:

<testElement>
    <String>one</String>
    <ArrayOneWrapper>
        <ArrayOne>one</ArrayOne>
        <ArrayOne>two</ArrayOne>
    </ArrayOneWrapper>
</testElement>

Upvotes: 2

Related Questions