1. 程式人生 > >XML檔案解析--xpath技術

XML檔案解析--xpath技術

最近用到xml檔案解析,剛開始竟然忘了xpath,一股腦不斷的用各種for,for,for迴圈遍歷,還在想break來減少迴圈…,寫得差不多的時候覺得很不對勁,終於想到xpath(我不是菜鳥,我是小菜鳥…)。先了解下皮毛吧,記錄一下。

一、Element(元素)和節點(Node)
節點:
- element 元素(常用)
- attribute 屬性(常用)
- text 文字(常用)
- namespace 名稱空間
- processing-instruction 處理指令
- comment 註釋
- root 根節點(文件節點)

可以這麼理解,一個Element(元素)一定是節點(Node),但一個節點不一定是Element(元素)。

XML

<?xml version="1.0" encoding="UTF-8"?>
    <School>
        <class id="1">
            <classNo>C_1</classNo>
            <className>class 1</className>
            <students>
                <student
>
<sno>C_1_1</sno> <sname>Jack</sname> <age>13</age> </student> <student> <sno>C_1_2</sno> <sname>Tom</sname
>
<age>12</age> </student> </students> </class> <class id="2"> <classNo>C_2</classNo> <className>class 2</className> <students> <student> <sno>C_2_1</sno> <sname>Jim</sname> <age>13</age> </student> </students> </class> <class > <classNo>C_3</classNo> <className>class 3</className> <students> <student> <sno>C_3_1</sno> <sname>Jim</sname> <age>13</age> </student> </students> </class> </School>

二、選擇節點的規則
nodeName: 表示選擇該節點下名稱為nodeName的子節點
“/”: 表示選擇根節點
“/”: 同時也用作路徑分隔符
“//”: 表示選擇任意位置的符合條件的節點。不管它們在文件中的位置
“.” : 表示當前節點,
“..” 表示當前結點的父節點
“@” : 選擇屬性

package com.peter.test;
import java.io.File;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;

public class Test1 {

    private static String path = "D:/CSDN/test/xmlTest.xml";
    private static Document document = null;

    static {
        SAXReader sr = new SAXReader();
        try {
            document = sr.read(new File(path));
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void getNodes() {
        // 獲取根節點
        Node rootNode = document.selectSingleNode("/");
        System.out.println(rootNode.getName()); // file:///D:/CSDN/test/xmlTest.xml

        Node rootNode1 = document.selectSingleNode("School"); // School是document的子節點
        System.out.println(rootNode1.getName()); // School

        Node rootNode2 = document.selectSingleNode("/School");
        System.out.println(rootNode2.getName()); // School

        List<Node> classNode = rootNode2.selectNodes("class"); // class是School的子節點
        System.out.println(classNode.size()); // 2
        System.out.println(classNode.get(0).getName() + "---"
                + classNode.get(1).getName()); // class---class

        //無視節點在文件的路徑      “//” 只要符合條件,無視在文件的位置,全部抓取到
        List students = document.selectNodes("//student");
        System.out.println(students.size()); //3 (xml文件中有3個student節點) 

        //相對路徑 "."表示當前的節點  
        Node shelfNode = classNode.get(0).selectSingleNode(".");
        Node NoNode = classNode.get(0).selectSingleNode("./classNo");
        System.out.println(shelfNode.getName()); //class
        System.out.println(NoNode.getName()+"---"+NoNode.getText()); //classNo---C_1

        //父節點
        Node pNode = classNode.get(0).selectSingleNode("..");
        System.out.println(pNode.getName()); //School

        //屬性 獲取所有名為id的屬性
        Node attriNode = document.selectSingleNode("//@id"); //
        System.out.println(attriNode.getName()+"--"+attriNode.getText()); //id--1

    }

}

三、謂語(帶條件過濾)
用來查詢某個特定的節點或者包含某個指定的值的節點。
[] : 謂語寫在中括號中。

@Test
    public void getNodes() {
        // 獲取根節點
        Node rootNode = document.selectSingleNode("/");
        System.out.println(rootNode.getName()); // file:///D:/CSDN/test/xmlTest.xml

        Node rootNode1 = document.selectSingleNode("School"); // School是document的子節點
        System.out.println(rootNode1.getName()); // School

        //謂語 (過濾條件)
        /**
         *      "//student[sno='C_1_1']" 
         *      //student:把所有的student節點抓取到
         *      [sno='C_1_1']:在抓取到的節點中篩選 出 sno="C_1_1"的節點
         */
        //獲取班號為C_1_1的班級
        List<Node> studentNodes = document.selectNodes("//student[sno='C_1_1']");
        System.out.println(studentNodes.size()); //1
        System.out.println(studentNodes.get(0).selectSingleNode("./sname").getText()); //Jack

        //獲取id為2的班級
        List<Node> classNodes = document.selectNodes("//class[@id='2']");
        System.out.println(classNodes.size());//1
        System.out.println(classNodes.get(0).selectSingleNode("./className").getText());//class 2

        //獲取擁有屬性名為id的班級
        List<Node> classNodes2 = document.selectNodes("//class[@id]");
        System.out.println(classNodes2.size());//2
        System.out.println(classNodes2.get(0).selectSingleNode("./className").getText());//class 1
        System.out.println(classNodes2.get(1).selectSingleNode("./className").getText());//class 2
    }

四、萬用字元
“*” : 匹配任何元素節點
“@*” : 匹配任何屬性節點
Node() 匹配任何型別的節點

@Test
    public void getNodes() {
        // 獲取根節點
        Node rootNode = document.selectSingleNode("/");
        System.out.println(rootNode.getName()); // file:///D:/CSDN/test/xmlTest.xml

        Node rootNode1 = document.selectSingleNode("School"); // School是document的子節點
        System.out.println(rootNode1.getName()); // School

        // "*" 萬用字元表示任何的元素節點
        List<Node> studentInfoElems = document.selectNodes("//student/*");
        System.out.println(studentInfoElems.size()); //12

        // “@*” : 匹配任何屬性節點
        List<Node> attriElems = document.selectNodes("//@*");
        System.out.println(attriElems.size()); //2
        System.out.println(attriElems.get(0).getName()+"---"+attriElems.get(0).getText());//id---1
        System.out.println(attriElems.get(1).getName()+"---"+attriElems.get(1).getText());//id---2

    }

待續…

五、選取若干路徑
使用”|”運算子,可以選取若干個路徑。
//book/title | //book/price 選取 book 元素的所有 title 和 price 元素。

六、相對路徑和絕對路徑
絕對路徑必須要以”/”開頭
相對路徑可以 以”./”開頭,也可以直接以元素名稱開頭。