Seite 1 von 1

XML effizient nach Schlüssel-Wert-Paaren durchsuchen

Verfasst: Samstag 27. Mai 2017, 15:30
von XCDRiVER
Hallo,

ich suche eine effiziente Methode um aus den Attributen der Elemente bestimmte Daten auszulesen.
Im Moment bin ich an dieser Stelle angekommen.
Erst mal die Struktur der XML Datei:

[codebox=xml file=Unbenannt.xml]
<data show="------">
<section unit="A" unitTrigger="001" unitTargetIp="10.0.0.11" unitTargetPort="51000">
<event>
<trigger name="" value="666" />
<target ip="192.168.0.5" port="6000" command="abc" value="75" />
</event>
<event>
<trigger name="switch_05" value="1" />
<target ip="192.168.0.5" port="6000" command="efg" value="10" />
</event>
<event>
<trigger name="" value="666" />
<target ip="192.168.0.18" port="8800" command="hij" value="1" />
</event>
</section>

<section unit="B" unitTrigger="002" unitTargetIp="10.0.0.11" unitTargetPort="50000">
<event>
<trigger name="" value="555" />
<target ip="" port="" command="lmn" value="100" />
</event>
<event>
<trigger name="" value="666" />
<target ip="" port="" command="opq" value="50" />
</event>
</section>
</data>[/code]


Mit dem nachfolgenden Python-Schnipsel möchte ich einen Wert, hier z.B. 666
aus dem Element 'trigger' Attribute 'value' finden.
Das soll so Ressourcen schonend wie 'sinnvoll möglich' gehen.
Es ist so,
es kommen etwa 150 Trigger-Werte/Sekunde in das Programm und ich möchte eine Vorauswahl treffen ob die Weiterverarbeitung der
Daten notwendig ist, also, ob eine Reaktion (hinterlegt in XML Element <target>) auf diese Werte erfolgen soll.
Ich möchte also Rechenleistung sparen.
Gibt es einen besseren (dennoch lesbareren) Weg, das zu realisieren?

Code: Alles auswählen

import xml.etree.ElementTree as ET

tree = ET.parse('test.xml')
root = tree.getroot()

if __name__ == "__main__":

## SUCHE NACH value SO KURZ WIE GEHT
    i = 0
    for child in root:
        for werte in root[i].iter('trigger'):
            if (werte.get('value') == "666"):
                print(i)
        i += 1
Vielen Dank für Eure Hinweise

Re: XML effizient nach Schlüssel-Wert-Paaren durchsuchen

Verfasst: Samstag 27. Mai 2017, 18:32
von __deets__
Wenn du schon "child" hast, wozu das gemurkse mit i & root ? Das ist doch das child.

Und "iter('trigger')" kannst du doch gleich auf Root aufrufen, da eh rekursiv (und das nutzt du ja schon)

Last but not least: wenn du Kontrolle über den Prozess hast, der diese xml Daten generiert - hör auf xml zu benutzen. Ereignisse und schließende Tags vertragen sich schlecht. Entweder du generierst lauter kleine xml snippets, dann brauchst du den Aufriss einer hierarchischen Auszeichnung nicht. Oder du schreibst ein großes Dokument - dann ist das so lange ungültig wie nicht das schließende root-Tag kommt.

Re: XML effizient nach Schlüssel-Wert-Paaren durchsuchen

Verfasst: Samstag 27. Mai 2017, 18:49
von BlackJack
@XCDRiVER: Ich würde es ja erst einmal richtig machen, bevor so effizient wie möglich kommt, und wenn man es ganz normal löst, auch erst einmal schauen ob das überhaupt zu langsam ist.

Was bei Deinem Code auffällt ist a) das `child` überhaupt nicht verwendet wird, und b) das ``root`` ja sicher irgendwann zu einer Ausnahme führen wird, denn es wird da ja nicht unendlich viele Elemente geben.

Ansonsten ist die Aufteilung des Code zwischen Modulebene und ``if __name__ …``-Zweig unsinnig. Das gehört dort alles rein. Besser noch in eine Funktion.

Bevor man am eigenen Quelltext rumbastelt, würde ich erst einmal schauen ob `lxml.etree` den gewünschten Geschwindigkeitszuwachs bringt. Das hat grundsätzlich die gleiche API, kann aber beispielsweise auch XPath und man kann von Knoten aus zum Elternknoten navigieren:

Code: Alles auswählen

from lxml import etree
 

def main():
    tree = etree.parse('test.xml')
    for trigger_node in tree.xpath('.//trigger[@value=$value]', value='666'):
        print(trigger_node.getparent().find('target').attrib)
 

if __name__ == "__main__":
    main()

Re: XML effizient nach Schlüssel-Wert-Paaren durchsuchen

Verfasst: Sonntag 28. Mai 2017, 09:56
von XCDRiVER
@ __deets__

danke für deine Hinweise, ich habe den Schnipsel mal so abgeändert wie ich das verstanden habe
Es funktioniert.
an dem Dateiformat xml wollte ich erst mal noch nicht rütteln, es sollte ein Format sein, was von Menschenhand editierbar und durchschaubar ist.
Mir ist da als erstes xml eingefallen.
Auf jeden Fall ist der Code kürzer und übersichtlicher so.

Code: Alles auswählen

import xml.etree.ElementTree as ET

tree = ET.parse('test.xml')
root = tree.getroot()

if __name__ == "__main__":

    for werte in root.iter('trigger'):
        if (werte.get('value') == "666"):
            print("data found")

Re: XML effizient nach Schlüssel-Wert-Paaren durchsuchen

Verfasst: Sonntag 28. Mai 2017, 10:44
von XCDRiVER
@BlackJack,
ich denke, so ist das erst mal ganz brauchbar.
muss mir aber die lxml Bibliothek später anschauen,
weil ich vorerst versuche, mit der Standardbibliothek auszukommen.
danke dir sehr

Re: XML effizient nach Schlüssel-Wert-Paaren durchsuchen

Verfasst: Sonntag 28. Mai 2017, 11:35
von __deets__
XCDRiVER hat geschrieben:@ __deets__
an dem Dateiformat xml wollte ich erst mal noch nicht rütteln, es sollte ein Format sein, was von Menschenhand editierbar und durchschaubar ist.
Mir ist da als erstes xml eingefallen.
Ein klassisches zeilenbasiertes Format wie zB Apache logfiles haben ist auch Menschen-les - und -änderbar, aber robuster und passender.

Und du solltest BlackJacks Kritik an der Codeverteilung außerhalb und innerhalb des __main__-Blocks beherzigen. So ist das Sinn- weil wirkungslos.

Re: XML effizient nach Schlüssel-Wert-Paaren durchsuchen

Verfasst: Sonntag 28. Mai 2017, 11:48
von BlackJack
Wenn man es etwas strukturierter haben möchte, bietet sich JSON Lines oder YAML an.

Re: XML effizient nach Schlüssel-Wert-Paaren durchsuchen

Verfasst: Sonntag 28. Mai 2017, 12:48
von XCDRiVER
Danke sehr,
zukünftig bestimmt denkbar,
aber im Moment muss ich bei xml bleiben.
viele Grüße