Ricebridge
Search This Site
Jul 29 2010 17:03 UTC

Got a question for us?
Just Ask!


$15 Gift Certificate for every bug you find.

Bookmark Ricebridge Java Components - user friendly and well documented at del.icio.us Digg Ricebridge Java Components - user friendly and well documented at Digg.com Bookmark Ricebridge Java Components - user friendly and well documented at reddit.com Bookmark Ricebridge Java Components - user friendly and well documented at YahooMyWeb Bookmark Ricebridge Java Components - user friendly and well documented at Spurl.net Bookmark Ricebridge Java Components - user friendly and well documented at Simpy.com Bookmark Polyphasic Mutants at NewsVine Blink this Ricebridge Java Components - user friendly and well documented at blinklist.com Bookmark Ricebridge Java Components - user friendly and well documented at Furl.net Fark Ricebridge Java Components - user friendly and well documented at Fark.com

Getting Started

XML Manager is a Java component that makes it easy to save and load XML data containing lots of individual data records. This includes things like RSS and Atom feeds, web service APIs from Amazon, Google and eBay, and your own data stored using in-house schemas. The thing that XML Manager makes easy is getting a list of data fields for each record out of the XML, without having to handle all of the elements individually.

You use XML Manager by calling the methods of the com.ricebridge.xmlman.XmlManager class. This is the main entry point to the XML Manager component. This guide will show you some simple examples of how to use the XmlManager class.

Update Your Classpath

For installation instructions you should read the Installation Guide. Assuming you have unzipped the XML Manager download file into a folder of your choice, simply copy the xmlman.jar jar file, found in the lib folder of the distribution, into a folder in your CLASSPATH. Then add a reference to xmlman.jar in your CLASSPATH. This ensures that the classes in xmlman.jar can be found by your Java program. Depending on your development environment, you may need to alter your CLASSPATH setting in your IDE.

Loading XML Data

To load XML data using XML Manager, you create a new instance of the XmlManager class and call one of its load methods. The data is then returned as a Java data structure. You have four built-in data structures to choose from: a List of String[] arrays, a List of Lists of Strings, a Swing TableModel, and a JDBC ResultSet. You can also load your data as a set of Java Beans, and via a streaming interface.

To make things easy, we will use the simplest data structure, a List of String[] arrays.

Here is a complete code example. You can try this example out by compiling the Load.java file in the doc/examples/simple folder of the distribution (the doc folder contains this guide).

Load.java

import com.ricebridge.xmlman.XmlManager;
import com.ricebridge.xmlman.RecordSpec;

import java.util.List;

public class Load {
  public static void main( String[] args ) {
    XmlManager xmlman = new XmlManager();
    RecordSpec rs = new RecordSpec( "/list/president", 
                                    new String[] {"name","email"} );

    List data = xmlman.load( "presidents.xml", rs );

    for( int pres = 0; pres < data.size(); pres++ ) {
      String[] record = (String[]) data.get(pres);
      System.out.println( "NAME:"+record[0]+" EMAIL:"+record[1] );
    } 
  }
}

This class prints out the data records in the file presidents.xml XML file. This file has the following contents:

presidents.xml

<list>
  <president>
    <name>Ronald Reagan</name>
    <email>gipper@whitehouse.gov</email>
  </president>
  <president>
    <name>Theodore Roosevelt</name>
    <email>teddy@whitehouse.gov</email>
  </president>
  <president>
    <name>Dwight D. Eisenhower</name>
    <email>ike@whitehouse.gov</email>
  </president>
</list>

The following lines show how XmlManager is used:

    XmlManager xmlman = new XmlManager();
    RecordSpec rs = new RecordSpec( "/list/president", 
                                    new String[] {"name","email"} );

    List data = xmlman.load( "presidents.xml", rs );

All you need to do to load XML data is to create a new XmlManager class, create a RecordSpec class to describe the XML you want to pull out, and call the XmlManager.load method with the name of the XML file.

The RecordSpec object is used to provide the record specification to XML Manager. The record specification is a set of XPath expressions that describe the data to pull out of the XML file.

