XML那点事儿
一. XML简介
XML(Extensible Markup Language,可扩展标记语言)是一个用于构造其他语言的元语言。XML描述了创造这些语言的规则,每种语言都互不相同,但都使用标签来标记内容。XML定义的语言的一个例子是XHTML,相当于是XML的词汇。目前,XML已经成为一种通用的数据交换格式,是一种用于描述结构化信息的技术,它具有平台无关性,语言无关性,系统无关性,为数据交换带来了极大的便利。
1.1 XML文档结构图
DTD和schema包含了用于解释文档是如何构成的规则,通过DTD或schema可以定义XML词汇。这些规则定义了每个元素的子元素和属性。可以根据DTD或schema来验证一个文档是否是合法的。由于DTD和schema内容比较多,这里不做详细介绍。
(1) DTD Document Type Defination
DTD描述的是文档的结构,它指明一个元素可以出现多少次、是否可选以及它是否包含属性等,这样就定义了一个文档的类型。可以直接将DTD写入一个XML文件,或DTD为一个独立的文件,然后在XML文件中通过文档声明对其引用。
(2) schema
schema也用于定义XML文档的结构,但它的功能更强,结构也更复杂。schema也是XML词汇的一种,完全符合XML的规则。
可以通过CSS或XSL将XML的内容可视化地展现出来,这样就可以显示在Web浏览器或者打印出来。CSS可以按照应用于XHTML的方式应用于XML,但是XML中引入CSS的方法只有一种:就是通过处理指令将样式表关联到XML文档中,
<?xml-stylesheet type="text/css" href="style.css"?>
CSS有一个缺点就是它是按照元素在XML文档中出现的顺序来呈现他们,不能够对它们进行排序,过滤。CSS大家比较熟悉,这里不做深入探讨。下面将介绍一下XSL,另一种功能更强大的显示XML的技术。
XSL(Extensible Sheet Language, 可扩展样式表语言)分为两 部分:XSLT(XSL转换)和XSL-FO(XSL格式对象)。XSLT将XML源文档转换为另一个XML文档(结果树)。XSL-FO为结果树添加格式。因为XHTML是XML的一个词汇(XML定义的语言),所以XSLT可以将XML转换为XHTML,并XHTML添加样式表,然后显示在Web浏览器中,从而实现XML的显示。
下面的例子,将实现XML文档转换为XHTML然后在Web浏览器中显示
XML文档为:DVD.xml
XSL样式表
用浏览器打开XML文件会看到使用样式后的效果。
XPATH用于定位XML文档的特定部分,可以通过XPATH表达式得到一个单独的节点,一组节点等等,从而避免遍历DOM树节点进行查找。XPATH将XML文档看作是由节点构成的层次树,每棵树包括元素节点、属性节点、文本节点、处理指令、注释和命名空间,通过相应的路径来定位相应的节点。根节点是XML文档树的起始点,一个XML文档就是根节点,"/"代表根节点。下面以DVD.xml为例,接单介绍一下XPATH的使用。
(1) /library/DVD
定位library的所有DVD子元素,得到一组节点
(2) /library/DVD[2]
定位library的第2个DVD子元素,得到一个节点
(3) /library/DVD/@id
得到所有DVD的id属性
(4) /library/DVD[2]/@id
得到第2个DVD的id属性
(5) /library/DVD[genre='Comedy']
过滤条件,定位genre等于Comedy的DVD
(6) count(/library/DVD)
得到DVD的数量
JDK5.0中增加了API来处理XPATH,下面例子是通过XPATH来查询DVD.xml
二. XML处理模型
应用程序需要通过XML处理程序从XML文档中提取信息。XML处理程序通常被称为XML解析器。
XML有两种处理模式:基于树和基于事件。基于树的解析器通常称为DOM(Document Object Model,文档对象模型)解析器,而基于事件的解析器通常称为SAX(Simple API for XML,XML简单应用编程接口)解析器。DOM是W3C推荐的标准,允许通过编程语言或脚本语言(JavaScript)访问这些元素以及它们的值。SAX是以一串事件的形式展现XML文档,必须为每个事件(比如,开始或是结束某个元素)编写 处理程序,当事件触发处理程序会产生相应的结果,由于SAX是以事件处理机制为基础的,所以在有良好事件处理机制的语言中很实用。
(1). DOM提供了对整个XML文档的完整的读写访问,并且可以通过遍历文档树对文档内的节点进行访问。基于DOM的解析会将整个XML读入内存,在内存中构造整棵XML树,所以当遇到较大XML文档时,DOM解析会变慢。
(2). SAX是串行操作的,一个节点被处理后就被丢弃了,并且不会再被处理。整个文档不是一次性读入内存,从而避免了较大XML文档引起的处理问题。如果只是对某些节点感兴趣,而不关心其上下文,这种情况应该用SAX(例如,网络爬虫只关心<a>标签所以适合用SAX解析)。但是,SAX模型不会记录已经丢弃的节点的信息,所以必须由开发人员自己来维护XML文档中的可供后续使用的信息。从而SAX使用起来比较繁琐。
DOM提供了对XML的读写,XPATH查询,文档验证等功能,SAX只是提供简单的解析功能。SAX和DOM属于操作XML文档较低层的类库,目前已有很多类库实现了这两种方式,并对其进行封装,使用户用起来更加方便。比如Dom4J,JDom等。下文将对Dom4J进行介绍。
三. SAX
SAX解析器在解析XML文件时,如果遇到XML构件(例如:标签)就会触发相应的事件,但它不会以任何方式存储文档,由事件处理程序决定是否建立数据结构存储信息。实际上,DOM解析器是建立在SAX解析器的基础之上的,在读入XML信息时接受相应的时间然后建立DOM树。
在使用SAX解析器时,需要建立一个事件处理器来处理不同事件。ContentHandler接口定义了多个回调方法来处理相应的事件,其中比较重要的方法有:
startDocument() 在文档开始时调用
endDocument() 在文档结束时调用
startElement(String uri, String localName, String qName, Attributes attributes) 在元素开始时调用
endElement(String uri, String localName, String qName) 在元素结束时调用
characters(char[] ch, int start, int length) 每当遇到字符数据时调用
处理器必须覆盖这些方法,完成在解析文件时要执行的动作。
这里给出示例程序,打印一个XHTML文件中的所有<a href=...>元素:
四. DOM
DOM(Document Object Model, 文档对象模型)解析器将读入的XML文档转化为树结构。DOM解析器的接口已经被W3C标准化,org.w3c.dom包中包含了所有的接口,例如:Document和Element等。Document对象是文档树在内存中的表现,可以通过它访问该树的节点,它由实现Node接口及其多个子接口的对象构成。接口Node的层次结构如下:
下面例子是通过DOM操作DVD.xml显示详细信息:
五. Dom4J
Dom4J对SAX和DOM进行了封装,使其用起来更加方便。