Python讀取xml文件(DOM方法)


  參考:https://www.cnblogs.com/fnng/p/3581433.html

  什么是xml

  xml即可擴展標記語言,它可以用來標記數據,定義數據類型,是一種允許用戶對自己的編輯語言進行定義的源語言。  

  測試 adc.xml

<?xml version="1.0" encoding="utf-8"?>
<catalog>
    <maxid>4</maxid>
    <login username="pytest" passwd='123456'>
        <caption>Python</caption>
        <item id="4">
            <caption>測試</caption>
        </item>
    </login>
    <item id="2">
        <caption>Zope</caption>
    </item>
</catalog>

  Ok ,從結構上,它很像我們常見的HTML超文本標記語言。但他們被設計的目的是不同的,超文本標記語言被設計用來顯示數據,其焦點是數據的外觀。它被設計用來傳輸和存儲數據,其焦點是數據的內容。

  那么它有如下特征: 

  首先,它是有標簽對組成 <aa> </aa>

  標簽可以有屬性: <aa id='123'> </aa>

  標簽可以嵌入數據:<aa>abc</aa>

  標簽可以嵌入子標簽(具有層級關系)

  <aa>

    <bb></bb>

  </aa>

  獲得標簽屬性

  那么,下面我們介紹如何用python來讀取這種類型的文件

# coding=utf-8
# 導入模塊
import  xml.dom.minidom
# 打開xml文檔
dom = xml.dom.minidom.parse('abc.xml')

#得到文檔元素對象
root = dom.documentElement

# 節點名稱
print(root.nodeName)
# catalog
# 節點值,只對文件節點有效
print(root.nodeValue)
# None
# 節點類型
print(root.nodeType)
# 1
print(root.ELEMENT_NODE)
# 1

  如果xml文檔不是文件而是str則使用以下方法獲得對象文檔

xml.dom.minidom.parseString(str)

  無需使用documentElement這個屬性

  注意:測試文件abc.xml和腳本放置在同一個文件夾下,並且腳本運行目錄也是在該文件夾下,否則可能找不到文件

  vscode終端的路徑需要到當前腳本的路徑,如下圖

 

   mxl.dom.minidom模塊用來處理xml文件,所以要先引入。

  xml.dom.minidom.parse() 用於打開一個xml文件,並將這個文件對象賦值給dom變量。

  documentElement 用於得到dom對象的文檔元素,並把獲得的對象給賦值給root變量。

  每一個結點都有它的nodeName,nodeValue,nodeType屬性。

  nodeName為結點名字。

  nodeValue是結點的值,只對文本結點有效。

  nodeType是結點的類型。catalog是ELEMENT_NODE類型

  現在有以下幾種:

  'ATTRIBUTE_NODE'
  'CDATA_SECTION_NODE'
  'COMMENT_NODE'
  'DOCUMENT_FRAGMENT_NODE'
  'DOCUMENT_NODE'
  'DOCUMENT_TYPE_NODE'
  'ELEMENT_NODE'
  'ENTITY_NODE'
  'ENTITY_REFERENCE_NODE'
  'NOTATION_NODE'
  'PROCESSING_INSTRUCTION_NODE'
  'TEXT_NODE'

  NodeTypes - 有名常數

  http://www.w3school.com.cn/xmldom/dom_nodetype.asp

  獲得子標簽

  現在要獲得catalog的子標簽,對於知道元素名字的子元素,可以使用getElementsByTagName方法獲取

  例如獲取元素名為maxid和login的子標簽

#得到文檔元素對象
root = dom.documentElement
# 獲取的還是DOM對象,生成列表,有多少個同名子標簽則有多少個列表元素
# 'maxid'只有一個元素
bb = root.getElementsByTagName('maxid')
# 把列表的第一個元素賦值給b
b = bb[0]
# 打印子元素的nodeName屬性
print(b.nodeName)
# maxid

bb = root.getElementsByTagName('login')
b = bb[0]
print(b.nodeName)
# login

  如何區分相同標簽名字的標簽

  <caption>和<item>標簽不止一個如何區分?

# 區分相同名字標簽,使用下標
import  xml.dom.minidom

#打開xml文檔
dom = xml.dom.minidom.parse('abc.xml')

#得到文檔元素對象
root = dom.documentElement

bb = root.getElementsByTagName('caption')
# 第三個
b= bb[2]
print(b.nodeName)
# caption

bb = root.getElementsByTagName('item')
# 第二個
b= bb[1]
print(b.nodeName)
# item

  root.getElementsByTagName('caption') 獲得的是標簽為caption 一組標簽,b[0]表示一組標簽中的第一個;b[2] ,表示這一組標簽中的第三個。

  獲得標簽屬性值

  <login>和<item>標簽是有屬性的,如何獲得他們的屬性?

  獲取標簽login的屬性值username和passwd以及標簽item的id值

# 獲取標簽屬性值
import  xml.dom.minidom

#打開xml文檔
dom = xml.dom.minidom.parse('abc.xml')

#得到文檔元素對象
root = dom.documentElement
# 查找'login'
itemlist = root.getElementsByTagName('login')
# 找到的第一個元素賦值給item
item = itemlist[0]
# 獲取標簽的屬性值username
un=item.getAttribute("username")
print(un)
# pytest
pd=item.getAttribute("passwd")
print(pd)
# 123456

ii = root.getElementsByTagName('item')
i1 = ii[0]
i=i1.getAttribute("id")
print(i)
# 4

i2 = ii[1]
i=i2.getAttribute("id")
print(i)
# 2

  對應關系如下

 

   獲取標簽直接的數據

  <caption> </caption>標簽之間是有數據的,如何獲得這些數據

  獲得標簽之間數據有多種方法

  方法一

# 獲取標簽之間的數據
# 獲取標簽屬性值
import  xml.dom.minidom

#打開xml文檔
dom = xml.dom.minidom.parse('abc.xml')

#得到文檔元素對象
root = dom.documentElement

cc = root.getElementsByTagName('caption')
c1 = cc[0]
print(c1.firstChild.data)
# Python

c2 = cc[1]
print(c2.firstChild.data)
# 測試

c3 = cc[2]
print(c3.firstChild.data)
# Zope

  firstChild 屬性返回被選節點的第一個子節點,.data表示獲取該節點的數據。

  對應關系如下

 

   方法二

from xml.etree import ElementTree as ET
per=ET.parse('abc.xml')
p=per.findall('./login/item')

for oneper in p:
    for child in oneper.getchildren():
        print(child.tag,':',child.text)


p=per.findall('./item')

for oneper in p:
    for child in oneper.getchildren():
        print(child.tag,':',child.text)

# caption : 測試
# caption : Zope

  方法二有點復雜,所引用模塊也與前面的不一樣,findall用於指定在哪一級標簽下開始遍歷。

  getchildren方法按照文檔順序返回所有子標簽。並輸出標簽名(child.tag)和標簽的數據(child.text)

   其實,方法二的作用不在於此,它核心功能是可以遍歷某一級標簽下的所有子標簽。

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM