XMLBeans 2.0 - A Java Developer's Perspective
Pages: 1, 2, 3, 4

Generics with XMLBeans

At a glance, JDK 5.0 generics enable the creation of parameterized classes and methods. The Collections API is one of the first places you will see generics used within XMLBeans. In an XML Schema, when an element contains the attribute maxOccurs with a value greater than 1, by default XMLBeans will create a Java array for these types. To enable generics, an additional parameter needs to be added to scomp, and a JDK 5.0-compatible VM needs to be used.

By default, the API for getting the item elements from the channel contains the following methods:

RssDocument.Rss.Channel.Item getItemArray(int i)
Gets "item" element
RssDocument.Rss.Channel.Item[] getItemArray()
Gets array of all "item" elements
void setItemArray(int i, RssDocument.Rss.Channel.Item item)
Sets "item" element
void setItemArray(RssDocument.Rss.Channel.Item[] itemArray)
Sets array of all "item" elements

However, the API changes after performing the compilation step with generics enabled:

/home/user>scomp
Compiles a schema into XML Bean classes and metadata.
Usage: scomp [opts] [dirs]* [schema.xsd]* [service.wsdl]* 
             [config.xsdconfig]*
Options include:
...
                         
-javasource [version] - generate java source compatible for a 
                               Java version (1.4 or 1.5)
...
        
#This is all it takes to enable Generics in your use of XMLBeans
/home/user>scomp -javasource 1.5 schema0.xsd
                      

Using the example above, the new methods available look like:

 java.util.List<RssDocument.Rss.Channel.Item> getItemList()
          Gets a List of "item" elements

Let's look at how the use of generics makes the code for implementing the method to get all of the items reported by a single user simpler:

 1 public List<Item> getItemsFromReporter(String reporter) {
 2 
 3  // We already loaded the data as above
 4  // ...
 5  RssDocument.Rss.Channel channel = rss.getChannel();
 6 
 7  // We will use this object to get most of our data
 8  List<RssDocument.Rss.Channel.Item> items = 
                                           channel.getItemList();
 9 
10  for (int i = 0; i < items.size(); i++) {
11    RssDocument.Rss.Channel.Item item =  items.get(i);
12     
13    //Remove results from list
14    if (item.getReporter().getUsername().compareTo(reporter) 
                                                           != 0)
15        items.remove(i);
16    }
17  }
18   
19  return items;
20 }

This is great, but there's an even easier way to get the item information for each user—well, easier once you understand XPath and/or XQuery.

XQuery and XPath

XQuery and XPath integration with XMLBeans was reworked in version 2.0. In version 1, Jaxen (an XPath implementation) was used, but the integration with XMLBeans didn't provide support for namespaces and prefixes. The latest release builds on the XQuery implementation provided by Saxon version 8.1.1. Since XQuery builds on top of XPath, Saxon also provides the XPath implementation for XMLBeans. To use the features of XQuery and XPath, the XmlObject class that all XMLBeans types are derived from provides two methods for performing queries and statements on an instance. The execQuery() and selectPath() methods of the XmlObject API return an array of the matching components. These methods also exist on the XmlCursor object, but the return object is another XmlCursor object populated with a list of matching values:

 1 String xq = "for $e in //employee 
                where $e/name='Bob' return $e ";
 2 
 3 // Input is a valid xml instance
 4 XmlObject o = XmlObject.Factory.parse(input);
 5 
 6 XmlObject[] xObjres = o.execQuery(xq);
 7 XmlCursor xCurres = o.newCursor.selectPath(xq);

In the above code snippet, you see that the APIs are relatively simple to use, and you can handle the resulting data in the manner you find easiest. On line 4, we build up our query statement, and on lines 6 and 7 we run the query using the different APIs. XQuery is a powerful tool, and in the following code, note how simple getting the item data becomes:

 1 public XmlObject[] getItemsFromReporter(String reporter) {
 2  
 3  //Load Jira RSS feed data
 4  URL jiraFeedUrl; = new URL("<JiraFeedURL>");
 5  
 6  //This is the only object we need
 7  RssDocument rssDoc = RssDocument.Factory.parse(jiraFeedUrl);
 8  
 9  //Build the statement for the xpath engine
10  String xpathStatement = 
                     "//item[reporter/@username='"+reporter+"']";
11  
12  //Execute the statement on the instance
13  //We could cast this to an Item[] if we wanted
14  XmlObject[] queryResult = rssDoc.selectPath(xpathStatement);
15  
16  return queryResult;
17 }

Using XQuery alongside XMLBeans is powerful and makes working with XML much simpler. Numerous resources are available if you would like to learn more about XQuery. We recommend starting with the XMLBeans sample available on the Apache XMLBeans Web site.

At this point, implementing a solution to the problem of tracking quality metrics for XMLBeans has been made much easier thanks to the latest features of XMLBeans. We used the inst2xsd utility to create a schema for an instance, saving time by not having to write one from scratch. We saw how enabling generics can increase our productivity by making our business logic easier to code. Finally, we saw how using the newer XQuery integration provides us with a feature-rich way of manipulating and querying XML.

These were only the basics of the new features in the latest release of XMLBeans. Several other features make XMLBeans the right tool for all your development needs when you work with XML. This next feature will help to increase your productivity by giving you much more detailed information about the errors you may receive when working with XML and XML Schema.

Pages: 1, 2, 3, 4

Next Page »