优秀的编程知识分享平台

网站首页 > 技术文章 正文

XML之dom4j的xpath解析(dom4j解析xml生成对象)

nanyue 2024-11-14 16:47:57 技术文章 2 ℃

简介:

XPath 可用来在 XML 文档中对元素和属性进行遍历。

参考文档:

https://www.w3cschool.cn/xpath/xpath-syntax.html
  • XPath 使用路径表达式在 XML 文档中进行导航
  • XPath 包含一个标准函数库
  • XPath 是 XSLT 中的主要元素
  • XPath 是一个 W3C 标准
节点:
在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。

请看下面这个 XML 文档:
 <?xml version="1.0" encoding="ISO-8859-1"?>

 <bookstore>
  <book>
     <title lang="en">Harry Potter</title>
     <author>J K. Rowling</author>
     <year>2005</year>
     <price>29.99</price>
   </book>
</bookstore> 
上面的XML文档中的节点例子:
 <bookstore> (文档节点)
 <author>J K. Rowling</author> (元素节点)
 lang="en" (属性节点) 

基本值(或称原子值,Atomic value):
基本值是无父或无子的节点。  
基本值的例子:
 J K. Rowling

 "en" 
项目(Item):
项目是基本值或者节点。

节点关系:

 <bookstore>

 <book>
   <title>Harry Potter</title>
   <author>J K. Rowling</author>
   <year>2005</year>
   <price>29.99</price>
 </book>

 </bookstore> 
父(Parent)
每个元素以及属性都有一个父。
book 元素是 title、author、year 以及 price 元素的父:

子(Children):
元素节点可有零个、一个或多个子。
title、author、year 以及 price 元素都是 book 元素的子:

同胞(Sibling):
拥有相同的父的节点
title、author、year 以及 price 元素都是同胞:
先辈(Ancestor):
某节点的父、父的父,等等。
title 元素的先辈是 book 元素和 bookstore 元素:

后代(Descendant):
某个节点的子,子的子,等等。
bookstore 的后代是 book、title、author、year 以及 price 元素:

XPath 轴(Axes)

轴可定义相对于当前节点的节点集。

轴名称

结果

ancestor

选取当前节点的所有先辈(父、祖父等)。

ancestor-or-self

选取当前节点的所有先辈(父、祖父等)以及当前节点本身。

attribute

选取当前节点的所有属性。

child

选取当前节点的所有子元素。

descendant

选取当前节点的所有后代元素(子、孙等)。

descendant-or-self

选取当前节点的所有后代元素(子、孙等)以及当前节点本身。

following

选取文档中当前节点的结束标签之后的所有节点。

namespace

选取当前节点的所有命名空间节点。

parent

选取当前节点的父节点。

preceding

选取文档中当前节点的开始标签之前的所有节点。

preceding-sibling

选取当前节点之前的所有同级节点。

self

选取当前节点。


XPath 运算符

下面列出了可用在 XPath 表达式中的运算符:

运算符

描述

实例

返回值

|

计算两个节点集

//book | //cd

返回所有拥有 book 和 cd 元素的节点集

+

加法

6 + 4

10

-

减法

6 - 4

2

*

乘法

6 * 4

24

div

除法

8 div 4

2

=

等于

price=9.80

如果 price 是 9.80,则返回 true。

如果 price 是 9.90,则返回 false。

!=

不等于

price!=9.80

如果 price 是 9.90,则返回 true。

如果 price 是 9.80,则返回 false。

<

小于

price<9.80

如果 price 是 9.00,则返回 true。

如果 price 是 9.90,则返回 false。

<=

小于或等于

price<=9.80

如果 price 是 9.00,则返回 true。

如果 price 是 9.90,则返回 false。

>

大于

price>9.80

如果 price 是 9.90,则返回 true。

如果 price 是 9.80,则返回 false。

>=

大于或等于

price>=9.80

如果 price 是 9.90,则返回 true。

如果 price 是 9.70,则返回 false。

or

price=9.80 or price=9.70

如果 price 是 9.80,则返回 true。

如果 price 是 9.50,则返回 false。

and

price>9.00 and price<9.90

如果 price 是 9.80,则返回 true。

如果 price 是 8.50,则返回 false。

mod

计算除法的余数

5 mod 2

1

dom4j使用XPath:

默认时dom4j是不支持XPath,所以想要使用XPath就需要导入对应的jar包:

1、在dom4j网址中下载的文件中导入jaxen-1.1-beta-6.jar包,这个包是dom4j对XPath的支持:

https://dom4j.github.io/

然后是包jar包导入到项目中:

详见:https://www.cnblogs.com/0099-ymsml/p/16062244.html

使用XPath:

在dom4j中提供了两个方法用来支持XPath:

代码实现:

xml文档:

<?xml version="1.0" encoding="UTF-8"?>

<person> 
  <p1> 
    <name id="1">zs</name>  
    <age>100</age>  
    <sex>nv</sex> 
  </p1>  
  <p1> 
    <name>ls</name>  
    <age>11</age> 
  </p1> 
</person>
package XPathDemo1;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Node;
import cn.dom4jUtile.lm.Dom4jUtils;

