Tài liệu XML by Example- P6 - Pdf 87

After the opening tag, the parser sees the content of the
name
element:
XML
Training
. It generates an event by passing the application the content as a
parameter.
The next event indicates the closing tag for the
name
element. The parser
has completely parsed the
name
element. It has fired five events so far:
three events for the
name
element, one event for the declaration, and one
for
product
opening tag.
The parser now moves to the first
price
element. It generates two events
for each
price
element: one event for the opening tag and one event for the
closing tag.
Even though the closing tag is reduced to the
/
character in the opening
tag, the parser generates an event for it. The parser passes the element’s
parameters to the application in the event for the opening tag.

needs.
The main reason people prefer event-based interfaces is efficiency. Event-
based interfaces are lower level than object-based interfaces. On the posi-
tive side, they give you more control over parsing and enable you to
optimize your application. On the downside, it means more work for you.
As already discussed, an event-based interface consumes fewer resources
than an object-based one, simply because it does not need to build the docu-
ment tree.
Furthermore, with an event-based interface, the application can start pro-
cessing the document as the parser is reading it. With an object-based
interface, the application must wait until the document has been com-
pletely read.
Therefore, event-based interfaces are particularly popular with applications
that process large files (which would take a lot of time to read and create a
document tree) and for servers (which process many documents simultane-
ously).
The major limitation of event-based interfaces is that it is not possible to
navigate through the document as you can with a DOM tree. Indeed, after
firing an event, the parser forgets about it. As you will see, the application
must explicitly buffer those events it is interested in. It might also have
more work in managing the state.
Of course, whether it uses an event-based or an object-based interface, the
parser does a lot of useful work: It reads the document, enforces the XML
syntax, and resolves entities. When using a validating parser, it might vali-
date the document against its DTD. So, there are many reasons to use a
parser.
236
Chapter 8: Alternative API: SAX
10 2429 CH08 11/12/99 1:09 PM Page 236
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

www.microstar.com
) and James Clark’s XP
(
www.jclark.com
) support only the SAX interface.
Getting Started with SAX
Listing 8.2 is a Java application that finds the cheapest price from the list
of prices in Listing 8.1. The application prints the best price as well as the
name of the vendor.
Listing 8.2: Simple SAX Application
/*
* XML By Example, chapter 8: SAX
*/
package com.psol.xbe;
import org.xml.sax.*;
import org.xml.sax.helpers.ParserFactory;
237
SAX: The Alternative API
EXAMPLE
continues
10 2429 CH08 11/12/99 1:09 PM Page 237
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
/**
* SAX event handler to find the cheapest offering
* in a list of prices.
* @author
*/
public class Cheapest
extends HandlerBase
{

if(min > price)
{
min = price;
vendor = attributes.getValue(“vendor”);
}
}
}
}
/**
* helper method: turn a string in a double
* @param string number as a string
* @return the number as a double, or 0.0 if it cannot convert
* the number
*/
protected double toDouble(String string)
{
Double stringDouble = Double.valueOf(string);
if(null != stringDouble)
return stringDouble.doubleValue();
else
return 0.0;
}
/**
* property accessor: vendor name
* @return the vendor with the cheapest offer so far
*/
public String getVendor()
{
return vendor;
}

// command-line arguments
if(args.length < 1)
{
System.out.println(“java com.psol.xbe.CheapestCL
➥filename”);
return;
}
// creates the event handler
Cheapest cheapest = new Cheapest();
// creates the parser
240
Chapter 8: Alternative API: SAX
Listing 8.2: continued
10 2429 CH08 11/12/99 1:09 PM Page 240
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Parser parser = ParserFactory.makeParser(PARSER_NAME);
parser.setDocumentHandler(cheapest);
// invokes the parser against the price list
parser.parse(args[0]);
// prints the results
System.out.println(“The cheapest offer is “ +
cheapest.getVendor() +
“ ($” + cheapest.getMinimum() + ‘)’);
}
}
Compiling the Example
To compile this application, you need a Java Development Kit (JDK) for
your platform. For this example, the Java Runtime is not enough. You can
download the JDK from
java.sun.com

The programs in this chapter do essentially no error checking. The programs minimize
errors; however, if you type parameters incorrectly, the programs can crash.
241
SAX: The Alternative API
10 2429 CH08 11/12/99 1:09 PM Page 241
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Running this program against the price list in Listing 8.1 gives the result:
The cheapest offer is XMLi ($699.0)
Note that the classpath points to the parser and to the classes directory.
The fully qualified name of the file is
com.psol.xbe.Cheapest
.
CAUTION
This example won’t work unless you have installed a Java Development Kit.
If there is an error message similar to
“Exception in thread “main”
java.lang.NoClassDefFoundError”
, it means that either the classpath is incorrect
(be sure it points to the right directories) or that you typed an incorrect class name
(
com.psol.xbe.Cheapest
).
SAX Interfaces and Objects
Events in SAX are defined as methods attached to specific Java interfaces.
An application implements some of these methods and registers as an
event-handler with the parser.
Main SAX Events
SAX groups its events in a few interfaces:

DocumentHandler

, a method of
Parser
:
parser.parse(args[0]);
242
Chapter 8: Alternative API: SAX
OUTPUT
EXAMPLE
10 2429 CH08 11/12/99 1:09 PM Page 242
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Parser
defines the following methods:

parse()
starts parsing an XML document. There are two versions of
parse()
—one accepts a filename or a URL, the other an
InputSource
object (see section “InputSource”).

setDocumentHandler()
,
setDTDHandler()
,
setEntityResolver()
, and
setErrorHandler()
allow the application to register event handlers.

setLocale()

other an
InputSource
. The string version uses the default
InputSource
to
load the document from a file or a URL.
DocumentHandler
Listing 8.2 is simple because it needs to handle only the
startElement
mes-
sage. As the name implies, the message is sent when the parser sees the
opening tag of an element.
The event is defined by the
DocumentHandler
interface. The application cre-
ates a new class,
Cheapest
, which overrides the
startElement()
method.
The application registers
Cheapest
as an event handler with the parser.
// creates the event handler
243
SAX Interfaces and Objects
EXAMPLE
EXAMPLE
10 2429 CH08 11/12/99 1:09 PM Page 243
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

characters()
/
ignorableWhitespace()
notify the application when the
parser finds content (text) in an element. The parser can break a
piece of text in several events or pass it all at once as it sees fit.
However, one event is always attached to a single element. The
ignorableWhitespace
event is used for ignorable spaces as defined
by the XML specs.

processingInstruction()
notifies the application of processing instruc-
tions.

setDocumentLocator()
passes a
Locator
object to the application; see
the section “Locator” that follows. Note that the SAX parser is not
required to supply a
Locator
, but if it does, it must fire this event
before any other event.
AttributeList
In the event, the application receives the element name and the list of
attributes in an
AttributeList
.
In this example, the application waits until a

event. As the name
implies, an
AttributeList
encapsulates a list of attributes. It defines the
following methods:

getLength()
returns the length of the attribute list.

getName(i)
returns the name of the ith attribute (where i is an integer).

getType(i)
/
getType(name)
return the type of the ith attribute or the
type of the attribute whose name is given. The first method accepts an
integer, the second a string. The type is a string, as used in the DTD:
“CDATA”
,
“ID”
,
“IDREF”
,
“IDREFS”
,
“NMTOKEN”
,
“NMTOKENS”
,


getLineNumber()
returns the line where the current event ends. In an
endElement
event, it would return the last line of the end tag.

getPublicId()
returns the public identifier for the current document
event.

getSystemId()
returns the system identifier for the current document
event.
245
SAX Interfaces and Objects
10 2429 CH08 11/12/99 1:09 PM Page 245
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
DTDHandler
DTDHandler
declares two events related to parsing the DTD:

notationDecl()
notifies the application that a notation has been
declared.

unparsedEntityDecl()
notifies the application that an unparsed entity
declaration has been found.
EntityResolver
✔ The EntityResolver interface defines only one event, resolveEntity(). The

