Home arrow XML arrow Page 3 - XML Parsing With SAX and Xerces (part 2)

Nailing It To The Wall - XML

The first part of this article demonstrated the basics of the Xerces XML parser, explaining how it could be used to process XML documents in a non-Web environment. This concluding section closes the circle, taking everything you've learned so far and demonstrating how it can be applied to create dynamic Web pages from static XML documents with Xerces.

TABLE OF CONTENTS:
  1. XML Parsing With SAX and Xerces (part 2)
  2. The Write Stuff
  3. Nailing It To The Wall
  4. When Things Go Wrong
  5. Endnote
By: icarus, (c) Melonfire
Rating: starstarstarstarstar / 1
February 12, 2002

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement
Now, how about something a little more useful? Consider the following modification of the previous example:

<?xml version="1.0"?> <inventory> <item> <id>758</id> <name>Rusty, jagged nails for nailgun</name> <supplier>NailBarn, Inc.</supplier> <cost>2.99</cost> <quantity alert="500">10000</quantity> </item> <item> <id>6273</id> <name>Power pack for death ray</name> <supplier>QuakePower.domain.com</supplier> <cost currency="USD">9.99</cost> <quantity alert="20">10</quantity> </item> <item> <id>3784</id> <name>Axe</name> <supplier>Axe And You Shall Receive, Inc.</supplier> <cost currency="USD">56.74</cost> <quantity alert="5">25</quantity> </item> <item> <id>986</id> <name>NVGs</name> <supplier>Quake Eyewear</supplier> <cost currency="USD">1399.99</cost> <quantity alert="5">2</quantity> </item> </inventory>
Now, let's suppose I want to display this information in a neatly-formatted table, with those items that I'm low on highlighted in red. My preferred output would look something like this:



Here's the code to accomplish this:

