XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

A Survey of APIs and Techniques for Processing XML
by Dare Obasanjo | Pages: 1, 2

Tree Model APIs

A tree-based API is an object model that represents an XML document as a tree of nodes. The object model consists of objects that map to various concepts from the XML 1.0 recommendation such as elements, attributes, processing instructions and comments. Such APIs provide mechanisms for loading, saving, accessing, querying, modifying, and deleting nodes from an XML document. The canonical example of a tree model API for processing XML is the W3C XML Document Object Model (DOM) which has inspired various programming language specific variations including JDOM and PyXML, for Java and Python respectively

Typically tree model APIs load the entire XML document into memory, and thus do not limit users to forward-only access of the XML data. This prevents traditional tree model APIs from being used in situations where large XML documents have to be processed. Although it is possible to build optimized tree model APIs that only load portions of an XML document as needed, such APIs are not in widespread usage.

The following code sample uses the Apache Xerces DOM API to display the contents of the title and author elements of books that have the on-loan attribute set.


import org.apache.xerces.parsers.*;
import org.apache.xerces.dom.*;
import org.w3c.dom.*; 

public class Test{

  public static void main(String[] args) {
  
        
    try {

	DOMParser parser = new DOMParser(); 
        parser.parse("books2.xml"); 
	
        org.w3c.dom.Document doc  = parser.getDocument();

	NodeList list = doc.getElementsByTagName("book"); 

for(int i = 0, length = list.getLength(); i < length; i++){

    Element book  = (Element)list.item(i);
    Attr borrower = book.getAttributeNode("on-loan"); 
	    
    if(borrower != null){
     System.out.print(borrower.getValue() + " was loaned ");

    //cast elements to Xerces specific classes 
    //to get access to getTextContent() method
    ParentNode title = (ParentNode)
              book.getElementsByTagName("title").item(0); 
    ParentNode author = (ParentNode)
              book.getElementsByTagName("author").item(0); 
		
    System.out.println(title.getTextContent() + " by " 
                                  + author.getTextContent());
	    }
	} 
      
    }catch (Exception e) {         
        System.out.println(e.getMessage());
    }      
  
  }

}      

The W3C DOM offers fairly limited functionality, primarily because it was designed to be a generic API that could be implemented in a variety of programming languages. This usually means that most people who utilize the DOM API use helper methods, that is, extensions to the DOM API which are specific to particular implementations (such as the call to getTextContent() in the previous sample).

Cursor APIs

XML cursors are the newest class of APIs for processing XML. An XML cursor acts like a lens that focuses on one XML node at a time, but, unlike pull-based or push-based APIs, the cursor can be positioned anywhere along the XML document at any given time. In a way, pull model APIs are forward-only versions of a cursor model. Examples of XML cursor APIs are the .NET Framework's XPathNavigator class and the XmlCursor class from BEA's XMLBeans toolkit.

Just like tree model APIs, an XML cursor allows one to navigate, query, and manipulate an XML document loaded in memory. However, an XML cursor does not require the heavyweight interface of a traditional tree model API, where every significant token in the underlying XML must map to an object. This means that XML cursor APIs are potentially more memory efficient than tree model APIs.

More importantly, the fact that node objects do not need to be created for each information item in the underlying XML means that it makes it easier to create "XML views" of non-XML data. Whereas with traditional tree model APIs one had to duplicate an entire data source into a DOM or something similar to present the data source as XML, with XML cursors one can just implement a cursor over that data source that presents the underlying data as XML nodes when viewed through the cursor. This is the concept behind the ObjectXPathNavigator, which uses the .NET Framework's XPathNavigator, enabling one to treat an arbitrary set of objects as a virtual XML document that can be queried with XPath or transformed with XSLT.

The following code sample uses the .NET Framework's XPathNavigator class to display the contents of the title and author elements of books that have the on-loan attribute set.

   
using System; 
using System.Xml.XPath; 

public class Test{

  public static void Main(string[] args){

    XPathDocument doc  = new XPathDocument("books2.xml"); 
    XPathNavigator nav = doc.CreateNavigator(); 

    //select every book with an on-loan attribute 
    XPathNodeIterator iterator = 
                        nav.Select("/books/book[@on-loan]"); 

    while (iterator.MoveNext()){
      
      //create a navigator pointing at same position
      XPathNavigator nav2 = iterator.Current.Clone(); 
      string borrower     = nav2.GetAttribute("on-loan", "");

      nav2.MoveToFirstChild();
      string title        = nav2.Value; 
      nav2.MoveToNext(); 
      string author       = nav2.Value; 

      Console.WriteLine("{0} was loaned {1} by {2}", 
                                   borrower, title, author);
    }    
  }
}      

Object to XML Mapping APIs

It is often convenient to map the contents of an XML document to objects that better represent the data within the XML document than interacting with the data via an XML-based object model. Developers working in object oriented languages typically prefer working with information as objects and classes as opposed to attempting to extract information from untyped XML nodes.

There are numerous advantages to this approach. First, the memory footprint of XML data can be reduced because information isn't being stored as nodes and textual data but as classes and programming language primitives. A DOM node that represents a <foo> element that contains a numeric value as text is more memory intensive than its counterpart foo class with an integer field. In particular, the memory footprint is better if you are able to turn lots of leaf values into primitive valued fields, or if you can do away with parent and sibling pointers. Second, it is more convenient to perform calculations on certain types of data such as numbers or dates as native programing language constructs than it is to interact with them as string values stored in nodes. But, third, the most compelling argument is the improved ease of use. It's no longer nessary to navigate the XML tree to access the information but instead one can simply access data as fields and properties of an object.

Object to XML mapping technologies have certain limitations that prevent them from replacing traditional methods for accessing XML data. Most of these technologies cannot represent all the information in an XML document with full fidelity. Many do not preserve processing instructions and comments. Similarly mixed content is problematic to map to objects since the tendency is to map element and attribute nodes to objects and text nodes to the values of fields or properties in said objects. Although the order of elements is significant in an XML document, this typically cannot be enforced on objects. Most object oriented languages do not have a way of expressing that in a book class the title field precedes the author field, although one could use ordered collections to get around this problem.

In most cases an XML document's schema (which could be a DTD, W3C XML Schema document, or proprietary schema language) is used as a basis for mapping the XML to native objects in the target programming language. Examples of such Object<->XML mapping technologies include JAXB, the .NET Framework's XmlSerializer and Castor. Another limitation of Object<->XML mapping technologies is that there are often impedance mismatches between XML schema languages such as W3C XML Schema and object oriented concepts.

The following sample shows how to utilize the .NET Framework's XmlSerializer class to display the contents of the title and author elements of books that have the on-loan attribute set.

  1. Obtain the schema for your XML document. Below is a schema for my XML file generated using the Microsoft XSD Inference tool.
        
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
        attributeFormDefault="unqualified"
        elementFormDefault="qualified">
    
     <xs:element name="books"> 
      <xs:complexType>
       <xs:sequence> 
        <xs:element name="book" maxOccurs="unbounded">
         <xs:complexType>
          <xs:sequence>
           <xs:element name="title" type="xs:string" />
           <xs:element name="author" type="xs:string" />
           </xs:sequence>
           <xs:attribute name="publisher" type="xs:string" 
                                            use="required" />
           <xs:attribute name="on-loan" type="xs:string" 
                                            use="optional" />
          </xs:complexType>
        </xs:element>
       </xs:sequence> 
      </xs:complexType>
     </xs:element>
    
    </xs:schema>         
  2. Generate a C# class from the XML schema using xsd.exe
    using System.Xml.Serialization;
    
    /// <remarks/>
    [System.Xml.Serialization.XmlRootAttribute("books", 
                                 Namespace="", IsNullable=false)]
    public class books {
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("book")]
        public booksBook[] book;
    }
    
    /// <remarks/>
    public class booksBook {
        
        /// <remarks/>
        public string title;
        
        /// <remarks/>
        public string author;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute
              (Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public string publisher;
        
        /// <remarks/>
       [System.Xml.Serialization.XmlAttributeAttribute("on-loan",
          Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public string onloan;
    }    
         
  3. Write code
     
    using System; 
    using System.Xml.Serialization; 
    using System.IO; 
    
    public class Test{
    
      public static void Main(string[] args){
    
        TextReader reader = new StreamReader("books2.xml");
        XmlSerializer serializer = 
                           new XmlSerializer(typeof(books));
        books myBooks = 
                          (books)serializer.Deserialize(reader);
        reader.Close();
    
        foreach(booksBook book in myBooks.book){
    
          if(book.onloan != null){
    	Console.WriteLine("{0} was loaned {1} by {2}", 
                           book.onloan, book.title, book.author);
          }    
        }
      
      }
    }         

XML Specific Languages

It seems natural that one would process XML using a language that is designed for processing XML as opposed to going through traditional programming languages. For performing complex operations on XML data, all of the aforementioned techniques suffer from either being too cumbersome, require too many lines of code, or do not handle all of XML. In such cases, the wise decision is to go with a language which natively understands how to process XML to do the heavy lifting and invoke that from the target programming language. Examples of languages specifically designed for processing and manipulating XML include XPath, XQuery, XSLT, and Xtatic.

The following sample is an XQuery expression that displays the contents of the title and author elements of books that have the on-loan attribute set.

    
    for $b in document("books2.xml")/books/book[@on-loan]
     return (string($b/@on-loan), " was loaned ", 
                  $b/title/text(), " by ", $b/author/text())
    
   

There are various sites where one can try out sample XQuery expressions, including QEXO XQuery Sandbox and Microsoft's XQuery demo site

Conclusion

This article shows that processing XML isn't simply a choice of in-memory (DOM) versus streaming (SAX). Rather, it's a tradeoff between a number of choices with lots of small nuances. The following table is s supplement to this article: it provides a quick overview of the distinguishing characteristics of the various approaches and techniques

Push Model Pull Model Tree Model Cursor Model Object to XML Mapping XML-Specific Languages
Forward-Only Access (streaming) X X        
Random Access (in memory)     X X X X
Schema Required         X  
Read-only access X X       depends
Event based X          
Emphasizes XML data model X X X X   X


1 to 5 of 5
  1. String based API
    2003-08-06 05:38:05 Julian Turner
  2. Similiar article from Elliotte Rusty Harold?
    2003-07-17 16:43:39 Wai Yip Tung
  3. Xineo OAX is another free software alternative
    2003-07-17 01:29:09 Frédérik Bilhaut
    • The link !
      2003-07-17 01:29:56 Frédérik Bilhaut
  4. Don't forget STX
    2003-07-16 05:56:54 Oliver Becker
  5. Well-done article
    2003-07-11 03:01:48 Reinout van Rees
1 to 5 of 5