ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

XML-Java Data Binding Using XMLBeans
Pages: 1, 2

Unmarshal XML Documents Using XMLBeans Classes

The following bit of code from weather_unmarshal.java illustrates how to use XMLBeans classes to get weather details from an XML document in a file called weatherInput.xml.



String filePath = "weatherInput.xml";
java.io.File inputXMLFile =
new java.io.File(filePath);

// Parse XML Document.

WeatherDocument weatherDoc =
WeatherDocument.Factory.parse(inputXMLFile);

// Get object reference of root element Weather.

WeatherDocument.Weather weatherElement =
weatherDoc.getWeather();

Here the XML document is parsed by calling the WeatherDocument.Factory.parse(File) method, which returns a WeatherDocument object. Then the getWeather() method is called on the weatherDocument object to get the object reference of the root element Weather.

To get the contents of the Weather element, simply call the appropriate get methods of the weatherElement that directly map to the element and attribute names defined in the schema:

// Call the appropriate 'get' methods of
// weatherElement that
// directly map to the element and attribute names
// defined in the schema.

Calendar timeStamp = weatherElement.getDatetime();

System.out.println("Weather details of zipcode "
 + weatherElement.getZipcode() + " at "
 + timeStamp);
System.out.println("Temperature is "
 + weatherElement.getTemperature());
System.out.println("Humidity is "
 + weatherElement.getHumidity());
System.out.println("Visibility is "
 + weatherElement.getVisibility());

This produces the output:

Weather details of zipcode 92834-2345 at 2003-11-13T05:29:27-03:01
Temperature is 85.3
Humidity is 50.0
Visibility is 5.5

Unmarshal When Multiple Global Elements are Declared in the Schema

In the above example, we assumed that the input XML document is always carrying weather details. However, in the real world, the input XML document might carry either weather details or latlong details, because weather_latlong.xsd describes both by declaring two global elements: Weather and Latlong.

There are two ways to parse an XML document and bind it to an instance of the corresponding XMLBeans type. In the above example, we parsed the XML document using WeatherDocument.Factory.parse(). Another way is to use XMLBeans' built-in class XmlObject.

The following bit of code from weather_unmarshal_xmlObject.java illustrates how to use XmlObject to get the weather or latlong details contained in an XML instance document.

public static void main(String args[]) {

try {

if (args.length < 1 ) {

System.out.println("Usage : java "
+"weather_unmarshal_xmlObject <<InputFilePath>>");

return;

}

 String filePath = args[0];
 java.io.File inputXMLFile
   = new java.io.File(filePath);

 XmlObject xmlObjExpected =
 XmlObject.Factory.parse(inputXMLFile);


// Check document type of the object returned by
// the call to XmlObject.Factory.parse() method.
// If type of object returned is of
//noNamespace.WeatherDocument, then input xml
//document carries weather details of a location.

 if (xmlObjExpected instanceof
 noNamespace.WeatherDocument) {


  WeatherDocument weatherDoc =
    (noNamespace.WeatherDocument)xmlObjExpected;
  WeatherDocument.Weather weatherElement =
	weatherDoc.getWeather();

  Calendar timeStamp =
    weatherElement.getDatetime();

  System.out.println
    ("Weather details of zipcode "
    + weatherElement.getZipcode() + " at "
    + timeStamp  + " : \n\n");
  System.out.println("Temperature is "
	+ weatherElement.getTemperature());
  System.out.println("Humidity is "
	+ weatherElement.getHumidity());
  System.out.println("Visibility is "
	+ weatherElement.getVisibility());

// else if type of object returned is of
// noNamespace.LatlongDocument, then input xml
//document carries latlong details of a location.

} else if(xmlObjExpected instanceof
    noNamespace.LatlongDocument) {

	LatlongDocument latLongDoc =
	(noNamespace.LatlongDocument)xmlObjExpected;
	LatlongDocument.Latlong latLongElement =
	latLongDoc.getLatlong();

    System.out.println
    ("Latlong details of zipcode "
      + latLongElement.getZipcode() + " : \n\n");
    System.out.println("Latitude is "
      + latLongElement.getLatitude());
    System.out.println("Longitude is "
      + latLongElement.getLongitude());


// else input xml document is well formed , but
// doesn't conform to weather_latlong.xsd schema
// file.

} else {
	System.out.println("Input xml document "
	  + "doesn't conform to weather_latlong.xsd");
}


} catch (Exception e) {


    e.printStackTrace();
  }

}

}

