dom4j使用的解析器对象都是由其他包提供的,虽然它可以使用不同的解析器(SAX,DOM,StAX等),但通常使用的是SAX。
解析文档
dom4j不是一个XML解析器,它必须使用独立的解析器来创建Document对象。通常,你可以通过dom4j中的org.dom4j.io.SAXReader类来使用SAX解析器。调用SAXReader的read()方法将创建一个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(); } } }