Gezielt in XML Strukturen suchen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Tim86
User
Beiträge: 2
Registriert: Dienstag 9. März 2021, 15:34

Dienstag 9. März 2021, 15:46

Guten Tag zusammen,

ich bin inzwischen wirklich absolut verzweifelt und hoffe bei euch jemanden zu finden, der/die mir helfen kann.
Ich möchte ganz gerne aus einer XML gezielt Daten auslesen. Jedoch sind in dieser XML mehrere solcher Datafields vorhanden mit den selben Tag-Names.

Code: Alles auswählen

<datafield>
   <data>Humidity</data>
   <shortcut>HUM</shortcut>
   <description>Descriptor</description>
   <info>Information</info>
   <bitoffs>8</bitoffs>
   <bitsize>8</bitsize>
   <range>
      <min>0</min>
      <max>250</max>
   </range>
   <scale>
     <min>0</min>
     <max>100</max>
   </scale>
     <unit>%</unit>
</datafield>
Hab inzwischen alles mögliche an Methoden ausprobiert aber entweder bekomme ich nichts raus oder in oftmals zB alle max-werte von Ranges aus allen datafields in der XML :(

Wäre euch wirklich dankbar, wenn mir jemand weiterhelfen könnte.

Beste Grüße
Tim
nezzcarth
User
Beiträge: 1315
Registriert: Samstag 16. April 2011, 12:47

Dienstag 9. März 2021, 18:33

Das geht zum Beispiel per XPath sehr gut, am besten über lxml.etree.
Benutzeravatar
__blackjack__
User
Beiträge: 8823
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Dienstag 9. März 2021, 21:44

@Tim86: Es fehlt die Information was Du denn nun daraus haben willst, und wie Du genau dieses <datafield> als dasjenige welche identifiziert hast aus dem Du etwas haben willst. Und was Du versucht hast wäre auch interessant. *Alles* sicher nicht, denn da wäre dann ja auch die richtige Lösung dabei gewesen. 😉
Q: What is the volume of a pizza of radius z and thickness a?
A: pi·z·z·a
Tim86
User
Beiträge: 2
Registriert: Dienstag 9. März 2021, 15:34

Mittwoch 10. März 2021, 11:08

Alles sicherlich noch nicht. Sonst würde ich nicht glauben dass hier vllt. jemand die Lösung kennt :mrgreen:

Ich will unterschiedliche Informationen. Die bitoffs, bitsizes und jeweils die Werte in range und scale.
und wie Du genau dieses <datafield> als dasjenige welche identifiziert hast aus dem Du etwas haben willst
Die Frage versteh ich nicht ganz. Falls sie jedoch darauf abzielt, dass ich attributes verwenden sollte, dann muss ich leider sagen, dass ich auf die XML keinen Einfluss habe. Ich lese sie in genau der Form aus.

Versucht habe ich bisher über den Index ranzukommen. Also z.B.

Code: Alles auswählen

hum_bitsize = int(root[0][0][3][2][4][5][5].text)
Das funktioniert zwar auch super. Aber sobald die XML wechselt verändert sich leider auch die Strukur vom Tree. Die Elemente bleiben jedoch die selben. Daher funktioniert diese Lösung nur statisch für eine XML. Daher suche sich ewas flexibleres.

Code: Alles auswählen

for a in root.findall('profile/rorg/func/type/case/datafield/data'):
    print(a.text)
Ich habe auch schon über findall versucht. Aber wie der Name schon sagt, findet er dann alle data im gesamten Dokument. Da es ja mehrere datafields gibt.

Die bisher aufwendigste Lösung war, dass ich die XML in ein Dictionary umgewandelt habe um dann anschließend über die Elemente versucht hab durchzugehen.

Code: Alles auswählen

print(xmldict['profile']['rorg']['func']['type']['case']['datafield'])
Das funktioniert bis datafield auch ganz gut. Aber sobald dann mehrere Datafields des gleichen Namens kommen sprengt es diese Methode ebenfalls =(
Benutzeravatar
__blackjack__
User
Beiträge: 8823
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mittwoch 10. März 2021, 11:59

@Tim86: Meine Frage zielt darauf ab das Du sagst es gibt im Dokument mehrere <datafield>-Elemente und Du willst nur aus einem davon Daten und dann zeigst Du nur *ein* <datafield>. Was ist denn das Kriterium das Du ausgerechnet *dieses* herausgegriffen hast? Das muss sich doch irgendwie von den anderen unterscheiden und das muss man ja wissen wenn man Code schreiben will der genau dieses aussucht und keines der anderen. Der Code muss letztlich alle <datafield> durchgehen und bei jedem entscheiden ob es das ist welches Du haben willst. Oder willst Du einfach nur das erste <datafield> im Dokument?

Auf jeden Fall ist das mehr als ein Schritt. Du musst erst das <datafield> raus suchen. Und dann im nächsten Schritt die <data>-Elemente daraus die Dich interessieren.

Code: Alles auswählen

#!/usr/bin/env python3
from lxml import objectify

SOURCE = """\
<root>
    <datafield>
        <data>Humidity</data>
        <shortcut>HUM</shortcut>
        <description>Descriptor</description>
        <info>Information</info>
        <bitoffs>8</bitoffs>
        <bitsize>8</bitsize>
        <range>
            <min>0</min>
            <max>250</max>
        </range>
        <scale>
            <min>0</min>
            <max>100</max>
        </scale>
            <unit>%</unit>
    </datafield>
</root>
"""


def main():
    document = objectify.fromstring(SOURCE)
    #
    # TODO An dieser Stelle ist halt interessant nach welchen Kriterium das
    #   <datafield> ausgewählt werden soll.  Im Moment ist es einfach das erste
    #   Kindelement das vorkommt.
    #
    datafield = document.find("datafield")
    print(
        datafield.bitoffs,
        datafield.bitsize,
        (datafield.range.min, datafield.range.max),
        (datafield.scale.min, datafield.scale.max),
    )


if __name__ == "__main__":
    main()
Ausgabe:

Code: Alles auswählen

8 8 (0, 250) (0, 100)
Q: What is the volume of a pizza of radius z and thickness a?
A: pi·z·z·a
Antworten