Fork me on GitHub

XML 解析之 dom4j 解析器

  • dom4j 的使用需要导入 jar 包, 包括: dom4j-1.6.1 和 jaxen-1.1-beta
    • 步骤: 在项目目录下,"Folder" 创建一个 lib 文件夹
    • 复制 jar 包到 lib 下面
    • 右键 "build path" , 然后 "add to buildpath"
// 示例:
// xml 文档
<?xml version="1.0" encoding="gbk"?>
<person>
    <p1 id="102">
        <name>zhangsan</name>
        <age>20</age>
    </p1>
    <p1>
        <name>wangcai</name>
        <age>25</age>
    </p1>
</person>

// 需求一: 查询 xml 中所有 name 元素里面的值
    /*
     * 思路:
     *    1. 创建解析器
     *    2. 得到 document 对象
     *    3. 得到根节点, getRootElement
     *    4. 得到所有的 p1 标签
     *         element(qname);   // 返回标签 qname 下面的第一个符合查找的子标签
     *         elements(qname);  // 返回标签下面的属于 qname 的所有第一层子标签, 结果是 list 集合
     *         elements();  // 返回标签下面的所有一层子标签
     *
     *    5. 得到 name 元素
     *    6. 获取 name 元素里面的值, getText()
     */

     public static void main(String[] args){

        // 1. 创建解析器, 需要导入 org.dom4j.io.SAXReader 包
        SAXReader saxReader = new SAXReader();

        // 2. 获取 document 对象, 需要导入 org.dom4j.Document 包
        Document document = saxReader.read("src/person.xml");

        // 3. 获取根节点
        Element root = document.geteRootElement();

        // 4. 获取所有的 p1
        List<Element> list = root.elements("p1");

        // 5. 遍历 list 集合
        for(Element p : list){

            // element 就是每一个 p1 元素
            // 获取 p1 下面的第一个 name 元素
            Element name1 = p.element("name");
            // 得到 name 元素里面的值
            String s = name1.getText();
        }
    }

// 需求二: 在第一个 p1 标签中的末尾处添加 <sex>male</sex>
    /*
     * 思路:
     *    1. 创建解析器
     *    2. 得到 document 对象
     *    3. 得到根节点, getRootElement
     *    4. 得到第一个 p1 标签
     *    5. 在 p1 下面直接添加 p1.addElement("标签名");  返回 Element 对象
     *    6. 在 sex 标签中添加文本, sex.setText("文本内容");
     *
     *    7. 回写 xml,    org.dom4j.io 包
     *  XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("文件地址"), OutputFormat format);
     *    关于第二个参数 OutputFormat format
     *       第一种方式: OutputFormat.createPrettyPrint();  带有缩进效果的输出
     *       第二种方式: OutputFormat.createCompactFormat();  不带格式的输出
     *       第三种方式: 
     *     OutputFormat format = new OutputFormat(String indent, boolean newlines);
     *                             第一个参数: 缩进方式, "\t" 或者 空格;  第二个参数: 是否换行.
     *               format.setTrimText(true);   // 清空文档原有的换行和缩进
     */

     public static void main(String[] args){

        // 1. 创建解析器,
        SAXReader saxReader = new SAXReader();

        // 2. 获取 document 对象
        Document document = saxReader.read("src/person.xml");

        // 3. 获取根节点
        Element root = document.getRootElement();

        // 4. 获取第一个 p1 标签
        Element p = root.element("p1");

        // 5. 添加 sex 标签
        Element sex2 = p.addElement("sex");

        // 6. 添加文本
        sex2.setText("male");

        // 7. 回写 xml
        OutputFormat format = OutputFormat.createPrettyPrint();
        XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/person.xml"), format);
        xmlWriter.write(document);
        xmlWriter.close();   // 关闭资源
    }

    // 需求三: 在特定的位置添加元素, 例如在第一个 p1 下面的 age 标签之前添加 <school>University</school>
        /*
         * 思路:
         *   1. 获取解析器
         *   2. 得到 document 对象
         *   3. 得到第一个 p1 标签
         *   4. 获取 p1 标签下面的所有元素: elements(); 返回值类型: List 集合
         *       使用 List 集合中的方法, add(int index, E element); 在指定位置添加元素
         *   5. 添加元素之前,需要先创建元素
         *        Element school = DocumentHelper.creatElement("school");
         *   6. 在元素中添加文本: school.setText("University");
         *   7. 回写 xml
         */


