ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Learning and Using Jakarta Digester

by Philipp K. Janert
10/23/2002

Turning an XML document into a corresponding hierarchy of Java bean objects is a fairly common task. In a previous article, I described how to accomplish this using the standard SAX and DOM APIs.

Although powerful and flexible, both APIs are, in effect, too low-level for the specific task at hand. Furthermore, the unmarshalling procedure itself requires a fair amount of coding: a parse-stack must be maintained when using SAX, and the DOM-tree must be navigated when using DOM.

This is where the Apache Jakarta Commons Digester framework comes in.

The Jakarta Digester Framework

The Jakarta Digester framework grew out of the Jakarta Struts Web toolkit. Originally developed to process the central struts-config.xml configuration file, it was soon recognized that the framework was more generally useful, and moved to the Jakarta Commons project, the stated goal of which is to provide a "repository of reusable Java components." The most recent version, Digester 1.3, was released on August 13, 2002.

The Digester class lets the application programmer specify a set of actions to be performed whenever the parser encounters certain simple patterns in the XML document. The Digester framework comes with 10 prepackaged "rules," which cover most of the required tasks when unmarshalling XML (such as creating a bean or setting a bean property), but each user is free to define and implement his or her own rules, as necessary.

The Example Document and Beans

In this example, we will unmarshall the same XML document that we used in the previous article:

<?xml version="1.0"?>

<catalog library="somewhere">

   <book>
      <author>Author 1</author>
      <title>Title 1</title>
   </book>

   <book>
      <author>Author 2</author>
      <title>His One Book</title>
   </book>

   <magazine>
      <name>Mag Title 1</name>

      <article page="5">
         <headline>Some Headline</headline>
      </article>

      <article page="9">
         <headline>Another Headline</headline>
      </article>
   </magazine>

   <book>
      <author>Author 2</author>
      <title>His Other Book</title>
   </book>

   <magazine>
      <name>Mag Title 2</name>

      <article page="17">
         <headline>Second Headline</headline>
      </article>
   </magazine>

</catalog>

The bean classes are also the same, except for one important change: In the previous article, I had declared these classes to have package scope -- primarily so that I could define all of them in the same source file! Using the Digester framework, this is no longer possible; the classes need to be declared as public (as is required for classes conforming to the JavaBeans specification):

import java.util.Vector;

public class Catalog {
   private Vector books;
   private Vector magazines;

   public Catalog() {
      books = new Vector();
      magazines = new Vector();
   }

   public void addBook( Book rhs ) {
      books.addElement( rhs );
   }
   public void addMagazine( Magazine rhs ) {
      magazines.addElement( rhs );
   }

   public String toString() {
      String newline = System.getProperty( "line.separator" );
      StringBuffer buf = new StringBuffer();

      buf.append( "--- Books ---" ).append( newline );
      for( int i=0; i<books.size(); i++ ){
         buf.append( books.elementAt(i) ).append( newline );
      }

      buf.append( "--- Magazines ---" ).append( newline );
      for( int i=0; i<magazines.size(); i++ ){
         buf.append( magazines.elementAt(i) ).append( newline );
      }

      return buf.toString();
   }
}

public class Book {
   private String author;
   private String title;

   public Book() {}

   public void setAuthor( String rhs ) { author = rhs; }
   public void setTitle(  String rhs ) { title  = rhs; }

   public String toString() {
      return "Book: Author='" + author + "' Title='" + title + "'";
   }
}

import java.util.Vector;

public class Magazine {
   private String name;
   private Vector articles;

   public Magazine() {
      articles = new Vector();
   }

   public void setName( String rhs ) { name = rhs; }

   public void addArticle( Article a ) {
      articles.addElement( a );
   }

   public String toString() {
      StringBuffer buf = new StringBuffer( "Magazine: Name='" + name + "' ");
      for( int i=0; i<articles.size(); i++ ){
         buf.append( articles.elementAt(i).toString() );
      }
      return buf.toString();
   }
}

public class Article {
   private String headline;
   private String page;

   public Article() {}

   public void setHeadline( String rhs ) { headline = rhs; }
   public void setPage(     String rhs ) { page     = rhs; }

   public String toString() {
      return "Article: Headline='" + headline + "' on page='" + page + "' ";
   }
}

Pages: 1, 2, 3

Next Pagearrow