JIBX Unmarshalling

I am demonstrating a simple jibx example. Jibx is used to parse XML documents and create Java objects out of them by unmarshalling and vice versa through marshalling.
To begin with you only need the requisite jars, a meaningful xsd file, a build.xml for the purpose and a relevant folder structure.
If you are using Eclipse, remember to set the default output folder to the folder where the build delivers your class files, failing which you will get cryptic errors indicating that jibx is looking for the class files in the wrong folder.
The jars I needed were:

bcel.jar
commons-lang-2.0.jar
commons-logging-1.0.4.jar
jaxme-js-0.3.jar
jibx-bind.jar
jibx-extras.jar
jibx-run.jar
qdox-1.6.1.jar
stax-api.jar
wstx-asl.jar
xmlpull_1_1_4.jar
xpp3.jar
xsd2jibx.jar

You don’t even need to initially create classes, the objects of which you are going to create from the input xml file – jibx utilities can do it for you.
You need a proper directory structure. My directory structure looks as follows:

<root>
     <lib>
          jibx jars
     <src>
          <com.mattiz.main>
               MattizMain.java(class that does jibx unmarshalling)
          <com.mattiz.vo>
              (..jibx generator populates this folder with POJOs..)
     <classes>
          (..populated by java &amp; jibx compilers...)
     <docs>
          <xml>
              Author.xsd(used for creation of POJOs by jibx utility based on xsd)
              mattiz.xml(input xml to be unmarshalled)
build.xml(jibx compilation and java source compilation)
build-generate.xml(POJO creation - one time process)

Jibx utility jars allow you to create java classes on the fly from the description in the xsd file.
My xsd file looks like this:

Author.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.com/mattiz/vo" xmlns="http://www.com/mattiz/vo"
	xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
	<xs:complexType name="Book">
		<xs:sequence>
			<xs:element name="Title" type="xs:string" nillable="false" />
			<xs:element name="Isbn" type="xs:string" nillable="false" />
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="Author">
		<xs:sequence>
			<xs:element name="Book" type="Book" maxOccurs="unbounded" />
			<xs:element name="Name" type="xs:string" nillable="false" />
		</xs:sequence>
	</xs:complexType>
</xs:schema>

Now you are ready to create the pojos using the following build-generate.xml

<project name="Mattiz" default="generate-jibx">
	<property file="build.properties" />
	<target name="clean">
		<delete dir="classes" />
	</target>
	<path id="classpath">
		<fileset dir="lib" includes="**/*.jar" />
	</path>
	<target name="generate-jibx">
		<echo message="Generating Jibx mappings" />
		<java classname="org.jibx.xsd2jibx.Generate" fork="yes"
			classpathref="classpath" failonerror="true">
			<classpath path="src" />
			<arg value="-d" />
			<arg value="src" />
			<arg value="docs/xml/Author.xsd" />
		</java>
		<move file="src/com/mattiz/vo/binding.xml" tofile="src/com/mattiz/vo/binding-Author.xml" />
	</target>
</project>

Once you run build-generate.bat file you see that

src/<com.mattiz.vo>

is populated with Author.java and Book.java – jibx generated POJOs and a binding file – binding-Author.xml.
Generation is a one time process once you have no other changes to the xsd file.
Here is how my JIBX generated files look like:

Author.java

package com.mattiz.vo;

import java.util.ArrayList;

public class Author {
	protected String name;

	public void addBook(Book book) {
		bookList.add(book);
	}

	public Book getBook(int index) {
		return (Book) bookList.get(index);
	}

	public int sizeBookList() {
		return bookList.size();
	}

	public ArrayList getBookList() {
		return this.bookList;
	}

	public void setBookList(ArrayList bookList) {
		this.bookList = bookList;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	protected ArrayList bookList = new ArrayList();
}

Book.java

package com.mattiz.vo;

public class Book {
	protected String title;
	protected String isbn;

