python - como escrever um nó de árvore vazio como string vazia no arquivo xml
Quero remover elementos de um determinado valor de tag e, em seguida, escrever o.xml
arquivo SEM tags para esses elementos excluídos; é minha única opção para criar uma nova árvore?
Existem duas opções para remover / excluir um elemento:
Claro() Redefine um elemento. Essa função remove todos os subelementos, limpa todos os atributos e define os atributos de texto e cauda como Nenhum.
No começo, eu usei isso e funciona com o objetivo de remover odados do elemento, mas ainda estou com um elemento vazio:
# 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)
O problema é quexml.etree.ElementTree.ElementTree.write()
ainda grava tags vazias, não importa o que:
... O parâmetro short_empty_elements-keyword-only controla a formatação de elementos que não contêm conteúdo. Se True (o padrão), eles são emitidos como umetiqueta única fechada automaticamentecaso contrário, eles são emitidos comopar de tags de início / fim.
Por que não existe uma opção para simplesmente não imprimir essas tags vazias! Tanto faz.
Então pensei em tentar
remover (subelemento) Remove o subelemento do elemento. Diferentemente dos métodos find *, esse método compara elementos com base na identidade da instância, não no valor ou no conteúdo da tag.
Mas isso opera apenas nos elementos filho.
Então eu teria quefaça 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)
Mas há um grande problema aqui: estou invalidando o iterador removendo elementos, certo?
Basta verificar se o elemento está vazio adicionandoif subel
?:
if subel and subel.tag != "make" and subel.tag != "job" and subel.tag != "build"
Ou preciso obter um novo iterador para os elementos da árvore toda vez que eu o invalidar?
Lembre-se: eu só queria escrever o arquivo xml sem tags para os elementos vazios.
Aqui está um exemplo.
<?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 eu queira remover qualquer menção deneighbor
. Idealmente, eu gostaria dessa saída após a remoção:
<?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>
Problema, é quando eu executo o código usando clear () (veja o primeiro bloco de código acima) e o escrevo em um arquivo, eu recebo o seguinte:
<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>
Aviso prévioneighbor
ainda aparece.
Eu sei que eu poderia facilmente executar um regex na saída, mas deve haver uma maneira (ou outra API Python) que faça isso em tempo real, em vez de exigir que eu toque minha.xml
arquivo novamente.