2010-11-23 7 views
1

Je suis en train d'accomplir avec lxml bibliothèque quelque chose comme ceci: http://www.xml.com/pub/a/2005/01/19/amara.htmlPassage de amara à lxml en Python

from amara import binderytools 

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

mais j'ai eu le plus de temps pour obtenir mon sensation humide! Ce que je veux faire est: descendre au noeud racine nommé 'X', puis descendre à son deuxième enfant nommé 'Y', puis saisir tous ses enfants 'nommé Z', alors de ceux-ci gardent seulement les enfants que d'avoir un attribut 'nom' défini sur 'bacon', puis pour chaque noeud restant, regarde tous ses enfants nommés 'W', et garde seulement un sous-ensemble basé sur un filtre, qui regarde les seuls enfants de W nommés A, B et C. Puis Je dois les traiter avec les éléments suivants (non optimisé) pseudo-code:

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) 

C'est un peu ce que je suis en train d'accomplir. Avant d'essayer de rendre ce code plus propre, j'aimerais le faire fonctionner.

S'il vous plaît aider, car je suis perdu dans cette API. Faites moi savoir si vous avez des questions.

Répondre

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']] 

Cela pourrait être un moyen de resserrer-la boucle intérieure, bien que je ne devine ce que vous souhaitez conserver enregistre:

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 je commence à écrire une réponse quand j'ai réalisé mon le code ressemblait à environ 90% au vôtre, et dans les 10% qui étaient différents, le vôtre était meilleur. – snapshoe

+0

Merci, cela aide! –

+0

Je voudrais poser une question de suivi. Si je regarde quelque chose comme ' abc ...', alors comment puis-je regarder '' column.id' et column.name'? J'ai déjà vu un exemple: 'Zs = doc.xpath ('// X/Y [2]/Z [@ name =" bacon "]')', mais ce dont j'ai besoin, c'est la possibilité de regarder les attributs individuels à un noeud que j'ai déjà "sélectionné". –

Questions connexes