Wednesday, February 03, 2010

XMLBeans for Handling XML in Java

XMLBeans is a useful library which allows you to convert XML files into Java objects, call methods on the objects and then write the objects back to XML. This post shows you how you can use XMLBeans to:
  • Generate an XSD schema from an XML file
  • Compile the schema into Java classes
  • Use the classes to create an XML structure
  • Use the classes to read an XML file
Generating a Schema from an XML File
If you have an XML file, you can generate a schema using the inst2xsd command. For example, say you have the following xml:
<books>
    <book id="1">
        <title>Snow Crash</title>
        <author>Neal Stephenson</author>
    </book>
    <book id="2">
        <title>Neuromancer</title>
        <author>William Gibson</author>
    </book>
</books>
You can generate an XSD, using the following different design types: Russian Doll, Salami Slice or Venetian Blind. This is what the output looks like:

Russian Doll Design:

inst2xsd -design rd -enumerations never C:\temp\books.xml

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="books">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="book" maxOccurs="unbounded" minOccurs="0">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:string" name="title"/>
              <xs:element type="xs:string" name="author"/>
            </xs:sequence>
            <xs:attribute type="xs:byte" name="id" use="optional"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
Salami Slice Design:
inst2xsd -design ss -enumerations never C:\temp\books.xml

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="books">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="book" maxOccurs="unbounded" minOccurs="0"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="author" type="xs:string"/>
  <xs:element name="title" type="xs:string"/>
  <xs:element name="book">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="title"/>
        <xs:element ref="author"/>
      </xs:sequence>
      <xs:attribute type="xs:byte" name="id" use="optional"/>
    </xs:complexType>
  </xs:element>
</xs:schema>
Venetian Blind Design:
inst2xsd -design vb -enumerations never C:\temp\books.xml

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="books" type="booksType"/>
  <xs:complexType name="booksType">
    <xs:sequence>
      <xs:element type="bookType" name="book" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="bookType">
    <xs:sequence>
      <xs:element type="xs:string" name="title"/>
      <xs:element type="xs:string" name="author"/>
    </xs:sequence>
    <xs:attribute type="xs:byte" name="id" use="optional"/>
  </xs:complexType>
</xs:schema>
Compiling a Schema into Java Classes
Once you have generated a schema, you can use the Maven xmlbeans plugin to compile it into Java classes:
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>xmlbeans-maven-plugin</artifactId>
  <version>2.3.2</version>
  <executions>
    <execution>
      <goals>
        <goal>xmlbeans</goal>
      </goals>
    </execution>
  </executions>
  <inherited>true</inherited>
  <configuration>
    <schemaDirectory>src/main/xsd</schemaDirectory>
    <sourceSchemas>
      <sourceSchema>books.xsd</sourceSchema>
    </sourceSchemas>
    <sourceGenerationDirectory>target/generated-sources/xmlbeans</sourceGenerationDirectory>
  </configuration>
</plugin>
You can also use the scomp command which will create a jar file containing the compiled classes.
C:\xmlbeans-2.4.0\bin> scomp -compiler %JAVA_HOME%\bin\javac books.xsd
Creating an XML Document Using the Compiled Classes
Add the jars to your classpath. Build an XML document as shown below (note that I am using the schema with the Russian Doll design. Different design types will produce different classes.):
BooksDocument doc = BooksDocument.Factory.newInstance();
Books books = doc.addNewBooks();
Book book = books.addNewBook();
book.setId((byte) 1);
book.setAuthor("Isaac Asimov");
book.setTitle("I, Robot");
System.out.println(doc.toString());
Produces:
<books>
  <book id="1">
    <title>I, Robot</title>
    <author>Isaac Asimov</author>
  </book>
</books>
Reading an XML Document Using the Compiled Classes
You can read an xml document and parse it into objects in the following way:
BooksDocument doc = BooksDocument.Factory.parse(
                    new File("C:\\temp\\books.xml"));
Books books = doc.getBooks();
Book[] bookArr = books.getBookArray();
for (Book book : bookArr) {
 String author = book.getAuthor();
 String title = book.getTitle();
 byte id = book.getId();
 System.out.println(author + '\t' + title);
}

4 comments:

  1. Anonymous1:57 PM

    Thanks very much, i love for the rest of my life

    ReplyDelete
  2. Hi, thanks for this post. But I've a previous problem adding dependencies to pom.xml in maven2.

    For xmlbeans i'm using this dependency:

    <dependency>
    <groupId>org.apache.xmlbeans</groupId>
    <artifactId>xmlbeans</artifactId>
    <version>2.4.0</version>
    </dependency>


    and for

    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.4.2</version>
    <configuration>
    <skipTests>true</skipTests>
    </configuration>
    </plugin>
    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>xmlbeans-maven-plugin</artifactId>
    <version>2.3.3</version>
    <executions>
    <execution>
    <goals>
    <goal>xmlbeans</goal>
    </goals>
    </execution>
    </executions>
    <inherited>true</inherited>
    <configuration>
    <schemaDirectory>src/main/xsd</schemaDirectory>
    </configuration>
    </plugin>
    </plugins>

    and i ever obtain the "Missing artifact" message updating this dependencies.

    How to configure POM to use XMLBeans and XMLBeans-plugin for eclipse-maven??

    Thanks!

    ReplyDelete
  3. Anonymous4:01 PM

    Hi fadh,

    I am trying to create a new instance of Books, as below:
    BooksDocument booksDoc = BooksDocument.Factory.newInstance();

    but am not able to instantiate. The control is not passing this line and the reference variable is not getting assigned any value.

    Please suggest some solution.

    ReplyDelete

Note: Only a member of this blog may post a comment.