Mon fichier XML ressemble à ceci:
<?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>
Tout ce que je veux faire, c'est extraire le ListPrice.
Voici le code que j'utilise:
>> 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
>>
Absolument aucune sortie. J'ai aussi essayé
>> e = element.findall('Items/Item/ItemAttributes/ListPrice/Amount')
Aucune différence.
Qu'est-ce que je fais mal?
Vous avez 2 problèmes.
1) element
ne contient que l'élément racine, pas récursivement tout le document. Il est de type Element et non ElementTree.
2) Votre chaîne de recherche doit utiliser des espaces de noms si vous conservez l'espace de noms dans le XML.
Pour résoudre le problème # 1:
Vous devez changer:
element = ET.parse(fp).getroot()
à:
element = ET.parse(fp)
Pour résoudre le problème # 2:
Vous pouvez retirer les xmlns du document XML pour qu'il ressemble à ceci:
<?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>
Avec ce document, vous pouvez utiliser la chaîne de recherche suivante:
e = element.findall('Items/Item/ItemAttributes/ListPrice/Amount')
Le code complet:
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
Solution alternative au problème # 2:
Sinon, vous devez spécifier les xmlns à l'intérieur de la chaîne de recherche pour chaque élément.
Le code complet:
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
Les deux imprimés:
2260
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
Pensez également à utiliser lxml . C'est beaucoup plus rapide.
from lxml import ElementTree as ET
J'ai fini par retirer les xmlns du xml brut comme ça:
def strip_ns(xml_string):
return re.sub('xmlns="[^"]+"', '', xml_string)
Évidemment, soyez très prudent avec cela, mais cela a bien fonctionné pour moi.
L'arborescence des éléments utilise des espaces de noms, donc tous les éléments de votre xml ont un nom comme { http://webservices.Amazon.com/AWSECommerceService/2008-08-19 } Éléments
Donc, faites en sorte que la recherche inclue l'espace de noms, par ex.
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 )
donne l'élément correspondant à 2260
L'une des approches les plus simples et fonctionne même avec python 3.0 et d'autres versions est comme ci-dessous:
Il prend juste la racine et commence à y entrer jusqu'à ce que nous obtenions la balise "Amount" spécifiée
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)