To pull out data records from the XML file, we specify that we are interested in all the president elements. These are the elements that are the data records. They hold all the information for each president. To point at all the president elements using XPath, we use the expression:

/list/president
This says, inside each the list element, look for all the president elements.

To get at the data fields of each president record, we use a set of XPath expressions. These data field expressions, one for each data field, point out the XML elements that make up the data fields of the data record. Each data field XPath expression is understood to start from the record element. So the expression

name
points out the name element inside the president element.

The XML data is returned to you as a List of String[] arrays. Each element of the List corresponds to each data record in the XML file and each data field corresponds to an element in the String[] array. The data fields are placed into the String[] array in the order they appear in the RecordSpec String[] array parameter. This is the simplest and most basic data structure for your XML data. In the code example above, we just loop through all the String[] arrays in the List, and print out the data fields that we are interested in.

To load your data from a file, XmlManager provides two options; you can specify the file as a java.io.File object, with XmlManager.load(File,RecordSpec) or, if it is more convenient, as a simple Java String containing the file path, with XmlManager.load(String,RecordSpec) (this is the one used in the example).

If your XML data does not come from a file, then you can also provide it using a java.io.InputStream, with XmlManager.load(InputStream,RecordSpec). You can even load XML data from a String variable, using XmlManager.loadFromString(String,RecordSpec).

Saving XML Data

To save XML data using XML Manager, you need an instance of the XmlManager class, and you call one its the save methods. The XML data is then output to a file. You can provide the XML data in the standard formats that XML Manager uses: a List of String[] arrays, a List of Lists of Strings, a Swing TableModel, and a JDBC ResultSet. You can also save your data by reading the properties of a set of Java Beans, and via a streaming interface.

Here is a complete code example. You can try this example out by compiling the Save.java file in the doc/examples/simple folder.

Save.java

import com.ricebridge.xmlman.XmlManager;
import com.ricebridge.xmlman.RecordSpec;

import java.util.List;
import java.util.ArrayList;

public class Save {
  public static void main( String[] args ) {
    ArrayList data = new ArrayList();
    data.add( new String[] { "Richard Nixon", "tricky@whitehouse.gov" } );
    data.add( new String[] { "Harry S. Truman", "haberdasher@whitehouse.gov" } );
    data.add( new String[] { "Thomas Jefferson", "sage@whitehouse.gov" } );

    XmlManager xmlman = new XmlManager();
    RecordSpec rs = new RecordSpec( "/list/president", 
                                    new String[] {"name","email"} );
    xmlman.save( "more-presidents.xml", rs, data );
  }
}

This class creates an XML file more-presidents.xml containing the data in the ArrayList. Here is the contents of the file:

more-presidents.xml

<list>
  <president>
    <name>Richard Nixon</name>
    <email>tricky@whitehouse.gov</email>
  </president>
  <president>
    <name>Harry S. Truman</name>
    <email>haberdasher@whitehouse.gov</email>
  </president>
  <president>
    <name>Thomas Jefferson</name>
    <email>sage@whitehouse.gov</email>
  </president>
</list>

The following lines show how XmlManager is used:

    XmlManager xmlman = new XmlManager();
    RecordSpec rs = new RecordSpec( "/list/president", 
                                    new String[] {"name","email"} );
    xmlman.save( "more-presidents.xml", rs, data );

All you need to do to save XML data is to use an XmlManager object and call its save method with the name of the XML file, the RecordSpec defining the XML format, and a List containing the data.

How does the RecordSpec object define the output XML? By converting the XPath expressions into a simple element structure. In fact, the same RecordSpec can often by used for input and output. In our case, we used the same RecordSpec for loading the presidents.xml file as we used for saving the more-presidents.xml file.

Here's how it works: The data record XPath is /list/president. This tells XML Manager that we want to put president elements inside a list element. Then we specified that the name and email elements are for the data fields. They start from the president element, so they are its children. This defines the following XML structure:

more-presidents.xml

<list>
  <president>
    <name>[NAME]</name>
    <email>[EMAIL]</email>
  </president>
</list>

Now we simply take each data record, and put it into the structure. Since we have defined the record data fields using:

