1. 程式人生 > 其它 >XML之dom4j的xpath解析

XML之dom4j的xpath解析

 

簡介:

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:

NO.

方法

引數

作用

1、

獲取多個節點:public List selectNodes(String xpathExpression)

xpathExpression:xpath表示式

根據 XPath 表示式將結果作為節點例項或字串例項的列表返回。

2、

  獲取一個節點:public Node selectSingleNode(String xpathExpression)  
xpathExpression:xpath表示式
 根據XPath 表示式並將結果作為單個 Node 例項返回

 

程式碼實現:

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;
    }
}

輸出結果: