How to generate simple-xml java annotated object from xsd schema

11,373

Solution 1

I do not believe that JAXB can be used on Android because of missing package requirements (see here), especially with earlier versions of the Android API. What you could do instead is send your XSD through xjc and get JAXB class output and then write a script to convert the JAXB annotations into the equivalent Simple XML annotations. This should do exactly what you were looking for.

However, ideally, and if you had the time, you could check out the source for xjc and extend it to be able to output JAXB or Simple annotated classes.

Solution 2

I wrote a library to generate SimpleXML Java annotated classes from XSD.

Here is the link: https://github.com/yeshodhan/android-jaxb

Eg:

XML Schema

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://person.mickoo.com/"
            targetNamespace="http://person.mickoo.com/" elementFormDefault="qualified">

    <xsd:element name="Person" type="Person"/>

    <xsd:complexType name="Person">
        <xsd:sequence>
            <xsd:element name="FirstName" type="xsd:string" minOccurs="0" />
            <xsd:element name="LastName" type="xsd:string" minOccurs="0" />
            <xsd:element name="Adult" type="xsd:boolean" minOccurs="0" />
            <xsd:element name="Addresses" type="Addresses" minOccurs="0" />
            <xsd:element name="Gender" type="Gender" minOccurs="0" />
            <xsd:element name="Favorite_Fruits" type="Fruits" minOccurs="0" maxOccurs="3"/>
            <xsd:element name="SomeThing_really_whacky-by-the-user" type="xsd:string" minOccurs="0" />
        </xsd:sequence>
        <xsd:attribute name="id" type="xsd:string"/>
    </xsd:complexType>

    <xsd:complexType name="Addresses">
        <xsd:sequence>
            <xsd:element name="Address" type="Address" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="Address">
        <xsd:sequence>
            <xsd:element name="Line1" type="xsd:string" minOccurs="0" />
            <xsd:element name="Line2" type="xsd:string" minOccurs="0" />
            <xsd:element name="City" type="xsd:string" minOccurs="0" />
            <xsd:element name="State" type="xsd:string" minOccurs="0" />
            <xsd:element name="Country" type="xsd:string" minOccurs="1" />
            <xsd:element name="PostalCode" type="xsd:string" minOccurs="0" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:simpleType name="Gender">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="MALE"/>
            <xsd:enumeration value="FEMALE"/>
            <xsd:enumeration value="NOT_SPECIFIED"/>
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="Fruits">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="Apple"/>
            <xsd:enumeration value="Banana"/>
            <xsd:enumeration value="Mango"/>
            <xsd:enumeration value="Orange"/>
            <xsd:enumeration value="Grapes"/>
            <xsd:enumeration value="Watermelon"/>
            <xsd:enumeration value="Peach"/>
            <xsd:enumeration value="Apricot"/>
            <xsd:enumeration value="Grapefruit"/>
        </xsd:restriction>
    </xsd:simpleType>

</xsd:schema>

Generated Java Classes

package com.mickoo.person;

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.Root;


@Root(name = "Address")
@Namespace(reference = "http://person.mickoo.com/")
public class Address {

    @Element(name = "Line1", required = false)
    private String line1;
    @Element(name = "Line2", required = false)
    private String line2;
    @Element(name = "City", required = false)
    private String city;
    @Element(name = "State", required = false)
    private String state;
    @Element(name = "Country", required = true)
    private String country;
    @Element(name = "PostalCode", required = false)
    private String postalCode;

    public Address() {
    }

    public String getLine1() {
        return line1;
    }

    public void setLine1(String line1) {
        this.line1 = line1;
    }

    public String getLine2() {
        return line2;
    }

    public void setLine2(String line2) {
        this.line2 = line2;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getPostalCode() {
        return postalCode;
    }

    public void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }

}

package com.mickoo.person;

import java.util.List;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.Root;


@Root(name = "Addresses")
@Namespace(reference = "http://person.mickoo.com/")
public class Addresses {

    @ElementList(name = "Address", entry = "Address", inline = true, required = false)
    private List<Address> address;

    public Addresses() {
    }

    public List<Address> getAddress() {
        return address;
    }

    public void setAddress(List<Address> address) {
        this.address = address;
    }

}

package com.mickoo.person;

import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.Root;

@Root(name = "Fruits")
@Namespace(reference = "http://person.mickoo.com/")
public enum Fruits {

    Apple,
    Banana,
    Mango,
    Orange,
    Grapes,
    Watermelon,
    Peach,
    Apricot,
    Grapefruit;

}

package com.mickoo.person;

import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.Root;

@Root(name = "Gender")
@Namespace(reference = "http://person.mickoo.com/")
public enum GenderEnum {

    MALE(0, "Men are from Mars"),
    FEMALE(1, "Women are from Venus"),
    NOT_SPECIFIED(2, "Can't say anything");
    private final Integer id;
    private final String description;

    private GenderEnum(Integer id, String description) {
        this.id = id;
        this.description = description;
    }

    public Integer id() {
        return id;
    }

    public String description() {
        return description;
    }

}


package com.mickoo.person;

import java.util.List;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.Root;


@Root(name = "Person")
@Namespace(reference = "http://person.mickoo.com/")
public class Person {