new String[]{ "name", "email" }

we know that we must provide a list of String[] arrays with two elements. The first element is the name, and the second element is the email.

Thus, the XML data is provided as a List of String[] arrays. Each element of the List corresponds to each data record in the XML file and each data field corresponds to an element in the String[] array. This is the simplest and most basic data structure for your XML data. In the example above, we just hard-coded this data into an ArrayList object.

To save your data to a file, XmlManager provides two options; you can specify the file as a java.io.File object, with XmlManager.save(File,RecordSpec,List) or, if it is more convenient, as a simple Java String containing the file path, with XmlManager.save(String,RecordSpec,List).

If you need to save your XML to something that is not a file, then you can also send the data to a java.io.OutputStream, with XmlManager.save(OutputStream, RecordSpec, List). You can also save XML data to a String variable, using XmlManager.saveToString(RecordSpec,List).

Importing and Exporting XML Data from a Database

If you are using XML to store data records then you will probably want to get that data into and out of a database at some point. XML Manager makes this really easy. For this example, assume we have a Product database table defined by:

product.sql

CREATE TABLE Product ( 
id    integer primary key, 
code  varchar(20), 
name  varchar(255), 
price integer 
);

The data that we want to insert into this table is in the products.xml XML file:

products.xml

<database>
  <product id="1">
    <code>A01</code>
    <name>Apple</name>
    <price>99</price>
  </product>
  <product id="2">
    <code>O01</code>
    <name>Orange</name>
    <price>149</price>
  </product>
  <product id="3">
    <code>S01</code>
    <name>Satsuma</name>
    <price>219</price>
  </product>
  <product id="4">
    <code>B01</code>
    <name>Banana</name>
    <price>29</price>
  </product>
  <product id="5">
    <code>P01</code>
    <name>Pear</name>
    <price>129</price>
  </product>
</database>

Both of these files are in the doc/examples/simple folder.

In this example, we want to import this data into the Product database table. Once we have the data in the database, we can then export the data in the Product table back out to the file products-export.xml. If it all works correctly, the data in products.xml will match the data in products-export.xml. Here is the code:

Database.java

import com.ricebridge.xmlman.XmlManager;
import com.ricebridge.xmlman.RecordSpec;

import java.sql.*;
import java.util.*;
import java.io.*;

public class Database {
  public static void main( String[] args ) throws Exception {
    XmlManager xmlman = new XmlManager();
    RecordSpec rs = new RecordSpec("/database/product", 
                                   new String[]{"@id","code","name","price"});

    String dburl 
      = "jdbc:mysql://localhost/mydatabase?"
      + "user=username&password=password";
    Driver d = (Driver) Class.forName( "com.mysql.jdbc.Driver" ).newInstance(); 
    DriverManager.registerDriver( d );
    Connection con = DriverManager.getConnection(dburl);

    PreparedStatement ps = con.prepareStatement( "INSERT INTO Product VALUES (?,?,?,?)" ); 
    List data = xmlman.load( "products.xml", rs );
    for( int line = 0; line < data.size(); line++ ) {
      String[] fields = (String[]) data.get(line);
      ps.setInt(    1, Integer.parseInt( fields[0] ) );
      ps.setString( 2, fields[1] );
      ps.setString( 3, fields[2] );
      ps.setInt(    4, Integer.parseInt( fields[3] ) );
      ps.executeUpdate();
    }

    ps = con.prepareStatement( "SELECT * FROM Product" ); 
    ResultSet resultset = ps.executeQuery();
    xmlman.saveResultSet( "products-export.xml", rs, resultset );

    con.close();
  }
}

The following lines show how XmlManager is used to load and save the data:

    XmlManager xmlmanager = new XmlManager();
    XmlManager xmlman = new XmlManager();
    RecordSpec rs = new RecordSpec("/database/product", 
                                   new String[]{"@id","code","name","price"});
    ...
    List data = xmlman.load( "products.xml", rs );
    ...
    xmlman.save( "products-export.xml", rs, resultset );

So to convert data in a database to and from XML format, all you need to do is use the standard JDBC API calls and the load(File,RecordSpec) and saveResultSet(File,RecordSpec,ResultSet) methods.

