日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python之lxml处理xml

發布時間:2025/3/20 python 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python之lxml处理xml 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? 學習過程中遇到了通信的報文為xml的的消息體,將通訊的內容依附于xml的載體進行傳輸,開始嘗試使用包括ElementTree等在內的諸多庫,但是因為一些處理皆不盡人意,最后選擇了lxml庫,該庫無論處理速度還是函數功能封裝基本可以滿足需求。因為lxml不是Python自帶的標準庫,因此需要自己安裝

pip3 install lxml

對于讀取xml常見的有兩種方式,一種是xml的字符串,即字符串的內容是xml文件,另一種是工程中包含xml文件,讀取xml后進行操作,由于實際運用中一般不會直接讀取一段字符串的形式(自己遇到的),都是以xml文件的形式進行讀取,因此這里也以也是先讀取文件,再操作文件。這里以? intuit.xml? 文件為例

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Intuit xmlns="http://schema.intuit.com/finance/v3" time="2016-10-14T10:48:39.109-07:00"><QueryRequest startPosition="1" maxResults="79" totalCount="79"><Bill domain="QBO" sparse="false"><Id>=1</Id><name>zhagsan</name><MsgId>20200406</MsgId></Bill></QueryRequest><QueryResponse startPosition="1" maxResults="79" totalCount="79"><Bill domain="QBO" sparse="false"><Id>=2</Id><name>lisi</name><responseId>20200407</responseId></Bill></QueryResponse> </Intuit>

在xml文件的開頭明顯的發現不同于常規的xml文件,因為攜帶了命名空間xmlns,因此與沒有命名空間的xml相比每一個節點前都用命名空間,如下:

# 讀取xml文件 xml = etree.parse("Intuit.xml") root = xml.getroot() #獲取根節點 # 獲取命名空間 ns = {'x':root.nsmap[None]} print(ns) {'x': 'http://schema.intuit.com/finance/v3'}

xml中每一個節點通常有3個特性,分別是標簽tag,屬性attrib,文本text,因此為了獲取某一個節點的以上特性,需要查找獲取到需要的結點,常用的方法可以是遍歷查找,一種是遍歷所有,另一種是遍歷某個節點

print("遍歷所有節點:") for node in root.iter():print(node.tag)print("遍歷指定節點:") ns = "{http://schema.intuit.com/finance/v3}" for node in root.iter(f"{ns}name"):print(node.tag)

輸出結果為:

當然還有一些其他的查找方法如find,findall,具體使用方法在這里不再贅述,參考xml文檔

常見的還有獲取屬性的函數如:

#獲取屬性 print(root.items()) #獲取全部屬性和屬性值 print(root.keys()) #獲取全部屬性 print(root.get('version', '')) #獲取具體某個屬性

此外使用xpath操作xml是非常常用且重要的功能的,自己在學習中希望的是知道某個節點tag,去修改text值,然后發送修改后的xml文件的消息到服務器,對于xpath,其他的文章已有介紹。對于沒有命名空間的可以通過相對路徑或者絕對路徑進行訪問:

#通過相對路徑 root.xpath('//name')#通過絕對路徑 root.xpath('Intuit/QueryResponse/name')

但這里自然是訪問不了的,因為有命名空間的限制,因此有命名空間的話:

# 導入庫 import lxml.etree as etree# 讀取xml文件 xml = etree.parse("Intuit.xml") root = xml.getroot() #獲取根節點# 獲取命名空間 ns = {'x':root.nsmap[None]} node = root.xpath("//x:name",namespaces=ns) print(node)

輸出結果:

[<Element {http://schema.intuit.com/finance/v3}name at 0x263aa0d4d88>, <Element {http://schema.intuit.com/finance/v3}name at 0x263aa0d4e88>]

注意這里輸出的結果是 list,因此比如需要修改的是? QueryResponse/Bill/name這個標簽的性質,可以使用

node[1].text = "4"

當然還可以通過絕對路徑進行修改

node = root.xpath("//x:Intuit//x:QueryResponse//x:Bill//x:name",namespaces=ns)

其實我們也發現使用絕對路徑貌似有點sha哈,一個是路徑深度太深,第二個是每一個結點都需要加上//x:*使用起來非常麻煩,因此如果能唯一定位,比如MsgId或者是responseId這樣最方便,但是有些結點重復且深度較深。對于結點的定位使用xpath有以下三種形式:

xml = etree.parse("Intuit.xml") root = xml.getroot() #獲取根節點# 獲取命名空間 ns = {'x':root.nsmap[None]}MsgId = root.xpath("//x:MsgId",namespaces=ns) print(MsgId[0].text)name = root.xpath("//x:QueryResponse//..//x:name",namespaces=ns) print(name[0].text)Id = root.xpath("//x:Intuit//x:QueryResponse//x:Bill//x:Id",namespaces=ns) print(Id[0].text)

注意:如果是使用相對路徑中含有..的形式,該..前不能加上//x:*。

當然實際使用過程中發現xml結點較多,且使用多個不同的xml文件,因為每一個xml都有命名空間,因此封裝了文件用于操作xml。

# 導入庫 import reimport lxml.etree as etree# 讀取xml文件 import osclass XmlOperation():def __init__(self):passdef readXml(self,fileName):path = os.path.join("..","resource",fileName)tree = etree.parse(path)self.root = tree.getroot()return self#region設置文本節點def setNodeText(self,xpath="",replaceName="",index=0):ns = {'x':self.root.nsmap[None]}path = ""#如果傳入的xpath以/開頭或者/結尾,則去除開頭或者結尾的/if re.match(r"^(/).+?",xpath) or re.match(r".+?(/)$",xpath):path = xpath.strip("/")#可以唯一定位,如MsgIdif not re.search(r"/",xpath):path = "//x:" + xpathelif re.search(r"/",xpath):pathList = xpath.split("/")#路徑拼接path = "//x:" + "//x:".join(pathList)pattern = re.compile(r"(x:\W{2)")#如果是//x:A//x:..//x:c的形式修改修改為//x:A//..//x:cif pattern.search(path):path = path.replace(r"x:..",r"..")else:raise Exception("路徑輸入有誤")self.root.xpath(path,namespaces=ns)[index].text = replaceName#endregion#region刪除屬性def del_node_attrib(self,node,attrib):if node.getchildren():for child in node.getchildren():del_node_attrib(child,attrib):else:attri = node.attrib.get(attrib)if attri and attri == "√":del node.attrib[attrib]#endregion

這里再插入一點小常識:

1.使用pycharm的時候,生成類(大寫首字母,寫完類名)按下Alt+Enter,導入庫(比如直接使用os.path選中os)按下Alt+Enter都是很好的快捷方法

2.函數的編寫,加入#region...#endregion,可以更方便的瀏覽函數

寫在最后,在學習使用lxml處理的時候遇到了不少問題,推薦幾篇入門的帖子,對于如何使用lxml中攜帶有命名空間的比較有幫助,python讀取xml,和命名空間使用以及lxml處理命名空間

總結

以上是生活随笔為你收集整理的python之lxml处理xml的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。