Как удалить определенный тег, который может быть пустым в файле XML - PullRequest
0 голосов
/ 03 июня 2019

Я пытаюсь удалить определенный тег из XML-файла, но только если он пуст.

файл:

<?xml version="1.0" encoding="utf-8"?>
<parent>
  <child>
    <value1>Foo<value1/>
    <value2>Bar<value2/>
    <value3>Hello World<value3/>
    <value3/>
    <value3/>
    <value3/>
  <child/>
<parent/>

ожидаемый результат:

<?xml version="1.0" encoding="utf-8"?>
<parent>
  <child>
    <value1>Foo<value1/>
    <value2>Bar<value2/>
    <value3>Hello World<value3/>
  <child/>
<parent/>

У меня проблемы с чтением файла и его синтаксическим анализом с lxml, поэтому я открыт для любых других методов / модулей python3. в идеале, код должен выглядеть примерно так:

def remove_empty_tag(tag=tagname, file=data):
   ...

data = open("file.xml").read()
new_xml = remove_empty_tag(tag="value3", data)
print(new_xml)

но открыты для любой помощи на самом деле или даже для направления.

Ответы [ 2 ]

1 голос
/ 03 июня 2019

Вам не нужно open() файл для чтения или записи;используйте lxml's parse() для разбора файла и write() для записи нового.

Вы также можете использовать ось self:: xpathвместо питона if для проверки имени тега.

Пример ...

Ввод XML (old.xml)

<parent>
  <child>
    <value1>Foo</value1>
    <value2>Bar</value2>
    <value3>Hello World</value3>
    <value3/>
    <value3/>
    <value3/>
  </child>
</parent>

Python

from lxml import etree


def remove_empty_tag(tag, original_file, new_file):
    root = etree.parse(original_file)
    for element in root.xpath(f".//*[self::{tag} and not(node())]"):
        element.getparent().remove(element)

    # Serialize "root" and create a new tree using an XMLParser to clean up
    # formatting caused by removing elements.
    parser = etree.XMLParser(remove_blank_text=True)
    tree = etree.fromstring(etree.tostring(root), parser=parser)
    # Write to new file.
    etree.ElementTree(tree).write(new_file, pretty_print=True, xml_declaration=True, encoding="utf-8")


remove_empty_tag("value3", "old.xml", "new.xml")

Вывод XML (new.xml)

<?xml version='1.0' encoding='UTF-8'?>
<parent>
  <child>
    <value1>Foo</value1>
    <value2>Bar</value2>
    <value3>Hello World</value3>
  </child>
</parent>

Примечание: Сериализация и создание нового дерева не являются строго необходимыми.Вместо этого вы можете сделать это:

root.write(new_file, pretty_print=True, xml_declaration=True, encoding="utf-8")

, но форматирование вывода будет немного другим (обратите внимание на дополнительный отступ конечного тега child:

<?xml version='1.0' encoding='UTF-8'?>
<parent>
  <child>
    <value1>Foo</value1>
    <value2>Bar</value2>
    <value3>Hello World</value3>
    </child>
</parent>
0 голосов
/ 03 июня 2019
from lxml import etree


def remove_empty_tag(tag, original_file, new_file):
    file = open(original_file, 'r', encoding='utf8').read()
    root = etree.fromstring(file)
    for element in root.xpath(".//*[not(node())]"):
        if element.tag == tag:
            element.getparent().remove(element)
    with open(new_file, 'wb') as f:
        f.write(etree.tostring(root, pretty_print=True))


remove_empty_tag("value3", "old.xml", "new.xml")

Это то, чего я пытался достичь, и по какой-то причине он жалуется на файл / данные, если в нем есть <?xml version="1.0" encoding="utf-8"?>. Так что просто удалите это, и это исправлено. На самом деле это не дубликат, потому что в ответе из другого потока не указано, как удалить только определенный пустой тег и нет никакой помощи в том, что он на самом деле делает, или как записать его в новый файл без случайного '\ n' везде ...

...