2

I need to map an xml file subset of nodes to a Java Bean.

For example map

<data>
    <field1>Value</field1>
    <field2>Value</field2>
    <field3>Value</field3>
    <field4>Value</field4>
    <field5>Value</field5>
</data>

to

public class DataBean {
    private String field2;
    private String field5;
    // ...getter/setter
}

then manipulate the bean and update the source xml file without loosing elements that are not mapped. How can I use to do it? What library?

Thanks for help, Maurizio

dash1e
  • 7,677
  • 1
  • 30
  • 35

2 Answers2

2

Note: I'm the EclipseLink JAXB (MOXy) lead an a member of the JAXB 2 (JSR-222) expert group.

Below is how this can be done with MOXy's implementation of the JAXB Binder:

DataBean

package forum9988170;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="data")
public class DataBean {

    private String field2;
    private String field5;

    public String getField2() {
        return field2;
    }

    public void setField2(String field2) {
        this.field2 = field2;
    }

    public String getField5() {
        return field5;
    }

    public void setField5(String field5) {
        this.field5 = field5;
    }

}

jaxb.properties

To specify MOXy as your JAXB provider you need to add a file named jaxb.properties in the same package as your domain classes with the following entry,

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Demo

package forum9988170;

import java.io.File;
import javax.xml.bind.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

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

public class Demo {

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

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        File xml = new File("src/forum9988170/input.xml");
        Document document = db.parse(xml);

        Binder<Node> binder = jc.createBinder();
        DataBean dataBean = (DataBean) binder.unmarshal(document);
        dataBean.setField2("NEW FIELD 2");
        dataBean.setField5("NEW FIELD 5");
        binder.updateXML(dataBean);

        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        StreamResult result = new StreamResult(System.out);
        t.transform(source, result);
    }

}

Output

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<data>
    <field1>Value</field1>
    <field2>NEW FIELD 2</field2>
    <field3>Value</field3>
    <field4>Value</field4>
    <field5>NEW FIELD 5</field5>
</data>

For More Information

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • Great works very well, and with EclipseLink I can map using xpath, beautiful. But, if I don't need @XmlPath can I do the same with standard JAXB? – dash1e Apr 03 '12 at 12:35
  • 1
    @MaurizioMerli - EclipseLink MOXy is a standard JAXB/JSR-222 (http://jcp.org/en/jsr/detail?id=222) implementation passing all the JAXB and Java EE compliance tests. I have been a member of that expert group for a while now (see section 1.5 of the JAXB spec). The JAXB reference implementations implementation of `Binder` appears to act differently which I have always considered a bug in that implementation. – bdoughan Apr 03 '12 at 14:22
  • The example did not work for me. Seems the `jabx.properties` has not be token in consideration. It worked with a direct use of the class in the definition of the Jabx-Context: `JAXBContext jc = org.eclipse.persistence.jaxb.JAXBContextFactory .createContext(new Class[] {DataBean.class}, null);` – Olivier Faucheux Jul 26 '23 at 06:25
-1

If you decide what is in structure xml then you may use XStream (http://x-stream.github.io/) to serialize and deserialize. But if you only deserialize from xml to bean (from foreign format), then you should use Smooks (http://www.smooks.org/).

Both of these libraries are very light in contrast to JAXB. JAXB is not flexible and requires that creating XML Schema. I do not recommend, because you lose more time than on creating a simple DOM parse.

JAXB is very academic. Example: many of "SOAP envelopes" is not fully described by WSDL documents, but adds some xml into WSDL field (in a simple text field). In such a case, you lose a lot of time to create a JAXB infrastructure...

Of course this is just my personal opinion. But remember these two tools and try to use them. You'll see that it really worth.

facundofarias
  • 2,973
  • 28
  • 27
wojand
  • 142
  • 5
  • So with XStream I'm able to update the source xml document, change only the mapped fields and let invariant other xml elements? – dash1e Apr 03 '12 at 09:41
  • JAXB (JSR-222) implementations do not require an XML schema (http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/TheBasics), and is quite lightweight and easy to use compared to XStream (http://blog.bdoughan.com/2010/10/how-does-jaxb-compare-to-xstream.html). JAXB is leveraged by JAX-WS to create SOAP messages, but is also used on its own. JAXB is hardly "academic" as it is used in more enterprise applications that anything else. – bdoughan Apr 03 '12 at 09:53
  • Blaise: JAXB need schema which describes data types, look to http://jaxb.java.net/tutorial/section_2_1-Writing-an-XML-Schema-for-JAXB.html#Writing%20an%20XML%20Schema%20for%20JAXB, and to http://jaxb.java.net/tutorial/section_1_3-Hello-World.html#Hello%20World. JAXB of course contains schema builder. – wojand Apr 03 '12 at 15:02
  • 1
    @wojand - Trust me, JAXB (JSR-222) implementations do not require an XML Schema. For many examples please check out my blog: http://blog.bdoughan.com/ – bdoughan Apr 03 '12 at 15:22
  • Maurizio: XStream is designed to write XML snippets. So, you do not need write any xml document which defines xml structure. But this only serialization tool. Probably is faster than JAXB, because can be use XPP parser. For binding foreign format Smooks is better. Do not get me wrong, JAXB is not bad tool :-) Everything depends on what you really need it. – wojand Apr 03 '12 at 15:27
  • @Blaise: it is just that JAXB during the build by maven generates the schema? I spent a few days on JAXB tool, after this time I was very angry and I found alternatives. To use XStream you need only a few minutes, you do not need any dtd or builder configuration which create dtd. XStream in my opinion is very simple tool. But of course it is not JSR standard. – wojand Apr 03 '12 at 15:42
  • @wojand - There is no point where JAXB needs to generate an XML schema. JAXB implementations can also use pull parsers (StAX), I expect them to be faster than XStream because JAXB impls preinitialize the Metadata when the `JAXBContext` is created. – bdoughan Apr 03 '12 at 16:50
  • @Blaise: XPP parser it is not a StAX parser. Idea is similar, but it is not the same (ex. diferences in API). JAXB must use parser which is compliance with JSR-173. XPP3 and kXML2 is not compliance with JSR-173. XPP/kXML2 is little faster than StaX ex. Woodstox. – wojand Apr 03 '12 at 21:02
  • @Blaise: Also you are wrong when you write "I_expect_them_to_be_faster_than XStream_because_JAXB_impls_preinitialize_the_Metadata_when_the JAXBContext_is_created." To increase performance XStream caches quite a lot like classes, converters to use, aliasing, tag names. This works on demand, so XStream do not lost time in beginning to preinitialize all classes – wojand Apr 03 '12 at 21:03
  • @Blaise: Another thing: JAXB 2 which not need dtd working only in jdk 5 and higher. XStream not need annotations. Otherwise, you're not referred to the Smooks. In my opinion JAXB loses fight with Smooks in data integration on _all fronts_ :-P JAXB based on the idealistic idea that all data that comes in SOAP are described in the dtd, and this is completely untrue. – wojand Apr 03 '12 at 21:47