JMU
Processing XML in Java
An Introduction


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


The Java API for XML Processing (JAXP)
Element-Based Parsing
Element-Based Parsing (cont.)
Element-Based Parsing (cont.)

A Simple Example

javaexamples/jaxp/AccidentReportHandler.java
import org.xml.sax.*;
import org.xml.sax.helpers.*;

/**
 * Handles accident-reports contained in an incidents file
 *
 * Note: This class both contains logic and performs I/O.  It would
 * be better to use the Observer pattern.  The current approach is used
 * for simplicity.
 *
 * @version  1.0
 * @author   Prof. David Bernstein, James Madison University
 */
public class AccidentReportHandler extends DefaultHandler
{


    /**
     * Receive notification of the start of an element
     *
     * @param uri        The namespace URI 
     * @param localName  The local name or the empty string (if no namespace)
     * @param qName      The qualified name (with prefix)
     * @param attributes The specified or default attributes
     */
    public void startElement(String uri, String localName, String qName,
                             Attributes attributes)
    {
       String       size, type;


       if (qName.equals("accident-report")) 
       {
          size = attributes.getValue("size");
          type = attributes.getValue("type");

          System.out.println("\n\nAccident Report: ");
          System.out.println("    Description:     " + type);
          System.out.println("    No. of vehicles: " + size);
       }
    }

}

        
Element-Based Parsing (cont.)

A Simple Example (cont.)

javaexamples/jaxp/AccidentReporter.java
import java.io.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

/**
 * Displays accident-reports contained in an incidents file
 *
 * @version  1.0
 * @author   Prof. David Bernstein, James Madison University
 */
public class AccidentReporter
{
 
    /**
     * The entry-point of the application
     *
     * @param args   The command line arguments
     */
   public static void main(String[] args) throws Exception
    {
        AccidentReportHandler  handler;
        File                   incidents;
        SAXParser              parser;
        SAXParserFactory       factory;


        incidents = new File("incidents.xml");
        factory   = SAXParserFactory.newInstance();
        parser    = factory.newSAXParser();
        handler   = new AccidentReportHandler();
        
        parser.parse(incidents, handler);
    }
}
        
Element-Based Parsing (cont.)

An Example that Uses Some Containment Properties

javaexamples/jaxp/DepartureTimeFinder.java
import org.xml.sax.*;
import org.xml.sax.helpers.*;

/**
 * Finds a particular departure-time in a timetable
 *
 * Note: This implementation assumes that the station 
 *       preceeds the time in the stop.
 *
 * @version  1.0
 * @author   Prof. David Bernstein, James Madison University
 */
public class DepartureTimeFinder extends DefaultHandler
{
    private String    characters, dt, station, targetTrain, targetStation;
    private String    time, waitingFor;


    /**
     * Explicit value Constructor
     *
     * @param targetTrain   The train of interest (e.g., "191") 
     * @param targetStation The station of interest (e.g., "Newark, NJ") 
     */
    public DepartureTimeFinder(String targetTrain, String targetStation)
    {
       this.targetTrain   = targetTrain;
       this.targetStation = targetStation;
       time = null;
    }



    /**
     * Return the departure time (or null if the train and station were
     * not found)
     *
     * @return   The departure time
     */
    public String getDepartureTime()
    {
       return time;
    }


    /**
     * Receive notification of the beginning of the document
     *
     */
    public void startDocument()
    {
       waitingFor = "train";
    }



    /**
     * Receive notification of the start of an element
     *
     * @param uri        The namespace URI 
     * @param localName  The local name or the empty string (if no namespace)
     * @param qName      The qualified name (with prefix)
     * @param attributes The specified or default attributes
     */
    public void startElement(String uri, String localName, String qName,
                             Attributes attributes)
    {
       String       number;


       if (qName.equals(waitingFor)) 
       {
          if (qName.equals("train")) 
          {
             number = attributes.getValue("number");
             if ((number != null) && (number.equals(targetTrain))) 
             {
                waitingFor = "stop";
             }
          } 
          else if (qName.equals("stop")) 
          {
             waitingFor = "station";
          } 
          else if (qName.equals("station")) 
          {
             // Need the characters
          }
       }
    }



    /**
     * Receive notification of character data inside an element
     *
     * @param ch     The characters
     * @param start  The start position in the character array
     * @param length The number of characters to use from the character array
     */
    public void characters(char[] ch, int start, int length)
    {
       if (waitingFor.equals("station")) 
       {
          characters = new String(ch, start, length).trim();
       } 
       else if (waitingFor.equals("time")) 
       {
          characters = new String(ch, start, length).trim();
       }
    }



    /**
     * Receive notification of the start of an element
     *
     * @param uri        The namespace URI 
     * @param localName  The local name or the empty string (if no namespace)
     * @param qName      The qualified name (with prefix)
     */
    public void endElement(String uri, String localName, String qName)
    {
       if (waitingFor.equals("station")) 
       {
          if ((characters != null) && characters.equals(targetStation)) 
          {
             waitingFor = "time";
          }
          // Otherwise wait for another station
       } 
       else if (waitingFor.equals("time")) 
       {
          // This only happens when the train and station
          // have already been confirmed
          time = characters;
          waitingFor = "";
       }
    }
    
}

        
Element-Based Parsing (cont.)

