November 28, 2014
Hot Topics:

Going Beyond XML Manipulation with Apache AXIOM

  • March 19, 2009
  • By Deepal Jayasinghe
  • Send Email »
  • More Articles »

Serialization

Now you should have a good understanding on creating and traversing the Axiom tree, therefore next most important part is to learn how to serialize or write Axiom tree into an output stream. Axiom can be serialized either as the pure object model or the pull event stream. The serialization uses an XMLStreamWriter object to write out the output and hence, the same serialization mechanism can be used to write different types of outputs (such as text, binary, etc.).

A caching flag is provided by Axiom to control the building of the in-memory Axiom. The OMNode has two methods, serializeAndConsume and serialize. When serializeAndConsume is called, the cache flag is reset and the serializer does not cache the stream. Hence, the object model will not be built if the cache flag is not set in which case it will serialize XML stream directory to the output stream without creating object model. If the serializeAndConsume method is called, then you can serialize the axiom tree only once, since it does not build the axiom tree into memory. However, the serialize method can be called any number of times. I will cover the difference between the two later in this section.

Serialize to OutputStream

OutputStream out = new FileOutputStream(“filename”);
XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(out);
//dump the output to console with caching
root.serialize(writer); 
writer.flush();

Note: You can call also call the toString() method of any given OMElement to serialize the element.

The difference between serializeAndConsume() and serialize()

Now you should try to understand the difference between the serializeAndConsume() and serialize() methods. First try to call the serialize method twice in the axiom element as shown in the following sample code.

String xmlStream = 
    "<ns:name></ns:name><ns:isbn></ns:isbn></ns:book>";
 
 //Create an input stream for the string
 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xmlStream.getBytes());
 //create a builder. Since we want the XML as a plain XML, we can just use the plain OMBuilder
StAXBuilder builder = new StAXOMBuilder(byteArrayInputStream);
OMElement root = builder.getDocumentElement();
 root.serialize(System.out);
 root.serialize(System.out);

If you run the above sample code then you will see the following output in the console.

<ns:book xmlns:ns="axis2" type="web-services"><ns:name></ns:name><ns:isbn></ns:isbn></ns:book>
<ns:book xmlns:ns="axis2" type="web-services"><ns:name></ns:name><ns:isbn></ns:isbn></ns:book>

However, if you call serializeAndConsume() first and then call serialize(), you’ll get an exception. This is because once you have called the serializeAndConsume() method, the Axiom tree will not be built and the cache flag is reset. As such, the next time you try to call serialize you have nothing left to serialize so you will get an exception.

String xmlStream = "<ns:book xmlns:ns="axis2" type="web-services"><ns:name></ns:name><ns:isbn></ns:isbn></ns:book>";
 //Create an input stream for the string
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xmlStream.getBytes());
//create a builder. Since we want the XML as a plain XML, we can just use the plain OMBuilder
 StAXBuilder builder = new StAXOMBuilder(byteArrayInputStream);
OMElement root = builder.getDocumentElement();
 root.serializeAndConsume(System.out);
root.serialize(System.out);

Xpath Navigation

Axiom has Xpath navigation support through Jaxen, so you can write Xpath query and invoke them in Axiom. Write an Xpath query to get an ISBN number from the book element you created. If you run the following sample then you should get “56789”as output in the console.

String xmlStream = "<book type="web-services"><name></name><isbn>56789</isbn></book>";
        
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xmlStream.getBytes());
StAXBuilder builder = new StAXOMBuilder(byteArrayInputStream);
OMElement root = builder.getDocumentElement();
AXIOMXPath xpath = new AXIOMXPath("/book/isbn[1]");
OMElement selectedNode = (OMElement) xpath.selectSingleNode(root);
System.out.println(selectedNode.getText());

Axiom and SOAP

As discussed, Axiom was developed as XML representation mechanism in Axis2, therefore as a SOAP processing framework Axis2 needs to work with SOAP. SOAP is also XML but it has its own structure to be a special type of XML, so it is easy if you can get SOAP level API from Axiom. Axiom has built-in support for SOAP representation and navigation. You can create and navigate SOAP 1.1 and 1.2 documents easily with Axiom. When you navigate SOAP, Axiom has API to get the headers and body, therefore you do not need to get an iterator and navigate. The following two samples shows how to create SOAP 1.1 and 1.2 document easily with Axiom.

Creating SOAP 1.1 document

OMFactory factory = OMAbstractFactory.getOMFactory();
OMNamespace axis2 = factory.createOMNamespace("axis2", "ns");
OMElement root = factory.createOMElement("book", axis2);
OMAttribute type = factory.createOMAttribute("type",null,"web-services");
root.addAttribute(type);
OMElement name = factory.createOMElement("name", axis2);
OMElement isbn = factory.createOMElement("isbn", axis2);
root.addChild(name);
root.addChild(isbn);

SOAPFactory soapFactory = OMAbstractFactory.getSOAP11Factory();
 //get the default envelope
SOAPEnvelope env = soapFactory.getDefaultEnvelope();
//add the created child
env.getBody().addChild(root);
System.out.println( env);

As seen in the listing, first you create a book element as the body of the SOAP message, then create a default SOAP 1.1 envelope, and finally add the created book element as the body.

Creating SOAP 1.2 document

Creating SOAP 1.2 documents is almost the same as above except for the factory. Here you need to use 1.2 factory instead of 1.1 factory.

OMFactory factory = OMAbstractFactory.getOMFactory();
OMNamespace axis2 = factory.createOMNamespace("axis2", "ns");
OMElement root = factory.createOMElement("book", axis2);
OMAttribute type = factory.createOMAttribute("type",null,"web-services");
root.addAttribute(type);
OMElement name = factory.createOMElement("name", axis2);
OMElement isbn = factory.createOMElement("isbn", axis2);
root.addChild(name);
root.addChild(isbn);

SOAPFactory soapFactory = OMAbstractFactory.getSOAP12Factory();
 //get the default envelope
SOAPEnvelope env = soapFactory.getDefaultEnvelope();
//add the created child
env.getBody().addChild(root);
 System.out.println( env);

Summary

In the first part of the article Axiom basis and usage was covered along with some of the XML processing API of Axiom. In this part navigating Axiom was covered along with how to use Xpath expression to process Axiom, and how to serialize Axiom into an output stream. Finally, the Axiom APIs for processing SOAP were discussed. If you follow both of the articles with samples then you should be ready to work with Axiom.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel