Preservando el tipo de documento original y la statement de un xml analizado lxml.etree

Estoy usando el lxml de python y estoy tratando de leer un documento xml, modificarlo y escribirlo, pero el doctype original y la statement xml desaparecen. Me pregunto si hay una manera fácil de volver a incluirlo en lxml o alguna otra solución.

Lo siguiente incluirá el DOCTYPE y la statement XML:

 from lxml import etree from StringIO import StringIO tree = etree.parse(StringIO('''  ]>  &tasty;  ''')) docinfo = tree.docinfo print etree.tostring(tree, xml_declaration=True, encoding=docinfo.encoding) 

Tenga en cuenta que tostring no conserva el DOCTYPE si crea un Element (por ejemplo, utilizando fromstring ), solo funciona cuando procesa el XML utilizando el parse .

Actualización: como lo señaló JF Sebastian, mi afirmación sobre fromstring no es cierta.

Aquí hay un código para resaltar las diferencias entre la serialización de Element y ElementTree :

 from lxml import etree from StringIO import StringIO xml_str = '''  ]>  &tasty;  ''' # get the ElementTree using parse parse_tree = etree.parse(StringIO(xml_str)) encoding = parse_tree.docinfo.encoding result = etree.tostring(parse_tree, xml_declaration=True, encoding=encoding) print "%s\nparse ElementTree:\n%s\n" % ('-'*20, result) # get the ElementTree using fromstring fromstring_tree = etree.fromstring(xml_str).getroottree() encoding = fromstring_tree.docinfo.encoding result = etree.tostring(fromstring_tree, xml_declaration=True, encoding=encoding) print "%s\nfromstring ElementTree:\n%s\n" % ('-'*20, result) # DOCTYPE is lost, and no access to encoding fromstring_element = etree.fromstring(xml_str) result = etree.tostring(fromstring_element, xml_declaration=True) print "%s\nfromstring Element:\n%s\n" % ('-'*20, result) 

y la salida es:

 -------------------- parse ElementTree:   ]>  eggs  -------------------- fromstring ElementTree:   ]>  eggs  -------------------- fromstring Element:   eggs  

También puede conservar DOCTYPE y la statement XML con fromstring() :

 import sys from StringIO import StringIO from lxml import etree xml = r'''    example   

This is an example

''' tree = etree.fromstring(xml).getroottree() # or etree.parse(file) tree.write(sys.stdout, xml_declaration=True, encoding=tree.docinfo.encoding)

Salida

     example   

This is an example

Tenga en cuenta que la statement xml (con la encoding correcta) y doctype están presentes. Incluso (posiblemente de forma incorrecta) utiliza ' lugar de " en la statement xml y agrega Content-Type a .

Para la entrada de ejemplo de @John Keyes , produce los mismos resultados que etree.tostring() en la respuesta.