October 22, 2016
Hot Topics:

Cure Your Java XML Troubles with a Dose of Castor Oil

  • December 21, 2006
  • By James Turner
  • Send Email »
  • More Articles »

The first interesting content in the file is the declaration of the top level element, the collection. This definition maps a specific class to an XML element. The only XML elements that you need to use the "map-to" tag with are ones that appear at the top level of XML documents, all others are mapped using the "bind-xml" tag. The "field" tag defines a relationship between a child element of the current element and a Java class or collection. In this case, there are two fields defined. The simpler is the "type" field, which maps to the type bean property of the Collection class. The "direct" attribute indicates whether Castor should use direct access to the properties, or the accessor methods. Since you declared our properties private in the classes, you need to set "direct" to false. You also set "node" to "attribute", which means that the property is stored as an XML attribute rather than as text or an element.

The more interesting field is the books field, which is used to store the list of books in the collection. Because there are more than one books potentially in a single book collection, you have to specify the "collection" attribute and set it equal to the type of Java Collection you're going to store the values in. In this case, you use an ArrayList. The type attribute tells Castor what the type of the individual elements is. In this case, you use the node type of "element" to indicate that the class is populated from an XML sub-element.

The rest of the file follows the same pattern. You define a book, with an ISBN code and title. The ISBN is an attribute, and the title comes from the contents of the title element. The book also has a list of authors, just as the collection had a list of books. Notice that you don't even have to define the author class, Castor will figure out how to populate the two fields because the Java properties match the XML element names.

	<class name="com.blackbear.examples.castor.Book">
		<field name="isbn" direct="false" 
			<bind-xml name="isbn" node="attribute"/>
		<field name="title" direct="false" 
			<bind-xml name="title" node="element"/>
		<field name="authors" collection="arraylist" 
			<bind-xml name="author" node="element"/>

Now it's just a matter of loading the mapping file, doing an unmarshall using the mapping, and walking the resulting Java objects. As you can see from the code below, you only need about 8 lines of Java to actually unpack the XML into POJOs, the rest of the code is processing the resulting objects to product a list of books by each author.

 public static void main(String[] args) {
    try {
        Mapping mapping = new Mapping();
        InputStream mappingStream =
        mapping.loadMapping(new InputSource(mappingStream));
        Unmarshaller unmarshaller = new Unmarshaller();
        InputStream xmlFile = 
        InputSource f = new InputSource(xmlFile);
        Object shouldBeCollection = unmarshaller.unmarshal(f);

	  // Done demarshalling XML, rest is processing

        if (shouldBeCollection instanceof Collection) {
            Collection collection = (Collection) shouldBeCollection;
            Map<String, List> authors = new HashMap<String, List>();
            if (collection.getBooks() != null) {
                List<Book> books = collection.getBooks();
                int numBooks = books.size();
                for (int i = 0; i < numBooks; i++) {
                    Book book = books.get(i);
                    List<Author> bookAuthors = book.getAuthors();
                    int numAuthors = bookAuthors.size();
                    for (int j = 0; j < numAuthors; j++) {
                        Author author = bookAuthors.get(j);
                        String name = author.getLastname()
                                + ","
                                    + author.getFirstname();
                        List authorBooks = authors.get(name);
                        if (authorBooks == null) {
                            authorBooks = new ArrayList<Book>();
                            authors.put(name, authorBooks);
                Iterator<String> keys = authors.keySet().iterator();
                while (keys.hasNext()) {
                    String key = keys.next();
                    List<Book> authorBooks = authors.get(key);
                    int numAuthorBooks = authorBooks.size();
                    for (int i = 0; i < numAuthorBooks; i++) {
                        Book book = authorBooks.get(i);
                        System.out.println("   "
                                + book.getTitle() + "("
                                + book.getIsbn() + ")");
    } catch (MarshalException e) {
    } catch (ValidationException e) {
    } catch (MappingException e) {

Running this code results in the output below:

   The Ringworld Engineers(0345334302)


You can also turn things around and marshall up some XML with Castor from the same Java objects. Let's try the code show here. First you create a pair of outstanding Java books to turn into XML:

public static void main(String[] args) {
    try {
        Collection col = new Collection();
        Book book = new Book();
        book.setTitle("MySQL and JSP Web Applications");
        Author james = new Author();
        book = new Book();
        book.setTitle("Struts Kick Start");
        Author kevin = new Author();

Page 2 of 3

Comment and Contribute


(Maximum characters: 1200). You have characters left.



Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date
Rocket Fuel