// 升级版, 将获取 document 对象 和 回写 xml 的代码封装成方法
    class Dom4jUtils{

        // 获取 document 对象
        public static Document getDocument(String path){

            try{
                SAXReader saxReader = new SAXReader();
                Document document = saxReader.read(path);
                return document;
            } catch (Exception e){
                    e.printStackTrace();
            }

            return null;
        }

        // 回写 xml 操作
        public static void myXmlWriter(Document document, String path){
            try{
                OutputFormat format = OutputFormat.createPrettyPrint();

                XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(path); format);

                xmlWriter.write(document);
                xmlWriter.close();
            } catch (Exception e){
                    e.printStackTrace();
            }
        }
    }

    // 需求四: 修改 (需要回写 xml)
            // 将 p1 标签下面的 age 标签中的内容修改为 30

            /*
             * 思路: 使用 setText("30"); 方法
             */

    // 需求五: 删除 (需要回写 xml)
            // 将第一个 p1 标签下面的 school 标签删除

            /*
             * 思路:
             *    1. 获取第一个 p1 标签
             *              root.element("p1");
             *    2. 获取 p1 标签下面的 school 标签
             *              Element school2 = p1.element("school");
             *    3. 使用父节点, 删除 school 标签
             *              p1.remove(school2);
             */

    // 需求六: 获取属性值
            // 获取第一个 p1 里面的属性 id 的值

            /*
             * 思路:
             *    p1.attributeValue("属性名"); // 返回值: 属性对应的值
             */

dom4j 解析器使用 XPath 语言操作 xml 文档

  • 导入支持 xpath 的 jar 包, jaxen-1.1-beta-6.jar
  • dom4j 里面提供了两个方法, 用来支持 XPath
    • selectNodes("XPath 表达式"); 表示获取多个节点
    • SelectSingleNode("Xpath 表达式"); 表示获取单个节点
// 示例:
// xml 文档
<?xml version="1.0" encodint="gbk"?>
<bookstore>
    <book>
        <title lang="eng">Harry Potter</title>
        <price>30</price>
    </book>

    <book>
        <title lang="cn">Learning XML</title>
        <price>26</price>
    </book>
</bookstore>

    // 需求一: 查询
            // 查询 xml 文档中所有 title 元素的值

            /*
             * 思路:
             *    1. 获取 document 对象
             *    2. 直接使用 document.selectNodes("//title"); 返回 List<Node> 集合
             */

             public static void main(String[] args){

                Document document = Dom4jUtils.getDocument("src/bookstore.xml");

                // 此处 Node 对象, 需要导入 org.dom4j.Node 包
                List<Node> list = document.selectNodes("//title");

                // 遍历 list 集合
                for(Node node : list){

                    // 获取 title 元素里面的值
                    String s = node.getText();
                    System.out.println(s);
                }
            }

**参考资料:** - [JavaWeb 视频教程](https://www.bilibili.com/video/av12750191/#page=6) - [dom4j API 文档](http://tool.oschina.net/apidocs/apidoc?api=dom4j1.6.1%2Fapidocs) - [dom4j jar包下载](https://dom4j.github.io/) - [XPath jar包下载](http://mvnrepository.com/artifact/jaxen/jaxen/1.1-beta-6) - [W3School XPath 教程](http://www.w3school.com.cn/xpath/xpath_syntax.asp)
posted @ 2017-09-21 12:05  小a的软件思考  阅读(181)  评论(0编辑  收藏  举报