XML einlesen ohne Typenangabe ??

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
denoise
User
Beiträge: 4
Registriert: Montag 28. Februar 2011, 18:55

Hallo Community!

bin gerade dabei eine große xml Datei einzulesen, was mir soweit auch ganz gut gelingt (Python 2.6, import xml.dom.minidom).

Nun aber mein Problem:

Code: Alles auswählen

<fx:SIGNAL ID="_9d506f6ae2d34b64a52961ab73a6fa88_3" ho:OID="_9d506f6ae2d34b64a52961ab73a6fa88">
  <ho:SHORT-NAME>ST_KL</ho:SHORT-NAME> 
  <ho:LONG-NAME xml:lang="de">Status_Klemme</ho:LONG-NAME> 
  <ho:LONG-NAME xml:lang="en">status_klemme</ho:LONG-NAME> 
Ich kann einfach nicht die "SIGNAL ID" einlesen. Hier steht kein Typ und nichts! Wenn ich die Zeile einlese bekomme ich einmal als NodeType 3 ( TEXT_NODE) und 1 ELEMENT_NODE.

Meine Funktion zum Einlesen der Knoten:

Code: Alles auswählen

def _knoten_auslesen(knoten):    
    return eval("%s('%s')" % (knoten.getAttribute("xml:lang=\"de\""),
                                knoten.firstChild.data.strip()))
Und die "main":

Code: Alles auswählen

def lade_dict(dateiname): 
    d = {} 
    baum = dom.parse(dateiname)
    SIGNAL_ID_Pattern = re.compile(r'fx:SIGNAL ID')
    print baum.firstChild
    for eintrag in baum.firstChild.childNodes:

        if eintrag.nodeName == "fx:ELEMENTS":
            wert = None
            
            for knoten in eintrag.childNodes: 
                if knoten.nodeName == "fx:SIGNALS": 
                    print "Signal"
                    
                    """ Ebene der einzelnen Signale """
                    for knoten2 in knoten.childNodes:
                        
                        if SIGNAL_ID_Pattern.findall(knoten2.nodeName) != "":

                            print "Typ: ", knoten2.nodeType
                            print _knoten_auslesen(knoten2) """ FEHLER !!!!!!!! """
                                

""" okay ab hier """
                            for knoten3 in knoten2.childNodes:
                                """ KURZNAME des Signals """
                                if knoten3.nodeName == "ho:SHORT-NAME":
                                    wert = _knoten_auslesen(knoten3)
                                    print wert
                                """ deutscher LANGNAME des Signals """
                                if knoten3.nodeName == "ho:LONG-NAME":
                                    if knoten3.getAttribute("xml:lang")=="de":
                                        wert = _knoten_auslesen(knoten3)
                                        print wert                         
Danke schon mal!!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ein kleiner Tipp: du solltest statt minidom besser ElementTree verwenden. Minidom ist durch ElementTree quasi obsolet geworden und sollte für neuen Code nicht mehr verwendet werden. Poste doch mal die XML-Datei.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@denoise: Vergiss bitte mal ganz schnell dass es die `eval()`-Funktion gibt. Und dann musst Du halt schauen wie man mit `minidom` an den Inhalt von Textknoten kommt.

Ich persönlich mag ja die `ElementTree`-API lieber.
denoise
User
Beiträge: 4
Registriert: Montag 28. Februar 2011, 18:55

Danke schon mal. Werd das heute mal mit dem Element Tree versuchen.
Kann die xml leider nicht posten, hat über 150k Zeilen.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Code: Alles auswählen

SIGNAL_ID_Pattern = re.compile(r'fx:SIGNAL ID')
Du kannst nicht "fx:SIGNAL ID" suchen, denn das ist nicht der Name. Das Element heißt fx:SIGNAL und hat ein Attribut ID. Eigentlich müsste der Name aus der Namensraum URI und dem kurzen Namen bestehen, doch das kann Minidom offenbar nicht.

Code: Alles auswählen

s = """
<root xmlns:fx="urn:whatever-fx" xmlns:ho="urn:whatever-ho">
<fx:SIGNAL ID="_9d506f6ae2d34b64a52961ab73a6fa88_3" ho:OID="_9d506f6ae2d34b64a52961ab73a6fa88">
  <ho:SHORT-NAME>ST_KL</ho:SHORT-NAME> 
  <ho:LONG-NAME xml:lang="de">Status_Klemme</ho:LONG-NAME> 
  <ho:LONG-NAME xml:lang="en">status_klemme</ho:LONG-NAME>
</fx:SIGNAL>
</root>
"""
from xml.dom.minidom import parseString
d = parseString(s)
e = d.getElementsByTagNameNS("urn:whatever-fx", "SIGNAL")[0]
print e.tagName, e.nodeName, e.localName, e.namespaceURI
lxml, was ich für alle ernsthaften XML-Arbeiten empfehlen würde, nennt das Element IMHO korrekt "{urn:whatever-fx}SIGNAL".

Ich würde bei korrekten und validen XML-Dokumenten (siehe meine Ergänzung der Namensräume in <root>) übrigens dringend davon abraten, auf Namensraumpräfixe zu prüfen, denn diese sind beliebig und nur die Namensraum URI ist, was ein Element eindeutig identifiziert.

Stefan
denoise
User
Beiträge: 4
Registriert: Montag 28. Februar 2011, 18:55

Danke an alle! Habs jetzt mit TreeElement gelöst, ist wesentlich komfortabler!
Diese Präfix Geschichte muss ich mir noch einmal genauer anschauen. Bisher mache ichs noch über die getiterator Methode.
z.B.
knoten.getiterator("{http://www.asam.net/xml}SIGNALS")
Antworten