Changing the Settings

The XML Manager component uses the XmlSpec class to change the way that XML is handled. The XmlSpec class contains a number of get and set methods to change the settings that XML Manager uses.

For example, when loading XML, you can use the setValidating method to enable or disable validation of the XML file against a DTD or Schema (the default is not to validate).

When saving XML, you can use the setIndent method to enable or disable indenting of the XML file (the default is to indent). When you want to make the file as small as possible, use setIndent(false), and no additional whitespace will be added to the output. This is useful for XML files that must be transmitted over the network.

There are a number of other properties you can set, including the encoding of the XML file (default: UTF-8), and you can also access the SAX Features of the underlying SAX parser that XML Manager uses.

Handling Namespaces

You will often come across XML files that use namespaces. The most common example is probably XSLT files. Let's look at a simple case and see how XML Manager handles XML namespaces.

namespace.xml

<root>
  <foo xmlns="http://www.ricebridge.com/first" >
    <bar>bar one</bar>
  </foo>
  <foo xmlns="http://www.ricebridge.com/second" >
    <bar>bar two</bar>
  </foo>
</root>

By default, XML Manager supports namespaces. But we can turn this off. In fact, this is often a quick way to work with XML that uses namespaces. We can pretend they aren't there and carry on as normal. Here is the code to do that.


public static void main( String[] args ) {
  XmlManager xmlman = new XmlManager();
  xmlman.getXmlSpec().setNamespaceAware( false );
  RecordSpec rs = new RecordSpec( "/root/foo", new String[] {"bar"} );
  print( "no namespace", xmlman, rs );
}

/** A utility method to print the data. */
public static void print( String pMessage, XmlManager xmlman, RecordSpec rs ) {
  System.out.println( pMessage );
  List data = xmlman.load( "namespace.xml", rs );
  for( int foo = 0; foo < data.size(); foo++ ) {
    String[] record = (String[]) data.get(foo);
    System.out.println( "BAR:"+record[0] );
  }
}

This prints out:


no namespace
BAR:bar one
BAR:bar two

The important line to notice is:


  xmlman.getXmlSpec().setNamespaceAware( false );

Of course, we should deal with namespaces properly. XML Manager needs to be told in advance about the namespaces in the XML file. You do this by calling the XmlSpec.addNamespace method. Here is the code (we use the print method from the previous example):


  xmlman.getXmlSpec().setNamespaceAware( true );
  xmlman.getXmlSpec().addNamespace( "f1", "http://www.ricebridge.com/first" );
  rs = new RecordSpec( "/root/f1:foo", new String[] {"f1:bar"} );
  print( "namespace: f1", xmlman, rs );

This prints out:


namespace: f1
BAR:bar one

Notice that in this case only the foo element with the matching namespace is selected. It is also important to realise that the namespace prefix f1 used in the RecordSpec and XmlSpec objects is completely arbitrary. We can use anything we like, so long as the namespace URI, http://www.ricebridge.com/first, is the same as the one in the XML file. The complete code for this example can be found in the Namespace.java file in the doc/examples/simple folder.

More Information

This Getting Started guide only covers the basics of what you can do with XML Manager. For more information on settings, refer to the reference documentation. For a list of examples, including a Swing example with JTable, see the examples page. For a detailed description of any feature or method, check out the API documentation. The API documentation also includes the source code for a number of classes in the system, as part of the Ricebridge Open Source API policy. This source code will help you to understand the system faster and help you to develop your own applications by providing definitive examples. Finally, visit the Ricebridge website for up-to-date information about XML Manager.

Please review the licensing terms and conditions under which the Ricebridge XML Manager component can be used. We're always happy to come up with licensing solutions that suit your needs, so please contact us by mail at sales@ricebridge.com if our existing licensing system isn't quite what you need.

Thanks for using XML Manager! If you have any problems or questions feel free to mail us at xmlman@ricebridge.com.

comment on this page Home | Search | About Us | Contact Us | Our Products | Documentation | Resources | Login
Copyright © 2004-2010 Ricebridge. All Rights Reserved.