Our Java application receives XML messages from a number of external systems and from these we want to create domain objects. We do not have schemas for these documents.
Currently we are are using XPaths to pull o开发者_Python百科ut strings from the XML and then calling setters on the new domain object. We use a home-baked XmlUtils class to do this.
foo.setBar(XmlUtils.number("/bar", document));
What alternative Java-based approaches are there, which do not require access to the document's schema?
Note: I'm the EclipseLink JAXB (MOXy) lead, and a member of the JAXB 2.X (JSR-222) expert group.
MOXy offers the @XmlPath
extension which enables you to do XPath based mapping:
Path Based Mapping
Match the bar
element under the foo
element:
@XmlPath("foo/bar/text()")
public int getBar() {
return bar;
}
Position Based Mapping
Match the second bar
element:
@XmlPath("bar[2]/text()")
public int getBar() {
return bar;
}
Predicate Based Mapping
Match the bar
element that has a type
attribute with value foo
:
@XmlPath("bar[@type='foo']/text()")
public int getBar() {
return bar;
}
Combined
All of the above concepts can be used together:
@XmlPath("foo[2]/bar[@type='foo']/text()")
public int getBar() {
return bar;
}
For More Information
- http://bdoughan.blogspot.com/2010/07/xpath-based-mapping.html
- http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html
- http://bdoughan.blogspot.com/2011/03/map-to-element-based-on-attribute-value.html
I recommend using Apache Commons Digester for this. The usage pattern is something like this:
digester.addObjectCreate("parent", Parent.class);
digester.addObjectCreate("parent/child", Child.class);
digester.addCallMethod("parent/child", "setName", 1);
digester.addCallParam("parent/child/name", 0);
digester.addSetNext("parent/child", "addChild");
Also if you already have domain objects with structure similar to source xml, you can try to annotate it manually to unmarshal with JAXB.
Simple framework. I never used it but some time ago I took a look at the documentation and examples and it might be worth a closer look. Its job is Java bean serialization/deserialization to/from XML using annotated bean.
I would go either with MOXy that was recommend, or JAXB (javax.xml.bind, bundled with JDK 6, available separately for JDK 5).
Use of "manual" XPath is rather inefficient, error prone; data binding is usually the way to go if you really don't care about XML per se, just data an XML document contains. This is a big difference (data- vs document-oriented XML), and quite often XPath is much more useful for document-oriented use cases.
Digester mentioned by @JustYo is perfect. But I'd add some tip: take a look on class DigetserDigester. It allows mapping classes to XML without writing code at all. It is done using other XML document. Very cool.
Other possibility is JAXB. it is annotation based and is 2 directional. The only possible problem that could be that it is sometimes hard to map any class to any xml schema. But if you can change at least one of them (classes of XML) or better both I'd recommend you to use JAXB.
精彩评论