使用DOM4J读和写文档

dom4j使用的解析器对象都是由其他包提供的,虽然它可以使用不同的解析器SAXDOM,StAX等),但通常使用的是SAX

解析文档

dom4j不是一个XML解析器,它必须使用独立的解析器来创建Document对象。通常,你可以通过dom4j中的org.dom4j.io.SAXReader类来使用SAX解析器。调用SAXReaderread()方法将创建一个org.xml.sax.XMLReader类的实例,并且通过它实现的ContentHandler接口调用DocumentFactory创建dom4j对象树。解析java.io.File对象的代码如下:

//假设我们获得了一个路径作为命令行参数
File file = new File(args[0]);
SAXReader reader = new SAXReader();
Document doc = reader.read(file);

在创建SAXReader实例时,通过使用不同的构造器参数来确定(更确切地说,SAXReader是由下层的SAX解析器来确认),是使用预备的DocumentFactory实现,还是特定的SAX实现。此外,在SAXReader对象中还有各种setter方法(setValidating(),setDocumentFactory()等)来设置这些属性和其他的属性。可以参考dom4j的javadoc完整文档信息。read()方法是一个重载方法,它能接收下面输入参数中的一项:

  • A java.io.File object

  • A java.net.URL object

  • A system ID as a String object (which could be a URL or a filename)

  • A java.io.InputStream object

  • A java.io.Reader object

  • A java.io.InputStream object and  a system ID resolving relative URLs

  • A java.io.Reader object and a system ID for resolving relative URLs

  • An org.xml.sax.InputSource object

如果将一个String对象当作XML来解析,你可以把这个String对象封装在java.io.StringReader中,也可以把它传送给一个实用方法DocumentHelper.parseText()。parseText()方法将确定正确的编码,解析String对象,并返回一个Document对象。

使用dom4j解析XML文档示例:

package org.wangwa;

import java.io.File;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/*解析XML文档简单示例*/
public class Dom4jParseXml {
    @SuppressWarnings("rawtypes")
    public static void main(String[] args) {
        File file = new File("/home/fuhd/apk/gw/a" + 
            "/com.application.zomato.apk/AndroidManifest.xml");
        SAXReader reader = new SAXReader();
        try {
            Document doc = reader.read(file);
            Element root = doc.getRootElement();
            List listE = root.elements("uses-feature");
            if(listE != null){
                for(Object e : listE){
                    System.out.println(((Element)e).asXML());
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}

创建Document对象

Document对象的创建可以由DocumentFactory类或者它的子类来完成。DocumentHelper类也提供一些静态方法,用来创建Document,Element,Attribute等对象。这些静态方法调用DocumentFactory实例中相对应的方法。为了简化,你可以这样写:

DocumentFactory factory = DocumentFactory.getInstance();
Document doc = factory.createDocument();

你也可以写成这样:

Document doc = DocumentHelper.createDocument();

因为没有直接使用DocumentFactory对象,因此只保留了一行代码,但是,我们失去了使用不同工厂类的这一优势,这将是我们稍后进行深入讨论的内容。

一旦创建了Document对象,使用add()方法增加节点是件非常容易的事。根据XML规范,可以根据自己的要求添加多个Comment和ProcessingInstruction对象到Document中,但只能有一个Element。除add()方法外,在Document的父接口Branch中还定义了一组名称为addElement()方法,这些方法可以接收QName对象,本地名称或者是本地名称和命名空间的URI。当你调用一个addElement()方法时,DocumentFactory的createElement()方法将会被调用,而且这个Element对象将会被设置成为Document对象的根元素。因此,这里的两块代码做的是相同的事情:

//块1:完整方法
Element myElement = factory.createElement("name");
doc.add(myElement);
//块2:简短方式
doc.addElement("name");

addElement()方法返回的是一个新创建的对象,它允许你像这样链式地调用方法:

doc.addElement("root").addElement("child").addElement("innerChild");

生成的文档应该是这样:

<root>
    <child>
        <innerChild />
    </child>
</root>

名称空间和限定名            在dom4j中,对于其他XML API,元素的名称和属性是用一个三元组来表示的本地名,名称空间前缀和名称空间URI来表示的名称空间前缀和名称空间URI都封装在org.dom4j.Namespace类中,而它自己又被封装在org.dom4j.QName中。Namespace和QName被实例化后,它们的属性就不可更改了,虽然它们都提供了公共的构造方法,但最好是通过类的静态方法get()方法来实例化这两个实例。get()方法利用了对象缓存,这样当使用相同参数重复调用get()方法时,就可以返回相同的对象,从而降低内存消耗,加快了对象比较的速率,增加了XML的一致性。

输出文档

在dom4j中输出文档既包含了对XML的序列化,还包含了将dom4j对象传递给其他的XML APIs(非dom4j的API)。dom4j采用了最为简单的机制将Document对象转换成String对象:

String output = doc.asXML();

就是这样,asXML()方法是Node接口的一部分,因此,它在dom4j对象模型中的每一个接口中都有效。asXML()方法不能进行格式化的输出,除Document对象之外,它使用的字符集编码总是UTF-8。如果你想要设置自己的输出格式,就需要使用org.dom4j.io.XMLWriter类。XMLWriter将输出格式以XML对象的形式写入到java.io.Writer对象,或者是java.io.InputStream对象。当你创建一个XMLWriter实例时,就可以使用org.dom4j.io.OutputFormat对象来控制XML对象的输出格式。dom4J包含了三种格式:

  • Default:由new OutputFormat()创建,Raw格式。没有缩进或增加换行符。XML声明的编码总是写在新的一行中。

  • Pretty Print:由OutputFormat.createPrettyPrint()创建,会在元素之间产生两个空格的缩进,并且产生换行符。文本会被裁剪,使之标准化。

  • Compact:由OutputFormat.createCompactFormat()创建,默认格式是对文本进行微调,增强文本格式的标准化。

你可以传入OutputFormat对象到XMLWriter构造器中。可是XMLWriter并没有setOutputFormat()或getOutputFormat()这些方法集,这样就不能再更改XMLWriter的格式了。你创建OutputFormat对象,并把它传递给XMLWriter构造器,然后再去调用OutputFormat实例中的mutator方法。但是不推荐这么做,因为这会导致行为不一致。在创建XMLWriter之前,要配置好OutputFormat对象,以免出错。实际上,OutputFourmat对象能定制出远超出这三种默认格式的输出格式。事实上,它可以作为这些定义的模板,这里我们就不做介绍了。

创建Document对象并输出的示例:

package org.wangwa;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

public class CreateDocument {
    public static void main(String[] args) {
        Document doc = DocumentHelper.createDocument();
        doc.addElement("class").addElement("student").addAttribute("name", "fuhd").addText("这是个好学生");
        //OutputFormat format = new OutputFormat();                                      //创建Raw格式,默认
        OutputFormat format = OutputFormat.createPrettyPrint();                   //创建Pretty Print格式
        //OutputFormat format = OutputFormat.createCompactFormat();        //创建Compact格式
        try {
            XMLWriter writer = new XMLWriter(format);
            writer.setOutputStream(new BufferedOutputStream(
                        new FileOutputStream(new File("/home/fuhd/student"))) );
            writer.write(doc);
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        } catch (IOException e2) {
            e2.printStackTrace();
        } catch (Exception e3) {
            e3.printStackTrace();
        }
    }
}


你可能感兴趣的:(java与XML)