public class XPathDemo1_1 {
    public static void main(String[] args) {
        System.out.print("selectAll: ");
        selectAll();
        System.out.print("\nselectSigle: ");
        selectSigle();
    }

    /**
     * 使用xpath获取单个标签
     */
    public static void selectSigle() {
        // 获取解析xml后的Document多像
        Document doc = Dom4jUtils.getDocument();
        // 获取对应单个节点
        Node name = doc.selectSingleNode("/person/p1/name");
        // 打印信息
        System.out.println(name.getName() + ": " + name.getText());
    }

    /**
     * 使用xpath获取所有name标签
     */
    public static void selectAll() {
        // 获取解析xml后的Document多像
        Document doc = Dom4jUtils.getDocument();
        // 通过方法selectNodes()获取对应的标签
        List<Node> name = doc.selectNodes("//name");
        // 增强for遍历列表输出信息
        for (Node node : name) {
            System.out.print("{" + node.getName() + ": " + node.getText() + "} ");
        }
    }
}

注意上面的代码有个封装类(注意修改xml文件的路径):

package cn.dom4jUtile.lm;
import java.io.File;
import java.io.FileOutputStream;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public final class Dom4jUtils {
    public static final String PATH="src" + File.separator + "XPathDemo1" + File.separator + "XPathDemo1_1.xml";
    
    /**
     * 将xml的回写操作封装为一个方法
     * @param xmlPath:xml的路径
     * @param doc:回写操作前修改数据后的Document对象
     */
    public static void ReWriteXml(Document doc) {
        try {
        //缩进文本
        OutputFormat format = OutputFormat.createPrettyPrint();
        // 创建写入流
            XMLWriter Writer = new XMLWriter(new FileOutputStream(PATH),format);
            Writer.write(doc);
            Writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 将创建解析器和解析xml的步骤封装为一个方法
     * @param path    xml文件的路径
     * @return
     */
    public static Document getDocument() {
        try {
            // 创建解析器
            SAXReader reader = new SAXReader();
            // 解析xml得到Document
            Document doc = reader.read(PATH);
            return doc; 
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

输出结果:

有xml文档:

<?xml version="1.0" encoding="UTF-8"?>

<person> 
  <p1 id="1"> 
    <name>zs</name>  
    <age>100</age>  
    <sex>nv</sex> 
  </p1>  
  <p1> 
    <name>ls</name>  
    <age>11</age> 
  </p1> 
</person>
package cn.dom4jUtile.lm;
import java.io.File;
import java.io.FileOutputStream;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public final class Dom4jUtils {
    public static final String PATH="src" + File.separator + "XPathDemo1" + File.separator + "XPathDemo1_1.xml";
    
    /**
     * 将xml的回写操作封装为一个方法
     * @param xmlPath:xml的路径
     * @param doc:回写操作前修改数据后的Document对象
     */
    public static void ReWriteXml(Document doc) {
        try {
        //缩进文本
        OutputFormat format = OutputFormat.createPrettyPrint();
        // 创建写入流
            XMLWriter Writer = new XMLWriter(new FileOutputStream(PATH),format);
            Writer.write(doc);
            Writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 将创建解析器和解析xml的步骤封装为一个方法
     * @param path    xml文件的路径
     * @return
     */
    public static Document getDocument() {
        try {
            // 创建解析器
            SAXReader reader = new SAXReader();
            // 解析xml得到Document
            Document doc = reader.read(PATH);
            return doc; 
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

上面是工具类

package XPathDemo1;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Node;
import cn.dom4jUtile.lm.Dom4jUtils;

public class XPathDemo1_1 {
    public static void main(String[] args) {
        System.out.print("selectAll: ");
        selectAll();
        System.out.println("\n");
        System.out.print("selectSigle: ");
        selectSigle();
        System.out.println("\n");
        System.out.print("<p1 id='1'>:");
        selectP1Name();
    }
    /**
     * 获取第一个p1下面name的值
     */
    public static void selectP1Name() {
        // 获取解析的doc对象
        Document doc = Dom4jUtils.getDocument();
        // 获取id="1"的p1下的name
        Node name = doc.selectSingleNode("//p1[@id='1']/name");
        // 打印信息
        System.out.print("{" + name.getName() + ": " + name.getText() + "}");
    }

    /**
     * 使用xpath获取单个标签
     */
    public static void selectSigle() {
        // 获取解析xml后的Document多像
        Document doc = Dom4jUtils.getDocument();
        // 获取对应单个节点
        Node name = doc.selectSingleNode("/person/p1/name");
        // 打印信息
        System.out.print("{" + name.getName() + ": " + name.getText() + "} ");
    }

    /**
     * 使用xpath获取所有name标签
     */
    public static void selectAll() {
        // 获取解析xml后的Document多像
        Document doc = Dom4jUtils.getDocument();
        // 通过方法selectNodes()获取对应的标签
        List<Node> name = doc.selectNodes("//name");
        // 增强for遍历列表输出信息
        for (Node node : name) {
            System.out.print("{" + node.getName() + ": " + node.getText() + "} ");
        }
    }
}

输出结果:

Tags:

最近发表
标签列表