dom4j基础教程

转自 http://blog.csdn.net/whatlonelytear/article/details/42234937

Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。

 

DOM4J使用起来非常简单。只要你了解基本的XML-DOM模型,就能使用。然而他自己带的指南只有短短一页(html),不过说的到挺全。国内的中文资料很少。

之前看过IBM developer社区的文章(参见附录),提到一些XML解析包的性能比较,其中DOM4J的性能非常出色,在多项测试中名列前茅。(事实上DOM4J的官方文档中也引用了这个比较)所以这次的项目中我采用了DOM4J作为XML解析工具。
在国内比较流行的是使用JDOM作为解析器,两者各擅其长,但DOM4J最大的特色是使用大量的接口,这也是它被认为比JDOM灵活的主要原因。

interface java.lang.Cloneable  

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 

一目了然,很多事情都清楚了。大部分都是由Node继承来的。知道这些关系,将来写程序就不会出现ClassCastException了。
下面给出一些例子(部分摘自DOM4J自带的文档),简单说一下如何使用。

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;  

}  

其中,reader的read方法是重载的,可以从  InputStream, File, Url 等多种不同的源来读取。得到的Document对象就带表了整个XML。
根据本人自己的经验,读取的字符编码是按照XML文件头定义的编码来转换。如果遇到乱码问题,注意要把各处的编码名称保持一致即可。

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

public Element getRootElement(Document doc){  

    return doc.getRootElement();  

}  

3. 遍历XML树

DOM4J提供至少3种遍历节点的方法:

// 枚举所有子节点  

for ( Iterator i = root.elementIterator(); i.hasNext(); ) {  

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

    // do something  

}  

// 枚举名称为foo的节点  

for ( Iterator i = root.elementIterator(foo); i.hasNext();) {  

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

    // do something  

}  

// 枚举属性  

for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {  

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

    // do something  

}  

3) Visitor模式
最令人兴奋的是DOM4J对Visitor的支持,这样可以大大缩减代码量,并且清楚易懂。了解设计模式的人都知道,Visitor是GOF设计模式之一。其主要原理就是两种类互相保有对方的引用,并且一种作为Visitor去访问许多Visitable。我们来看DOM4J中的Visitor模式(快速文档中没有提供)
只需要自定一个类实现Visitor接口即可。

public class MyVisitor extends VisitorSupport {  

    public void visit(Element element){  

        System.out.println(element.getName());  

    }  

    public void visit(Attribute attr){  

        System.out.println(attr.getName());  

    }  

}  

调用: root.accept(new MyVisitor()) 

Visitor接口提供多种Visit()的重载,根据XML不同的对象,将采用不同的方式来访问。上面是给出的Element和Attribute的简单实现,一般比较常用的就是这两个。VisitorSupport是DOM4J提供的默认适配器,Visitor接口的Default Adapter模式,这个模式给出了各种visit(*)的空实现,以便简化代码。
注意,这个Visitor是自动遍历所有子节点的。如果是root.accept(MyVisitor),将遍历子节点。我第一次用的时候,认为是需要自己遍历,便在递归中调用Visitor,结果可想而知。

4. XPath支持

DOM4J对XPath有良好的支持,如访问一个节点,可直接用XPath选择。

public void bar(Document document) {  

List list = document.selectNodes( "//foo/bar" );  

Node node = document.selectSingleNode("//foo/bar/author");  

String name = node.valueOf( "@name ");  

}  

例如,如果你想查找XHTML文档中所有的超链接,下面的代码可以实现: 

public void findLinks(Document document) throws DocumentException {  

    List list = document.selectNodes( "//a/@href" );  

    for (Iterator iter = list.iterator(); iter.hasNext(); ) {  

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

        String url = attribute.getValue();  

    }  

}

5. 字符串与XML的转换

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

Document document = null;  

String text = document.asXML();

// 字符串转XML

String text = "<person> <name>James</name> </person>";  

Document document = DocumentHelper.parseText(text);

6 用XSLT转换XML

public Document styleDocument(Document document,String stylesheet) throws Exception {  

    // load the transformer using JAXP  

    TransformerFactory factory = TransformerFactory.newInstance();  

    Transformer transformer = factory.newTransformer( new StreamSource( stylesheet ) ) ;  

    // now lets style the given document  

    DocumentSource source = new DocumentSource( document );  

    DocumentResult result = new DocumentResult();  

    transformer.transform( source, result );  

    // return the transformed document  

    Document transformedDoc = result.getDocument();  

    return transformedDoc;  

}  

7. 创建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;  

}  

8. 文件输出

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

FileWriter out = new FileWriter( foo.xml );  

document.write(out);  
public void write(Document document) throws IOException {  

// 指定文件  

XMLWriter writer = new XMLWriter(new FileWriter( output.xml ));  

writer.write( document );  

writer.close();  

// 美化格式  

OutputFormat format = OutputFormat.createPrettyPrint();  

writer = new XMLWriter( System.out, format );  

writer.write( document );  

// 缩减格式  

format = OutputFormat.createCompactFormat();  

writer = new XMLWriter( System.out, format );  

writer.write( document );  

}

