接着,我们就来以“暴力“区分标签名的办法把数据映射到不同的对象:
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import java.io.*;
import java.util.*;
import common.*;
public class Example5 extends DefaultHandler {
// 借肋用于捕获某个标签内容的标志。
private boolean inCircle = false;
private boolean inTriangle = false;
private boolean inSquare = false;
// 不同形体的本地向量表...
private Vector triangles = new Vector();
private Vector squares = new Vector();
private Vector circles = new Vector();
// 当前形体的本地引用...
private Triangle currentTriangle;
private Circle currentCircle;
private Square currentSquare;
// 从"characters" SAX事件中收集数据的缓存。
private CharArrayWriter contents = new CharArrayWriter();
// 重载DefaultHandler类以拦截SAX事件的方法。
//
// 头于所有有效事件的详细内容,参见org.xml.sax.ContentHandler。
//
public void startElement( String namespaceURI,
String localName,
String qName,
Attributes attr ) throws SAXException {
contents.reset();
if ( localName.equals( "Circle" ) ) {
inCircle = true;
currentCircle = new Circle();
currentCircle.name = attr.getValue( "name" );
circles.addElement( currentCircle );
}
if ( localName.equals( "Square" ) ) {
inSquare = true;
currentSquare = new Square();
currentSquare.name = attr.getValue( "name" );
squares.addElement( currentSquare );
}
if ( localName.equals( "Triangle" ) ) {
inTriangle = true;
currentTriangle = new Triangle();
currentTriangle.name = attr.getValue( "name" );
triangles.addElement( currentTriangle );
}
}
public void endElement( String namespaceURI,
String localName,
String qName ) throws SAXException {
if ( localName.equals( "x" ) ) {
if ( inCircle ) {
currentCircle.x =
Integer.valueOf
(contents.toString().trim()).intValue();
}
else if ( inSquare ) {
currentSquare.x =
Integer.valueOf
(contents.toString().trim()).intValue();
}
else {
currentTriangle.x =
Integer.valueOf
(contents.toString().trim()).intValue();
}
}
if ( localName.equals( "y" ) ) {
if ( inCircle ) {
currentCircle.y =
Integer.valueOf
(contents.toString().trim()).intValue();
}
else if ( inSquare ) {
currentSquare.y =
Integer.valueOf
(contents.toString().trim()).intValue();
}
else {
currentTriangle.y =
Integer.valueOf
(contents.toString().trim()).intValue();
}
}
if ( localName.equals( "width" ) ) {
if ( inCircle ) {
currentCircle.width =
Integer.valueOf
(contents.toString().trim()).intValue();
}
else if ( inSquare ) {
currentSquare.width =
Integer.valueOf
(contents.toString().trim()).intValue();
}
else {
currentTriangle.width =
Integer.valueOf
(contents.toString().trim()).intValue();
}
}
if ( localName.equals( "height" ) ) {
if ( inCircle ) {
currentCircle.height =
Integer.valueOf
(contents.toString().trim()).intValue();
}
else if ( inSquare ) {
currentSquare.height =
Integer.valueOf
(contents.toString().trim()).intValue();
}
else {
currentTriangle.height =
Integer.valueOf
(contents.toString().trim()).intValue();
}
}
if ( localName.equals( "Circle" ) ) {
inCircle = false;
}
if ( localName.equals( "Square" ) ) {
inSquare = false;
}
if ( localName.equals( "Triangle" ) ) {
inTriangle = false;
}
}
public void characters( char[] ch, int start, int length )
throws SAXException {
// 将数据内容写入缓存。
contents.write( ch, start, length );
}
public Vector getCircles() {
return circles;
}
public Vector getSquares() {
return squares;
}
public Vector getTriangles() {
return triangles;
}
public static void main( String[] argv ){
System.out.println( "Example5:" );
try {
// 创建SAX 2解析器...
XMLReader xr = XMLReaderFactory.createXMLReader();
// 安装ContentHandler...
Example5 ex5 = new Example5();
xr.setContentHandler( ex5 );
// 解析文件...
xr.parse( new InputSource(
new FileReader( "Example5.xml" )) );
// 将圆形对象显示到标准输出...
Circle c;
Vector items = ex5.getCircles();
Enumeration e = items.elements();
while( e.hasMoreElements()){
c = (Circle) e.nextElement();
c.print( System.out );
}
// 将长方形对象显示到标准输出...
Square s;
items = ex5.getSquares();
e = items.elements();
while( e.hasMoreElements()){
s = (Square) e.nextElement();
s.print( System.out );
}
// 将三角形对象显示到标准输出...
Triangle t;
items = ex5.getTriangles();
e = items.elements();
while( e.hasMoreElements()){
t = (Triangle) e.nextElement();
t.print( System.out );
}
}catch ( Exception e ) {
e.printStackTrace();
}
}
}
下面是我们收集到我们的形体类中的数据对应的输出:
Example5:
Circle: circ1 x: 10 y: 10 width: 3 height: 3
Square: sq1 x: 0 y: 0 width: 3 height: 3
Triange: tri1 x: 3 y: 0 width: 5 height: 3
Triange: tri2 x: 5 y: 0 width: 5 height: 3
第二个方案利用了你可以在运行时替换SAX 解析器的SAX Content这一点。这就允许我们将映射任务分解成一个个小模块。我们可以把映射代码实现到某一XML文档的特定片段。
第二个例子中的endElement()没有用到嵌套的if语句。这种模块化的设计在处理更加复杂的XML文档时尤其有效。这种方式同时也解决了XML文档中不可预测地出现的重复标签。
虽然第二个办法因为大多数类定义的重复出现而略显臃肿,这种更换ContentHandler类的方法却是走向一种更一般的SAX解析方法的第一步。替换ContentHandler也是另一个在SAX解析器的龙头下轮换啤酒杯(译注:Robert极可能是个大肚皮形象:-))的方法。