XML解析


XML解析

DOM4J

DOM4J是dom4j.org出品的一个开源XML解析包Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT的解析及相关应用。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。与其他一些XML解析包的比较,DOM4J的性能上存在明显优势,在多项测试中名列前茅。DOM4J使用起来非常简单。只要你了解基本的XML-DOM模型,就能使用。

10.2  DOM4J的接口

DOM4J最大的特色是使用大量的接口,它的主要接口都在org.dom4j这个包里定义:

Attribute

Attribute定义了XML的属性

Branch

Branch为能够包含子节点的节点如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为,

CDATA

CDATA 定义了XML CDATA 区域

CharacterData

CharacterData是一个标识借口,标识基于字符的节点。如CDATA,Comment, Text.

Comment

Comment 定义了XML注释的行为

Document

定义了XML文档

DocumentType

DocumentType 定义XML DOCTYPE声明

Element

Element定义XML 元素

ElementHandler

ElementHandler定义了 Element 对象的处理器

ElementPath

被   ElementHandler 使用,用于取得当前正在处理的路径层次信息

Entity

Entity定义 XML entity

Node

Node为所有的dom4j中XML节点定义了多态行为

NodeFilter

NodeFilter 定义了在dom4j节点中产生的一个滤镜或谓词的行为(predicate)

ProcessingInstruction

ProcessingInstruction 定义 XML 处理指令.

Text

Text 定义XML 文本节点.

Visitor

Visitor 用于实现Visitor模式.

XPath

XPath 在分析一个字符串后会提供一个XPath 表达式

表 10.1

看名字大致就知道它们的涵义如何了。要想弄懂这套接口,关键的是要明白接口的继承关系,如下图所示,大部分接口都是由Node继承来的。

  • interface   org.dom4j.Node

    • interface   org.dom4j.Attribute
    • interface org.dom4j.Branch
    • interface   org.dom4j.Document
    • interface   org.dom4j.Element
    • interface   org.dom4j.CharacterData
    • interface   org.dom4j.CDATA
    • interface   org.dom4j.Comment
    • interface   org.dom4j.Text
    • interface   org.dom4j.DocumentType
    • interface   org.dom4j.Entity
    • interface   org.dom4j.ProcessingInstruction

表 10.2

10.3  下载与安装

可以到http://sourceforge.net/projects/dom4j下载其最新版。dom4j1.5的完整版大约13M,是一个名为dom4j-1.5.zip的压缩包,解压后有一个dom4j-1.5.jar文件,这就是应用时需要引入的类包,另外还有一个jaxen-1.1-beta-4.jar文件,一般也需要引入,否则执行时可能抛java.lang.NoClassDefFoundError: org/jaxen/JaxenException异常,其他的包可以选择用之。

10.4  程序示例

10.4.1  读取并解析XML文档

读写XML文档主要依赖于org.dom4j.io包,其中提供DOMReader和SAXReader两类不同方式,而调用方式是一样的。这就是依靠接口的好处。

// 从文件读取XML,输入文件名,返回XML文档

public Document read(String fileName) throws MalformedURLException, DocumentException   {

SAXReader reader = new SAXReader();

Document document = reader.read(new File(fileName));

return document;

}

表10.3

其中,reader的read方法是重载的,可以从InputStream, File, Url等多种不同的源来读取。得到的Document对象就带表了整个XML。

10.4.2  取得Root节点

读取后的第二步,就是得到Root节点。熟悉XML的人都知道,一切XML分析都是从Root元素开始的。

public Element getR9ootElement(Document doc){

     return doc.getRootElement();

}

表10.4

10.4.3  遍历XML树

DOM4J提供至少3种遍历节点的方法:枚举(Iterator),递归,Visitor模式。通常我们使用枚举方式,详细见下例。

// 枚举所有子节点

Iterator i = root.elementIterator();

while(i.hasNext()) {

Element element = (Element) i.next();

}

i = root.elementIterator(foo);

// 枚举名称为foo的节点

while(i.hasNext()) {

Element foo = (Element) i.next();

}

i = root.attributeIterator();

// 枚举属性

while(i.hasNext()) {

Attribute attribute = (Attribute) i.next();

}

表10.5

10.4.4  字符串与XML的转换

有时候经常要用到字符串转换为XML或反之,

// XML转字符串

Document document = ...;

String text =   document.asXML();

// 字符串转XML

String text = “<person>   <name>James</name> </person>”;

Document document =   DocumentHelper.parseText(text);

表10.6

10.4.5  创建XML

一般创建XML是写文件前的工作,这就像StringBuffer一样容易。

