Considérez le XML suivant qui ne contient que deux nœuds appelés Mydoc:

<?xml version="1.0" encoding="UTF-8" ?>
<Mydoc Time="2017-01-02"
    Period="2017-01-03">
    <mycontent ClassID="kinder">
        <bibliography>
            <Id>
                <Num>123456</Num>
            </Id>
                <Body>
this is some crazy text my friend
                </Body>
                <myreaders>
                    <names>
                        <Id>john</Id>
                        <value>95</value>
                    </names>
                </myreaders>
                <school>
                    <myclass>
                        <Id>12</Id>
                        <name>Laura</name>
                    </myclass>
                    <myclass>
                        <Id>14</Id>
                        <name>Frank</name>
                    </myclass>
                    <myclass>
                        <Id>144</Id>
                        <name>Jonny</name>
                    </myclass>
                    <myclass>
                        <Id>222</Id>
                        <name>Alex</name>
                    </myclass>
                    <myclass>
                        <Id>5443</Id>
                        <name>Johnny Doe</name>
                    </myclass>
                </school>
        </bibliography>
</mycontent>
    <mycontent ClassID="preK">
        <bibliography>
            <Id>
                <Num>123456</Num>
            </Id>
                <Body>
this is another crazy text my friend
                </Body>
                <myreaders>
                    <names>
                        <Id>fritz</Id>
                        <value>133</value>
                    </names>
                </myreaders>
        </bibliography>
</mycontent>
</Mydoc>

J'essaie d'utiliser xml.etree pour l'analyser et de le placer sur chaque nœud mydoc sur une seule ligne dans une trame de données Pandas.

Cependant, comme vous pouvez le voir, il y a plusieurs éléments appelés myclass que je voudrais combiner en une seule cellule de ma trame de données.

Par exemple, la sortie attendue (une Pandas trame de données avec deux lignes et deux colonnes ) serait quelque chose comme:

myreaders      school
"(john-95)"  "(12-Laura),(14-Frank),(144-Johnny),(222-Alex),(5443-Johnny Doe)"
"(fritz-133)" ""

J'ai essayé de jouer avec xpath mais je n'ai pas pu combiner mes xpath recherches dans une liste stringifiée comme "(12-Laura),(14-Frank),(144-Johnny),(222-Alex),(5443-Johnny Doe)"

Aucune suggestion?

Merci!

0
ℕʘʘḆḽḘ 16 avril 2018 à 23:22

4 réponses

Meilleure réponse

Semblable à d'autres réponses, un peu plus courtes, fonctionne avec les nœuds nouvellement ajoutés:

parsedXML = ET.parse( "sample.xml")
root = parsedXML.getroot()
pairs0 = []
pairs1 = []
for mycontent in root.iter('mycontent'):
    pairs0.append(','.join(['(' + name[0].text + '-' + name[1].text + ')' for name in mycontent.iter('names')]))
    pairs1.append(','.join(['(' + myclass[0].text + '-' + myclass[1].text + ')' for myclass in mycontent.iter('myclass')]))
df = pd.DataFrame(data = {"myreaders": pairs0, "school": pairs1}, columns=['myreaders', 'school'])

Edit: retravaillé pour traiter plusieurs cas.

1
Turo 17 avril 2018 à 14:03

Vous pouvez essayer XmlToDict, et analyser votre XML dans des dictionnaires / listes, cela pourrait faire ce que vous essayez de faire beaucoup plus facile. Vous pouvez ensuite parcourir / parcourir ce qui serait une liste de dictionnaires myclass. J'espère que ça aide un peu.

1
DevOps1 16 avril 2018 à 20:50

Avez-vous envisagé d'utiliser le module lxml? Il a quelques méthodes assez pratiques pour analyser et parcourir un fichier xml. Par exemple, j'ai essayé les listes de recherche suivantes et les ai combinées, que vous pouvez ensuite ajouter au "reste" de votre enregistrement:

from lxml import etree
root = etree.parse(path_to_xml_file)
ids = [i.text for i in root.findall(".//myclass/Id")]
names = [n.text for n in root.findall(".//myclass/Name")]
comb = list(zip(ids,names))

Cela vous donnerait:

[('12', 'Laura'), ('14', 'Frank'), ('144', 'Jonny'), ('222', 'Alex')]
1
Ronny Meissner 16 avril 2018 à 21:07

C'est devenu tout à fait l'engin de compréhension de liste, mais je pense que c'est ce dont vous avez besoin.

import xml.etree.ElementTree as ET
import pandas as pd
tree = ET.parse('test.xml')
root = tree.getroot()
dicty = {}
dicty['myreaders'] = [','.join(['(' + x.findall('Id')[0].text + '-' + x.findall('value')[0].text + ')' for x in (root.findall('.//mycontent/bibliography/myreaders/names'))])]
dicty['school'] = [','.join(['(' + x.findall('Id')[0].text + '-' + x.findall('name')[0].text + ')' for x in (root.findall('.//mycontent/bibliography/school/myclass'))])]
print(dicty)
print(pd.DataFrame(dicty))

Production:

   myreaders                                             school
0  (john-95)  (12-Laura),(14-Frank),(144-Jonny),(222-Alex),(...

Il n'y a pas de moyen vraiment simple d'analyser le XML, vous avez besoin de beaucoup de détails sur la structure des données.

1
Joost 16 avril 2018 à 20:51