如何使用python基于条件删除xml文件中的特定行?

时间:2015-08-05 09:40:26

标签: python python-2.7 python-3.x subprocess

我遇到问题,正在寻找解决方案。

我想根据条件删除该行。例如,xml文件是

<app>
    .
    .
<process>
    <tag>any tag</tag>
    <trigger order="1" name="activity1" perform="y">
        <external>
                <action name="check_req"/>
                <action name="event"/>
        </external>
        <var name="type"/>
        <var name="user" />
          </trigger>
</process>
<process>
<tag>any tag</tag>
<trigger order="3" name="activity1" perform="y">
    <external>
            <action name="check_req"/>
            <action name="event"/>
            <action name="ckeck"/>
        </external>
        <var name="type"/>
        <var name="user" />
          </trigger>
</process>
<process>
<tag>any tag</tag>
<trigger order="2" name="activity1" perform="y">
    <external>
            <action name="event"/>
            <action name="ckeck"/>
        </external>
        <var name="type"/>
        <var name="user" />
          </trigger>
</process>
<process>
<tag>any tag</tag>
  <trigger order="1" name="activity1" perform="y">
    <external>
            <action name="check_req"/>
            <action name="event"/>
            <action name="ckeck"/>
        </external>
        <var name="type"/>
        <var name="user" />
     </trigger>
</process>
<process>
   <tag>any tag</tag>
   <trigger order="4" name="activity1" perform="y">
    <external>
            <action name="ckeck"/>
            <action name="check_req"/>
        </external>
        <var name="type"/>
        <var name="user" />
   </trigger>
</process>
</app>

所以从这段代码中我想删除行<action name="ckeck"/>,只要在触发器中出现这两个动作

<action name="ckeck"/> 
<action name="ckeck_req"/>

<action name="ckeck_req"/>
<action name="ckeck"/>

所以我必须删除行<action name="ckeck"/>,只有在上述两个操作结合在一起的情况下,否则它不会删除任何行。

所以我是python语言的新手,所以我无法做到这一点。问题是它的文件包含许多触发块,其中一些触发块既包含动作块,又包含一个动作块。特定的行只是在给定的情况下才会删除

2 个答案:

答案 0 :(得分:1)

您应该使用一些xml解析库,例如xml.etree.ElementTreelxml

然后,您可以使用 XPATH 查找<external>下的所有<trigger>元素,然后获取名称属性为action的{​​{1}}元素和名称属性为check_req的{​​{1}}元素。然后,如果两者都不是,那意味着两个孩子都存在,删除其中的元素。 name属性为action,然后将xml保存到其他文件(甚至同一文件)。示例 -

ckeck

示例/演示 -

我的ckeck -

import xml.etree.ElementTree as ET
file = ET.parse('a.xml')
root = file.getroot()
for elem in root.findall('.//trigger/external'):
    check_req_elems = elem.find('./action[@name="check_req"]')
    check_elem = elem.find('./action[@name="ckeck"]')
    if check_req_elems is not None and check_elem is not None:
            elem.remove(check_elem)

file.write('b.xml')

代码 -

a.xml

我的<app> <process> <tag>any tag</tag> <trigger order="3" name="activity1" perform="y"> <external> <action name="check_req"/> <action name="event"/> <action name="ckeck"/> </external> <var name="type"/> <var name="user" /> </trigger> </process>> <process> <tag>any tag</tag> <trigger order="2" name="activity1" perform="y"> <external> <action name="event"/> <action name="ckeck"/> </external> <var name="type"/> <var name="user" /> </trigger> </process> </app> 变成 -

>>> file = ET.parse('a.xml')
>>> root = file.getroot()
>>> for elem in root.findall('.//trigger/external'):
...     check_req_elems = elem.find('.//action[@name="check_req"]')
...     check_elem = elem.find('.//action[@name="ckeck"]')
...     if check_req_elems is not None and check_elem is not None:
...             elem.remove(check_elem)
...
>>> file.write('b.xml')

答案 1 :(得分:-1)

当触发器中出现两个动作时,它们是否总是以相同的方式排序,即“ckeck”之后的“ckeck”和一行分开?如果是这种情况,您可以根据该条件给出条件,例如

action1 = "ckeck_req"
action2 = "ckeck"
with open(xmlfile, "r") as f:
    x = f.readlines()
y = [] # new list without the unwanted actions
for i in range(len(x)):
    if action2 in x[i] and action1 in x[i-2]:
        continue
    else:
        y.append(x[i])

然后将新列表y写入文件。我只是把这一点写在了我的头顶,所以很可能有一个更好的方法来做到这一点。现在我考虑一下你可能想看看Regular Expressions