2008年7月2日星期三

XML_010:JAXP介绍(摘录+整理)

前一篇讲了很多有关XML的概念,对于开发人员来说肯定更关心如何使用XML。对于Java开发人员来说,答案不言自明:就是JAXP。
【JAXP】:Java API for XML Processing。
“The Java API for XML Processing, or JAXP for short, enables applications to parse and transform XML documents using an API that is independent of a particular XML processor implementation. JAXP also provides a pluggability feature which enables applications to easily switch between particular XML processor implementations.”(英文定义来自
https://jaxp.dev.java.net/1.4/index.html
这里不再翻译,相信大家都看得懂。简明扼要的说:“JAXP is an abstract layer over an XSLT processor and an XML parser.”
JAXP1.3.x已经被包含在J2SE 5.0中,目前JAXP最新版本是1.4.2,被包含在J2SE 6.0中。更多信息请访问:
https://jaxp.dev.java.net/1.4/index.html

有一个事实必须首先明确:JAXP 本身不提供语法分析功能!语法分析功能是由语法分析器供应商提供的,如DOM4J。
那为何还要使用JAXP?——因为它能以一种独立于语法分析器供应商的方式处理XML。
JAXP主要依赖的API有:DOM和SAX 。

【DOM】:Document Object Model,文档对象模型。
DOM是处理XML文档的标准编程接口。由W3C制定,更多信息请访问:
http://www.w3.org/DOM/
DOM 是以层次结构组织起来的节点,或信息片段的集合。开发者可以“基于树”的方式来查找或修改信息。需要注意的是,浏览之前,内存需要装入整个“树结构”文档。

【SAX】:Simple API for XML。
由于DOM需要读取整个文件并将它存储到“树结构”中,因而效率不高并且消耗资源。SAX提供一个“基于事件”的机制:允许正在读取文档时处理该文档从XML文件读取资料,从而避免了在采取操作之前需要等待装入整个文档的所有内容。SAX的缺点是由于SAX不存储数据,所以无法对数据进行更改,或者“返回”数据流中前面的数据。注意,没有类似W3C的官方组织维护SAX的标准,SAX的标准由XML社区维护,更多信息请访问:
http://www.saxproject.org/
以下面这个XML为例,让我们看看DOM和SAX是如何解析的。

<?xml version="1.0"?>
<samples>
<server>UNIX</server>
<monitor>color</monitor>
</samples>


DOM 解析器将生成一个“树结构”装入内存中。矩形框表示元素节点,椭圆形表示文本节点。

SAX 解析器将生成以下事件:
Start document
Start element (samples)
Characters (white space)
Start element (server)
Characters (UNIX)
End element (server)
Characters (white space)
Start element (monitor)
Characters (color)
End element (monitor)
Characters (white space)
End element (samples)

问题1:何时选择DOM?
1. 需要对数据本身修改(不是光修改结构,如果是那样可以使用XSLT)。
2. 需要作为XML输出。

问题2:何时选择
SAX?1. 大文件。
2. 如果只使用一小部分数据,使用SAX 将数据抽取出来再处理。注意,处理中如果需要引用已经处理过的信息,SAX无法完成。
3. 性能要求高。

问题3:能否同时使用DOM和SAX?
当然可以。可以使用DOM 来创建事件的SAX 流,可以使用SAX来创建DOM树。事实上,大多数解析器实际常常使用SAX来创建DOM 树!

问题4:如何让我写的代码独立于不同的Parser供应商(不用修改代码)?
1. 更改Parser供应商际意味着更改类工厂,因为所有SAXParser 和DocumentBuilder 实例都来自这些类工厂。通过设置Java 系统属性可以更改类工厂的实现,比如:
javax.xml.parsers.DocumentBuilderFactory=com.foo.ConcreteDocumentBuilder
javax.xml.parsers.SAXParserFactory=com.foo.ConcreteSAXParser
javax.xml.transform.TranformerFactory=com.foo.ConcreteTransformer
2. 如果系统属性中没有指定,JAXP将会在JRE的目录中查找lib/jaxp.properties属性文件。
3. 如果jaxp.properties不存在或者没有相应的值,那么JAXP将会使用JAR文件的服务提供体制来定位正确的子类。简单地说,你可以在jar文件的META-INF/services目录下新建一个名为javax.xml.transform.TransformerFactory的文件,这个文件中只有一行:com.foo.ConcreteTransformer就可以了。
4. 如果上面3步都没有找到任何具体的实现,JAXP将使用缺省的实现。具体来说,在J2SE 1.4中使用的是Crimson + Xalan-J, 在J2SE 1.5中使用的是Xerxes 2.7 + XSLT,详细信息请参考:
https://jaxp.dev.java.net/1.4/JAXP-FAQ.html

参考文献:
1. JAXP官方网站:
https://jaxp.dev.java.net/1.4/index.html
2. 《JAXP 专述》 作者:
http://www-128.ibm.com/developerworks/cn/xml/jaxp/index.html
3. 《理解 DOM》 作者:
http://www.ibm.com/developerworks/cn/views/xml/tutorials.jsp?cv_doc_id=84890
3. 《理解 SAX》 作者:
http://www.ibm.com/developerworks/cn/views/xml/tutorials.jsp?cv_doc_id=84979

没有评论: