XML String Parsen mit xml.dom.minidom

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
TTS
User
Beiträge: 3
Registriert: Freitag 18. Februar 2011, 14:32

Hi zusammen

Ich bin am verzweifeln. Ich bin an einem Python Projekt und komme einfach nicht weiter und mein Chef ist in nem Meeting und ich sollte das so schnell wie möglich erledigt haben.
Und zwar geht es darum automatisierte testScripts mit unittest zu schreiben.

Nun soll ich einen xml String auswerten und in ein 2d array zu schreiben. Das ganze muss mit der xml bibliothek passieren.

Ich habe einen XML String, der folgende form hat, nur etwas länger:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8" ?>

<response>

<operation name="get" path="/unit-15/status/outputcircuittable">

  <execution status="success" />

  <OutputCircuitTable>

    <OutputCircuitTableRow>

      <OutputCircuit>tpo-1</OutputCircuit>

      <AppOutputSignal>cmd-1</AppOutputSignal>

      <IsCmdAlarmGenerated>false</IsCmdAlarmGenerated>

    </OutputCircuitTableRow>

    <OutputCircuitTableRow>

      <OutputCircuit>tpo-2</OutputCircuit>

      <AppOutputSignal>cmd-2</AppOutputSignal>

      <IsCmdAlarmGenerated>false</IsCmdAlarmGenerated>

    </OutputCircuitTableRow>

  </OutputCircuitTable>

</operation>

</response>
nun sollten die Daten in den outputCircuits, AppOutputSignal und IsCmdAlarmGenerated in ein 2d-Array geschrieben werden. Nur habe ich keine Ahnung wie ich das anstelle.

Könnt Ihr mir sagen wie ich den Wert der childNodes von OutputCircuitTableRow herauslösen kann?

Bisher bin ich so weit (Ich kann nun schon auf die 3 gewünschten Nodes zugreifen):

Code: Alles auswählen

xml = xml.dom.minidom.parseString(xmlString)
nodeResponse = xml.childNodes[0]
nodeOperation = nodeResponse.childNodes[1]
nodeTable = nodeOperation.childNode[3]
nodeTableRow = nodeTable.childNodes[1]
for node in nodeTableRow.childNodes:
    #Hier sollten dann die 3 childNodes von der <OutputCircuitTableRow> in ein array geschrieben werden
Könnt Ihr mir erklären wie ich den Wert zwischen den <> und </> herausbekomme?
evtl. ein Beispiel mit print oder in einer Variable speichern.

Danke für eure Hilfe
Zuletzt geändert von Anonymous am Freitag 18. Februar 2011, 17:41, insgesamt 1-mal geändert.
Grund: Quelltext in Python- und XML-Code-Tags gesetzt.
BlackJack

@TTS: Als erstes würde ich die Finger von `minidom` lassen. Mit der `ElementTree`-API gibt es einen IMHO schöneren und einfacheren Ansatz dazu in der Standardbibliothek.

Mit "2d array" meinst Du wahrscheinlich verschachtelte Listen. Wenn man bei Python von Arrays spricht, sind normalerweise nicht Listen gemeint, sondern `numpy`-Arrays, oder in selteneren Fällen auch das `array`-Modul aus der Standardbibliothek.

Auf XML-Knoten sollte man nur in Ausnahmefällen über Indizes zugreifen. Es ist unverständlicher als die Tag-Namen zu zu verwenden und unflexibel, weil sich die Struktur der Daten dann nicht verändern darf. Insbesondere weil man über Namensräume beliebige andere XML-Elemente in Dokumente einbetten darf, ist Code der sich auf absolute Positionen von Elementen in Form von Indizes verlässt, nicht besonders robust.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from xml.etree import ElementTree as etree


def main():
    def parse_row(node):
        return [node.find(n).text for n
                in ['OutputCircuit', 'AppOutputSignal', 'IsCmdAlarmGenerated']]
    
    doc = etree.parse('test.xml')
    table_node = doc.find('.//OutputCircuitTable')
    result = map(parse_row, table_node.getiterator('OutputCircuitTableRow'))
    print result


if __name__ == '__main__':
    main()
TTS
User
Beiträge: 3
Registriert: Freitag 18. Februar 2011, 14:32

[quote="BlackJack"]@TTS: Als erstes würde ich die Finger von `minidom` lassen. Mit der `ElementTree`-API gibt es einen IMHO schöneren und einfacheren Ansatz dazu in der Standardbibliothek.

Code: Alles auswählen

# -*- coding: utf-8 -*-
    doc = etree.parse('test.xml')
    table_node = doc.find('.//OutputCircuitTable')
    result = map(parse_row, table_node.getiterator('OutputCircuitTableRow'))
    print result
Danke BlackJack für deine Hilfe. Jedoch verlang die funktion etree.parse ein xml-File, doch den angegebenen xml-string erhalte ich direkt über eine Funktion von einem Gerät. Das heisst es wird nicht ein xmlFile erstellt sondern ist nur in einem string gespeichert. Und etree enthält keine Funktion wie z.B. minidom parseString.

oder ist es doch igendwie möglich statt einem File einen string zu parsen?
BlackJack

@TTS: Ja das ist möglich. Such einfach die passende Funktion in der Dokumentation. :-)
TTS
User
Beiträge: 3
Registriert: Freitag 18. Februar 2011, 14:32

Vielen Dank mit der Funktion .fromString() erhalte ich genau das was ich brauche :D
Antworten