import org.apache.xerces.parsers.SAXParser; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; import java.io.*; public class MyFifthSaxApp extends DefaultHandler { private Writer out; private String ElementName, AttributeName,AttributeValue = ""; private Integer Quantity, Alert; // constructor public MyFifthSaxApp (String xmlFile, Writer out) throws SAXException { this.out = out; // Create a Xerces SAX parser SAXParser parser = new SAXParser(); // Set the Content Handler parser.setContentHandler(this); // parse the Document try { parser.parse(xmlFile); out.flush(); } catch (IOException e) { throw new SAXException(e); } } // call this when opening element found public void startElement (String uri, String local, String qName, Attributes atts) throws SAXException { try { // this is useful later ElementName = local; // display table header if(local.equals("inventory")) { out.write("<h1><font face=Verdana>Inventory Management</font></h1>n<table width="55%" cellpadding="5" cellspacing="5" border="1"><tr><td><p align=right><b><font face=Verdana size=2>Code</font></b></p></td><td><b><font face=Verdana size=2>Name</font></b></td><td><b><font face=Verdana size=2>Supplier</font></b></td><td><p align=right><b><font face=Verdana size=2>Cost</font></b></p></td><td><p align=right><font face=Verdana size=2><b>Quantity</b></font></p></td></tr>"); } else if(local.equals("item")) { // "item" element starts a new row out.write("<tr>"); } else if( local.equals("name") || local.equals("supplier")) { // create table cells within row // align strings left, numbers right out.write("<td><p align=left><font face=Verdana size=2>"); } else if( local.equals("id") || local.equals("cost") || local.equals("quantity")) { out.write("<td><p align=right><font face=Verdana size=2>"); } else { out.write("<br>"); } for (int i = 0; i < atts.getLength(); i++) { AttributeName = atts.getLocalName(i); AttributeValue = atts.getValue(AttributeName); if(AttributeName.equals("currency")) { out.write(AttributeValue + "&nbsp;"); } else if(AttributeName.equals("alert")) { Alert = new Integer(AttributeValue); } else { out.write("&nbsp;"); } } } catch (IOException e) { throw new SAXException(e); } } // call this when cdata found public void characters(char[] text, int start, int length) throws SAXException { try { String Content = new String(text, start, length); if (!Content.trim().equals("")) { if ((ElementName != null && ElementName.equals("quantity")) && (AttributeName != null && AttributeName.equals("alert"))) { Quantity = new Integer(Content); // if quantity lower than expected, highlight in red if((Quantity.intValue()) < (Alert.intValue())) { out.write("<font color="#ff0000">" + Quantity + "</font>"); } else { out.write("<font color="#000000">" + Quantity + "</font>"); } } else { out.write(Content); } } } catch (IOException e) { throw new SAXException(e); } } // call this when closing element found public void endElement (String uri, String local, String qName) throws SAXException { try { if(local.equals("inventory")) { out.write("</table>"); } else if(local.equals("item")) { // "item" closes table row out.write("</tr>"); } else if(local.equals("id") || local.equals("name") || local.equals("supplier") || local.equals("cost") || local.equals("quantity")) { // close table cells out.write("</font></p></td>"); } else { out.write("&nbsp;"); } } catch (IOException e) { throw new SAXException(e); } } }
As you can see, the callback functions used here have evolved substantially from the previous examples - they now contain more conditional tests, and better error handling capabilities. Let's take a closer look.

Most of the work in this script is done by the startElement() callback function. This function prints specific HTML output depending on the element encountered by the parser.

// call this when opening element found public void startElement (String uri, String local, String qName, Attributes atts) throws SAXException { try { // this is useful later ElementName = local; // display table header if(local.equals("inventory")) { out.write("<h1><font face=Verdana>Inventory Management</font></h1>n<table width="55%" cellpadding="5" cellspacing="5" border="1"><tr><td><p align=right><b><font face=Verdana size=2>Code</font></b></p></td><td><b><font face=Verdana size=2>Name</font></b></td><td><b><font face=Verdana size=2>Supplier</font></b></td><td><p align=right><b><font face=Verdana size=2>Cost</font></b></p></td><td><p align=right><font face=Verdana size=2><b>Quantity</b></font></p></td></tr>"); } else if(local.equals("item")) { // "item" element starts a new row out.write("<tr>"); } else if( local.equals("name") || local.equals("supplier")) { // create table cells within row // align strings left, numbers right out.write("<td><p align=left><font face=Verdana size=2>"); } else if( local.equals("id") || local.equals("cost") || local.equals("quantity")) { out.write("<td><p align=right><font face=Verdana size=2>"); } else { out.write("<br>"); } for (int i = 0; i < atts.getLength(); i++) { AttributeName = atts.getLocalName(i); AttributeValue = atts.getValue(AttributeName); if(AttributeName.equals("currency")) { out.write(AttributeValue + "&nbsp;"); } else if(AttributeName.equals("alert")) { Alert = new Integer(AttributeValue); } else { out.write("&nbsp;"); } } } catch (IOException e) { throw new SAXException(e); } }
This function maps different XML elements to appropriate HTML markup. As you can see, the document element "inventory", which marks the start of the XML document, is used to create the skeleton and first row of an HTML table, while the different "item" elements correspond to rows within this table. The details of each item - name, supplier, quantity et al - are formatted as cells within each row of the table.

Next, the characters() callback function handles formatting of the content embedded within the elements.

// call this when cdata found public void characters(char[] text, int start, int length) throws SAXException { try { String Content = new String(text, start, length); if (!Content.trim().equals("")) { if ((ElementName != null && ElementName.equals("quantity")) && (AttributeName != null && AttributeName.equals("alert"))) { Quantity = new Integer(Content); // if quantity lower than expected, highlight in red if((Quantity.intValue()) < (Alert.intValue())) { out.write("<font color="#ff0000">" + Quantity + "</font>"); } else { out.write("<font color="#000000">" + Quantity + "</font>"); } } else { out.write(Content); } } } catch (IOException e) { throw new SAXException(e); } }
For most of the elements, I'm simply displaying the content as is. The only deviation from this standard policy occurs with the "quantity" element, which has an additional "alert" attribute. This "alert" attribute specifies the minimum number of units that should be in stock of the corresponding item; if the quantity drops below this minimum level, an alert should be generated. Consequently, the characters() callback includes some code to test the current quantity against the minimum quantity, and highlight the data in red if the test fails.

And finally, to wrap things up, the endElement() callback closes the HTML tags opened earlier.

// call this when closing element found public void endElement (String uri, String local, String qName) throws SAXException { try { if(local.equals("inventory")) { out.write("</table>"); } else if(local.equals("item")) { // "item" closes table row out.write("</tr>"); } else if(local.equals("id") || local.equals("name") || local.equals("supplier") || local.equals("cost") || local.equals("quantity")) { // close table cells out.write("</font></p></td>"); } else { out.write("&nbsp;"); } } catch (IOException e) { throw new SAXException(e); } }
Once you've compiled this class, you can use it in a JSP page, as you did with the previous example. Here's the code,

<%@ page language="java" import="java.io.IOException" %> <html> <head> </head> <body> <% try { MyFifthSaxApp myFifthExample = new MyFifthSaxApp("/www/xerces/WEB-INF/classes/inventory.xml",out); } catch (Exception e) { out.println("<font face="verdana" size="2">The following error occurred: <br><b>" + e + "</b></font>"); } %> </body> </html>
and here's the output:



 
 
>>> More XML Articles          >>> More By icarus, (c) Melonfire
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

XML ARTICLES

- Google Docs and Xpath Data Functions
- Flex Array Collection Sort and Filtering
- The Flex Tree Control
- Flex List Controls
- Working with Flex and Datagrids
- How to Set Up Podcasting and Vodcasting
- Creating an RSS Reader Application
- Building an RSS File
- An Introduction to XUL Part 6
- An Introduction to XUL Part 5
- An Introduction to XUL Part 4
- An Introduction to XUL Part 3
- An Introduction to XUL Part 2
- An Introduction to XUL Part 1
- XML Matters: Practical XML Data Design and M...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: