2012-05-12 28 views
5

¿Es posible usar lxml (o la biblioteca incorporada etree) para crear un objeto que represente un fragmento de xml, pero contenga dos (o más) árboles disjuntos (es decir, cada árbol tiene su propia raíz separada, pero no comparten antecesor común?)?lxml ¿Crear fragmento XML sin elemento raíz?

Es decir, ¿hay algo que podría representar la siguiente sin crear otro elemento para sostener ambos:

<tree id="A"><anotherelement/></tree> 
<tree id="B"><yetanotherelement/></tree> 

no puedo ver nada en la documentación lxml que permitiría eso, y parece stackoverflow no tener nada directamente en el punto.

El caso de uso aquí es que estoy generando xml mediante programación, y los fragmentos se ensamblarán en un solo documento para su salida. Me gustaría un objeto que no necesite iterar/caso especial, simplemente pasar a los métodos lxml como si fuera un árbol apropiado.

(Soy consciente de que esos fragmentos no serían por sí mismos un documento xml completo y correcto; quiero almacenar los productos intermedios antes de ensamblarlos en dicho documento).

+0

¿Qué tal si hacemos una lista de objetos lxml? Eso es más o menos lo que tienes ... – larsks

+0

@larsks Correcto, pero luego necesito escribir un código que maneje la presencia de una lista, en lugar de pasar un objeto del tipo que la API xml espera. Eso también implica una envoltura especial en mi código, o siempre una lista. Por eso sería preferible. – Marcin

Respuesta

4

sí, hay una funcionalidad tal en el paquete lxml.html, se llama fragment_fromstring o fragments_fromstring, pero en la mayoría de los casos, el analizador de HTML también maneja XML bastante bien:

from lxml import etree, html 

xml = """ 
    <tree id="A"><anotherelement/></tree> 
    <tree id="B"><yetanotherelement/></tree> 
""" 

fragments = html.fragments_fromstring(xml) 

root = etree.Element("root") 
for f in fragments: 
    root.append(f) 

print etree.tostring(root, pretty_print=True) 

de salida:

<root> 
    <tree id="A"> 
    <anotherelement/> 
    </tree> 
    <tree id="B"> 
    <yetanotherelement/> 
    </tree> 
</root> 

si nos fijamos en what's going on under the hood, probablemente no sería demasiado difícil hacer lo mismo con el analizador xml si no está satisfecho con el otro resultado.

+0

Gracias por esto. De hecho, quiero crear el fragmento programáticamente, por lo que voy a mirar debajo del capó. – Marcin

+0

Ah, todavía devuelve una lista. Esperaba que hubiera una forma de crear un objeto que no necesite iterar/caso especial, solo pase a los métodos lxml como si fuera un árbol apropiado. Aceptaré esta respuesta en los próximos días, suponiendo que nadie más sepa de algún método mágico. – Marcin

+0

+1 pero definitivamente es importante saber que 'fragments_fromstring()' devuelve una lista y 'fragment_fromstring()' solo mostrará un solo elemento – JCotton

Cuestiones relacionadas