XML解析(Dom4j)

Dom(文檔對象模型(Document Object Model))

W3C 文檔對象模型 (DOM) 是中立於平臺和語言的接口(可用於任何編程語言),它允許程序和腳本動態地訪問和更新文檔的內容、結構和樣式。

Dom的特點:將文檔一次性加入到內存,並解析爲樹狀結構的數據。所以說Dom只適合於解析相對較小的文件,不然的話一次性讀入到內存中,將很容易造成內存溢出。
    整個文檔是一個文檔節點
    每個 HTML 標籤是一個元素節點
    包含在 HTML 元素中的文本是文本節點
    每一個 HTML 屬性是一個屬性節點
    註釋屬於註釋節點

——————————JAVA——————————
下面舉個例子詳細說明:用Dom4j解析people.xml文件
總結下,學習過程中遇到的小坑:
1.因爲我創建的是一個maven項目,當時就是把people.xml放在代碼文件一起,同一級目錄下的,後來,始終都報null Nested exception,找不到對應的xml文件,才知道maven項目,非.java結尾的文件,放到src/main/java文件中都會找不着,必須對應的放到resource中去。
2.Collections.sort(people,(o1, o2) -> o1.getName().compareTo(o2.getName()));當name是中文字符的時候,這種方法的比較可能並不會得到我們想要的答案,我們需要利用Collactor來進行比較。如果需要使用特定地點的比較規則,則需要使用Collator.getInstance(Locale desiredLocale).

Collections.sort(people,(o1, o2) -> Collator.getInstance().compare(o1.getName(),o2.getName()));

先看一下people.xml文件:
people.xml
第一步:生成saxreader對象,

SAXReader saxReader = new SAXReader();

第二步:生成document對象

Document document = saxReader.read(DomTest.class.getClassLoader().getResourceAsStream("com/bigdata/BBTree/people.xml"));

第三步:獲取根節點

Element root =  document.getRootElement();

第四步:獲取根節點的子節點,返回值是一個list列表。

List<Element> el = root.elements();

對於Element,我們可以調用elements()方法,得到它的所有子節點。
一步步遞歸下去,就能得到所有的節點。

List<Element> el = root.elements();
    for (Element e:el) { }

將每一步得到的結果進行輸出,就可以得出樹的大概結構。

這裏寫圖片描述

那麼我們通過遍歷就能解析出每個節點的數據,從而進行對應的操作。

List<Person> people = new ArrayList<>();
    Person p;
    for (Element e:el) {
        String name = e.element("name").getText();
        int age = Integer.valueOf(e.elementText("age"));
        String tel = e.elementText("tel");
        p= new Person(name,age,tel);
        people.add(p);
    }
    System.out.println(people);

——————————PYTHON——————————

對於python中使用dom4j,和java相比較就是換湯不換藥。
首先需要的是,
1.手動導入模塊:

from xml.dom.minidom import parse

2.運用導入的模塊,生成document對象,此處people.xml跟python文件放用一級目錄即可。

doc=parse("people.xml")

3.獲取根節點:

e=doc.documentElement

4.根據tag獲取各個節點信息,返回一個列表,可使用index訪問具體某一個元素.

ps=e.getElementsByTagName("person")
nm=e.getElementsByTagName("name")[0]

這個時候就將xml中的數據解析出來了。不過通過對比,我感覺這棵樹,和我們用java解析出來的那棵樹還是不同的,具體我們來看下。
子節點運行結果
由圖中運行結果可以看出,第一個Person元素的子節點就有7個,4個text node,3個element。這讓我很是納悶,搗鼓了好一會終於發現了,原來所謂的element元素就是寫在尖括號中,也就是標籤,而Text Node指的是寫在外面的text,看下面這張圖:
tree
4個text node節點分別爲元素節點和元素節點之間的回車換行和空格,
3個Element節點爲name,age,tel三個元素。
而對於name節點而言,它的子節點就是一個Text node,zhangsan,這麼一想,樹的結構就清晰多啦。

下面就可以對解析出來的數據做處理啦:

people=[]
ps=e.getElementsByTagName("person")
for p in ps:
    name=p.getElementsByTagName("name")[0].childNodes[0].data
    age=p.getElementsByTagName("age")[0].childNodes[0].data
    tel=p.getElementsByTagName("tel")[0].childNodes[0].data
    p=Person(name,age,tel)
    people.append(p)
print(people)
for p in sorted(people,key=lambda i:i.age ):
    print(p)
people.sort(key=lambda p:p.name,reverse=True)
print(people)

總體來說還是比較簡單,但是因爲是一次性讀取文件,所以在使用上只適用於小文件的解析,有一定的侷限性,需要導入jar包才能使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章