14XML解析

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解析包,性能优异,开发便捷。

转载于:https://www.cnblogs.com/Aha-Best/p/10883245.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值