2010-11-23 4 views
1

ich mit lxml Bibliothek, so etwas zu erreichen versuchen: http://www.xml.com/pub/a/2005/01/19/amara.htmlWechsel von Amara lxml in Python

from amara import binderytools 

container = binderytools.bind_file('labels.xml') 
for l in container.labels.label: 
    print l.name, 'of', l.address.city 

aber ich habe die härteste Zeit habe mein Gefühl nass! Was ich tun möchte, ist: Abstieg zum Wurzelknoten mit dem Namen "X", dann Abstieg zu seinem zweiten Kind mit dem Namen "Y", dann alle seine Kinder mit dem Namen Z ', dann von denen behalten nur die Kinder als ein Attribut 'name' wird auf 'bacon' gesetzt, dann für jeden verbleibenden Knoten alle seine Kinder mit dem Namen 'W' betrachten und nur eine Teilmenge basierend auf einem Filter behalten, der auf die einzigen Kinder von W mit den Namen A, B und C schaut ich brauche sie mit dem folgenden (nicht optimierte) Pseudo-Code zu verarbeiten:

result = [] 
X = root(doc(parse(xml_file_name))) 
Y = X[1] # Second child 
Zs = Y.children() 
for Z in Zs: 
    if Z.name != 'bacon': continue # skip 
    Ws = Z.children() 
    record = [] 
    assert(len(Ws) == 9) 
    W0 = Ws[0] 
    assert(W0.A == '42') 
    record.append(str(W0.A) + " " + W0.B + " " + W0.C)) 
    ... 
    W1 = Ws[1] 
    assert(W1.A == '256') 
    ... 
    result.append(record) 

Dies ist eine Art, was ich zu tun versuchen. Bevor ich versuche, diesen Code sauberer zu machen, möchte ich es zum Laufen bringen.

Bitte helfen, da ich in dieser API verloren bin. Lass es mich wissen, falls du fragen hast.

Antwort

3
import lxml.etree as le 
import io 

content='''\ 
<foo><X><Y>skip this</Y><Y><Z name="apple"><W>not here</W></Z> 
<Z name="bacon"><W><A>42</A><B>b</B><C>c</C></W><W><A>256</A><B>b</B><C>c</C></W></Z> 
<Z name="bacon"><W><A>42</A><B>b</B><C>c</C></W><W><A>256</A><B>b</B><C>c</C></W></Z> 
</Y></X></foo> 
''' 
doc=le.parse(io.BytesIO(content)) 
# print(le.tostring(doc, pretty_print=True)) 
result=[] 
Zs=doc.xpath('//X/Y[2]/Z[@name="bacon"]') 
for Z in Zs: 
    Ws=Z.xpath('W') 
    record=[] 
    assert(len(Ws)==2) #<--- Change to 9   
    abc=Ws[0].xpath('descendant::text()') 
    # print(abc) 
    # ['42', 'b', 'c'] 
    assert(abc[0] == '42') 
    record.append(' '.join(abc)) 
    abc=Ws[1].xpath('descendant::text()')  
    assert(abc[0] == '256') 
    result.append(record) 
print(result) 
# [['42 b c'], ['42 b c']] 

Dies könnte eine Art und Weise zu straffen-up der inneren Schleife, obwohl ich nur raten, was Sie halten erfasst wollen:

for Z in Zs: 
    Ws=Z.xpath('W') 
    assert(len(Ws)==2) #<--- Change to 9 
    a_vals=('42','256') 
    for W,a_val in zip(Ws,a_vals): 
     abc=W.xpath('descendant::text()') 
     assert(abc[0] == a_val) 
     result.append([' '.join(abc)]) 
print(result) 
# [['42 b c'], ['256 b c'], ['42 b c'], ['256 b c']] 
+0

+1 begann ich eine Antwort zu schreiben, als ich meine realisiert Der Code sah ungefähr zu 90% ähnlich wie deiner aus, und in den 10%, die anders waren, sah dein besser aus. – snapshoe

+0

Danke, das hilft! –

+0

Ich möchte eine Folgefrage stellen. Wenn ich etwas wie ' abc ...' ansehe, wie kann ich dann 'column.id' und' column.name' betrachten? Ich habe bereits ein Beispiel gesehen: 'Zs = doc.xpath ('// X/Y [2]/Z [@ name =" speck "]'), aber was ich brauche, ist die Fähigkeit, einzelne Attribute zu betrachten ein Knoten, den ich bereits "ausgewählt" habe. –