开发者

Remove elements with text using lxml

I have the following xml file

<xml>
  <network id="5">
    <nodelist>
      <IP>10.10.0.135::3111</IP>
      <IP>10.10.0.130::3111</IP>
      <IP>10.10.0.129::3111</IP>
      <IP>10.10.0.129::3111</IP>
    </nodelist>
    <nodelist2/>
  </network>
</xml>

I want to remove all the elements with IP 10.10.0.129 where network id=5. How can I do it in lxml?

Currently, I'm tr开发者_StackOverflow社区ying to find the nodes using xpath and I'm trying to remove it.

But,

netid=xml.xpath("network[@id=%s]/nodelist/IP[contains(text(),%s)]"%(id,node))

Gives me error lxml.etree.XPathEvalError: Invalid expression.


I'm a python programmer, so I have it coded in python 2.7. If you need to use a different language, you will have to port it yourself since I don't do anything but Python.

Note, although this seemingly deals with xpath, most of my processing is done with python.

import lxml.etree as etree  #import etree, like c's include

def delete(xml,networkid,ipaddr):
    tree = etree.fromstring(xml)
    networks = tree.findall('.//network[@id="%s"]'%str(networkid)) #I think you forgot the quotes in your insertion.  
    for network in networks:  #for each network that has id='5'.
        ips = network.findall('.//IP') #All the IP elements under the network
        for ip in ips:  #iterating through a list of ips
            if ipaddr in ip.text:  #if ipaddr is inside the text, even if a port is appended
                ip.getparent().remove(ip)  #the ip's parent (nodelist) removes the ip element
return tree  # I give you the tree


s = r'''<xml>  #Here's your original xml
  <network id="5">
    <nodelist>
      <IP>10.10.0.135::3111</IP>
      <IP>10.10.0.130::3111</IP>
      <IP>10.10.0.129::3111</IP>
      <IP>10.10.0.129::3111</IP>
    </nodelist>
    <nodelist2/>
  </network>
</xml>'''

res = delete(s,'5','10.10.0.129')  #here's the result
print res  #and it's a tree.
print list(res.iter())  #so I print all the items under it.
print etree.tostring(res)  #and you have your edited xml.


This should be it.

tree.xpath(r'''network[@id="%s"]/nodelist/IP[not(contains(text(),"%s"))]'''%('5','10.10.0.129'))

Where the stuff between the triple-single-quotes is your xpath code (I tested with python so I have to). This gives you all the IP elements with your specifications. Apparently python's lxml.etree.xml.xpath won't let me remove, but this will give you everything else.


Using lxml under Python2.7:

tree = ET.fromstring(xml_fragment) ## Or tree = ET.parse(somefile)

for rn in tree.xpath('network[@id="5"]//IP[starts-with(text(),"10.10.0.129:")]'):
    rn.getparent().remove(rn)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