No sé si las versiones anteriores del código propuesto funcionaron muy bien y si el módulo elementtree se ha actualizado, pero me he enfrentado a problemas con el uso de este truco:
etree._original_serialize_xml = etree._serialize_xml
def _serialize_xml(write, elem, qnames, namespaces):
if elem.tag == '![CDATA[':
write("\n<%s%s]]>\n" % (
elem.tag, elem.text))
return
return etree._original_serialize_xml(
write, elem, qnames, namespaces)
etree._serialize_xml = etree._serialize['xml'] = _serialize_xml
El problema con este enfoque es que después de pasar esta excepción, serializador es tratar de nuevo como etiqueta de la normalidad después s. Obtenía algo así como:
<textContent>
<![CDATA[this was the code I wanted to put inside of CDATA]]>
<![CDATA[>this was the code I wanted to put inside of CDATA</![CDATA[>
</textContent>
Y, por supuesto, sabemos que solo causará muchos errores. ¿Por qué estaba pasando eso?
La respuesta está en este pequeño individuo:
return etree._original_serialize_xml(write, elem, qnames, namespaces)
No queremos a examinar el código una vez más a través de la función serializar original si hemos atrapado nuestra CDATA y superado con éxito a través de. Por lo tanto, en el bloque "if" tenemos que devolver la función de serialización original solo cuando CDATA no estaba allí. Nos faltaba "else" antes de devolver la función original.
Además, en mi versión del módulo ElementTree, serializar la función estaba pidiendo desesperadamente el argumento "short_empty_element". Así que la versión más reciente que recomendaría es similar al siguiente (también con "cola"):
from xml.etree import ElementTree
from xml import etree
#in order to test it you have to create testing.xml file in the folder with the script
xmlParsedWithET = ElementTree.parse("testing.xml")
root = xmlParsedWithET.getroot()
def CDATA(text=None):
element = ElementTree.Element('![CDATA[')
element.text = text
return element
ElementTree._original_serialize_xml = ElementTree._serialize_xml
def _serialize_xml(write, elem, qnames, namespaces,short_empty_elements, **kwargs):
if elem.tag == '![CDATA[':
write("\n<{}{}]]>\n".format(elem.tag, elem.text))
if elem.tail:
write(_escape_cdata(elem.tail))
else:
return ElementTree._original_serialize_xml(write, elem, qnames, namespaces,short_empty_elements, **kwargs)
ElementTree._serialize_xml = ElementTree._serialize['xml'] = _serialize_xml
text = """
<?xml version='1.0' encoding='utf-8'?>
<text>
This is just some sample text.
</text>
"""
e = ElementTree.Element("data")
cdata = CDATA(text)
root.append(cdata)
#tests
print(root)
print(root.getchildren()[0])
print(root.getchildren()[0].text + "\n\nyay!")
La salida me dio fue:
<Element 'Database' at 0x10062e228>
<Element '![CDATA[' at 0x1021cc9a8>
<?xml version='1.0' encoding='utf-8'?>
<text>
This is just some sample text.
</text>
yay!
les deseo el mismo resultado!
> Necesito generar XML que contenga las secciones CDATA ¿Por qué? Parece un requerimiento extraño. – bortzmeyer
Es un requisito que tengo: los trozos de CDATA a veces son mucho más legibles para los humanos. – grifaton
@bortzmeyer Es útil para agregar HTML a KML (archivos XML de Google Maps). –