To get the contents of the input XML document, we check the document type of the object returned by XmlObject.Factory.parse(), and then convert the returned object to the corresponding document type for further processing. Another interesting part of the code is the last else block, which handles the case where the XML document is well-formed but doesn't conform to the weather_latlong.xsd schema.

Create a New XML Document

The following bit of code from latlong_marshal.java illustrates how to use XMLBeans-generated classes to create a new XML instance document containing latlong details.

LatlongDocument latLongDoc;
LatlongDocument.Latlong latLongElement;
XmlOptions xmlOptions;

// LatlongDocument.Factory.newInstance() creates
// and returns a LatlongDocument object.

latLongDoc= LatlongDocument.Factory.newInstance();

// addNewLatlong() method is called on the
// document object to create and add a new
// LatLong Element to document.

latLongElement = latLongDoc.addNewLatlong();

LatlongDocument.Factory.newInstance() creates a LatlongDocument object and returns it. Then the addNewLatlong() method is called on the document object to create and add a new LatLong element to document.

To add data to the LatLong element, simply call the appropriate set methods of latLongElement that directly map to the element and attribute names defined in the schema.

latLongElement.setZipcode("91023");
latLongElement.setLatitude("33.8792");
latLongElement.setLongitude("117.8974");

The final block of code writes the current state of the LatLong element to a standard output stream.

xmlOptions = new XmlOptions();

// Requests use of whitespace for easier reading
xmlOptions.setSavePrettyPrint();

// Requests that nested levels of the xml
// document to be indented by multiple of 4
// whitespace characters
xmlOptions.setSavePrettyPrintIndent(4);

String xmlStr = latLongDoc.xmlText(xmlOptions);

// Writes the current state of the LatLong
// element to a standard output stream

System.out.println("XML Instance Document is : "
  + "\n\n\n " + xmlStr );

The xmlText method takes an optional xmlOptions object to control its behavior. setSavePrettyPrint() method requests use of white space for easier reading, and setSavePrettyPrintIndent(4) requests that nested levels of the XML document to be indented by multiple of four white-space characters.

This produces the output:

XML Instance Document is :

<Latlong Zipcode="91023">
    <Latitude>33.8792</Latitude>
    <Longitude>117.8974</Longitude>
</Latlong>

Performance Benefits

Unlike DOM, XMLBeans doesn't take the approach of unmarshalling an entire XML document and providing an object for each node in the XML document. With XMLBeans, unmarshalling and marshalling happens on demand, so if you never look at a piece of data, it's never unmarshalled or marshalled. This improves the performance of the XMLBeans solution.

XMLBeans also provides the efficient xget versions of functions to access XML schema built-in data types.

Validation

The value assigned to a built-in XMLBeans java type is validated as per the rules of the schema type it represents. So, for example, if a qualified name, whose prefix doesn't resolve to any URI, is assigned to an XmlQName data type, then an XmlValueOutOfRange exception will be thrown.

When an XML document is first parsed, the data contained can be validated based on the schema definition. More interestingly, any time the XML document is manipulated via the XMLBeans-generated Java classes, the XMLBeans system ensures that schema constraints are honored.

Other Features

XMLBeans objects are serializable, so they can be transmitted over RMI boundaries, and can be easily loaded from and saved to XML character streams and byte streams. XMLBeans also includes a configuration capability so that you can map XML names to your Java names. This will allow you to avoid rewriting Java code when XML names change. Space won't allow us to discuss them in more detail here.

Conclusion

XMLBeans gives an object view of the underlying XML data without losing access to the original XML structure, and delivers performance benefits via incremental unmarshalling and efficient xget...() methods to access XML schema built-in data types. These two features, along with nearly 100 percent support for XML schema, and provisions for on-time validation of XML data during data manipulation, make XMLBeans very useful for the kinds of XML-Java data binding used in implementations of web services, BPEL, BPML, rule-based XML data transformation engines, and so on.

Resources:

Hetal C. Shah is an IT consultant, specializing in Internet-related technologies


Return to ONJava.com.