介绍XML及其解析方式

XML

什么是XML?

XML(Extensible Markup Language)是一种标记语言,它定义了一组规则用于编码文档,既是机器可读也是人可读。

  • XML是为描述数据而开发的。
  • XML没有预定义标签。你需要根据需要自定义标签。
  • XML具有自我描述性。
  • XML不是HTML的替代品。
1
2
3
4
5
<Message>
<From>lilei</From>
<To>hanmeimei</To>
<Content>how are you?</Content>
</Message>

XML与HTML的差别

关键不同点:HTML是用于设计网页的标记语言。HTML中的标签是预定义的。HTML的主要设计目的为显示数据,焦点在于数据的外观。XML是以传输和储存数据为主要目的设计的标记语言,焦点在于数据的内容。它可以用于开发新的语言和定义其他新的语言。XML并没有一组预定义的标签,而是让开发者自行定义标签。

HTML XML
定义 用于在浏览器中显示网页的标记语言。设计用于显示数据,焦点在于数据的外观。 为编码文档定义了一组规则使机器和人都可阅读的标记语言。设计用于传输和储存数据,焦点在于数据的内容。
正式提出日期 1993 1996
扩展于 SGML SGML
类型 静态 动态
用途 显示网页 为应用和服务器传输数据。开发其他标记语言。
解析/规则 没有严格的规则。浏览器会全力生成数据。 必须遵循其规则否则将会终止解析文件
语言类型 描述语言 既不是描述语言也不是程序语言
标签 预定义标签 可以自行定义标签
空格 不会保存空格 保存空格

XML的解析方式

一般来说,有两种用来处理XML的编程模型:StreamingDocument Object Model(DOM)。其中Streaming又细分为两种解析方式:PushPull

Document Object Model(DOM)是指W3C的XML DOM。W3C的DOM分3个部分,其中一个是XML DOM,本文中的DOM如没有特别说明都是指XML DOM。

Streaming Push解析方式的最出名的是Simple API for XML(SAX),基本上排除了Java中其他的Push类型的API。Pull解析方式的标准则是Streaming API for XML(StAX),不过由于Android采用了XmlPull,所以也会介绍下。

DOM介绍

DOM由W3C定义。

DOM的API十分容易上手,采用基于树的数据结构描述对象。DOM会将解析XML文档生成的树状对象储存在内存中,所以可以随意访问、修改。但是代价是对处理器和内存的要求较高,因为树状对象在解析时会一直储存在内存中。

SAX介绍

SAX由XML-DEV邮件列表的成员合作开发。

SAX基于事件驱动的,采用顺序访问机制进行解析。

基于事件驱动是指解析器通过回调方法将事件(如element的start和end)发送给应用,由开发者自己去实现回调方法进行相关数据的处理。由于采用顺序访问机制,所以SAX不会将数据储存在内存中,也因为如此SAX不能退到之前解析过的位置,也不能随意跳到另一个位置。

之前说了SAX是Push类型的API,这种类型的API解析XML时通过回调方法通知应用感兴趣的事件。事件的请求不是由应用控制而是由解析器控制。

SAX的使用要比DOM复杂一些,由于基于事件驱动,开发者需要实现回调方法提供给解析器调用。

XmlPull介绍

XmlPull API由kXML的作者Stefan Haustein和XPP的作者Aleksander Slominski一起创作,它是为了减少在J2ME环境中处理XML时所占的内存而创作的,这让它并不适合桌面环境或服务端环境。

虽然SAX与XmlPull都是Streaming编程模型的API,但因为它们在事件产生的控制上有所区别,所以将它们分为Push类型和Pull类型。

Streaming Push解析是指XML解析器遇到一个元素就将其发送给程序,这意味着不论程序有没有准备接收解析器都会发送数据,即程序不能控制事件的产生。

Streaming Pull解析是指当程序需要与XML文档进行交互时程序才会调用XML解析器的方法,这意味着只有当程序请求数据时才会获取XML数据,即程序可以控制事件的产生。

SAX属于Push类型,XmlPull属于Pull类型。

它们的主要不同就在于这一点,这使得XmlPull的API相对简单。

StAX介绍

StAX由BEA System、Sun、XmlPull的开发者Stefan Haustein和Aleksandr Slominski、XML重量级人物James Clark以及Java Community Process的开发者共同开发。

StAX是Streaming Pull类型的解析器,它避免了XmlPull中存在的大部分问题。

StAX不只可以读取XML文档,它还可以创建XML文档。

在Pull类型的API中还可以分出两种类型:基于光标类型和基于迭代器。StAX为两种模型都建立了API:StAX光标模型和StAX迭代器模型,开发者可以根据需求选择使用。

StAX光标模型和迭代器模型的区别可以看看Java EE 5的教程最后一节。

四种API的区别

Streaming VS DOM

两者之间的主要区别在于XML数据是否储存在内存中。

DOM会将XML数据转换成树状结构对象后储存在内存中,因此能随意访问、修改XML结构。不过代价是需要等其将数据读取转换完后才能进行操作,且对cpu和内存的需求会随着XML文档的增加而增加。

Streaming模型的API不会将XML数据储存在内存中,且读取数据采用顺序访问机制,因此只能往前访问数据,也因为这样性能比DOM更好,且由于采用Streaming模型的原因能在读取数据的同时进行操作。

Pull VS Push

两者之间的主要区别在于读取XML数据时产生的事件由谁控制。

Push会从头到尾读取一次XML数据,将里面的事件一股脑通过回调方法传递给程序,由程序去处理感兴趣的事件。所以Push类型无法中途停止XML数据的读取。

Pull是由程序控制事件的产生,当程序需要数据时,调用next()方法来获取下一个事件。所以Pull类型可以在处理完数据后停止继续读取XML数。

XmlPull VS StAX

XmlPull存在两个主要的缺陷:

1.它给XML建模不对

XmlPull默认不支持名字空间,需要调用setNamespaceAware(true)手动开启,并且不会报告内部DTD子集中的错误。

2.它并不是面向对象的

XmlPull定义了一系列Int类型的数据来判断节点的类型,而不是类。

而StAX是在XmlPull的基础上创建的,因此StAX避免了XmlPull中出现的大部分问题。

尽管如此存在一些问题,在进行嵌入式或移动设备上的开发时,XmlPull还是不错的。

参考资源