Simple API for XML

What is an Event-Based API?

How SAX works?

     <?xml version="1.0"?>
     <Name>
        <Last_Name>Punin</Last_Name>
        <First_Name>John</First_Name>
     </Name>
     start document
     start element: Name
     start element: Last_Name
     characters: Punin
     end element: Last_Name
     start element: First_Name
     characters: John
     end element: First_Name
     end element: Name
     end document

SAX2/Java Parsers and Drivers

Working with SAX

Problem:   Print a list of the Elements of this XML file:
   <?xml version="1.0"?> 
   <course>
      <name id="csci_2962">Programming XML in Java</name>
      <teacher id="jp">
         <name>John Punin</name>
      </teacher>
      <student id="js">
         <name>John Smith</name>
         <hw1>30</hw1>
         <hw2>70</hw2>
         <project>80</project>
         <final>85</final>
      </student>
      <student id="gl">
         <name>George Lucas</name>
         <hw1>80</hw1>
         <hw2>90</hw2>
         <project>100</project>
         <final>40</final>
      </student>
      <student id="lr">
         <name>Elizabeth Roberts</name>
         <hw1>60</hw1>
         <hw2>95</hw2>
         <project>50</project>
         <final>90</final>
      </student>
   </course>

Using Xerces XML Parser

import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;

public class SaxNames extends DefaultHandler
{
    public static void main(String[] args)
    {
	  SaxNames SAXHandler = new SaxNames();
	  SAXParser parser = new SAXParser();
	  .
	  .
	  .
    }
}

DefaultHandler

SAXParser

     java.lang.Object
     |
     +--org.apache.xerces.framework.XMLParser
        |
        +--org.apache.xerces.parsers.SAXParser

Using Xerces XML Parser (2)

   import org.xml.sax.*;
   import org.xml.sax.helpers.DefaultHandler;
   import org.apache.xerces.parsers.SAXParser;

   public class SaxNames extends DefaultHandler
   {
      public void startElement(String uri, String localName, String rawName,
                               Attributes attributes)
      {
	 System.out.println("Element : " + localName);
      }

      public static void main(String[] args)
      {
         try{
            SaxNames SAXHandler = new SaxNames();
	    SAXParser parser = new SAXParser();
	    parser.setContentHandler(SAXHandler);
	    parser.setErrorHandler(SAXHandler);
	    parser.parse(args[0]);
	 }
	 catch(Exception e){
	    e.printStackTrace(System.err);
	 }
      }
   }

Compiling and Running SaxNames example

     Element : course
     Element : name
     Element : teacher
     Element : student
     Element : name
     Element : hw1
     Element : hw2
     Element : project
     Element : final
     Element : student
     Element : name
     Element : hw1
     Element : hw2
     Element : project
     Element : final
     Element : student
     Element : name
     Element : hw1
     Element : hw2
     Element : project
     Element : final

Working with SAX (2)

Problem:   Print a list of Students' Average and Course Average
   <?xml version="1.0"?> 
   <course>
      <name id="csci_2962">Programming XML in Java</name>
      <teacher id="jp">
         <name>John Punin</name>
      </teacher>
      <student id="js">
         <name>John Smith</name>
         <hw1>30</hw1>
         <hw2>70</hw2>
         <project>80</project>
         <final>85</final>
      </student>
      <student id="gl">
         <name>George Lucas</name>
         <hw1>80</hw1>
         <hw2>90</hw2>
         <project>100</project>
         <final>40</final>
      </student>
      <student id="lr">
         <name>Elizabeth Roberts</name>
         <hw1>60</hw1>
         <hw2>95</hw2>
         <project>50</project>
         <final>90</final>
      </student>
   </course>

Creating SAXHandler and Parser

   import org.xml.sax.*;
   import org.xml.sax.helpers.DefaultHandler;
   import org.apache.xerces.parsers.SAXParser;

   class SaxParserGrades extends DefaultHandler
   {
   ....
   }

   public class SaxGrades 
   {
      public static void main(String[] args)
      {
	 try{
	    SaxParserGrades SAXHandler = new SaxParserGrades();
	    SAXParser parser = new SAXParser();
	    parser.setContentHandler(SAXHandler);
	    parser.setErrorHandler(SAXHandler);
	    parser.parse(args[0]);
	 }
	 catch(Exception e){
	    e.printStackTrace(System.err);
	 }
      }
   }

Writing startElement and endElement

   static float grades[][] = new float[100][5];
   int gi = -1;
   int nstudent = 0;

   public void startElement(String uri, String localName, String rawName,
                            Attributes attributes)
   {
      if(localName.equals("hw1"))
	 gi = 0;
      else if(localName.equals("hw2"))
	 gi = 1;
      else if(localName.equals("project"))
	 gi = 2;
      else if(localName.equals("final"))
	 gi = 3;
      else if(localName.equals("student"))
	 nstudent++;
   }

   public void endElement(String uri, String localName, String rawName)
   {
      gi = -1;
   }

Writing characters

   public void characters(char characters[], int start, int length)
   {
      String chData = (new String(characters, start, length)).trim();
      if(chData.indexOf("\n") < 0 && chData.length() > 0) {
         if(gi >= 0){
            grades[nstudent-1][gi] = Integer.parseInt(chData);
         }
      }
   }

