Simple API for XML
- Common Interface implemented for many different XML Parsers
- Standard interface for event-based XML parsing
- SAX is not an XML Parser
- SAX2 is a new Java-based release of SAX
- SAX2 adds support for XML Namespaces
- SAX 2.0/Java final release at :
http://www.megginson.com/SAX/Java/index.html
What is an Event-Based API?
- Event-Based APIs report parsing events directly to
the application through callbacks.
- Start Element
- Start Document
- End Element
- Application implements handlers to deal with events
- Event-Based API provides a simpler, lower-level access to
an XML document
- Possible to parse large documents much larger than system memory
- Application constructs data structure using callback event handlers
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
- Default implementations for all required callback methods
- Required methods
- void characters(char[] ch, int start, int length)
- void endDocument()
- void endElement(String uri, String localName, String rawName)
- void startDocument()
- void startElement(String uri, String localName, String rawName
Attributes attributes)
SAXParser
- SAXParser class is derived from the XMLParser class
java.lang.Object
|
+--org.apache.xerces.framework.XMLParser
|
+--org.apache.xerces.parsers.SAXParser
- Register the SAXHandler object to the SAXParser object
- Four core SAX interfaces
- Entity Resolver - handles external entities
- DTDHandler - handles DTD events
- ContentHandler - handles content of a document
- ErrorHandler - handles error
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
- javac -classpath ":xerces.jar" SaxNames.java
- java -classpath ":xerces.jar" SaxNames students.xml
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
- xerces.jar, SaxNames.java, SaxNames.class and students.xml are in
the same directory
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
javac -classpath ":xerces.jar" SaxGrades.java
java -classpath ":xerces.jar" SaxGrades students.xml
Grades
Student 0= 66.25
Student 1= 77.5
Student 2= 73.75
Class Average = 72.5
- xerces.jar, SaxGrades.java, SaxGrades.class and students.xml are in
the same directory
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
javac -classpath ":xerces.jar" SaxFigures.java
java -classpath ":xerces.jar" SaxFigures figures.xml
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
- xerces.jar, SaxFigures.java, SaxFigures.class and figures.xml are in
the same directory