An Example that Uses Some Containment Properties (cont.)

javaexamples/jaxp/DTFDriver.java
import java.io.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

/**
 * Finds and displays departure-times of trains
 *
 * @version  1.0
 * @author   Prof. David Bernstein, James Madison University
 */
public class DTFDriver
{

    /**
     * The entry-point of the application
     *
     * @param args   The command line arguments (train, station)
     */
    public static void main(String[] args) throws Exception
    {
        DepartureTimeFinder  finder;
        File                 amtrak;
        SAXParser            parser;
        SAXParserFactory     factory;
        String               time;


        amtrak  = new File("amtrak.xml");
        factory = SAXParserFactory.newInstance();
        parser  = factory.newSAXParser();
        finder  = new DepartureTimeFinder(args[0], args[1]);
        
        parser.parse(amtrak, finder);
        time = finder.getDepartureTime();

        if (time == null) System.out.println("Sorry!");
        else              System.out.println("Train "+args[0]+
                                             " departs "+args[1]+
                                             " at "+time);

    }


}
        
Document-Based Parsing
Document-Based Parsing (cont.)

An Example

javaexamples/jaxp/TimeTable.java
import org.w3c.dom.*;
import org.xml.sax.*;
import java.io.*;
import javax.xml.parsers.*;

/**
 * Finds and displays departure-times of trains
 *
 * @version  1.0
 * @author   Prof. David Bernstein, James Madison University
 */
public class TimeTable
{

    /**
     * The entry-point of the application
     *
     * @param args   The command line arguments (train, station)
     */
    public static void main(String[] args) throws Exception
    {
       boolean                   found; 
       Document                  tree;
       DocumentBuilder           builder;
       DocumentBuilderFactory    factory;
       Element                   root, station, stop, time, train;
       File                      amtrak;
       int                       i, n;
       Node                      text;
       NodeList                  children, stations, stops, textNodes;
       NodeList                  times, trains;
       String                    departureTime, number, stationName;



       amtrak  = new File("amtrak.xml");
       factory = DocumentBuilderFactory.newInstance();
       builder = factory.newDocumentBuilder();
       tree    = builder.parse(amtrak);


       // Get the timetable element
       root = tree.getDocumentElement();

       System.out.println("\n\nService for "+root.getAttribute("title"));
       System.out.println(root.getAttribute("subtitle"));
       System.out.println("\n");

       // Get the trains
       trains = root.getElementsByTagName("train");

       // Find the desired train
       found = false;
       train = null;
       n = trains.getLength();
       for (i=0; i < n && !found; i++) 
       {
          train  = (Element)trains.item(i);
          number = train.getAttribute("number");
          found = (number.equals(args[0]));
       }

       // Find the desired station
       departureTime = null;
       if (found) 
       {
          stops = train.getElementsByTagName("stop");
          found = false;
          n = stops.getLength();
          for (i=0; i < n && !found; i++) 
          {
             stop     = (Element)stops.item(i);

             // Get the station for this stop
             stations = stop.getElementsByTagName("station");
             station  = (Element)stations.item(0);

             // Get the text for this station
             textNodes   = station.getChildNodes();
             text        = textNodes.item(0);
             stationName = text.getNodeValue();

             // Is it the desired station?
             if (stationName.equals(args[1])) 
             {
                found = true;

                // Get the time for this stop
                times = stop.getElementsByTagName("time");
                time  = (Element)times.item(0);

                // Get the text for this time
                textNodes   = time.getChildNodes();
                text        = textNodes.item(0);
                departureTime = text.getNodeValue();
             }
          }
       }

       if (!found) System.out.println("Sorry!");
       else        System.out.println("Train "+args[0]+
                                      " departs "+args[1]+
                                      " at "+departureTime);
    }

}
        
Transforming a Document
Transforming a Document (cont.)

An Example

javaexamples/jaxp/XSLT.java
import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

/**
 * Transform an XML file with an XSLT program
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class XSLT
{

    /**
     * The entry-point of the application
     *
     * @param args   The command line arguments (.xml, .xsl)
     */
    public static void main(String[] args) throws Exception
    {
        ByteArrayOutputStream    bos;
        StreamResult             result;
        StreamSource             program, source;
        Transformer              transformer;
        TransformerFactory       factory;



        // Create the streams
        source  = new StreamSource(new File(args[0]));
        program = new StreamSource(new File(args[1]));

        bos = new ByteArrayOutputStream(65536);// So we can process the result
        result  = new StreamResult(bos);


        // Create the factory
        factory = TransformerFactory.newInstance();
        transformer = factory.newTransformer(program);

        // Perform the transformation
        transformer.transform(source, result);

        // Print to the console
        System.out.print(bos.toString());
        
    }
}
        
Validating a Document
Validating a Document (cont.)

An Example

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    factory.setValidating(true);

    factory.setAttribute(
      "http://java.sun.com/xml/jaxp/properties/schemaLanguage",
      "http://www.w3.org/2001/XMLSchema");
        
    DocumentBuilder builder = factory.newDocumentBuilder();

    // Then use the builder as before