SAXException
.
A
SAXException
signals an error while parsing the XML document.
The error can either be a parsing error or an error in an event handler. To
report errors from the event handler, it is possible to wrap exceptions in
SAXException
.
246
Chapter 8: Alternative API: SAX
10 2429 CH08 11/12/99 1:09 PM Page 246
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Suppose an event handler catches an
IndexOutOfBoundsException
while
processing the
startElement
event. The event handler wraps the
IndexOutOfBoundsException
in a
SAXException
:
public void startElement(String name,AttributeList attributes)
{
try
{
// the code may throw an IndexOutOfBoundsException
}
catch(IndexOutOfBounds e)

If the user waits longer, he or she might get a better price. Figure 8.6 illus-
trates the structure of the document.
247
Maintaining the State
EXAMPLE
EXAMPLE
10 2429 CH08 11/12/99 1:09 PM Page 247
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Figure 8.6: Price list structure
Listing 8.3: Price List with Delivery Information
<?xml version=”1.0”?>
<product>
<name>XML Training</name>
<vendor>
<name>Playfield Training</name>
<price delivery=”5”>999.00</price>
<price delivery=”15”>899.00</price>
</vendor>
<vendor>
<name>XMLi</name>
<price delivery=”3”>2999.00</price>
<price delivery=”30”>1499.00</price>
<price delivery=”45”>699.00</price>
</vendor>
<vendor>
<name>WriteIT</name>
<price delivery=”5”>799.00</price>
<price delivery=”15”>899.00</price>
</vendor>
<vendor>

*/
public class BestDeal
{
/**
* the parser class (IBM’s XML for Java)
*/
private static final String
PARSER_NAME = “com.ibm.xml.parsers.SAXParser”;
/**
* main() method
* decodes command-line parameters and invokes the parser
* @param args command-line argument
* @throw Exception catch-all for underlying exceptions
*/
public static void main(String[] args)
throws Exception
{
249
Maintaining the State
continues
10 2429 CH08 11/12/99 1:09 PM Page 249
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
if(args.length < 2)
{
System.out.println(“java com.psol.xbe.BestDeal filename delivery”);
return;
}
ComparingMachine comparingMachine =
new ComparingMachine(Integer.parseInt(args[1]));
SAX2Internal sax2Internal =

/**
* This class receives events from the SAX2Internal adapter
* and does the comparison required.
* This class holds the “business logic.”
*/
class ComparingMachine
{
/**
* properties we are collecting: best price
*/
protected double bestPrice = Double.MAX_VALUE;
/**
* properties we are collecting: delivery time
*/
protected int proposedDelivery = Integer.MAX_VALUE;
/**
* properties we are collecting: product and vendor names
*/
protected String productName = null,
vendorName = null;
/**
* target delivery value (we refuse elements above this target)
*/
protected int targetDelivery;
/**
* creates a ComparingMachine
* @param td the target for delivery
*/
public ComparingMachine(int td)
{

}
}
}
/**
* property accessor: vendor’s name
* @return the vendor with the cheapest offer so far
*/
public String getVendor()
{
return vendorName;
}
252
Chapter 8: Alternative API: SAX
Listing 8.4: continued
10 2429 CH08 11/12/99 1:09 PM Page 252
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
/**
* property accessor: best price
* @return the best price so far
*/
public double getPrice()
{
return bestPrice;
}
/**
* property accessor: proposed delivery
* @return the proposed delivery time
*/
public int getDelivery()
{

VENDOR_NAME = 4,
VENDOR_PRICE = 5;
/**
* the current state
*/
protected int state = START;
/**
* current leaf element and current vendor
*/
protected LeafElement currentElement = null,
currentVendor = null;
/**
* BestDeal object this event handler interfaces with
*/
protected ComparingMachine comparingMachine;
/**
* creates a SAX2Internal
* @param cm the ComparingMachine to interface with
*/
public SAX2Internal(ComparingMachine cm)
{
comparingMachine = cm;
}
/**
* startElement event
* @param name element’s name
254
Chapter 8: Alternative API: SAX
Listing 8.4: continued
10 2429 CH08 11/12/99 1:09 PM Page 254


Nhờ tải bản gốc
Music ♫

Copyright: Tài liệu đại học © DMCA.com Protection Status