曝光台 注意防骗
网曝天猫店富美金盛家居专营店坑蒙拐骗欺诈消费者
独立的程序。下面首先给出要解析的文件:
程序清单6 - 5
第6章SAX 1.0: XML简易API使用151 下载
注意parse( )的参数是一个U R L字符串。稍后会给出如何用一个文件名代替U R L。因为程序
涉及到数据的输入和输出,所以必须添加“ throws Exception”到countBooks( )方法以使发生错
误时发出警告。
还需要添加Java main( ) 方法以使程序成为一个独立的应用程序。在m a i n方法中用n e w
BookCounter( )创建类的一个实例,然后调用对象的countBooks( )方法;同时对新建对象进行全
程跟踪。代码如下所示:
程序清单6 - 6
现在程序可以运行了:解析文档直至运行结束(当然假设存在要被解析的文档)。
唯一的不足是程序现在没有产生输出。为使程序更有用,需要添加一个方法对出现的
< b o o k >开始标签进行计数,另外添加方法在文档末尾输出书的统计数目。这些方法使用了全局
变量c o u n t。
应用程序的最后版本如下所示。可以在我们的站点h t t p : / / w w w. w r o x . c o m /上关于本书的专栏
里找到本章中的代码。
程序清单6 - 7
152使用XML 高级编程
下载
现在可以通过下列形式的命令从命令行运行应用程序:
程序会输出给出的X M L文件中< b o o k >元素的数目。假设c : \ d a t a \ b o o k s . x m l文件中包含下列文
件(可以从h t t p : / / w w w. w r o x . c o m下载获取本章中的代码):
程序清单6 - 8
这样在终端会显示下列输出:
第6章SAX 1.0: XML简易API使用153 下载
3. DocumentHandler接口
如上面的例子所示,一个S A X应用程序的主要工作是在实现D o c u m e n t H a n d l e r接口的类里完
成的。通常我们会对比上面简单例子包含的更多的事件感兴趣,因此让我们看一下构成接口的
其他方法。
(1) 文档事件
首先,有一对方法标记文档处理的开始与结束:
• startDocument( )
• endDocument( )
这两个方法没有参数和返回值。实际上,你通常可以不使用它们,因为程序开始进行的操
作一般可以在调用parse( )之前完成,而程序结束时要做的操作可以在parse( )返回值时完成。但
是在一个更复杂的应用程序中,你可能希望调用parse( )的应用程序是从D o c u m e n t H a n d l e r派生的
一不同的类,在此种情况下,这两个方法有助于初始化变量和最后回收变量资源。
注意一个S A X解析器(P a r s e r类的一个简单实例)应该同时只能解析一个X M L文档。一旦它
完成了解析,可以再使用它解析其他文档。如果你想同时解析几个文档,就需要为每个文档创
建一个P a r s e r类的实例。你肯定想把这种文档实例一一对应的规则应用到D o c u m e n t H a n d l e r,因
为在告知事件来源于哪个文档的事件信息中也没有进行什么其他操作。
(2) 元素事件
与文档事件一样,有一对可调用的方法用来标记文档中每个元素的开始和结束标签:
• startElement(String name,AttributeList attList)
• endElement(String name)
n a m e是指在元素开始和结束标签中出现的名称。
如果文档对一个空元素使用简短语法表示(即“ < t a g / >”),解析器将完全按你书写
“< t a g > < / t a g >”的方式通报开始和结束标签。这是因为X M L定义这两个结构是同等的,所以应
用程序不需要知道使用的是哪一个。
在开始标签里出现的属性捆绑在一起成为A t t r i b u t e L i s t对象,同时立刻被应用程序处理。基
于事件的模式即始于此,你可能希望每个属性在出现时都发出通报。A t t r i b u t e L i s t是S A X定义的
另一个接口。类似于解析器,它定义了一个实现接口的类:应用程序需要知道的是它为了获取
各个属性详细信息时可以调用的方法。其中最有用的一个是:
• getValue(String name)
该方法在属性存在时以字符串形式返回命名属性的值,否则返回空。
关于A t t r i b u t e L i s t需要注意的是它仅在startElement( )方法的生命周期中有效。一旦该方法将
控制权返回给解析器,它可能(并且经常会)用不同的信息覆盖A t t r i b u t e L i s t。如果想保留属性
信息以备后用,你需要做一个副本。一种简便的方式是使用S A X“h e l p e r”类A t t r i b u t e L i s t I m p l:
可以让你创建另一个A t t r i b u t e L i s t作为已给出A t t r i b u t e L i s t的私有副本。
(3) 字符数据
X M L文档中出现的字符数据一般通过下面的方法报告给应用程序:
• characters(char[] chars, int start, int len)
154使用XML 高级编程
下载
定义这种接口更多的是为了效率而不是方便。如果想把字符数据作为S t r i n g处理,你可以简
单地构造一个字符串:
解析器可能已经创建了S t r i n g结构,但是在J a v a中创建新的对象是需要占用大量资源的,所
以它只给出指向字符存放位置的指针。
使用J a v a处理X M L的一个优点是J a v a和X M L都是采用统一码标准字符集。不管开始的源文
档中使用哪种字符编码方式,以c h a r s数组形式传递的字符始终是本地化的J a v a统一码字符。
重要的一点是解析器可以任意分解字符数据,也可以同时只传送一部分。这就是说如果你
想在文档中查找“g o l d”,那么下面的代码就有错误:
程序清单6 - 9
为什么呢?因为可能文档中出现了“ g o l d”字符串,但是是通过两次或更多次characters( )
方法调用来告知应用程序。理论上,可能会有四个调用,分别对应“ g ” , “ o ” 和, “ “l d” ”。
问题的最坏情况是在测试中你可能没有发现这种问题,因为实际上解析器很少用这种方式
分解文本。例如,它们可能仅当文本恰好处于一个4 0 9 6字节边界时才分解文本(同时如果内存
中国航空网 www.aero.cn
航空翻译 www.aviation.cn
本文链接地址:
XML高级编程上(59)