Seite 1 von 1

Error handling: element tree

Verfasst: Donnerstag 24. Januar 2008, 11:53
von debian75
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 ?

Re: Error handling: element tree

Verfasst: Donnerstag 24. Januar 2008, 13:06
von Leonidas
debian75 hat geschrieben:vorschläge ?
Exceptions?! Python-typisch eben EAFP programmieren.

Verfasst: Donnerstag 24. Januar 2008, 13:31
von BlackJack
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']

Verfasst: Donnerstag 24. Januar 2008, 13:59
von debian75
danke

Verfasst: Freitag 25. Januar 2008, 13:52
von sma
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