參考: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)
其實,方法二的作用不在於此,它核心功能是可以遍歷某一級標簽下的所有子標簽。
