Error handling: element tree

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
debian75
User
Beiträge: 90
Registriert: Dienstag 27. November 2007, 01:05

Donnerstag 24. Januar 2008, 11:53

moin,

ich hab hier ein kleines problem mit element tree. ich bekomme in der regel ein xml file mit folgenden inhalten:

Code: Alles auswählen

<person>
<name>abc</name>
<vornae>def</vorname>
<telefon>
<privat>1234</privat>
<gesch>4567</gesch>
</telefon>
ich entehme die einzelnen felder jeweils so: person.find("telefon").findtext("privat")

jetzt fehlen aber manchmal ganze knoten (z.b telefon) oder aber der letzte eintrag (z.b. privat), was zu einer fehlermeldung führt, weil er kein .find oder .findtext auf NoneType anwenden kann. ich habe versucht das mit IF THE ELSE abzufagen, was auch gehen würde aber mir nicht gefällt. ich muss sonst quasi für JEDES level checken ob es existiert was ne menge IF THEN ELSE zur folge hat.

also:

Code: Alles auswählen

IF telefon:
  IF PRIVAT:
      blabla
  ELSE:
      blabla
ELSE:
etc..
da ich in wirklichkeit mehr levels habe, zieht sich das ins unendliche....

vorschläge ?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 24. Januar 2008, 13:06

debian75 hat geschrieben:vorschläge ?
Exceptions?! Python-typisch eben EAFP programmieren.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Donnerstag 24. Januar 2008, 13:31

Ansonsten muss man nicht jede Ebene mit einem einzelnen `find()` holen, weil `ElementTree` auch eine Untermenge von XPath versteht reicht *ein* `find()` aus um zu dem Kindknoten zu kommen:

Code: Alles auswählen

In [176]: person.find('telefon/privat').text
Out[176]: '1234'
Man käme also mit einem ``if``-Test aus bevor man auf das `text`-Attribut zugreift.

Das externe Modul `lxml` hat die gleiche API wie `ElementTree`, kann aber einiges mehr, unter anderem volle XPath-Unterstützung.

Code: Alles auswählen

In [177]: person.xpath('telefon/privat/text()')
Out[177]: ['1234']
debian75
User
Beiträge: 90
Registriert: Dienstag 27. November 2007, 01:05

Donnerstag 24. Januar 2008, 13:59

danke
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Freitag 25. Januar 2008, 13:52

Wie wäre es alternativ hiermit?

Code: Alles auswählen

class Wrapper(object):
    def __init__(self, element):
        self.element = element
        
    def __getattr__(self, name):
        e = self.element.find(name)
        if e:
            return Wrapper(e)
        return NoneWrapperInstance
        
    def __call__(self):
        return self.element.text

class NoneWrapper(object):
    def __getattr__(self, name):
        return NoneWrapperInstance
        
    def __call__(self):
        return None
        
NoneWrapperInstance = NoneWrapper()

e = Wrapper(e)
print e.telefon.privat.nummer()
print e.telefon.existiert.nicht.und.dies.auch.nicht()
Stefan
Antworten