9.生成Document

/**  

 *   

 * dom4j生成与解析XML文档  

 *  

 * @author wanglp 2012-2-23  

 */    

public class Dom4jDemo {    

    

    /**  

     * 利用dom4j进行xml文档的写入操作  

     */    

    public void createXml(File file) {    

    

        // XML 声明 <?xml version="1.0" encoding="UTF-8"?> 自动添加到 XML文档中    

        // 使用DocumentHelper类创建文档实例(生成 XML文档节点的 dom4j API工厂类)    

        Document document = DocumentHelper.createDocument();    

        // 使用addElement()方法创建根元素 employees(用于向 XML 文档中增加元素)    

        Element root = document.addElement("employees");    

        // 在根元素中使用 addComment()方法添加注释"An XML Note"    

        root.addComment("An XML Note");    

        // 在根元素中使用 addProcessingInstruction()方法增加一个处理指令    

        root.addProcessingInstruction("target", "text");    

        // 在根元素中使用 addElement()方法增加employee元素。    

        Element empElem = root.addElement("employee");    

        // 使用 addAttribute()方法向employee元素添加id和name属性    

        empElem.addAttribute("id", "0001");    

        empElem.addAttribute("name", "wanglp");    

        // 向employee元素中添加sex元素    

        Element sexElem = empElem.addElement("sex");    

        // 使用setText()方法设置sex元素的文本    

        sexElem.setText("m");    

        // 在employee元素中增加age元素 并设置该元素的文本。    

        Element ageElem = empElem.addElement("age");    

        ageElem.setText("25");    

        // 在根元素中使用 addElement()方法增加employee元素。    

        Element emp2Elem = root.addElement("employee");    

        // 使用 addAttribute()方法向employee元素添加id和name属性    

        emp2Elem.addAttribute("id", "0002");    

        emp2Elem.addAttribute("name", "fox");    

        // 向employee元素中添加sex元素    

        Element sex2Elem = emp2Elem.addElement("sex");    

        // 使用setText()方法设置sex元素的文本    

        sex2Elem.setText("f");    

        // 在employee元素中增加age元素 并设置该元素的文本。    

        Element age2Elem = emp2Elem.addElement("age");    

        age2Elem.setText("24");    

        // 可以使用 addDocType()方法添加文档类型说明。    

        // document.addDocType("employees", null, "file://E:/Dtds/dom4j.dtd");    

        // 这样就向 XML 文档中增加文档类型说明:    

        // <!DOCTYPE employees SYSTEM "file://E:/Dtds/dom4j.dtd">    

        // 如果文档要使用文档类型定义(DTD)文档验证则必须有 Doctype。   

        try {    

            XMLWriter output = new XMLWriter(new FileWriter(file));    

            output.write(document);    

            output.close();    

        } catch (IOException e) {    

            System.out.println(e.getMessage());    

        }    

    }    

    

    /**  

     * 利用dom4j进行xml文档的读取操作  

     */    

    public void parserXml(File file) {    

    

        Document document = null;    

        // 使用 SAXReader 解析 XML 文档 catalog.xml:    

        SAXReader saxReader = new SAXReader();    

        try {    

            document = saxReader.read(file);    

        } catch (DocumentException e) {    

            e.printStackTrace();    

        }    

        // 将字符串转为XML    

        // document = DocumentHelper.parseText(fileString);   

        // 获取根节点    

        Element root = document.getRootElement();    

        // 打印节点名称    

        System.out.println("<" + root.getName() + ">");    

        // 获取根节点下的子节点遍历    

        Iterator<?> iter = root.elementIterator("employee");    

        // 遍历employee节点    

        while (iter.hasNext()) {    

            // 获取当前子节点    

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

            System.out.println("<" + empEle.getName() + ">");    

            // 获取当前子节点的属性遍历    

            Iterator<?> attrList = empEle.attributeIterator();    

            while (attrList.hasNext()) {    

                Attribute attr = (Attribute) attrList.next();    

                System.out.println(attr.getName() + "=" + attr.getValue());    

            }    

            // 遍历employee节点下所有子节点    

            Iterator<?> eleIte = empEle.elementIterator();    

            while (eleIte.hasNext()) {    

                Element ele = (Element) eleIte.next();    

                System.out.println("<" + ele.getName() + ">" + ele.getTextTrim());    

            }    

            // 获取employee节点下的子节点sex值    

            // String sex = empEle.elementTextTrim("sex");    

            // System.out.println("sex:" + sex);    

        }    

        System.out.println("</" + root.getName() + ">");    

    }    

    

    public static void main(String[] args) {    

        Dom4jDemo dom4j = new Dom4jDemo();    

        File file = new File("e:/dom4j.xml");    

        // dom4j.createXml(file);    

        dom4j.parserXml(file);    

    }    

}

如何,DOM4J够简单吧,当然,还有一些复杂的应用没有提到,如ElementHandler等。如果你动心了,那就一起来用DOM4J.

你可能感兴趣的:(dom4j)