Code I/O

A topnotch WordPress.com site


Leave a comment

5 Minutes on Java : Validating XML data against a Schema …

Taking the idea of XML Schema generation : click here to read my previous article.  The XML document can be validated against its schema before processing it.  This is critical, otherwise, the document will be processed without validation which will be a bad process.

To illustrate XML validation, I’m using Apache XML Beans as suggested in my previous blog entry.

Here is the XMLValidator code that will help in validating XML document against a schema.

import java.io.File;
import java.io.IOException;

import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;

public class XMLValidator {
	public boolean validate(File dataFile, File schemaFile) {
		boolean status = false;

		try {
			// Only one schema to validate it against
			XmlObject[] schemas = { XmlObject.Factory.parse(schemaFile,
					new XmlOptions().setLoadLineNumbers()
							.setLoadMessageDigest()) };

			SchemaTypeLoader loader = XmlBeans.compileXsd(schemas, null,
					new XmlOptions().setErrorListener(null)
							.setCompileDownloadUrls().setCompileNoPvrRule());

			XmlObject object = loader
					.parse(dataFile,
							null,
							new XmlOptions()
									.setLoadLineNumbers(XmlOptions.LOAD_LINE_NUMBERS_END_ELEMENT));

			status = object.validate();

			System.out.println("Validation Status: " + status);
		} catch (XmlException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		return status;
	}
}


1 Comment

5 Minutes on Java : XML Schema generation

I was constantly using an online XSD generator … however, recently I found that the site was hacked 😦 which forced to home brew a similar solution.

One of the Apache’s projects XMLBeans exactly does what I needed : http://xmlbeans.apache.org/

You can install the binaries, and take the xmlbean.jar for invoking API for conversion.  Here is a XMLBean wrapper that can be reused.

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;

import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.inst2xsd.Inst2Xsd;
import org.apache.xmlbeans.impl.inst2xsd.Inst2XsdOptions;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;

public class XMLBeans {
	public static void main(String[] args) {
		try {
			XMLBeans xmlBeans = new XMLBeans();
			SchemaDocument schemaDocument = xmlBeans.generateSchema(new File(
					"/Shared/test-data/test-data.xml"));

			StringWriter writer = new StringWriter();
			schemaDocument.save(writer, new XmlOptions().setSavePrettyPrint());
			writer.close();

			String xmlText = writer.toString();
			System.out.println(xmlText);

			System.out.println("Schemann" + xmlText);

		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public SchemaDocument generateSchema(File inputFile) throws XmlException,
	IOException {
		return generateSchema(inputFile, XMLSchemaDesign.VENETIAN_BLIND);
	}

	public SchemaDocument generateSchema(File inputFile, XMLSchemaDesign design)
			throws XmlException, IOException {
		// Only 1 instance is required for now
		XmlObject[] xmlInstances = new XmlObject[1];
		xmlInstances[0] = XmlObject.Factory.parse(inputFile);

		return inst2xsd(xmlInstances, design);
	}

	public SchemaDocument generateSchema(InputStream is, XMLSchemaDesign design)
			throws XmlException, IOException {
		// Only 1 instance is required for now
		XmlObject[] xmlInstances = new XmlObject[1];
		xmlInstances[0] = XmlObject.Factory.parse(is);

		return inst2xsd(xmlInstances, design);
	}

	public SchemaDocument generateSchema(String input) throws XmlException,
	IOException {
		return generateSchema(input, XMLSchemaDesign.VENETIAN_BLIND);
	}

	public SchemaDocument generateSchema(String input, XMLSchemaDesign design)
			throws XmlException, IOException {
		// Only 1 instance is required for now
		XmlObject[] xmlInstances = new XmlObject[1];
		xmlInstances[0] = XmlObject.Factory.parse(input);

		return inst2xsd(xmlInstances, design);
	}

	private SchemaDocument inst2xsd(XmlObject[] xmlInstances,
			XMLSchemaDesign design) throws IOException {
		Inst2XsdOptions inst2XsdOptions = new Inst2XsdOptions();
		if (design == null || design == XMLSchemaDesign.VENETIAN_BLIND) {
			inst2XsdOptions.setDesign(Inst2XsdOptions.DESIGN_VENETIAN_BLIND);
		} else if (design == XMLSchemaDesign.RUSSIAN_DOLL) {
			inst2XsdOptions.setDesign(Inst2XsdOptions.DESIGN_RUSSIAN_DOLL);
		} else if (design == XMLSchemaDesign.SALAMI_SLICE) {
			inst2XsdOptions.setDesign(Inst2XsdOptions.DESIGN_SALAMI_SLICE);
		}

		SchemaDocument[] schemaDocuments = Inst2Xsd.inst2xsd(xmlInstances,
				inst2XsdOptions);
		if (schemaDocuments != null && schemaDocuments.length > 0) {
			return schemaDocuments[0];
		}

		return null;
	}
}


12 Comments

5 Minutes on Java – A quick tutorial on JAXB

New: You can get entire source code for this post from git-hub: http://github.com/udy/lifencode-samples/tree/master/java/jaxb-in-5-minutes/

This is my first post on 5 minutes series of articles on technology and it’s on JAXB.

Read about JAXB at:

http://java.sun.com/developer/technicalArticles/WebServices/jaxb

http://en.wikipedia.org/wiki/JAXB

My simple approach: Create the XML using bottom up approach, once you know how the XML representation is, things can be easy. Let’s say we want to process a email list and take some actions.

<items>
	<item>
		<firstname>George</firstname>
		<lastname>Cross</lastname>
		<email>George.Cross@somedomain.com</email>
	</item>
	<item>
		<firstname>Lisa</firstname>
		<lastname>Monroe</lastname>
		<email>Lisa.Monroe@somedomain.com</email>
	</item>
	<item>
		<firstname>Udy</firstname>
		<lastname>Udy</lastname>
		<email>Udy@somedomain.com</email>
	</item>
	<item>
		<firstname>Nitha</firstname>
		<lastname>Udy</lastname>
		<email>Nitha.Udy@somedomain.com</email>
	</item>
	<item>
		<firstname>Balaji</firstname>
		<lastname>Krishna</lastname>
		<email>Balaji.Krishna@somedomain.com</email>
	</item>
</items>

Once you know the data, you can submit it to some online tools to generate XML schema.  The one that’s cool and fast is

http://www.xmlforasp.net/CodeBank/System_Xml_Schema/BuildSchema/BuildXMLSchema.aspx

For the above above XML the following XSD schema is generated

<?xml version="1.0" encoding="utf-16"?>
<xsd:schema attributeFormDefault="unqualified"
	elementFormDefault="qualified" version="1.0"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">

	<xsd:element name="items" type="itemsType" />
	<xsd:complexType name="itemsType">
		<xsd:sequence>
			<xsd:element maxOccurs="unbounded" name="item" type="itemType" />
		</xsd:sequence>
	</xsd:complexType>
	<xsd:complexType name="itemType">
		<xsd:sequence>
			<xsd:element name="firstname" type="xsd:string" />
			<xsd:element name="lastname" type="xsd:string" />
			<xsd:element name="email" type="xsd:string" />
		</xsd:sequence>
	</xsd:complexType>

</xsd:schema>

AFter the schema definition is generated, JAXB plugin can be bought into action to generate code.

Install the JAXB plugin for eclipse from https://jaxb-workshop.dev.java.net/plugins/eclipse/xjc-plugin.html (looks like this plug-in is no longer supported).  I recommend you try it from http://sourceforge.net/projects/jaxb-builder/

Ccreate a XSD file under a eclipse project, and generate code using JAXB (the above URL should show you how to do so).  Make sure you choose the right package names and folder to put the code in.  The package name given here will be used later, I chose “org.onesun.blog.jaxb” as the package name, and chose “src” folder as the destination to generate JAXB classes.  The following source files should now be generated:

ItemsType.java, ItemType.java and ObjectFactory.java

I personally prefer writing an accessor to work the elements generated.  This way working with your email list becomes easy.   Lets examine the EmailListManager.java

While creating JAXB context, just make sure that the package name generated above is the one used, failing which, the application will fail during runtime.  The purpose of this class is just to load the file and unmarshall it, after which you can process the list and take some concrete actions.  Lets discuss about that in another post (say for instance using JavaMail to send HTML email to this users).

EmailListManager.java

package org.onesun.blog;

import java.io.InputStream;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.onesun.blog.jaxb.*;

public class EmailListManager {
	private ItemsType items = null;
	private JAXBContext jaxbContext = null;
	private Unmarshaller unmarshaller = null;

	public EmailListManager(String packageName) {
		try {
			jaxbContext = JAXBContext.newInstance(packageName);
			unmarshaller = jaxbContext.createUnmarshaller();
		} catch (JAXBException e) {
		}
	}

	@SuppressWarnings("unchecked")
	public List loadXML(InputStream istrm) {
		try {
			Object o = unmarshaller.unmarshal(istrm);
			if (items == null) {
				items = (ItemsType) (((JAXBElement) o).getValue());
				return (items.getItem());
			}
		} catch (JAXBException e) {
			e.printStackTrace();
		}
		return null;
	}
}

Finally the application can be validated with the xml document used for generating XSD, which will parse through the list of items and print them to stdout.
Main.java

package org.onesun.blog;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.onesun.blog.jaxb.*;

public class Main {
	public static void main(String[] args) {
		EmailListManager xmgr = new EmailListManager("org.onesun.blog.jaxb");
		File file = new File("etc/data.xml");
		List rtList = new ArrayList();
		try {
			FileInputStream fis = new FileInputStream(file);

			if(fis == null) {
				return;
			}
			rtList = xmgr.loadXML(fis);
			Iterator rtItr = rtList.iterator();
			while (rtItr.hasNext()) {
				ItemType item = (ItemType) rtItr.next();
				System.out.println("First Name = " + item.getFirstname().trim()
						+ "ttLast Name = " + item.getLastname().trim()
						+ "ttEmail = " + item.getEmail().trim());
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
}

With this you’re set to use XML you generated for anything you like to do.  Hope this was helpful to you in some way, and believe that you enjoyed the simplicity of it