	public String getTitle() {
		return this.title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getIsbn() {
		return this.isbn;
	}

	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}
}

The binding-Author.xml is also system generated:
It looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<binding>
	<mapping name="Book" class="com.mattiz.vo.Book">
		<namespace uri="http://www.com/mattiz/vo" default="elements" />
		<value name="Title" field="title" usage="required" />
		<value name="Isbn" field="isbn" usage="required" />
	</mapping>
	<mapping name="Author" class="com.mattiz.vo.Author">
		<namespace uri="http://www.com/mattiz/vo" default="elements" />
		<collection field="bookList">
			<structure map-as="com.mattiz.vo.Book" />
		</collection>
		<value name="Name" field="name" usage="required" />
	</mapping>
</binding>

Jibx compilation compiles the POJOs created in the previous step into Jibx classes. The following build.xml does this:

<project name="Mattiz" default="compile">
	<target name="clean">
		<delete dir="classes" />
	</target>
	<path id="classpath">
		<fileset dir="lib" includes="**/*.jar" />
	</path>
	<target name="compile" depends="compile-src, compile-jibx" />
	<target name="compile-src" depends="clean">
		<mkdir dir="classes" />
		<javac srcdir="src" destdir="classes" classpathref="classpath"
			debug="on">
			<include name="**/*.java" />
		</javac>
		<copy file="docs/xml/mattiz.xml" tofile="classes/com/mattiz/vo/mattiz.xml" />
	</target>
	<target name="compile-jibx">
		<echo message="Compiling Jibx mappings" />
		<java classname="org.jibx.binding.Compile" fork="yes"
			classpathref="classpath" failonerror="true">
			<classpath path="classes" />
			<arg value="-l" />
			<arg value="src/com/mattiz/vo/binding-Author.xml" />
		</java>
	</target>
</project>

Once you run build.xml file you see that your classes folder has the Author.class and Book.class files and in addition to this, JIBX compiler generated class files beginning with JIBX_

Now you are ready to perform the final steps.
MattizMain.java performs the jibx conversion of an xml to objects(Author and Book classes)

package com.mattiz.main;

import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;

import org.jibx.runtime.BindingDirectory;
import org.jibx.runtime.IBindingFactory;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;

import com.mattiz.vo.Author;
import com.mattiz.vo.Book;

public class MattizMain {
	public void extractListFromXML() {
		ClassLoader classLoader = Thread.currentThread()
				.getContextClassLoader();
		if (classLoader == null)
			classLoader = this.getClass().getClassLoader();
		File xmlFile = new File(classLoader.getResource(
				"./com/mattiz/vo/mattiz.xml").getPath());
		try {
			InputStream in = new FileInputStream(xmlFile);
			Closeable stream = in;
			Reader reader = new InputStreamReader(in, "UTF-8");
			stream = reader;
			StringBuilder inputBuilder = new StringBuilder();
			char[] buffer = new char[1024];
			while (true) {
				int readCount = reader.read(buffer);
				if (readCount < 0) {
					break;
				}
				inputBuilder.append(buffer, 0, readCount);
			}
			stream.close();
			String authorXML = inputBuilder.toString();
			// Unmarshall document using Jibx
			IBindingFactory bindingFactory = BindingDirectory
					.getFactory(Author.class);
			IUnmarshallingContext unmarshallingContext = bindingFactory
					.createUnmarshallingContext();
			Author author = (Author) unmarshallingContext.unmarshalDocument(
					new ByteArrayInputStream(authorXML.getBytes("UTF-8")),
					"UTF-8");
			// Extract list
			List bookslist = author.getBookList();
			System.out.println(author.getName());
			Iterator bli = bookslist.iterator();
			while (bli.hasNext()) {
				Book book = (Book) bli.next();
				System.out.println(book.getIsbn());
				System.out.println(book.getTitle());
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException uee) {
			uee.printStackTrace();
		} catch (JiBXException jibxe) {
			jibxe.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String args[]) {
		MattizMain mattizMain = new MattizMain();
		mattizMain.extractListFromXML();
	}
}

The xml source is mattiz.xml

<?xml version="1.0" encoding="UTF-8"?>
<author xmlns="http://www.com/mattiz/vo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.com/mattiz/vo">
	<book>
		<title>
<![CDATA[Seven Ways to Success]]>
		</title>
		<isbn>4324fd3243dgfd</isbn>
	</book>
	<book>
		<title>
<![CDATA[Seven Ways to Learn Chinese]]>
		</title>
		<isbn>vcxzvvzczr34</isbn>
	</book>
	<book>
		<title>
<![CDATA[Success in Seven Days]]>
		</title>
		<isbn>dfvcz43432xrrerw</isbn>
	</book>
	<book>
		<title>
<![CDATA[Sailing the Seven Seas]]>
		</title>
		<isbn>ffadf34242</isbn>
	</book>
	<book>
		<title>
<![CDATA[Seven Times in a Row]]>
		</title>
		<isbn>fdsfa3432432</isbn>
	</book>
	<name>Marc Figowitz</name>
</author>

The output looks something like this:

Marc Figowitz
4324fd3243dgfd Seven Ways to Success
vcxzvvzczr34 Seven Ways to Learn Chinese
dfvcz43432xrrerw Success in Seven Days
ffadf34242 Sailing the Seven Seas
fdsfa3432432 Seven Times in a Row

About cuppajavamattiz
Matty Jacob - Avid technical blogger with interests in J2EE, Web Application Servers, Web frameworks, Open source libraries, Relational Databases, Web Services, Source control repositories, ETL, IDE Tools and related technologies.

Comments are closed.

%d bloggers like this: