J'essaie d'analyser les données XML suivantes à partir d'un fichier avec python pour imprimer uniquement les éléments avec la balise "zip-code" avec son nom d'attribut
from xml.etree import ElementTree as ET
tree = ET.parse('file.xml')
root = tree.getroot()
items = root.iter('entry')
for item in items:
zip = item.find('zip-code').text
names = (item.attrib)
print(' {} {} '.format(
names, zip
))
Le code python que j'essaye à exécuter est
<response status="success" code="19"><result total-count="1" count="1">
<address>
<entry name="studio">
<zip-code>14407</zip-code>
<description>Nothing</description>
</entry>
<entry name="mailbox">
<zip-code>33896</zip-code>
<description>Nothing</description>
</entry>
<entry name="garage">
<zip-code>33746</zip-code>
<description>Tony garage</description>
</entry>
<entry name="playstore">
<url>playstation.com</url>
<description>game download</description>
</entry>
<entry name="gym">
<zip-code>33746</zip-code>
<description>Getronics NOC subnet 2</description>
</entry>
<entry name="e-cigars">
<url>vape.com/24</url>
<description>vape juices</description>
</entry>
</address>
</result></response>
Cependant, il échoue une fois qu'il parvient aux éléments sans balise "zip-code".
Comment puis-je faire cela? Merci d'avance
3 Réponses :
Votre boucle devrait ressembler à ceci:
# Find all <entry> tags in the hierarchy
for item in root.findall('.//entry'):
# Try finding a <zip-code> child
zipc = item.find('./zip-code')
# If found a child, print data for it
if zipc is not None:
names = (item.attrib)
print(' {} {} '.format(
names, zipc.text
))
Tout est une question d'apprendre à utiliser xpath correctement lors d'une recherche dans l'arborescence XML.
J'ai utilisé cette option, cela a fonctionné comme un charme. Merci!
Comme @AmitaiIrron l'a suggéré, xpath peut vous aider ici.
Ce code recherche dans le document l'élément nommé zip-code et retourne un ping pour obtenir le parent de cet élément. À partir de là, vous pouvez obtenir l'attribut name et l'associer au texte de l'élément zip-code
{ent.attrib.get('name') : ent.find('zip-code').text
for ent in root.findall(".//zip-code/..")}
{'studio': '14407', 'mailbox': '33896', 'garage': '33746', 'gym': '33746'}
OU
for ent in root.findall(".//zip-code/.."):
print(ent.attrib.get('name'), ent.find('zip-code').text)
studio 14407
mailbox 33896
garage 33746
gym 33746
Si vous n'avez aucun problème avec les expressions régulières, ce qui suit fonctionne très bien:
studio 14407 mailbox 33896 garage 33746 aystore 33746
et produit le résultat:
import re
file = open('file.xml', 'r').read()
pattern = r'name="(.*?)".*?<zip-code>(.*?)<\/zip-code>'
matches = re.findall(pattern, file, re.S)
for m in matches:
print("{} {}".format(m[0], m[1]))