public Document createDocument() {

Document document =   DocumentHelper.createDocument();

Element root =   document.addElement(root);

Element author1 =   root.addElement(author)

.addAttribute(name, James)

.addAttribute(location,   UK)

.addText(James Strachan);

Element author2 = root.addElement(author)

.addAttribute(name, Bob)

.addAttribute(location,   US)

.addText(Bob   McWhirter);

return document;

}

表10.7

10.4.6  文件输出

一个简单的输出方法是将一个Document或任何的Node通过write方法输出

FileWriter out = new FileWriter( foo.xml   );

document.write(out);

表10.8

10.5  用Dom4j解析XML及中文问题

本节主要讨论了用dom4j解析XML的基础问题,包括建立XML文档,添加、修改、删除节点,以及(美化)输出和中文问题

10.5.1  建立一个XML文档

/**

* 建立一个XML文档,文档名由输入属性决定

*   @param filename 需建立的文件名

* @return 返回操作结果, 0表失败, 1表成功

*/

public int createXMLFile(String filename){

/** 返回操作结果, 0表失败, 1表成功 */

int returnValue = 0;

/** 建立document对象 */

Document document =   DocumentHelper.createDocument();

/** 建立XML文档的根books */

Element booksElement = document.addElement("books");

/** 加入一行注释 */

booksElement.addComment("This is a test for dom4j");

/** 加入第一个book节点 */

Element bookElement = booksElement.addElement("book");

/** 加入show属性内容 */

bookElement.addAttribute("show","yes");

/** 加入title节点 */

Element titleElement = bookElement.addElement("title");

/** 为title设置内容 */

titleElement.setText("Dom4j Tutorials");

/** 类似的完成后两个book */

bookElement = booksElement.addElement("book");

bookElement.addAttribute("show","yes");

titleElement = bookElement.addElement("title");

titleElement.setText("Lucene Studing");

bookElement = booksElement.addElement("book");

bookElement.addAttribute("show","no");

titleElement = bookElement.addElement("title");

titleElement.setText("Lucene in Action");

/** 加入owner节点 */

Element ownerElement = booksElement.addElement("owner");

ownerElement.setText("O'Reilly");

try{

/** 将document中的内容写入文件中 */

XMLWriter writer = new XMLWriter(new FileWriter(new File(filename)));

writer.write(document);

writer.close();

/** 执行成功,需返回1 */

returnValue = 1;

}catch(Exception ex){

ex.printStackTrace();

}

return returnValue;

}

例10.2

说明:

Document document = DocumentHelper.createDocument();

通过这句定义一个XML文档对象。

Element booksElement =   document.addElement("books");

通过这句定义一个XML元素,这里添加的是根节点。

Element有几个重要的方法:

  • addComment:添加注释
  • addAttribute:添加属性
  • addElement:添加子元素

最后通过XMLWriter生成物理文件,默认生成的XML文件排版格式比较乱,可以通过OutputFormat类的createCompactFormat()方法或createPrettyPrint()方法格式化输出,默认采用createCompactFormat()方法,显示比较紧凑,这点将在后面详细谈到。

生成后的xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<books>

<book show="yes">

<title>Dom4j Tutorials</title>

</book>

<book show="yes">

<title>Lucene Studing</title>

</book>

<book show="no">

<title>Lucene in Action</title>

</book>

<owner>O'Reilly</owner>

</books>

表10.9

10.5.2  修改XML文档

有三项修改任务,依次为:

a. 如果book节点中show属性的内容为yes,则修改成no

b. 把owner项内容改为Tshinghua,并添加date节点

c. 若title内容为Dom4j Tutorials,则删除该节点

/**

* 修改XML文件中内容,并另存为一个新文件

* 重点掌握dom4j中如何添加节点,修改节点,删除节点

* @param filename 修改对象文件

* @param newfilename 修改后另存为该文件

* @return 返回操作结果, 0表失败, 1表成功

*/

public int ModiXMLFile(String filename,String   newfilename){

int returnValue = 0;

try{

SAXReader saxReader = new SAXReader();

Document document = saxReader.read(new File(filename));

/** 修改内容之一: 如果book节点中show属性的内容为yes,则修改成no */

/** 先用xpath查找对象 */

List list = document.selectNodes("/books/book/@show" );

Iterator iter = list.iterator();

while(iter.hasNext()){

Attribute attribute =   (Attribute)iter.next();

if(attribute.getValue().equals("yes")){

attribute.setValue("no");

}

}

/**

* 修改内容之二: 把owner项内容改为Tshinghua

* 并在owner节点中加入date节点,date节点的内容为2004-09-11,还为date节点

*添加一个属性type

**/

list = document.selectNodes("/books/owner" );

iter = list.iterator();

if(iter.hasNext()){

Element ownerElement =   (Element)iter.next();

ownerElement.setText("Tshinghua");

Element dateElement =   ownerElement.addElement("date");

dateElement.setText("2004-09-11");

dateElement.addAttribute("type","Gregorian   calendar");

}

/** 修改内容之三: 若title内容为Dom4j Tutorials,则删除该节点 */

list = document.selectNodes("/books/book");

iter = list.iterator();

while(iter.hasNext()){

Element bookElement =   (Element)iter.next();

Iterator iterator =   bookElement.elementIterator("title");

while(iterator.hasNext()){

Element titleElement=(Element)iterator.next();

if(titleElement.getText().equals("Dom4j   Tutorials")){

bookElement.remove(titleElement);

}

}

}

try{

/** 将document中的内容写入文件中 */

XMLWriter writer = new XMLWriter(new FileWriter(new   File(newfilename)));

writer.write(document);

writer.close();

/** 执行成功,需返回1 */

returnValue = 1;

}catch(Exception ex){

ex.printStackTrace();

}

}catch(Exception ex){

ex.printStackTrace();

}

return returnValue;

}

