2014-12-15 15 views
8

Używam xmltodict do parsowania konfiguracji XML. XML ma struktury, w których element może się pojawić w przypadkach od 1 do n, przy czym oba są ważne:Uchwyt od 1 do n elementów

<items> 
    <item-ref>abc</item-ref> 
</items> 

i

<items> 
    <item-ref>abc</item-ref> 
    <item-ref>dca</item-ref> 
    <item-ref>abb</item-ref> 
</items> 

mi analizę składniową to z xmltodict następująco:

document['items']['item-ref'] 

i zwraca pojedynczy kod Unicode lub listę (w zależności od znalezionych elementów), więc zawsze muszę dodać dodatkową kontrolę, aby upewnić się, czy potrzebuję obsługi listy lub ciągu znaków:

if isinstance(document['items']['item-ref'], list): 
    my_var = document['items']['item-ref'] 
else: 
    my_var = [document['items']['item-ref']] #create list manually 

Czy istnieje lepszy/prostszy/bardziej elegancki sposób na ich obsługę?

+1

wpadł na ten sam problem i sprawdzał wszystko:) – dm03514

+0

Jeśli chcesz, aby twoje ręce były trochę brudne, możesz załatać 'xmltodict.py'. Istnieje metoda "_DictSAXHandler.push_data", która określa, które elementy zamienić na listy. Możesz zmienić argumenty, abyś mógł przekazać analizatorowi zestaw elementów, aby * zawsze * zamienił się w listę. –

Odpowiedz

3

Nie jestem pewien super eleganckiego sposobu, aby to zrobić. Python nie ma żadnych wbudowanych metod ani funkcji, które pomogą ci to zrobić w jednym wierszu kodu. Niemniej jednak, w celu konsolidacji kodu, będziesz chciał coś zrobić. Jak wspomniano w komentarzu do matsjoyce, możesz po prostu stworzyć funkcję, która zajmie się tą logiką.

def listn(val=None): 
    if val is None: 
     return [] 
    return val if isinstance(val, list) else [val] 

>>> listn([1, 2, 3]) 
[1, 2, 3] 
>>> listn() 
[] 
>>> listn(3) 
[3] 

Teraz można po prostu nazwać tę funkcję ze swoim val i oczekują list zostaną zwrócone, czy jest to list, to int, lub NoneType obiektu:

my_var = listn(document['items']['item-ref']) 

(Moja pierwsza odpowiedź utworzył podklasę list, ale zajmuje to 6 linii zamiast 4 i zmienia type - nie jest to najbardziej idealny efekt uboczny.)

+0

Czy to nie byłoby przyjemniejsze jak funkcja? Możesz to zrobić w jedno-liniowej: 'listify = lambda x: x jeśli isinstance (x, list) else [x]' – matsjoyce

+0

Wystarczająco fair. Nie jestem pewien, czy skorzystałbym z jednej linijki, ale funkcja z pewnością byłaby łatwiejsza, zwłaszcza jeśli mogłaby również uwzględniać wartości "Brak". Zaktualizowałem swoją odpowiedź powyżej. –

+0

To dobre podejście, dzięki czemu mój kod staje się bardziej prosty i zwarty. – balas