    @Element(name = "FirstName", required = false)
    private String firstName;
    @Element(name = "LastName", required = false)
    private String lastName;
    @Element(name = "Adult", required = false)
    private Boolean adult;
    @Element(name = "Addresses", required = false)
    private Addresses addresses;
    @Element(name = "Gender", required = false)
    private GenderEnum gender;
    @ElementList(name = "Favorite_Fruits", entry = "Favorite_Fruits", inline = true, required = false)
    private List<Fruits> favoriteFruits;
    @Element(name = "SomeThing_really_whacky-by-the-user", required = false)
    private String someThingReallyWhackyByTheUser;
    @Attribute(name = "id", required = false)
    private String id;

    public Person() {
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Boolean getAdult() {
        return adult;
    }

    public void setAdult(Boolean adult) {
        this.adult = adult;
    }

    public Addresses getAddresses() {
        return addresses;
    }

    public void setAddresses(Addresses addresses) {
        this.addresses = addresses;
    }

    public GenderEnum getGender() {
        return gender;
    }

    public void setGender(GenderEnum gender) {
        this.gender = gender;
    }

    public List<Fruits> getFavoriteFruits() {
        return favoriteFruits;
    }

    public void setFavoriteFruits(List<Fruits> favoriteFruits) {
        this.favoriteFruits = favoriteFruits;
    }

    public String getSomeThingReallyWhackyByTheUser() {
        return someThingReallyWhackyByTheUser;
    }

    public void setSomeThingReallyWhackyByTheUser(String someThingReallyWhackyByTheUser) {
        this.someThingReallyWhackyByTheUser = someThingReallyWhackyByTheUser;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

}

Usage

➜  target git:(master) ✗ java -jar android-jaxb-1.0.jar --help
usage: java -jar android-jaxb-1.0.jar [options] your-schema-file.xsd
---------------------------------------------------------------------
 -b,--bindings <arg>      (optional) bindings JSON file
 -d,--destination <arg>   destination directory for generated classes
 -h,--help                Help on usage
 -p,--package <arg>       package name for generated classes. Eg.:
                          com.example.app
 -v,--version             Version
---------------------------------------------------------------------
Share:
11,373

Related videos on Youtube

chemical
Author by

chemical

Updated on May 31, 2022

Comments

  • chemical
    chemical about 2 years

    Ok, so I've searched stackoverflow and found unanswered sub-topics regarding this issue, that's why I'd like to have this question clearly pointed out:

    Is there any tool that will generate the Simple Xml library's annotated java class from an xsd schema?

    I received a couple of xsd files describing the objects returned by a restful web-service someone else has developed and currently I've translated those schemas to the simple-xml annotated classes. Those will be used in my Android app. It would be better to just automatically synchronize any changes to the schemas and regenerate the classes from them. The ws guys have a repository of Jackson compliant classes for those schemas, however I don't want to use Jackson - I'm using Spring Android, so I'd prefer to go with the preferred simple-xml. There must be something that does the trick like JAXB's xjc tool.

    If there is no such tool - can you think of any traps in implementing a script that generates a .java file for simple-xml from the schema? Maybe any hints for tools worth extending that would just require defining what annotations to generate and when?

    In advance - thanks a lot for your answers!

    • stackoverflowuser2010
      stackoverflowuser2010 almost 9 years
      Did you ever find a solution to this problem? I also would like to start with an XSD file, generate Java classes, and then use those classes with Simple-XML.
  • chemical
    chemical about 13 years
    Spring Android Rest Template module depends on simple-xml (source: static.springsource.org/spring-android/docs/1.0.x/reference/‌​…) I was curious about the tools dedicated for Simple. I am aware of the alternatives, I just wanted to use Spring Android :) The ws team is at the development of a server application that we want to access via Android client. The automation of the xsd -> java would mean less work. Once they change something, some scripts might automatically regenerate the objects in the Android client app.
  • Peter Barbanyaga
    Peter Barbanyaga over 8 years
    java -jar android-jaxb-1.0.jar -d ... Metadata.xsd Code Generator Initialized. Destination Directory: D:\Projects\Android\XsdToSimpleXML [Element /frequencyConfig Min Occurs: null, Max Occurs: null ] of type [null] [Start of sequence Min Occurs: 1, Max Occurs: 1 ] [Element /frequencyConfig/dateStart Min Occurs: 1, Max Occurs: 1 ] of type [dateTime] Exception in thread "main" java.lang.NullPointerException at com.sun.codemodel.JVar.annotate(JVar.java:188) at com.mickoo.xml.xsd2simplexml.GeneratedClass.addElement(Gener‌​atedClass .java:62)
  • Peter Barbanyaga
    Peter Barbanyaga over 8 years
    Your lib generate many exceptions like "Exception in thread "main" java.lang.NullPointerException at com.sun.codemodel.JVar.annotate" for sequences. Why?
  • Yeshodhan Kulkarni
    Yeshodhan Kulkarni over 8 years
    Can you send me the XSD you are trying to parse?
  • Peter Barbanyaga
    Peter Barbanyaga over 8 years
    How can I understand problem appeares because I don't use JSON-description. Is use JSON-description neccessery?
  • alicjab
    alicjab over 7 years
    Yeshodhan, is there any chance you're still working on this project? I'd like to use it but I get a NullPointerException when I try to
  • Selali Adobor
    Selali Adobor about 5 years
    I know this is pretty old, but I got a successful conversion out of it with, two things to note: 1. You need to pass the destination and package options. If you only pass the package option, the generator will throw an NPE 2. You can only use simple types or you'll get a NPE. "xsd:date" for example, is not supported. I manually replaced each type that caused a NPE. You can tell which type is causing the issue by looking at the last node that was printed out before the NPE, and replacing it with a basic type