Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Take the sting out of SAX

Generate SAX parsers with XML Schemas

  • Print
  • Feedback

Page 4 of 4

This process gives you a set of new classes that form the basis of a new SAX parser. They are located in your SAX generator's output/ subdirectory. Assuming you used example1.xsd, you will have classes called CompanyHandler, EmployeesHandler, EmployeeHandler, and NameHandler.

Use the generated SAX parser

To use the generated SAX parser, you must create an entry-point class instance, named Parser by default, and call the parse() method. Listing 5 shows you how to initiate the SAX parser:

Listing 5. Initiate the SAX parser

public static void main (String[] args) throws Exception
{
    Parser parser = new Parser();
    FileInputStream fis = new FileInputStream (args[0]);
    parser.parse (fis);
}


At this stage, the newly generated classes do nothing; we must write implementations for the relevant methods. We must write an implementation for the CompanyHandler class to print the company heading. Currently, the CompanyHandler class has only empty methods: The SAX parser calls this handler's start() method when it encounters the <company> element; the end() method executes when the closing </company> is parsed. The startEmployees() method executes when the parser enters an <employees> element.

In this case, we want to print the company name when the <company> element starts, so we must add code to the start() method. Note that the SAX generator has already declared local variables for the entity's attributes. After we add code to print the header line, the method looks like this:

Listing 6. Print the company header

public void start (Attributes attributes)  throws SAXException
{
    String Name = attributes.getValue("Name");
    System.out.println ("Employee Listing For "+Name);
    System.out.println ();
}


Before we can print the employee information, we first must handle the <name> entity. Because this entity is complex, it has a separate handler class and needs some way to communicate name information back to the EmployeeHandler class. For this purpose, I created a global map object, called params, which allows you to pass information from one handler to the other. The Parser class automatically creates this map for you; to use the map, you simply need to add some information to it.

Now we need to add the text data enclosed in the XML elements to the params map. To access an XML element's text content, use the getText() method. A utility method, getText() returns the text enclosed in an entity with leading and trailing white-space characters removed. The following code snippet adds the text from <first> and <last> to the params map:

Listing 7. Add information to global params

public void endfirst () throws SAXException
{
    params.put ("firstname",getText());
}
  
public void endlast () throws SAXException
{
    params.put ("lastname",getText());
}


Now we can extract this information from the EmployeeHandler class. Because we must wait until the entire entity has been parsed (remember the <name> tag has to be handled before we print the employee information), we must add the following code to the end() method:

Listing 8. The employee handler

public void end () throws SAXException
{
    String firstname = params.remove ("firstname").toString();
    String lastname = params.remove ("lastname").toString();
    System.out.println (office + "\t " + firstname + "\t" + lastname + 
"\t" + telephone);
}


If you need to do some processing, depending on the context in which an element occurs, you can use the Path object to find the current entity's context. Path is a stack containing the path of element names from the root element to the current element. Don't directly alter this stack, as doing so causes an invalid state for the SAX parser; you should use it as read-only information.

Now you can recompile the classes and run the new program. You will see the same output as Listing 2's example, with much less work and more readable source code.

Generate a simple parser

Because a computer can discover an XML file's structure by parsing the XML Schema, a Generator class can go a long way to helping create a SAX parser's structure. In this article, you learned how to create an easy-to-use skeleton SAX parser with a SAX code generator, and also saw how to use this parser to parse XML files. The code generator saves you hours of SAX parser development time, and its structure provides you with more readable and maintainable source code.

You have also received a set of source code templates that you can modify to meet your specific needs. With these templates, you can create any SAX structure. Of course, you can also apply these templates to problems other than SAX—I'd like to hear about any new and interesting ways in which you use the code generator.

About the author

Leon Messerschmidt, a Java developer and open source advocate, is currently working at Opticode Software. He has been involved in both commercial and open source Web application framework development for many years.

Read more about Enterprise Java in JavaWorld's Enterprise Java section.

  • Print
  • Feedback

Resources
  • "Programming XML in Java," Mark Johnson (JavaWorld):