Mit XPath in ElementTree
-
19-09-2019 - |
Frage
Meine XML-Datei sieht wie folgt aus:
<?xml version="1.0"?>
<ItemSearchResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2008-08-19">
<Items>
<Item>
<ItemAttributes>
<ListPrice>
<Amount>2260</Amount>
</ListPrice>
</ItemAttributes>
<Offers>
<Offer>
<OfferListing>
<Price>
<Amount>1853</Amount>
</Price>
</OfferListing>
</Offer>
</Offers>
</Item>
</Items>
</ItemSearchResponse>
Alles, was ich tun möchte, ist die Listprice extrahieren.
Dies ist der Code verwende ich:
>> from elementtree import ElementTree as ET
>> fp = open("output.xml","r")
>> element = ET.parse(fp).getroot()
>> e = element.findall('ItemSearchResponse/Items/Item/ItemAttributes/ListPrice/Amount')
>> for i in e:
>> print i.text
>>
>> e
>>
Absolut keine Ausgabe. Ich habe auch versucht,
>> e = element.findall('Items/Item/ItemAttributes/ListPrice/Amount')
Kein Unterschied.
Was mache ich falsch?
Lösung
Es gibt zwei Probleme, die Sie haben.
1) element
enthält nur das Wurzelelement, nicht rekursiv das gesamte Dokument. Es ist vom Typ Elemente nicht ElementTree.
2) Ihre Such-Stichwort Bedürfnisse Namespaces verwenden, wenn Sie den Namespace im XML halten.
zu beheben Problem # 1:
Sie müssen ändern:
element = ET.parse(fp).getroot()
zu:
element = ET.parse(fp)
zu beheben Problem # 2:
Sie können die xmlns aus dem XML-Dokument entfernen, so dass es wie folgt aussieht:
<?xml version="1.0"?>
<ItemSearchResponse>
<Items>
<Item>
<ItemAttributes>
<ListPrice>
<Amount>2260</Amount>
</ListPrice>
</ItemAttributes>
<Offers>
<Offer>
<OfferListing>
<Price>
<Amount>1853</Amount>
</Price>
</OfferListing>
</Offer>
</Offers>
</Item>
</Items>
</ItemSearchResponse>
Mit diesem Dokument, das Sie die folgenden Suchzeichenfolge verwenden können:
e = element.findall('Items/Item/ItemAttributes/ListPrice/Amount')
Der vollständige Code:
from elementtree import ElementTree as ET
fp = open("output.xml","r")
element = ET.parse(fp)
e = element.findall('Items/Item/ItemAttributes/ListPrice/Amount')
for i in e:
print i.text
Alternate Fix Problem # 2:
Ansonsten müssen Sie für jedes Element der xmlns innerhalb der srearch Zeichenfolge angeben.
Der vollständige Code:
from elementtree import ElementTree as ET
fp = open("output.xml","r")
element = ET.parse(fp)
namespace = "{http://webservices.amazon.com/AWSECommerceService/2008-08-19}"
e = element.findall('{0}Items/{0}Item/{0}ItemAttributes/{0}ListPrice/{0}Amount'.format(namespace))
for i in e:
print i.text
Sowohl Druck:
2260
Andere Tipps
from xml.etree import ElementTree as ET
tree = ET.parse("output.xml")
namespace = tree.getroot().tag[1:].split("}")[0]
amount = tree.find(".//{%s}Amount" % namespace).text
Bedenken Sie auch mit lxml . Es ist viel schneller.
from lxml import ElementTree as ET
Element Baum Anwendungen Namensraum, so dass alle Elemente in Ihrem xml haben Namen wie { http://webservices.amazon.com/AWSECommerceService/2008-08-19} Artikel
So ist die Suche machen umfassen den Namespace z.
search = '{http://webservices.amazon.com/AWSECommerceService/2008-08-19}Items/{http://webservices.amazon.com/AWSECommerceService/2008-08-19}Item/{http://webservices.amazon.com/AWSECommerceService/2008-08-19}ItemAttributes/{http://webservices.amazon.com/AWSECommerceService/2008-08-19}ListPrice/{http://webservices.amazon.com/AWSECommerceService/2008-08-19}Amount'
element.findall( search )
gibt das Element zu 2260 entspricht,
I beenden die xmlns aus dem rohen xml wie das Strippen oben:
def strip_ns(xml_string):
return re.sub('xmlns="[^"]+"', '', xml_string)
Offensichtlich sehr vorsichtig sein mit diesem, aber es funktionierte gut für mich.
Einer der direkteste Ansatz und arbeitet auch mit Python 3.0 und anderen Versionen ist wie folgt:
Es dauert nur die Wurzel und beginnt in sie bekommen, bis wir das bekommen angegeben "Betrag" Tag
from xml.etree import ElementTree as ET
tree = ET.parse('output.xml')
root = tree.getroot()
#print(root)
e = root.find(".//{http://webservices.amazon.com/AWSECommerceService/2008-08-19}Amount")
print(e.text)