Updating a particular element in JAXB generated xml

Sometimes xml documents are very big and our requirement is to update a particular section of the document. JAXB binder comes to our help. Binder object maintains the mapping between the java object and xml infoset like DOM. Any modification to java object can be synchronized to xml held by binder object and vice versa. Below is the example

Lets have a file with below contents in result.xml
<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>
<country>
<code>
<part1>1234</part1>
<part2>5678</part2>
</code>
<name>India</name>
<population>10000000</population>
</country>

and Java classes as shown below

Country


package JAXB;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Country {
    private ZipCode code;
    private String name;
    private int population;

    public ZipCode getCode() {
        return code;
    }
    public void setCode(ZipCode code) {
        this.code = code;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getPopulation() {
        return population;
    }
    public void setPopulation(int population) {
        this.population = population;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{").append("code:").append(this.code).append(",");
        sb.append("name:").append(this.name).append(",");
        sb.append("population:").append(this.population).append("}");

        return sb.toString();
    }
}

ZipCode


package JAXB;

public class ZipCode {
    private int part1;
    private int part2;

    public int getPart1() {
        return part1;
    }
    public void setPart1(int part1) {
        this.part1 = part1;
    }
    public int getPart2() {
        return part2;
    }
    public void setPart2(int part2) {
        this.part2 = part2;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{").append("part1:").append(this.part1).append(",");
        sb.append("part2:").append(this.part2).append("}");

        return sb.toString();
    }
}

JavaBinderDemo


package JAXB;

import java.io.File;

import javax.xml.bind.Binder;
import javax.xml.bind.JAXBContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class JAXBBinderDemo {

    public static void main(String[] args) {
        try
        {
            JAXBContext jaxbContext = JAXBContext.newInstance(Country.class);
            Binder<Node> binder = jaxbContext.createBinder();

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db = dbf.newDocumentBuilder();
            File file = new File("result.xml");
            Document doc = db.parse(file);
            Element documentElement = doc.getDocumentElement();

            Country country = (Country)binder.unmarshal(documentElement);
            ZipCode zipCode = country.getCode();
            zipCode.setPart1(1111);

            binder.updateXML(zipCode);

            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult streamResult = new StreamResult(file);
            transformer.transform(source, streamResult);
        }
        catch(Exception excep)
        {
            excep.printStackTrace();
        }
    }
}

In the JAXBBinderDemo code we first create the JAXBContext instance and from that we get the Binder object. I will use DOM to maintain the xml infoset. So the parameterized type for Binder is Node.

Binder<Node> binder

Get the DOM object of the xml as shown below

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
File file = new File(“result.xml”);
Document doc = db.parse(file);
Element documentElement = doc.getDocumentElement();

Convert the xml infoset to java object using Binder’s unmarshal method
Country country = (Country)binder.unmarshal(documentElement);

The above code unmarshal and return the country object and the binder object maps the java object with xml infoset.

Next we update the zip code of the country object
ZipCode zipCode = country.getCode();
zipCode.setPart1(1111);

Now the update in java object has to be replicated in the DOM object to keep the xml updated, which is done using updateXML method
binder.updateXML(zipCode);

Next we save the DOM object.
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult streamResult = new StreamResult(file);
transformer.transform(source, streamResult);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s