Python:在xml中,如何删除父节点中的节点

时间:2014-09-27 19:14:23

标签: python xml

我有一个非常大的xml,我需要删除另一个节点中的某些特定节点。 例如我有一个列表,其中包含应该存在于xml中的节点的名称。因此,除了这些节点之外,应删除父节点中的所有其他节点并将其写入新的xml文件。

我只需删除节点,即'实例',其中第一个'数据'元素不等于我列表中的值,我将会提供。其余的xml信息,即“描述”,“符号”标签不应受到干扰。

假设:我已经将应该从外部文件读取的数据解析为python列表变量。

DOM或SAX任何人都对我好。但我相信DOM非常快。 对任何BIF可用或逻辑的任何提示对我来说也没问题。

注意:我是Python的新手。所以请在我的代码中注释是否有任何错误。

我的代码如下:

from xml.etree.ElementTree import ElementTree
tree = ElementTree()
tree.parse('Test.xml')

file = open("File.txt")

list = []

for lines in file:
    list.append(lines)

Instance = tree.findall('Instance')
for i in Instance:
   while (i != list[i]):
       Instance.remove(i)

tree.write('new.xml')

以下是示例xml文件:

<?xml version='1.0' encoding='UTF-8'?>
<Identification>
<Description ID="12">Some text</Description>
</Identification>
<Symbols>
  <Name Width="1">abc</Name>
  <Name Width="2">def</Name>
</Symbols>

<Instance RowRef="A">
  <DataSet>
    <Data>12345678</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
</Instance>
<Instance RowRef="B">
  <DataSet>
    <Data>87654321</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
</Instance>
<Instance RowRef="C">
  <DataSet>
    <Data>06354237/Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>

1 个答案:

答案 0 :(得分:2)

你在很多方面感到困惑。

首先,您提供的xml缺少根标记。您的xml文件应该看起来更像这样(其中Root可以替换为必要的标记):

<?xml version='1.0' encoding='UTF-8'?>
<Root>
<Identification>
<Description ID="12">Some text</Description>
</Identification>
<Symbols>
  <Name Width="1">abc</Name>
  <Name Width="2">def</Name>
</Symbols>

<Instance RowRef="A">
  <DataSet>
    <Data>12345678</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
</Instance>
<Instance RowRef="B">
  <DataSet>
    <Data>87654321</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
</Instance>
<Instance RowRef="C">
  <DataSet>
    <Data>06354237</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
  <DataSet>
    <Data>abcd</Data>
  </DataSet>
</Instance>
</Root>

第二,如果您担心速度问题,请考虑使用cElementTree代替ElementTree

>>> import xml.etree.cElementTree as ET  # use cElementTree for faster processing

第三次,您需要为ET.parse方法的结果指定一个名称,否则您将无法在以后引用它:

>>> tree = ET.parse('Test.xml')

第四,现在您需要在找到该树的所有Instance元素之前找到该树的根目录:

>>> root = tree.getroot()  # now get the root
>>> keeper_data = ['06354237', '87654321']  # your list that you will apparently get from a file?
>>> instances = root.findall('Instance')

现在您需要找到InstanceData个值表示应删除Instance元素的元素:

第五,您需要检查第一个Data元素的文字是否在您的守门员列表中,第六个,您remove来自root(或父母恰好是)的元素,而不是来自instances的元素:

>>> for instance in instances:
        data1 = instance.find('./DataSet/Data')
        if data1.text not in keeper_data:
            # NOTE WELL: I remove from the root (not the instance) below!
            root.remove(instance)

现在写入新的xml文件:

>>> tree.write('New.xml')

您生成的xml文件如下所示:

<Root>
 <Identification>
  <Description ID="12">Some text</Description>
 </Identification>
 <Symbols>
  <Name Width="1">abc</Name>
  <Name Width="2">def</Name>
 </Symbols>
 <Instance RowRef="B">
  <DataSet>
   <Data>87654321</Data>
  </DataSet>
   <DataSet>
    <Data>abcd</Data>
   </DataSet>
   <DataSet>
    <Data>abcd</Data>
   </DataSet>
  </Instance>
  <Instance RowRef="C">
   <DataSet>
    <Data>06354237</Data>
   </DataSet>
   <DataSet>
    <Data>abcd</Data>
   </DataSet>
   <DataSet>
    <Data>abcd</Data>
   </DataSet>
  </Instance>
 </Root>

请注意,省略了具有值为12345678的数据元素且没有其他keeper_data元素的实例。