浅出Java 的Xml编程
作者:何双江(yarshray)
对于Xml,我的认识是,一个用来存放数据的标准格式.怎么看我都觉得XML和Html,完全不一样,也许仅仅只是都使用了标记来作为文档解释的原因吧.所以人们才喜欢把XML和HTML对比来看.对于我个人而言,XML就是一个简单方便的数据文件.因为.它不同与一般的关系型数据库,把数据看出二维表.通过基本的关系运算,获取二维表中的数据.XML仅仅把数据当成一个文档,然后正对文档解析获取数据.所以我的看法是,要操作XML文档,只要一个能够解释XML的文档解释器就可以了.然后把解释的内容.转变成程序所需要的数据就可以了.当操作完毕也可以把数据写回去.因此,这里主要介绍两中XML文档解释器,和java相关的Api.它们分别是DOM和SAX.及JDOM.
为了方便起见,我们需要一个简单的XML作为本文的示例参考:这个XML的主要目的是为了存放我的书籍信息.包括书名,书的作者,书的价格,书的编号.几个基本信息,
XML示例如下:
<?xml version="1.0" encoding="gb2312"?>
<Books>
<Book id="1">
<bookName>
编程珠玑
</bookName>
<bookAuthor>
Jon Bentley
</bookAuthor>
<bookISBN>
7-5083-1914-1
</bookISBN>
<bookPrice>
28.0
</bookPrice>
</Book>
<Book id="2">
<bookName>
Java编程思想(第2版)
</bookName>
<bookAuthor>
Bruce Eckel
</bookAuthor>
<bookISBN>
7-111-10441-2
</bookISBN>
<bookPrice>
99.0
</bookPrice>
</Book>
<Book id="3">
<bookName>
Inside VCL(深入核心VCL架构剖析)
</bookName>
<bookAuthor>
李维
</bookAuthor>
<bookISBN>
7-5053-9489-4
</bookISBN>
<bookPrice>
80.0
</bookPrice>
</Book>
</Books>
该XML记录了三本书和其相关的信息.
大体上操作XML文档可以分为三个步骤.
1.创建XML解释器
2.通过XML解释器和XML文件建立关联
3.通过XML解释器解释XML标记
XML解释器的类型.基本上可以分为:
? 验证和非验证解析器
? 支持一种或多种 XML Schema 语言的解析器
? 支持 Document Object Model (DOM) 的解析器
? 支持 Simple API for XML (SAX) 的解析器
这里主要介绍后两种.解释器.
Document Object Model(DOM)解释器:
Dom解释器是由W3C官方制定的标准解释器Api.只要符合该标准的编程接口都可以用来操作XML.目前该解释器主要有三个级别.Level1 Level2 Level3 这里只讨论到Level2.Dom模型实际上是把XML文件中的数据转变成了内存中的一颗树.该树大体有Doument Note NodeList Element这些对象构成.而Dom则是负责分析这颗树的结构,然后通过解释树从而起到了解释XML文档的作用.这里值得注意的是由于操作的树型结构.所以对于有些情况该解释器是无法分清楚的.例如属性值:
Id="1"
Id=
"1"
Id='1'
这对于Dom而言是完全相同的.因为.对于文档的格式Dom并不做任何解释.它仅是把文档中的数据转变成一颗树而已,原有的文档格式并不DOM中出现.
Simple API for XML (SAX) 的解析器
SAX解释器,可以说是一个把具体操作留给编程人员而把解释工作留给自己的一个编程模型.它并没有向DOM那样把整个XML文档加载到内存而是逐行解释然后通过事件通知给程序,由具体的程序使用这些通知,然后加以处理,这里就好像编写事件驱动的代码一样.因而就内存的占用率和解释效率而言SAX是有其适用性的.对于具体环境DOM和SAX都有其具体的应用面.
SAX的事件主要包括
文档的开始startDocument事件
对于元素而言的startElement和endElement
对于处理字符文本的characters 事件
以及文档的结束endDocment事件
JDOM API
DOM和SAX虽然提供了非常丰富的功能.可是对于开发人员而言这同时也带来巨大的负担.因为太过复杂,因此开源社区推出了的Jason Hunter 和 Brett McLaughlin 两位JAVA专家推出了JDOM作为一个比较简单的API.JDOM在背后会提供适配器选择具体的XML解释器.同样它也提供了树型结构来处理XML,而JDOM的树更简介.因此它兼顾了DOM和SAX的有点.当然也降低了灵活性.因此如果单纯的使用JDOM也是一个不错的选择.
三种API的对本
DOM 模型:
需要对整个文档结构有整体了解的情况
需要修改文档结构的情况
需要多次引用该文档的情况
SAX模型:
内存占有要求有限的情况
只需要读取XML部分元素的情况
只需要引用XML文档一次的情况
XML 文档对象模型(DOM)简介:
DOM由W3C推出的目的是为了提供一个良好的分析结构,用于操作XML中的标记.这个模型和类似于HTML的标记分析模型.它提供了一组操作接口,可以被各个具体平台所实现.因此可以选择任何满足DOM的解释器所提供的编程接口所实现的应用程序.将会很方便的移植到其他实现了DOM编程接口的平台工作.
对于标准DOM而言.它提供了的接口是一组可以描述XML文档树型结构的对象,以及通过这些对象可以对XML文档操作的方法.而应用程序只要调用这些对象以及对象操作.就等于在操作XML文件.这样就简化了XML文件的操作.使得编程接口足够的抽象.那么也就是说要熟悉DOM编程模型我们首要的就是熟悉DOM所提供的对象和方法.
下面我们就逐个熟悉DOM所提供的对象和方法:
Document:
该对象所描述的是整个XML文档.也就是整个树.对于树而言它可以表示为包含了很多节点的整体对象.而这些节点统称为Node.
Node:
node是一个相对抽象的概念,因此在java的定义中node被描述为接口.该接口扩展了几个子接口.
Element: 表示文档中的元素
Attribute:表示XML文件中的属性
Text:表示节点中的文字
其他的节点类型包括:Comment 表示 XML 文件中的注释、ProcessingInstruction 表示处理指令、CDATASection 表示 CDATA 节。对于这些有兴趣的读者可以参考相关文档.这里就不一一详解.
处理 DOM 经常要用到以下方法:
Document.getDocumentElement():返回 DOM 树的根。(该函数是 Document 接口的一个方法,没有定义其他的 Node 子类型。)
Node.getFirstChild() 和 Node.getLastChild():返回给定 Node 的第一个和最后一个孩子。
Node.getNextSibling() 和 Node.getPreviousSibling():返回给定 Node 的下一个和上一个兄弟。
Element.getAttribute(String attrName):对于给定的 Element,返回名为 attrName 的属性的值。如果需要 "id" 属性的值,可以使用 Element.getAttribute("id")。如果该属性不存在,该方法返回一个空字符串 ("")。
下面我们来做基本的DOM的示例,该示例很简单只是简单的显示上面的Book.xml文档中的内容.这也是DOM所做的基本事情.
代码如下:
import javax.xml.parsers.*;
import org.w3c.dom.*;
public class DomXml{
public static void main(String[] args)throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder bulider=factory.newDocumentBuilder();
Document doc=bulider.parse("BookXml.xml");
NodeList nl=doc.getElementsByTagName("Book");
for(int i=0;i<nl.getLength();i++){
Element node=(Element)nl.item(i);
System.out.println("BookName is :" +
node.getElementsByTagName("bookName").item(0).getFirstChild().getNodeValue().trim());
System.out.println("BookAuthor is :" +
node.getElementsByTagName("bookAuthor").item(0).getFirstChild().getNodeValue().trim());
System.out.println("BookISBN is :" +
node.getElementsByTagName("bookISBN").item(0).getFirstChild().getNodeValue().trim());
System.out.println("BookPrice is :" +
node.getElementsByTagName("bookPrice").item(0).getLastChild().getNodeValue().trim()+"/n/n");
}
}
}