2012-01-15 12 views
9

he tratado de usar la respuesta en esta pregunta, pero no puede hacer que funcione: How to create "virtual root" with Python's ElementTree?Cómo crear <!DOCTYPE> con cElementTree de Python

Aquí está mi código:

import xml.etree.cElementTree as ElementTree 
from StringIO import StringIO 
s = '<?xml version=\"1.0\" encoding=\"UTF-8\" ?><!DOCTYPE tmx SYSTEM \"tmx14a.dtd\" ><tmx version=\"1.4a\" />' 
tree = ElementTree.parse(StringIO(s)).getroot() 
header = ElementTree.SubElement(tree,'header',{'adminlang': 'EN',}) 
body = ElementTree.SubElement(tree,'body') 
ElementTree.ElementTree(tree).write('myfile.tmx','UTF-8') 

Al abrir la resultante archivo 'myfile.tmx', contiene esto:

<?xml version='1.0' encoding='UTF-8'?> 
<tmx version="1.4a"><header adminlang="EN" /><body /></tmx> 

¿Qué me falta? o, ¿hay una mejor herramienta?

Respuesta

7

Usted podría utilizar lxml y su función tostring:

from lxml import etree 

s = """<?xml version="1.0" encoding="UTF-8"?> 
<tmx version="1.4a"/>""" 

tree = etree.fromstring(s) 
header = etree.SubElement(tree,'header',{'adminlang': 'EN'}) 
body = etree.SubElement(tree,'body') 

print etree.tostring(tree, encoding="UTF-8", 
        xml_declaration=True, 
        pretty_print=True, 
        doctype='<!DOCTYPE tmx SYSTEM "tmx14a.dtd">') 

=>

<?xml version='1.0' encoding='UTF-8'?> 
<!DOCTYPE tmx SYSTEM "tmx14a.dtd"> 
<tmx version="1.4a"> 
    <header adminlang="EN"/> 
    <body/> 
</tmx> 
8

podría configurar xml_declaration argumento de la función write en False, por lo que la producción no tendrá declaración XML con la codificación, a continuación, sólo anexar lo cabecera que necesita de forma manual. En realidad, si se establece su codificación como 'UTF-8' (en minúsculas), declaración XML no se añadirá también:

import xml.etree.cElementTree as ElementTree 

tree = ElementTree.Element('tmx', {'version': '1.4a'}) 
ElementTree.SubElement(tree,'header',{'adminlang': 'EN',}) 
ElementTree.SubElement(tree,'body') 

with open('myfile.tmx', 'w') as f: 
    f.write('<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE tmx SYSTEM "tmx14a.dtd">') 
    ElementTree.ElementTree(tree).write(f, 'utf-8') 

archivo resultante (nuevas líneas añadidas para facilitar la lectura):

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE tmx SYSTEM "tmx14a.dtd"> 
<tmx version="1.4a"> 
    <header adminlang="EN" /> 
    <body /> 
</tmx> 
+0

¿Puedes explicar cómo agregaste una nueva línea al xml? – Learner

+0

@Learner: lo agregué manualmente para facilitar la lectura. Si desea tener XML con nuevas líneas de ElementTree, busque cómo imprimir bastante XML. – demalexx

0

no pude encontrar una solución a este problema, ya sea usando la vainilla elementtree, y la solución propuesta por demalexx XML no válida creada que fue rechazado por mi solicitud (DITA). Lo que propongo es una solución alternativa que involucre otros módulos y funciona perfectamente para mí.

import re 
# found no way for cleanly specify a <!DOCTYPE ...> stanza in ElementTree so 
# so we substitute the current <?xml ... ?> stanza with a full <?xml... + <!DOCTYPE... 
new_header = '<?xml version="1.0" encoding="UTF-8" ?>\n' \ 
       '<!DOCTYPE topic PUBLIC "-//OASIS//DTD DITA Topic//EN" "topic.dtd">\n' 

target_xml = re.sub(u"\<\?xml .+?>", new_header, source_xml) 
with open(filename, 'w') as catalog_file: 
    catalog_file.write(target_xml.encode('utf8')) 
Cuestiones relacionadas