Python: cómo escribir un nodo de árbol vacío como una cadena vacía en un archivo xml
Quiero eliminar elementos de un determinado valor de etiqueta y luego escribir el.xml
archivo SIN etiquetas para esos elementos eliminados; Cuál es mi única opción para crear un nuevo árbol?
Hay dos opciones para eliminar / eliminar un elemento:
claro() Restablece un elemento. Esta función elimina todos los subelementos, borra todos los atributos y establece los atributos de texto y cola en Ninguno.
Al principio usé esto y funciona con el propósito de eliminar eldatos del elemento pero todavía me queda un elemento vacío:
# Remove all elements from the tree that are NOT "job" or "make" or "build" elements
log = open("debug.log", "w")
for el in root.iter(*):
if el.tag != "job" and el.tag != "make" and el.tag != "build":
print("removed = ", el.tag, el.attrib, file=log)
el.clear()
else:
print("NOT", el.tag, el.attrib, file=log)
log.close()
tree.write("make_and_job_tree.xml", short_empty_elements=False)
El problema es esexml.etree.ElementTree.ElementTree.write()
todavía escribe etiquetas vacías sin importar qué:
... El parámetro short_empty_elements de solo palabras clave controla el formato de los elementos que no contienen contenido. Si es verdadero (el valor predeterminado), se emiten comoetiqueta única de cierre automáticode lo contrario, se emiten comopar de etiquetas de inicio / fin.
¿Por qué no hay una opción para no imprimir esas etiquetas vacías? Lo que sea.
Entonces pensé que podría intentar
eliminar (subelemento) Elimina el subelemento del elemento. A diferencia de los métodos find *, este método compara elementos basados en la identidad de la instancia, no en el valor de la etiqueta o el contenido.
Pero esto solo opera en los elementos hijos.
Entonces tendría quehacer algo como:
for el in root.iter(*):
for subel in el:
if subel.tag != "make" and subel.tag != "job" and subel.tag != "build":
el.remove(subel)
Pero aquí hay un gran problema: estoy invalidando el iterador eliminando elementos, ¿verdad?
¿Es suficiente simplemente verificar si el elemento está vacío agregandoif subel
?:
if subel and subel.tag != "make" and subel.tag != "job" and subel.tag != "build"
¿O tengo que obtener un nuevo iterador para los elementos del árbol cada vez que lo invalido?
Recuerde: solo quería escribir el archivo xml sin etiquetas para los elementos vacíos.
Aquí hay un ejemplo.
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
Digamos que quiero eliminar cualquier mención deneighbor
. Idealmente, me gustaría esta salida después de la eliminación:
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
</country>
</data>
El problema es que cuando ejecuto el código usando clear () (vea el primer bloque de código arriba) y lo escribo en un archivo, obtengo esto:
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor></neighbor><neighbor></neighbor></country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor></neighbor></country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor></neighbor><neighbor></neighbor></country>
</data>
Avisoneighbor
todavía aparece
Sé que podría ejecutar fácilmente una expresión regular sobre la salida, pero debe haber una forma (u otra API de Python) que haga esto sobre la marcha en lugar de requerir que toque mi.xml
archivo de nuevo.