5.9 Helpers


 
Building Parsers with Java
By Steven  John  Metsker

Table of Contents
Chapter  5.   Parsing Data Languages

    Content

The helpers that build a Coffee object are similar to their assembler counterparts. The Helper class is the top of a hierarchy of classes that help to build an object based on recognizing elements of an XML markup file. An application (such as ShowCoffeeXML ) that uses a SAX parser can pass control to helpers upon receiving SAX events. The idea is that the application will register itself with the SAX parser to receive recognition events. Then the application uses Helper objects to help build a target object.

 package sjm.examples.coffee;  /**  * This class is the top of a hierarchy of classes that help  * to build a coffee object, based on recognizing elements  * of an XML markup file....  */ public class Helper { /**  * An application that uses a SAX parser should call this  * method upon receiving a <code>characters</code> event.  */ public void characters(String s, Object target) { } /**  * An application that uses a SAX parser should call this  * method upon receiving a <code>startElement</code> event.  */ public void startElement(Object target) { } } 

This class does nothing in either of its methods, which allows subclasses to override only the methods they need to apply. You can write a Helper subclass and register it for each kind of interesting event, such as finding a new coffee description or finding that coffee's name .

For example, here is the code to register when you see a new coffee description:

 package sjm.examples.coffee;  import java.util.*; /**  * This helper adds a new coffee object to the end of  * a vector of coffees.  */  public class NewCoffeeHelper extends Helper { /**  * Add a new coffee object to the end of a vector of coffees.  */ public void startElement(Object target) {     Vector v = (Vector) target;     v.addElement(new Coffee()); } } 

Other helpers set the attributes of a target Coffee object. For example, this helper sets the coffee's name.

 package sjm.examples.coffee;  import java.util.*; /**  * This helper sets a target coffee object's <code>name  * </code> attribute.  */ public class NameHelper extends Helper { /**  * Sets a target coffee object's <code>name</code>  * attribute to the given string. The target coffee is  * the last coffee in a Vector of coffees.  */ public void characters(String s, Object target) {     Coffee c = (Coffee) ((Vector) target).lastElement();     c.setName(s); } } 

Subclasses similar to NameHelper set a coffee's former name, roast, country, price, and alsoOfferFrench attribute.

5.9.1 ShowCoffeeXML

This class uses a SAX parser from the Apache organization, which received some of its XML code from IBM. The class registers itself as the handler of SAX events, but then it delegates these events to appropriate Helper objects. The class uses a hashtable to look up which helper to use, depending on which element the SAX parser sees.

 package sjm.examples.coffee;  import java.util.*; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; import org.apache.xerces.parsers.SAXParser; /**  * Show the recognition of a list of types of coffee,  * reading from an XML file....  */ public class ShowCoffeeXML extends DefaultHandler {     protected Hashtable helpers;     protected Helper helper;     protected Vector coffees = new Vector(); /*  * Returns the lookup table that tells which helper to  * use for which element.  */ protected Hashtable helpers() {     if (helpers == null) {         helpers = new Hashtable();         helpers.put("coffee", new NewCoffeeHelper());         helpers.put("name", new NameHelper());         helpers.put("formerName", new FormerNameHelper());         helpers.put("roast", new RoastHelper());         helpers.put("orFrench", new OrFrenchHelper());         helpers.put("country", new CountryHelper());         helpers.put("price", new PriceHelper());     }     return helpers; } /**  * Receive notification of the start of an element.  *  * <p>If the <code>helpers</code> hashtable has a key  * for the given element name, then inform the helper that  * this element has appeared.</p>  */ public void startElement(     String uri, String local, String raw, Attributes atts) {     helper = (Helper) helpers().get(raw);     if (helper != null) {         helper.startElement(coffees);     } } /**  * Receive notification of character data inside an element.  * If there is a helper ready to go, ask the helper to  * process these characters.  */ public void characters(char ch[], int start, int len) {     if (helper != null) {         helper.characters(             new String(ch, start, len), coffees);     } } /**  * Receive notification of the end of an element, which  * means that no helper should be active.  */ public void endElement(     String uri, String localName, String rawName) {     helper = null; } /**  * Show how to recognize coffees in an XML file.  */ public static void main(String argv[]) throws Exception {     SAXParser parser = new SAXParser();     ShowCoffeeXML x = new ShowCoffeeXML();     parser.setContentHandler(x);     parser.setErrorHandler(x);     parser.parse("coffee.xml");     Enumeration e = x.coffees.elements();     while (e.hasMoreElements()) {         Coffee c = (Coffee) e.nextElement();         System.out.println(c);     } } } 

The ShowCoffeeXML extends DefaultHandler , a class in org.xml.sax.helpers that implements the ContentHandler and ErrorHandler interfaces from org.xml.sax . By subclassing DefaultHandler , ShowCoffeeXML makes itself an acceptable argument to the SAX parser's setContentHandler() and setErrorHandler() methods. The main() method creates an instance of the ShowCoffeeXML class and registers this object to receive parsing events.

When the parser sees a new element, it calls the ShowCoffeeXML object's startElement() method and indicates which element it saw. For example, when the parser encounters a <roast> tag, it calls startElement() and includes the parameter roast . This method, as ShowCoffeeXML implements it, establishes a RoastHelper object as the helper to handle the forthcoming data. When the parser sees the data between tags, it calls the characters() method. This method passes the data to the established helper object, which uses the data to help build a target coffee object.

Running this class prints the following:

 Brimful, Regular, Kenya, 6.95  Caress(Smackin), French, Sumatra, 7.95 Fragrant Delicto, Regular/French, Peru, 9.95 Havalavajava, Regular, Hawaii, 11.95 Launch Mi, French, Kenya, 6.95 Roman Spur(Revit), Italian, Guatemala, 7.95 Simplicity House, Regular/French, Colombia, 5.95 

This is exactly the same result as before, but note that you did not write a parser. Rather, you used an existing parser, augmented with helper classes.


   
Top


Building Parsers with Java
Building Parsers With Javaв„ў
ISBN: 0201719622
EAN: 2147483647
Year: 2000
Pages: 169

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net