chrk
chrk

Reputation: 41

JAXB mappable XML elements

In the root.class from my xi-schema, the element item and ohter objects are part of an itemList:

@XmlElementRef(name = "item", namespace = "xi", type = JAXBElement.class, required = false) 
//...
protected List<Object> itemList;

I've in the ObjectFactory.class from the main-schema some items as JAXBElements like this:

@XmlElementDecl(namespace = "de-schema", name = "detailedInformation", substitutionHeadNamespace = "xi", substitutionHeadName = "item")
public JAXBElement<numItemType> createDetailedInformation(numItemType num) {
    return new JAXBElement<numItemType>(_detailedInformation_QNAME, numItemType.class, null, num);
}

So the numItemType has some attributes and value(num) for the JAXBElement.

NumItemType.class:

@XmlJavaTypeAdapter(numItemTypeAdapter.class)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "numItemType", namespace = "xi", propOrder = {
    "num"
})

public class NumItemType {

    @XmlValue
    protected BigDecimal num;
    @XmlAttribute(name = "precision")
    protected String precision;
    @XmlAttribute(name = "decimals")
    protected String decimals;
    //... more Attributes

}

But when JAXB unmarshal the XML document, it will has only elements, for example:

<detailedInformation>
    <element1>1234</element1>
    <element2>5678</element2>
    <element3>bla</element3>
</detailedInformation>

When I marshal it, it should become (like the JAXB java code):

<detailedInformation element2="5678" element3="bla">1234</detailedInformation>

Therefore, I have written an numItemTypeAdapter.class with NumItemTypeAdapter extends XmlAdapter

AdaptedNum.class:

public class AdaptedNum {
    @XmlElement 
    private  double element1;
    @XmlElement
    private String element2;
    @XmlElement
    private String element3;

   /** Some getter/setter methods */
}

I thought, that would be help me http://blog.bdoughan.com/2012/02/xmlanyelement-and-xmladapter.html, but it is all a bit tricky :-/

Upvotes: 1

Views: 1697

Answers (3)

chrk
chrk

Reputation: 41

In other words:

I want to set new elements to the NumItemType.class for the unmarshalling without change the schema java code.

NumItemType.class

package forum11343610;

import java.math.BigDecimal;
import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "numItemType", namespace = "xi", propOrder = {
    "num"
})

    @XmlJavaTypeAdapter(NumItemTypeAdapter.class)
    public class NumItemType {

        @XmlValue
        protected BigDecimal num;
        @XmlAttribute(name = "precision")
        protected String precision;
        @XmlAttribute(name = "decimals")
        protected String decimals;
        //... more Attributes

    }

NumItemTypeAdapter.class

public  class NumItemTypeAdapter extends XmlAdapter<AdaptedNum, NumItemType> {

    @Override
    public NumItemType unmarshal(AdaptedNum an) throws Exception {
        NumItemType nit = new NumItemType();
        nit.setNum(an.getNum);
        nit.setPrecision(an.getPrecision);
        nit.setDecimals(an.getDecimals)
        return nit;
    }

}

AdaptedNum.class

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "adaptedNum", namespace = "", propOrder = {
        "element1",
        "element2",
        "element3"
    })

    public class AdaptedNum {

        @XmlElement(name ="element1")
        protected  BigDecimal num;
        @XmlElement(name ="element2")
            private String decimals;
        @XmlElement(name ="element3")
            private String precison;
            // set/get method
}

Upvotes: 0

chrk
chrk

Reputation: 41

Thank your for your comment.

That's the point:

Demo

NumItemType numItemType = new NumItemType();
numItemType.num = BigDecimal.TEN;
numItemType.decimals = "1";
numItemType.precision = "2";
root.getItemList().add(objectFactory.createDetailedInformation(numItemType));

It should unmarshal and map the XML automatically.

XML Input

<detailedInformation>
     <element1>1234</element1>
     <element2>5678</element2>
     <element3>bla</element3>
</detailedInformation>

With the Code:

Demo

JAXBContext jc = JAXBContext.newInstance(Root.class, ObjectFactory.class);
Unmarshaller u = jc.createUnmarshaller();
File xml = new File("D:/", "test.xml");
Root root = (Root) u.unmarshal(xml);

Output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns:ns2="de-schema" xmlns:ns3="xi">
    <ns2:detailedInformation precision="2" decimals="1">10</ns2:detailedInformation>
</root>

I could parse the XML Document with DOM to a tree and marhalling with JAXB...

Thank you!

Upvotes: 0

bdoughan
bdoughan

Reputation: 149047

It's a bit tricky to sort out exactly where your problem may be occurring. I'm assuming your original model was generated from an XML Schema, this should work as is without any modifications. I've attempted below to provide a scaled down version of your example which may help.

Root

package forum11343610;

import java.util.*;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlElementRef(name = "item", namespace = "xi", type = JAXBElement.class, required = false) 
    protected List<Object> itemList = new ArrayList<Object>();

    public List<Object> getItemList() {
        return itemList;
    }

    public void setItemList(List<Object> itemList) {
        this.itemList = itemList;
    }

}

NumItemType

package forum11343610;

import java.math.BigDecimal;
import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "numItemType", namespace = "xi", propOrder = {
    "num"
})

public class NumItemType {

    @XmlValue
    protected BigDecimal num;
    @XmlAttribute(name = "precision")
    protected String precision;
    @XmlAttribute(name = "decimals")
    protected String decimals;
    //... more Attributes

}

ObjectFactory

package forum11343610;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    private static final QName _detailedInformation_QNAME = new QName("de-schema", "detailedInformation");

    @XmlElementDecl(namespace = "xi", name = "item")
    public JAXBElement<NumItemType> createItem(NumItemType num) {
        return new JAXBElement<NumItemType>(_detailedInformation_QNAME, NumItemType.class, null, num);
    }

    @XmlElementDecl(namespace = "de-schema", name = "detailedInformation", substitutionHeadNamespace = "xi", substitutionHeadName = "item")
    public JAXBElement<NumItemType> createDetailedInformation(NumItemType num) {
        return new JAXBElement<NumItemType>(_detailedInformation_QNAME, NumItemType.class, null, num);
    }

}

Demo

package forum11343610;

import java.math.BigDecimal;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class, ObjectFactory.class);

        ObjectFactory objectFactory = new ObjectFactory();
        Root root = new Root();

        NumItemType numItemType = new NumItemType();
        numItemType.num = BigDecimal.TEN;
        numItemType.decimals = "1";
        numItemType.precision = "2";
        root.getItemList().add(objectFactory.createDetailedInformation(numItemType));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

Output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns:ns2="de-schema" xmlns:ns3="xi">
    <ns2:detailedInformation precision="2" decimals="1">10</ns2:detailedInformation>
</root>

Upvotes: 0

Related Questions