1
votes

Analyser XML avec des enfants qui ont des balises différentes en Python

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


0 commentaires

3 Réponses :


1
votes

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.


1 commentaires

J'ai utilisé cette option, cela a fonctionné comme un charme. Merci!



2
votes

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


0 commentaires

0
votes

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]))


2 commentaires