我正在嘗試決議具有多個名稱空間的 XML 檔案。我已經有一個生成命名空間映射的函式——一個帶有命名空間前綴和命名空間識別符號的字典(代碼中的示例)。但是,當我將此字典傳遞給該findall()方法時,它僅適用于第一個命名空間,但如果 XML 路徑上的元素位于另一個命名空間中,則不會回傳任何內容。
(它僅適用于具有None前綴的第一個命名空間。)
這是一個代碼示例:
import xml.etree.ElementTree as ET
file - '.\folder\example_file.xml' # path to the file
xml_path = './DataArea/Order/Item/Price' # XML path to the element node
tree = ET.parse(file)
root = tree.getroot()
nsmap = dict([node for _, node in ET.iterparse(exp_file, events=['start-ns'])])
# This produces a dictionary with namespace prefixes and identifiers, e.g.
# {'': 'http://firstnamespace.example.com/', 'foo': 'http://secondnamespace.example.com/', etc.}
for elem in root.findall(xml_path, nsmap):
# Do something
編輯: 根據 mzjn 的建議,我包括示例 XML 檔案:
<?xml version="1.0" encoding="utf-8"?>
<SampleOrder xmlns="http://firstnamespace.example.com/" xmlns:foo="http://secondnamespace.example.com/" xmlns:bar="http://thirdnamespace.example.com/" xmlns:sta="http://fourthnamespace.example.com/" languageCode="en-US" releaseID="1.0" systemEnvironmentCode="PROD" versionID="1.0">
<ApplicationArea>
<Sender>
<SenderCode>4457</SenderCode>
</Sender>
</ApplicationArea>
<DataArea>
<Order>
<foo:Item>
<foo:Price>
<foo:AmountPerUnit currencyID="USD">58000.000000</foo:AmountPerUnit>
<foo:TotalAmount currencyID="USD">58000.000000</foo:TotalAmount>
</foo:Price>
<foo:Description>
<foo:ItemCode>259601</foo:ItemCode>
<foo:ItemName>PORTAL GUN 6UBC BLUE</foo:ItemName>
</foo:Description>
</foo:Item>
<bar:Supplier>
<bar:SupplierID>4474</bar:SupplierID>
<bar:SupplierName>APERTURE SCIENCE, INC</bar:SupplierName>
</bar:Supplier>
<sta:DeliveryLocation>
<sta:RecipientID>103</sta:RecipientID>
<sta:RecipientName>WARHOUSE 664</sta:RecipientName>
</sta:DeliveryLocation>
</Order>
</DataArea>
</SampleOrder>
uj5u.com熱心網友回復:
您應該在 xml_path 中指定命名空間,例如:./foo:DataArea/Order/Item/bar:Price. 它與空命名空間一起使用的原因是因為它是默認值,您不必在路徑中指定該命名空間。
uj5u.com熱心網友回復:
根據 Jan Jaap Meijerink 的回答和 mzjn 在問題下的評論,解決方案是在 XML 路徑中插入命名空間前綴。這可以通過插入通配符{*}作為 mzjn 的評論來完成,這個答案(https://stackoverflow.com/a/62117710/407651)建議。
要記錄解決方案,您可以將這個簡單的操作添加到您的代碼中:
xml_path = './DataArea/Order/Item/Price/TotalAmount'
xml_path_splitted_to_list = xml_path.split('/')
xml_path_with_wildcard_prefix = '/{*}'.join(xml_path_splitted_to_list)
如果有兩個或多個節點具有相同的 XML 路徑但不同的命名空間,findall()方法(很自然)會訪問所有這些元素節點。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/418196.html
標籤:
