使用Python 3基于列表删除LXML元素树

时间:2018-03-07 15:01:25

标签: python xml python-3.x lxml

使用LXML,我希望打开一个现有的XML文件,根据设备列表中的匹配删除一些<device>元素树,并将编辑后的XML保存在相同的文件名下。

这是现有的XML内容:

<testsetup>
    <devices>
      <device>
        <name>DEVICE1</name>
        <id>SomeID</id>
        <keyitem>
          <file1>/some/file/path</file1>
          <file2>/some/file/path</file2>
        </keyitem>
      </device>
      <device>
        <name>DEVICE2</name>
        <id>SomeID</id>
        <keyitem>
          <file1>/some/file/path</file1>
          <file2>/some/file/path</file2>
        </keyitem>
      </device>
      <device>
        <name>DEVICE3</name>
        <id>SomeID</id>
        <keyitem>
          <file1>/some/file/path</file1>
          <file2>/some/file/path</file2>
        </keyitem>
      </device>
      <device>
        <name>DEVICE4</name>
        <id>SomeID</id>
        <keyitem>
          <file1>/some/file/path</file1>
          <file2>/some/file/path</file2>
        </keyitem>
      </device>
    </devices>
</testsetup>

我有一个需要删除的设备列表:

remove_items = ['DEVICE1', 'DEVICE3']

我希望在输出文件中输入以下内容:

<testsetup>
   <devices>
      <device>
        <name>DEVICE2</name>
        <id>SomeID</id>
        <keyitem>
          <file1>/some/file/path</file1>
          <file2>/some/file/path</file2>
        </keyitem>
      </device>
      <device>
        <name>DEVICE4</name>
        <id>SomeID</id>
        <keyitem>
          <file1>/some/file/path</file1>
          <file2>/some/file/path</file2>
        </keyitem>
      </device>
   </devices>
</testsetup>

我在下面做了一个混乱的尝试:

import lxml.etree as et

remove_items = ['DEVICE1', 'DEVICE3']

with open('somefile.xml', 'w+', newline='') as out_file:
    root = et.parse(out_file)

    for dev in remove_items:
        for elem in root.xpath(".//device/@name='"+dev+"'"):
            elem.getparent().remove(elem)

但我可能走错了路。我该怎么做呢?

2 个答案:

答案 0 :(得分:0)

您几乎就在那里,您需要做的一些事情才能使您的代码有效:

  1. read'r')打开文件并存储其内容,然后再将其打开('w+'
  2. 要选择<device>等于<name>的{​​{1}},请使用此xpath:'DEVICE1'
  3. 完成树的处理后,在根上使用.//device[name='DEVICE1']以获取与您的树相当的XML字符串。
  4. 在应用上述修改后,这是一个有效的解决方案:

    lxml.etree.tostring

答案 1 :(得分:0)

解决方案是:

import lxml.etree as et

remove_items = ['DEVICE1', 'DEVICE3']


with open('test1.xml', 'r') as reader, open('test2.xml', 'w') as writer:
    tree = et.parse(reader)
    devices = tree.getroot().find('devices')

    for element in devices.iter('device'):

        if element.findtext('name') in remove_items:
            print(element.findtext('name'))
            devices.remove(element)

    writer.write(et.tostring(devices, pretty_print = True).decode('utf-8'))