Writing endDocument

   public void endDocument()
   {
      float Ave = 0;
      int i = 0, j = 0;
      System.out.println("Grades");
      for(i = 0; i < nstudent ; i++){
         float total = 0;
         for(j = 0; j < 4; j++){
            total += grades[i][j];
         }		
         grades[i][4] = total/4;
         Ave += grades[i][4];
         System.out.println("Student " + i + "=" + grades[i][4]);
      }
      Ave /= nstudent;
      System.out.println("Class Average = " + Ave);
   }

Putting all together

   import org.xml.sax.*;
   import org.xml.sax.helpers.DefaultHandler;
   import org.apache.xerces.parsers.SAXParser;

   class SaxParserGrades extends DefaultHandler
   {
      static float grades[][] = new float[100][5];
      int gi = -1;
      int nstudent = 0;
    
      public void startElement(String uri, String localName, String rawName,
                               Attributes attributes)
      {
         if(localName.equals("hw1"))
            gi = 0;
         else if(localName.equals("hw2"))
            gi = 1;
         else if(localName.equals("project"))
            gi = 2;
         else if(localName.equals("final"))
            gi = 3;
         else if(localName.equals("student"))
         nstudent++;
      }

      public void endElement(String uri, String localName, String rawName)
      {
         gi = -1;
      }

      public void characters(char characters[], int start, int length)
      {
          String chData = (new String(characters, start,length)).trim();
          if(chData.indexOf("\n") < 0 && chData.length() > 0){
             if(gi >= 0){
                grades[nstudent-1][gi] = Integer.parseInt(chData);
             }
          }
      }

      public void endDocument()
      {
         float Ave = 0;
         int i = 0, j = 0;
         System.out.println("Grades");
         for(i = 0; i < nstudent ; i++){
            float total = 0;
            for(j = 0; j < 4; j++){
               total += grades[i][j];
            }		
            grades[i][4] = total/4;
            Ave += grades[i][4];
            System.out.println("Student " + i + "=" + grades[i][4]);
         }
         Ave /= nstudent;
         System.out.println("Class Average =" + Ave);
      }
   }

   public class SaxGrades 
   {
      public static void main(String[] args)
      {
         try{
            SaxParserGrades SAXHandler = new SaxParserGrades();
            SAXParser parser = new SAXParser();
            parser.setContentHandler(SAXHandler);
            parser.setErrorHandler(SAXHandler);
            parser.parse(args[0]);
      }
      catch(Exception e){
         e.printStackTrace(System.err);
      }
   }
}


Compiling and Running SaxGrades example

     Grades
     Student 0= 66.25
     Student 1= 77.5
     Student 2= 73.75
     Class Average = 72.5

Working with SAX (Using Attributes)

Attributes Interface

int getIndex(String rawName)
    Gets the index of an attribute given a raw name
String getRawName(int index)
    Gets the attribute's raw name by index
String getValue(int index)
    Gets an attribute's value by index
String getValue(String rawName)
    Gets an attribute's value by raw name

Working with SAX (Using Attributes) (2)

Problem:   Compute the area of each of these figures:
     <?xml version="1.0"?> 
     <figures>
        <circle x="20" y="10" r="20"/>
        <rectangle x="-3" y="4" w="5" h="36"/>
        <ellipse x="-5" y="6" w="30" h="50"/>
        <rectangle x="7" y="23" w="58" h="45"/>
        <circle x="-2" y="5" r="35"/>
        <ellipse x="-10" y="-8" w="45" h="30"/>
     </figures>

Working with SAX (Using Attributes) (3)

   import org.xml.sax.*;
   import org.xml.sax.helpers.DefaultHandler;
   import org.apache.xerces.parsers.SAXParser;

   public class SaxFigures extends DefaultHandler
   {
       public void startElement(String uri, String localName, String rawName,
                                Attributes attributes)
       {
          if(localName.equals("circle"))
          {
             String sr = attributes.getValue("r");
             float radius = Float.valueOf(sr).floatValue();
             float area = (float)Math.PI*radius*radius;
             System.out.println("Circle : Radius = " + radius + 
                                " Area = " + area);
          }
          else if(localName.equals("ellipse"))
          {
             String sw = attributes.getValue("w");
             String sh = attributes.getValue("h");
             float width = Float.valueOf(sw).floatValue();
             float height = Float.valueOf(sh).floatValue();
             float area = (float)Math.PI*(width/2)*(height/2);
             System.out.println("Ellipse : Width = " + width + 
                                " Height = " + height + 
                                " Area = " + area);
          }
          else if(localName.equals("rectangle"))
          {
             String sh = attributes.getValue("h");
             String sw = attributes.getValue("w");
             float width = Float.valueOf(sw).floatValue();
             float height = Float.valueOf(sh).floatValue();
             float area = width * height;
             System.out.println("Rectangle : Width = " + width +
                                " Height = " + height + 
                                " Area = " + area);
          }
      }

      public static void main(String[] args)
      {
         try{
            SaxFigures SAXHandler = new SaxFigures();
            SAXParser parser = new SAXParser();
            parser.setContentHandler(SAXHandler);
            parser.setErrorHandler(SAXHandler);
            parser.parse(args[0]);
         }
         catch(Exception e){
            e.printStackTrace(System.err);
         }
      }
   }

Compiling and Running SaxFigures example

     Circle : Radius = 20.0 Area = 1256.6371
     Rectangle : Width = 5.0 Height = 36.0 Area = 180.0
     Ellipse : Width = 30.0 Height = 50.0 Area = 1178.0973
     Rectangle : Width = 58.0 Height = 45.0 Area = 2610.0
     Circle : Radius = 35.0 Area = 3848.4512
     Ellipse : Width = 45.0 Height = 30.0 Area = 1060.2876