XPath 1.0 queries on JAXB objects? - java

JAXB has been great, a real timesaver, but it's still really time consuming to traverse the resulting object trees; almost as bad as working directly with the DOM.
Is there a way that I can do XPath 1.0 queries on a JAXBElement, without having to painstakingly marshal the document to and from a DOM model each time?

Not directly, no. However, you can use Apache Commons Jxpath, which allows you to run XPath queries across arbitrary object graphs, not just JAXB-bound ones. It can be run in "lenient" mode, which is tolerant of nulls.
Extremely handy for replacing those NPE-prone graph navigations.

The accepted answer was from 2010 and this post is for the benefit of others who are looking to use XPath with JAXB. Moxy implementation provides lots of nice extensions and one of them is to execute XPath. Read more about this on Moxy's tutorial. Example copied from the same place
Customer customer = (Customer) jaxbContext.createUnmarshaller().unmarshal(instanceDoc);
...
int customerId = jaxbContext.getValueByXPath(customer, "#id", null, Integer.class);
jaxbContext.setValueByXPath(customer, "first-name/text()", null, "Bob");
jaxbContext.setValueByXPath(customer, "phone-number/area-code/text()", null, "555");
...
jaxbContext.createMarshaller().marshal(customer, System.out);

Related

Evaluating JAXB

I have a couple of questions about JAXB:
What options are there for parsing? Can I implement / plugin my own parser easily?
What about validity? Suppose I have a relaxed parser that is somewhat relaxed regarding the schema. Can I still create an (invalid) object-structure?
Does JAXB provide special means to do e.g. validation on the objects? I'd like to parse to an "invalid" object structure, have some algorithm repair it, then validate (in Java).
Does JAXB provide other means to do fancy things on the objects (e.g. visitor pattern).
What about the memory footprint? Is the object representation (disregarding the parsing) feasible for XML files of 10-100MB?
Good tutorials covering this kind of questions are appreciated, Google revealed only coarse overviews.
Below are my answers to your questions:
What options are there for parsing? Can I implement / plugin my own
parser easily?
JAXB (JSR-222) implementations can unmarshal from many different input types: InputStream, InputSource',Node,XMLStreamReader,XMLEventReader,File,Source`. If your XML representation matches any of these then you're all set.
What about validity? Suppose I have a relaxed parser that is somewhat
relaxed regarding the schema. Can I still create an (invalid)
object-structure?
JAXB implementations requires that the XML be well formed, but does not require it be valid against an XML schema. It is designed to handle a wide range of documents. If you want to ensure "validity" then you can set an XML schema (see JAXB and Marshal/Unmarshal Schema Validation).
Does JAXB provide special means to do e.g. validation on the objects?
I'd like to parse to an "invalid" object structure, have some
algorithm repair it, then validate (in Java).
You can use the javax.xml.validation APIs to do validation on an object model. For a full example see:
http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html
Does JAXB provide other means to do fancy things on the objects (e.g.
visitor pattern).
JAXB models are POJOs so you can design them as you wish. You may be interested in the following classes:
http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.Listener.html
http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Unmarshaller.Listener.html
What about the memory footprint? Is the object representation
(disregarding the parsing) feasible for XML files of 10-100MB?
Yes JAXB can be used to process documents of that size. If you are concerned about size, you can use an XMLStreamReader to parse the XML file and then unmarshal objects from the XMLStreamReader in chunks.

using xsd:any for extensible schema

Until now, I've been handling extensions by defining a placeholder element that has "name" and "value" attributes as shown in the below example
<root>
<typed-content>
...
</typed-content>
<extension name="var1" value="val1"/>
<extension name="var2" value="val2"/>
....
</root>
I am now planning to switch to using xsd:any. I'd appreciate if you can help me choose th best approach
What is the value add of xsd:any over my previous approach if I specify processContents="strict"
Can a EAI/ESB tool/library execute XPATH expressions against the arbitrary elements I return
I see various binding tools treating this separately while generating the binding code. Is this this the same case if I include a namespace="http://mynamespace" and provide the schema for the "http://mynamespace" during code gen time?
Is this WS-I compliant?
Are there any gotchas that I am missing?
Thank you
Using <xsd:any processContents="strict"> gives people the ability to add extensions to their XML instance documents without changing the original schema. This is the critical benefit it gives you.
Yes. tools than manipulate the instances don't care what the schema looks like, it's the instance documents they look at. To them, it doesn't really matter if you use <xsd:any> or not.
Binding tools generally don't handle <xsd:any> very elegantly. This is understandable, since they have no information about what it could contain, so they'll usually give you an untyped placeholder. It's up the the application code to handle that at runtime. JAXB is particular (the RI, at least) makes a bit of a fist of it, but it's workable.
Yes. It's perfectly good XML Schema practice, and all valid XML Schema are supported by WS-I
<xsd:any> makes life a bit harder on the programmer, due to the untyped nature of the bindings, but if you need to support arbitrary extension points, this is the way to do it. However, if your extensions are well-defined, and do not change, then it may not be worth the irritation factor.
Regarding point 3
Binding tools generally don't handle
very elegantly. This is
understandable, since they have no
information about what it could
contain, so they'll usually give you
an untyped placeholder. It's up the
the application code to handle that at
runtime. JAXB is particular (the RI,
at least) makes a bit of a fist of it,
but it's workable.
This corresponds to the #XmlAnyElement annotation in JAXB. The behaviour is as follows:
#XmlAnyElement - Keep All as DOM Nodes
If you annotate a property with this annotation the corresponding portion of the XML document will be kept as DOM nodes.
#XMLAnyElement(lax=true) - Convert Known Elements to Domain Objects
By setting lax=true, if JAXB has a root type corresponding to that QName then it will convert that chunk to a domain object.
http://bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html