例10.3

说明:

List list = document.selectNodes("/books/book/@show" );

list =   document.selectNodes("/books/book");

上述代码通过xpath查找到相应内容。

通过setValue()、setText()修改节点内容。

通过remove()删除节点或属性。

10.5.3  格式化输出和指定编码

默认的输出方式为紧凑方式,默认编码为UTF-8,但对于我们的应用而言,一般都要用到中文,并且希望显示时按自动缩进的方式的显示,这就需用到OutputFormat类。

/**

* 格式化XML文档,并解决中文问题

* @param filename

* @return 执行结果码

*/

public int formatXMLFile(String filename){

int returnValue = 0;

try{

SAXReader saxReader = new SAXReader();

Document document = saxReader.read(new File(filename));

XMLWriter writer = null;

/** 格式化输出,类型IE浏览一样 */

OutputFormat format = OutputFormat.createPrettyPrint();

/** 指定XML编码 */

format.setEncoding("GBK");

writer= new XMLWriter(new FileWriter(new File(filename)),

format);

writer.write(document);

writer.close();

/** 执行成功,需返回1 */

returnValue = 1;

}catch(Exception ex){

ex.printStackTrace();

}

return returnValue;

}

例10.4

说明:

OutputFormat format = OutputFormat.createPrettyPrint();

这句指定了格式化的方式为缩进式,则非紧凑式。

format.setEncoding("GBK");

指定编码为GBK。

XMLWriter writer = new XMLWriter(new FileWriter(new   File(filename)),format);

这与前面两个方法相比,多加了一个OutputFormat对象,用于指定显示和编码方式。

 

 

10.6  总结

  • 扩展标记语言XML是一种简单的数据存储语言,结构严谨,使用方便,在当前WEB开发领域所起的作用越来越大,应用越来越广泛。
  • DOM4J是dom4j.org出品的一个开源XML解析包,性能优异,开发便捷。

最新文章

  1. mysql group by后 拼接某一字段
  2. DNS记录类型介绍(A记录、MX记录、NS记录等)
  3. 曲线救国,解决Mac系统下,Android sdk下载失败的问题
  4. 使用SQL字符串反转函数REVERSE巧妙实现lastindexof功能
  5. ubuntu 13.04下sublime text 3使用中文输入法
  6. 关于使用navigationController,前后2个视图控制器navigationBar隐藏属性不同,导致右滑手势失效问题的解决办法
  7. rsyslog Properties 属性:
  8. UVA 100 - The 3n+1 problem (3n+1 问题)
  9. Csharp多态的实现(虚方法)
  10. Ubuntu12.10 下搭建基于KVM-QEMU的虚拟机环境(十五)
  11. 100个精选zencart扩展插件
  12. magento1.x 运行在 php7 优惠券的问题
  13. 【java】内部类
  14. 错误记录:vue跟vue编译器版本不一致
  15. Zookeeper —— 初识
  16. C++成员函数在内存中的存储方式
  17. 在源文件(.c)和头文件(.h)中声明和定义的区别——C语言
  18. WebKit最新特性srcset简介(转)
  19. [原]Jenkins(十五)---jenkins插件之deploy
  20. Qt编写的RTSP播放器+视频监控(android版本)

热门文章

  1. HTML &lt;iframe&gt; 标签的 src 属性
  2. python库学习笔记——re库:正则表达式入门(一)
  3. luogu 1083 借教室
  4. MySQL:MySQL安装
  5. 1998 NOIP 拼数 string 和sort的新理解
  6. Bug分支(转载)
  7. 如何快速删除Linux下的svn隐藏文件及其他临时文件 (转载)
  8. E20180124-hm
  9. Rails5&#160;layout&#160;和&#160;template
  10. bzoj 1594: [Usaco2008 Jan]猜数游戏【二分+线段树】