Introduction
This tutorial introduces the JBoss XML binding framework. The advantages of which are:
no special interfaces or any other enforments for Java classes used for object models;
almost arbitrary class hierarchy loosely coupled with the XML schema structure;
the ability to populate the same object model with data from different XML files;
the ability to avoid representation of XML elements that are not useful in the object model (while still supporting marshalling where possible);
support of DTDs and XML schemas.
Sample XML content
As an example, the following simple representation of a book is used (which is taken from Using W3C XML Schema article at xml.com):
<?xml version="1.0" encoding="UTF-8"?> <book isbn="0836217462"> <title>Being a Dog Is a Full-Time Job</title> <author>Charles M. Schulz</author> <character> <name>Snoopy</name> <friend-of>Peppermint Patty</friend-of> <since>1950-10-04</since> <qualification>extroverted beagle</qualification> </character> <character> <name>Peppermint Patty</name> <since>1966-08-22</since> <qualification>bold, brash and tomboyish</qualification> </character> </book>
XML schema
XML schemas defining the structure of the above XML content could vary. We can choose any. Java classes that will represent the XML content structure will not depend on the chosen XML schema. Later, XML schema can be safely changed or even a DTD could be used instead without a need to modify the Java classes.
<?xml version="1.0" encoding="utf-8"?> <xs:schema targetNamespace="http://example.org/ns/books/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:bk="http://example.org/ns/books/" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="book"> <xs:complexType> <xs:sequence> <xs:element name="title" type="xs:string"></xs:element> <xs:element name="author" type="xs:string"></xs:element> <xs:element name="character" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string"></xs:element> <xs:element name="friend-of" type="xs:string" minOccurs="0" maxOccurs="unbounded"></xs:element> <xs:element name="since" type="xs:date"></xs:element> <xs:element name="qualification" type="xs:string"></xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="isbn" type="xs:string"></xs:attribute> </xs:complexType> </xs:element> </xs:schema>
In this case, book element should be modified to
<book isbn="54321" xmlns="http://example.org/ns/books/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://example.org/ns/books/ resources/books.xsd">
DTD
<?xml version='1.0' encoding='UTF-8'?> <!ELEMENT book (title, author, character*)> <!ATTLIST book isbn CDATA #REQUIRED> <!ELEMENT title (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ELEMENT character (name, friend-of?, since?, qualification?)> <!ELEMENT name (#PCDATA)> <!ELEMENT friend-of (#PCDATA)> <!ELEMENT since (#PCDATA)> <!ELEMENT qualification (#PCDATA)>
In case of DTD, we would need to add a DOCTYPE definition to the XML content above like
<!DOCTYPE book PUBLIC "-//DTD Books//EN" "resources/books.dtd">
Java classes
The class hierarchy could be arbitrary. For example, let's use two classes Book and BookCharacter to represent content of book and character elements correspondingly.
public class Book { private String isbn; private String title; private String author; private List characters = new ArrayList(); public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Iterator getCharacters() { return characters.iterator(); } public void addCharacter(BookCharacter character) { characters.add(character); } public String toString() { StringBuffer sb = new StringBuffer(100); sb.append('[') .append("isbn=").append(isbn) .append(", title=").append(title) .append(", author=").append(author) .append(", characters=").append(characters) .append(']'); return sb.toString(); } public boolean equals(Object o) { if(this == o) return true; if(!(o instanceof Book)) return false; final Book book = (Book)o; if(author != null ? !author.equals(book.author) : book.author != null) return false; if(characters != null ? !characters.equals(book.characters) : book.characters != null) return false; if(isbn != null ? !isbn.equals(book.isbn) : book.isbn != null) return false; if(title != null ? !title.equals(book.title) : book.title != null) return false; return true; } public int hashCode() { int result; result = (isbn != null ? isbn.hashCode() : 0); result = 29 * result + (title != null ? title.hashCode() : 0); result = 29 * result + (author != null ? author.hashCode() : 0); result = 29 * result + (characters != null ? characters.hashCode() : 0); return result; } } public class BookCharacter { private String name; private String friendOf; private String since; private String qualification; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getFriendOf() { return friendOf; } public void setFriendOf(String friendOf) { this.friendOf = friendOf; } public String getSince() { return since; } public void setSince(String since) { this.since = since; } public String getQualification() { return qualification; } public void setQualification(String qualification) { this.qualification = qualification; } public boolean equals(Object o) { if(this == o) return true; if(!(o instanceof BookCharacter)) return false; final BookCharacter bookCharacter = (BookCharacter)o; if(friendOf != null ? !friendOf.equals(bookCharacter.friendOf) : bookCharacter.friendOf != null) return false; if(name != null ? !name.equals(bookCharacter.name) : bookCharacter.name != null) return false; if(qualification != null ? !qualification.equals(bookCharacter.qualification) : bookCharacter.qualification != null) return false; if(since != null ? !since.equals(bookCharacter.since) : bookCharacter.since != null) return false; return true; } public int hashCode() { int result; result = (name != null ? name.hashCode() : 0); result = 29 * result + (friendOf != null ? friendOf.hashCode() : 0); result = 29 * result + (since != null ? since.hashCode() : 0); result = 29 * result + (qualification != null ? qualification.hashCode() : 0); return result; } public String toString() { StringBuffer sb = new StringBuffer(50); sb.append('[') .append("name=").append(name) .append(", friend-of=").append(friendOf) .append(", since=").append(since) .append(", qualification=").append(qualification) .append(']'); return sb.toString(); } }
Comments