Wednesday, May 18, 2011

How to convert XSD to XML or vice versa


- Preparation

1. JAXB library

download JAXB library from http://jaxb.java.net/

execute this jar as

java -jar <jaxb jar name>

On Windows, you can just double-click the jar file to execute.

2. Trang library

http://code.google.com/p/jing-trang/downloads/list


- XSD to XML

1. manually prepare the two XSD files


person.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"  xmlns:address="http://test.xsdxml.com/demo/detail"  elementFormDefault="qualified" targetNamespace="http://test.xsdxml.com/demo/person" xmlns="http://test.xsdxml.com/demo/person" >


<xs:import namespace="http://test.xsdxml.com/demo/detail" schemaLocation="detail.xsd" />

<xs:element name="person">
  <xs:complexType>
     <xs:sequence>
       <xs:element ref="header" />
       <xs:choice>
         <xs:element ref="address" />
         <xs:element ref="contactNo" />
       </xs:choice>
     </xs:sequence>
  </xs:complexType>
</xs:element>
 
<xs:element name="header" >
  <xs:complexType >
    <xs:sequence>
      <xs:element name="timestamp" type="xs:dateTime"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
 
<xs:element name="address">
  <xs:complexType>
    <xs:choice>
      <xs:sequence>
        <xs:element ref="postcode" />
        <xs:element ref="country" />
      </xs:sequence>
      <xs:sequence />
      <xs:element ref="address:detail" />
    </xs:choice>
    <xs:attribute name="name" use="required">
      <xs:simpleType>
      <xs:restriction base="xs:string">
        <xs:enumeration value="home" />
        <xs:enumeration value="office" />
     </xs:restriction>
     </xs:simpleType>
    </xs:attribute>
  </xs:complexType>
</xs:element>

<xs:element name="contactNo">
  <xs:complexType>
    <xs:choice>
      <xs:sequence>
        <xs:element ref="mobile" />
        <xs:element ref="fixline" />
      </xs:sequence>
      <xs:sequence />
    </xs:choice>
  </xs:complexType>
</xs:element>

<xs:element name="postcode" type="xs:string" />
<xs:element name="country" type="xs:string" />
<xs:element name="mobile" type="xs:string" />
<xs:element name="fixline" type="xs:string" />
</xs:schema>

detail.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://test.xsdxml.com/demo/detail" xmlns="http://test.xsdxml.com/demo/detail">

<xs:element name="detail">
  <xs:complexType>
     <xs:sequence>
       <xs:element name="street" type="xs:string" />
       <xs:choice>
         <xs:element ref="buildingNo" />
         <xs:element ref="roomNo" />
       </xs:choice>
     </xs:sequence>
  </xs:complexType>
</xs:element>
 
<xs:element name="buildingNo" type="xs:string" />
<xs:element name="roomNo" type="xs:string" />
</xs:schema>


run the command to generate the java classes.

C:\tmp\xjc>xjc person.xsd
parsing a schema...
compiling a schema...
com\xsdxml\test\demo\person\Address.java
com\xsdxml\test\demo\person\ContactNo.java
com\xsdxml\test\demo\person\Header.java
com\xsdxml\test\demo\person\ObjectFactory.java
com\xsdxml\test\demo\person\Person.java
com\xsdxml\test\demo\person\package-info.java
com\xsdxml\test\demo\detail\Detail.java
com\xsdxml\test\demo\detail\ObjectFactory.java
com\xsdxml\test\demo\detail\package-info.java


>> so person object is in package com.xsdxml.test.demo.person, and detail object is in package com.xsdxml.test.demo.detail


2. sample code


package com.xsdxml.test;

import java.io.StringWriter;
import java.util.GregorianCalendar;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import com.xsdxml.test.demo.detail.Detail;
import com.xsdxml.test.demo.person.Address;
import com.xsdxml.test.demo.person.ContactNo;
import com.xsdxml.test.demo.person.Header;
import com.xsdxml.test.demo.person.ObjectFactory;
import com.xsdxml.test.demo.person.Person;

public class JAXBSample {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance("com.xsdxml.test.demo.person");
        ObjectFactory factory = new ObjectFactory();
        // create person instance from ObjectFactory
        Person person = factory.createPerson();
        // create header instance from ObjectFactory
        Header header = factory.createHeader();
        XMLGregorianCalendar cal = DatatypeFactory.newInstance()
                .newXMLGregorianCalendar(new GregorianCalendar(2010, 10, 12));
        cal.setTime(13, 23, 45);
        // give value 2010-10-12T13:23:45 to timestamp
        header.setTimestamp(cal);
        person.setHeader(header);
        // create ContactNo instance from ObjectFactory
        ContactNo contNo = factory.createContactNo();
        contNo.setMobile("123445");
        person.setContactNo(contNo);

        Address address = factory.createAddress();
        address.setName("Home");
        address.setPostcode("112233");
        address.setCountry("myCountry");
        Detail detail = new Detail();
        detail.setStreet("street Name");
        detail.setBuildingNo("building 1");

        person.setAddress(address);

        Marshaller m = jc.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        // marshal to system.o
        m.marshal(person, System.out);
        // marshal to string
        System.out.println("----> " + asString(jc, person));

    }

    public static String asString(JAXBContext pContext, Object pObject)
            throws JAXBException {

        java.io.StringWriter sw = new StringWriter();

        Marshaller marshaller = pContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        marshaller.marshal(pObject, sw);

        return sw.toString();
    }
}


This is the output if run the class.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person xmlns="http://test.xsdxml.com/demo/person" xmlns:ns2="http://test.xsdxml.com/demo/detail">
    <header>
        <timestamp>2010-11-12T13:23:45+08:00</timestamp>
    </header>
    <address name="Home">
        <postcode>112233</postcode>
        <country>myCountry</country>
    </address>
    <contactNo>
        <mobile>123445</mobile>
    </contactNo>
</person>

- XML to XSD


1. manually perpare the XML file

person.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
    <header>
        <timestamp>2010-11-12T13:23:45+08:00</timestamp>
    </header>
    <address name="Home">
        <postcode>112233</postcode>
        <country>myCountry</country>
    </address>
    <contactNo>
        <mobile>123445</mobile>
    </contactNo>
</person>

2. run this command to generate XSD file

java -jar trang.jar person.xml person.xsd


this is the file person.xsd generated by trang

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="person">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="header"/>
        <xs:element ref="address"/>
        <xs:element ref="contactNo"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="header">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="timestamp"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="timestamp" type="xs:dateTime"/>
  <xs:element name="address">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="postcode"/>
        <xs:element ref="country"/>
      </xs:sequence>
      <xs:attribute name="name" use="required" type="xs:NCName"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="postcode" type="xs:integer"/>
  <xs:element name="country" type="xs:NCName"/>
  <xs:element name="contactNo">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="mobile"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="mobile" type="xs:integer"/>
</xs:schema>



Reference URLs

http://www.thaiopensource.com/relaxng/trang.html
http://ws.apache.org/jaxme/release-0.4/manual/ch02s02.html