Simple way to do Xml in Java

Is there is Simple way to read and write Xml in Java?
I've used a SAX parser before but I remember it being unintuitive, I've looked at a couple of tutorials for JAXB and it just looks complicated.
I don't know if I've been spoilt by C#'s XmlDocument class, but All I want to do is create an Xml Document that represents a a set of classes and their members (some are attributes some are elements).
I would look into serialization but the XML has to have the same format as the output of a c# app which I am reverse engineering into Java.
I recommend XOM. Its API is clear and intuitive.
You should check out Xstream. There is a 2 minute tutorial that is really simple. To get the same format, you would model the classes the same.
If you are using jdk 1.4 or newer take a look at XMLEncoder class.
Some of the more popular approaches to consider:
Java Archictecture for XML Binding
JAXB is a specification for a standard XML binding. If you already have an XSD, it can generate your Java classes for you, and then all that's left is to use a standard API for marshalling/unmarshalling.
Reference implementation from Glassfish
Apache's implementation JaxMe
Other binding approaches
As with JAXB, these approaches use XML-based binding configurations. They may provide more fine grained control of the unmarshalling process.
Castor
JIBX
Roll your own
Using StAX
Using XOM
Using plain XPath
Dom4j is a simple api for creating xml documents in java.
Document document = DocumentHelper.createDocument();
Element root = document.addElement( "root" );
Element author2 = root.addElement( "author" )
.addAttribute( "name", "Toby" )
.addAttribute( "location", "Germany" )
.addText( "Tobias Rademacher" );
The most simple way so far is the MarkupBuilder in Groovy. Think of Groovy as a new syntax for Java. The XmlSlurper can be used to read XML.
I think that Apache XMLBeans provides the functionality you are after.
The Wikipedia page gives a good overview and example usage.
There is a wide choice of XML processing options for Java, though judging from the .NET documentation for XmlDocument, the Java DOM implementation is the closest out-of-the-box equivalent.
.NET XmlDocument:
This class implements the W3C Document
Object Model (DOM) Level 1 Core and
the Core DOM Level 2.
Java Document:
See also the Document Object Model (DOM) Level 3 Core Specification.
Sample code:
public static void main(String[] args) throws Exception {
File xmlFile = new File(".classpath");
// read it
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(xmlFile);
// walk it
System.out.println("Node count=" + countNodes(document));
// write it
Source source = new DOMSource(document);
Result result = new StreamResult(System.out);
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(source, result);
}
/** Doesn't count attributes, etc */
private static int countNodes(Node node) {
int count = 0;
NodeList kids = node.getChildNodes();
count += kids.getLength();
for (int i = 0; i < kids.getLength(); i++) {
count += countNodes(kids.item(i));
}
return count;
}
I think JAXB is only complicated if you look at wrong examples. Specifically, yes, schema-based way can get messy. But code-first, annotation-based is trivially easy.
Another easy alternative is XStream. And for non-binding case, StaxMate, which is an add-on for streaming Stax parsers.
If SAX parsing is mandatory, JAXP is a good choice. I prefer DOM parsing and use jdom which seems a lot easier to me.
I would certainly use XOM if you want a DOM-like approach and SAX (www.sax.org) if you want a SAX-like approach. I was involved in the early development of XML and SAX was developed as an event-driven approach, which is useful for some applications. DOM/XOM and SAX are complementary - sometimes you need one, sometimes the other. If you wish to build objects as you go rather than read everything into memory, use SAX. If you are happy to read everything in and then process it, use XOM.
I spent far too much time trying to get the W3C DOM to work - IMO it is poorly defined with too many ways of doing some things and not enough for others. When XOM came it revolutionised my productivity.
The XOM community is very knowledgeable and focused and helpful.

JAVA: Build XML document using XPath expressions

I know this isn't really what XPath is for but if I have a HashMap of XPath expressions to values how would I go about building an XML document. I've found dom-4j's
DocumentHelper.makeElement(branch, xpath) except it is incapable of creating attributes or indexing. Surely a library exists that can do this?
Map xMap = new HashMap();
xMap.put("root/entity/#att", "fooattrib");
xMap.put("root/array[0]/ele/#att", "barattrib");
xMap.put("root/array[0]/ele", "barelement");
xMap.put("root/array[1]/ele", "zoobelement");
would result in:
<root>
<entity att="fooattrib"/>
<array><ele att="barattrib">barelement</ele></array>
<array><ele>zoobelement</ele></array>
</root>
I looked for something similar a few years ago - a sort of writeable XPath. In the end, having not found anything, I hacked up something which essentially built up the XML document by adding new nodes to parent expressions:
parent="/" element="root"
parent="/root" element="entity"
parent="/root/entity" attribute="att" value="fooattrib"
parent="/root" element="array"
parent="/root" element="ele" text="barelement"
(This was itself to be governed by an XML configuration file, hence the appearance of above.)
It would be tempting to try an automate some of this to just take the last path element, and make something of it, but I always felt that there were XPath expressions I could write which such a dumbheaded approach would get wrong.
Another approach I considered, though did not implement (the above was "good enough"), was to use the excellent Jaxen to generate elements that did not exist, on the fly if it didn't already exist.
From the Jaxen FAQ:
The only thing required is an implementation of the interface org.jaxen.Navigator. Not all of the interface is required, and a default implementation, in the form of org.jaxen.DefaultNavigator is also provided.
The DOMWriterNavigator would wrap and existing DOMNavigator, and then use the makeElement method if the element didn't exist. However, even with this approach,
you'd probably have to do some pre/post processing of the XPath query for things like attributes and text() functions.
The best I was able to come up with is to use a JAXB implementation, which will marshall/unmarshal objects to xml and then I used Dozer (http://dozer.sourceforge.net/documentation/mapbackedproperty.html) to map the xpaths which were keys in a map to the JAXB object method setters.
<mapping type="one-way" map-id="TC1">
<class-a>java.util.Map</class-a>
<class-b>org.example.Foo</class-b>
<field>
<a key="root/entity/#att">this</a>
<b>Foo.entity.att</b>
<a-hint>java.lang.String</a-hint>
</field>
It's more of a two step solution, but really worked for me.
I also wanted same kind of requirement where nature is so dynamic and dont want to use XSLT or any object mapping frameworks, so i've implemented this code in java and written blog on it please visit,
http://ganesh-kandisa.blogspot.com/2013/08/dynamic-xml-transformation-in-java.html
or fork code at git repository,
https://github.com/TheGanesh/DynamicXMLTransformer

Java object to XML schema

If you have a Java object and an XML schema (XSD), what is the best way to take that object and convert it into an xml file in line with the schema. The object and the schema do not know about each other (in that the java classes weren't created from the schema).
For example, in the class, there may be an integer field 'totalCountValue' which would correspond to an element called 'countTotal' in the xsd file. Is there a way of creating a mapping that will say "if the object contains an int totalCountValue, create an element called 'countTotal' and put it into the XML".
Similarly, there may be a field in the object that should be ignored, or a list in the object that should correspond to multiple XML elements.
I looked at XStream, but didn't see any (obvious) way of doing it. Are there other XML libraries that can simplify this task?
I believe this can be achieved via JAXB using it's annotations. I've usually found it much easier to generate Objects from JAXB ( as defined in your schema) using XJC than to map an existing Java object to match my schema. YMMV.
I'm doing Object do XML serialization with XStream. What don't you find "obvious" with this serializer? Once you get the hang of it its very simple.
In the example you provided you could have something like this:
...
XStream xstream = new XStream(new DomDriver());
xstream.alias("myclass", MyClass.class);
xstream.aliasField("countTotal", MyClass.class, "totalCountValue");
String xml = xstream.toXML(this);
...
for this sample class:
class MyClass {
private int totalCountValue;
public MyClass() {
}
}
If you find some serializer more simple or "cool" than this please share it with us. I'm also looking for a change...
Check the XStream mini tutorial here
I use a java library called JiBx to do this work. You need to write a mapping file (in XML) to describe how you want the XML Schema elements to map to the java objects. There are a couple of generator tools to help with automating the process. Plus it's really fast.
I tried out most of the libraries suggested in order to see which one is most suited to my needs. I also tried out a library that was not mentioned here, but suggested by a colleague, which was a StAX implementation called Woodstox.
Admittedly my testing was not complete for all of these libraries, but for the purpose mentioned in the question, I found Woodstox to be the best. It is fastest for marshalling (in my testing, beating XStream by around 30~40%). It is also fairly easy to use and control.
The drawback to this approach is that the XML created (since it is defined by me) needs to be run through a validator to ensure that it is correct with the schema.
You can use a library from Apache Commons called Betwixt. It can map a bean to XML and then back again if you need to round trip.
Take a look at JDOM.
I would say JAXB or Castor. I have found Castor to be easier to use and more reliable, but JAXB is the standard

Categories