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)
精彩评论