2010-08-09 15 views
10

En Python 2.6 utilisant ElementTree, quel est un bon moyen de récupérer le XML (comme une chaîne) dans un élément particulier, comme ce que vous pouvez faire en HTML et javascript avec innerHTML ?Python et ElementTree: return "inner XML" excluant l'élément parent

Voici un exemple simplifié du noeud XML Je commence avec:

<label attr="foo" attr2="bar">This is some text <a href="foo.htm">and a link</a> in embedded HTML</label> 

Je voudrais terminer avec cette chaîne:

This is some text <a href="foo.htm">and a link</a> in embedded HTML 

J'ai essayé itérer sur le parent noeud et concaténant le tostring() des enfants, mais cela m'a donné que les sous-noeuds:

# returns only subnodes (e.g. <a href="foo.htm">and a link</a>) 
''.join([et.tostring(sub, encoding="utf-8") for sub in node]) 

je peux pirater une solution en utilisant des expressions régulières, mais il espérait qu'il y aurait quelque chose de moins hacky que cela:

re.sub("</\w+?>\s*?$", "", re.sub("^\s*?<\w*?>", "", et.tostring(node, encoding="utf-8"))) 

Répondre

8

Que diriez-vous:

from xml.etree import ElementTree as ET 

xml = '<root>start here<child1>some text<sub1/>here</child1>and<child2>here as well<sub2/><sub3/></child2>end here</root>' 
root = ET.fromstring(xml) 

def content(tag): 
    return tag.text + ''.join(ET.tostring(e) for e in tag) 

print content(root) 
print content(root.find('child2')) 

Entraînant:

start here<child1>some text<sub1 />here</child1>and<child2>here as well<sub2 /><sub3 /></child2>end here 
here as well<sub2 /><sub3 /> 
1

Ce qui suit a fonctionné pour moi:

from xml.etree import ElementTree as etree 
xml = '<root>start here<child1>some text<sub1/>here</child1>and<child2>here as well<sub2/><sub3/></child2>end here</root>' 
dom = etree.XML(xml) 

(dom.text or '') + ''.join(map(etree.tostring, dom)) + (dom.tail or '') 
# 'start here<child1>some text<sub1 />here</child1>and<child2>here as well<sub2 /><sub3 /></child2>end here' 

dom.text or '' est utilisé pour obtenir le texte au début de l'élément root. S'il n'y a pas de texte dom.text est None.

Notez que le résultat n'est pas un XML valide - un XML valide ne doit avoir qu'un seul élément racine.

Jetez un oeil à la ElementTree docs about mixed content.


En utilisant Python 2.6.5, Ubuntu 10.04

+0

salut Emil - votre solution fonctionne bien si tout le texte est à l'intérieur des sous-éléments, mais casse dans mon cas où le texte est directement à l'intérieur de l'élément parent. Votre note sur le contenu mixte s'applique clairement ici, même si je ne suis pas sûr (encore) comment combiner la tête, la queue et les sous-éléments ensemble pour émettre une chaîne cohérente. –

+0

plus proche ... mais et.tostring() n'inclut pas la queue de chaque sous-élément. Et je pense que le dom.tail final n'est pas nécessaire puisque c'est la chaîne * après * un élément et non à l'intérieur. –

+0

Je ne semble pas vous comprendre Justin - «commencer ici», «et» et «fin ici» est un texte qui est juste à l'intérieur de l'élément racine ?! L'extrait ci-dessus peut nécessiter quelques manipulations - vous pouvez créer des cas de test et les améliorer - reportez-vous au lien de la documentation sur la gestion du contenu mixte. –