[英]Parse xsi:type in XML with ElementTree in Python
我正在嘗試連接到RESTful API,並且在構建XML請求時遇到問題,因為我正在使用Elementree庫。
我有一個我必須在請求中發送的XML示例。 從該示例中構建模型,然后按代碼編寫不同的屬性。 但輸出XML與我給出的示例不完全相同,我無法連接到API。
這是我的例子:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetLoc xmlns="http://abc/Getloc">
<request>
<Access>
<string xmlns="http://bcd/Arrays"></string>
</Access>
<Details xsi:type="Request">
<Postcode ></Postcode >
</Details>
<UserConsent>Yes</UserConsent>
</request>
</GetLoc>
</soap:Body>
</soap:Envelope>
這是我的代碼:
tree = ET.parse('model.xml')
root = tree.getroot()
ns = {'loc':'http://abc/Getloc',\
'arr':http://bcd/Arrays',\
'soapenv':'http://schemas.xmlsoap.org/soap/envelope/', \
'xsi':"http://www.w3.org/2001/XMLSchema-instance", \
xsd': "http://www.w3.org/2001/XMLSchema"}
tree.find('.//arr:string', ns).text = 'THC'
tree.find('.//Postcode ', ns).text = '15478'
這是輸出XML(SOAP):
<ns0:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://abc/Getloc" xmlns:ns2="http://bcd/Arrays" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns0:Body>
<ns1:GetLoc >
<ns1:request>
<ns1:Access>
<ns2:string>THC</ns2:string>
</ns1:Access>
<ns1:Details xsi:type="Request">
<ns1:Postcode >15478</ns1:Postcode >
</ns1:Details>
<ns1:UserConsent>Yes</ns1:UserConsent>
</ns1:request>
</ns1:GetLoc >
</ns0:Body>
</ns0:Envelope>
通過示例(上面的第一個),連接到API時沒有問題。 然而,第二個我得到並錯誤:
" status="Service Not Found. The request may have been sent to an invalid URL, or intended for an unsupported operation." xmlns:l7="http://www.layer7tech.com/ws/policy/fault"/>"
兩個XML都使用相同的標頭和auth發送到同一個URL。 我看到兩個XML等價,所以我期待相同的行為。 我不明白為什么它不起作用。
編輯:輸出XML需要像
<ns0:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://abc/Getloc" xmlns:ns2="http://bcd/Arrays" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns0:Body>
<ns1:GetLoc >
<ns1:request>
<ns1:Access>
<ns2:string>THC</ns2:string>
</ns1:Access>
<ns1:Details xsi:type="ns1:Request">
<ns1:Postcode >15478</ns1:Postcode >
</ns1:Details>
<ns1:UserConsent>Yes</ns1:UserConsent>
</ns1:request>
</ns1:GetLoc >
</ns0:Body>
</ns0:Envelope>
但我不知道如何更改代碼來獲取: xsi:type =“ns1:Request”
最后我自己找到了解決方案。
解決方案就在這里 (一篇非常完整的文章),因為我已經在使用ElementTree了。 您可以找到其他解決方案,例如使用lxml庫。
因此,對於ElementTree,我只需要使用自己的解析器而不是標准的ElementTree.parse('file.xml') 。
xsi屬性名稱由解析器處理,但解析器不知道該屬性恰好包含限定名稱,因此它保持原樣。 為了能夠處理這種格式,您可以使用知道如何處理某些屬性和元素的自定義解析器,或者跟蹤每個元素的前綴映射。 要執行后者,您可以使用iterparse解析器,並要求它報告“start-ns”和“end-ns”事件。 以下代碼段為每個元素添加了一個ns_map屬性,其中包含適用於該特定元素的前綴/ URI映射:
def parse_map(file):
events = "start", "start-ns", "end-ns"
root = None
ns_map = []
for event, elem in ET.iterparse(file, events):
if event == "start-ns":
ns_map.append(elem)
elif event == "end-ns":
ns_map.pop()
elif event == "start":
if root is None:
root = elem
elem.ns_map = dict(ns_map)
return ET.ElementTree(root)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.