XML Manipulation with Apache AXIOM, Page 2
|When you ask for the document element from the builder, it will give you the pointer to the Axiom wrapper. But, the XML stream is still in the stream and no object tree is created at that time. The object tree is created only when you navigate or build the Axiom.|
Sample 2: Creating AXIOM Using a String
At this point, try to create an Axiom document from a string that is also very straightforward. The only difference is that you first need to convert a string into a stream.
String xmlString = "<book>" + "<name>Qucik-start Axis</name>" + "<isbn>978-1-84719-286-8</isbn>" + "</book>"; //Convert string into a stream ByteArrayInputStream xmlStream = new ByteArrayInputStream(xmlString.getBytes()); //Create a builder. Because we want the XML as a plain XML, //we can just use the plain OMBuilder StAXBuilder builder = new StAXOMBuilder(xmlStream); //Return the root element. builder.getDocumentElement();
As you can see, when creating an Axiom from a string, first you get an input stream from that and follow the same procedure you did earlier. By looking at the example, it is clear that creating an Axiom from an input stream or from a string is pretty straightforward. However, elements and nodes also can be created programmatically to modify the structure of the AXIOM element that you created above. The recommended way to create Axiom objects programmatically is to use the factory.
The OMAbstractFactory.getOMFactory() method will return the proper factory and the creator methods for each type that should be called.
Sample 3: Creating AXIOM Programmatically
Creating an Axiom programmatically is a little bit difficult compared to previous two cases, and of course it involves additional steps.
//Obtain a factory. OMFactory factory = OMAbstractFactory.getOMFactory(); //Use the factory to create two namespace object. OMNamespace axis2 = factory.createOMNamespace("axis2","ns"); //Use the factory to create three elements to represent the book //element. OMElement root = factory.createOMElement("book",axis2); OMElement name = factory.createOMElement("name",axis2); OMElement isbn = factory.createOMElement("isbn",axis2);
As you can see above, in the factory there is a set of factory.create methods. That is mainly to cater to different implementations, but keep the programmer's code intact. When you use Axiom, it is a best practice to use the factory to create Axiom objects; this will ease the switching of different Axiom implementations. Several differences exist between a programmatically created OMNode and a conventionally creating OMNode. The most important difference is that the former will have no builder object enclosed; the latter always carries a reference to its builder. As discussed earlier, the object model is built as and when required. Therefore, each and every OMNode should have a reference to its builder. If this information is not available, it is due to the object being created without a builder. This difference becomes evident when the user tries to get a non-caching pull parser from the OMElement.
Sample 4: Adding a Child Node and Attributes
So far, you've learned how to create Axiom programmatically and by using StAX API, but these techniques are not enough to work with Axiom. You need to learn how to create and add child nodes to Axiom. Addition and removal methods are primarily defined in the OMElement interface. The following are the important methods for adding nodes.
public void addChild(OMNode omNode); public void addAttribute(OMAttribute omAttribute);
Now. try to complete the book element you previously created by adding "name" and "isbn" child elements to the root element.
- The addChild method will always add the child as the last child of the parent.
- A given node can be removed from the tree by calling the detach() method. A node also can be removed from the tree by calling the remove method of the returned iterator; this also will call the detach method of the particular node internally.
- Namespaces are a tricky part of any XML object model; it's the same in Axiom. However, the interface to the namespace has been made very simple. OMNamespace is the class that represents a namespace with intentionally removed setter methods. This makes the OMNamespace immutable and allows the underlying implementation to share the objects without any difficulty.
Sample 5: Working with OM Namespaces
As you just saw, namespace handling is a key part in XML processing. Hence, Axiom provides a set of APIs to handle namespaces.
public OMNamespace declareNamespace(String uri, String prefix); public OMNamespace declareNamespace(OMNamespace namespace); public OMNamespace findNamespace(String uri, String prefix) throws OMException;
As you can see, there are two declareNamespace methods and they are fairly straightforward. Note that a namespace declaration that has already been added will not be added twice. findNamespace is a very handy method to locate a namespace object higher up the object tree. It searches for a matching namespace in its own declarations section and jumps to the parent if it's not found. The search progresses up the tree until a matching namespace is found or the root has been reached.