问题
I have an xml element looking something like this:
<Description>
<ID>1234</ID>
<SubDescription>
<subID>4501</subID>
</SubDescription>
<SubDescription>
<subID>4502</subID>
</SubDescription>
</Description>
How can I delete the entire "Description" element according to the value of its "ID" child?
回答1:
You can use the following xpath to select Description nodes that contain an ID node with value 1234:
//Description[./ID[text()='1234']]
So to remove the node, you can do:
doc.xpath("//Description[./ID[text()='1234']]").remove
Example:
require 'nokogiri'
str = %q{
<root>
<Description>
<ID>2222</ID>
<SubDescription>
<subID>4501</subID>
</SubDescription>
<SubDescription>
<subID>4502</subID>
</SubDescription>
</Description>
<Description>
<ID>1234</ID>
<SubDescription>
<subID>4501</subID>
</SubDescription>
<SubDescription>
<subID>4502</subID>
</SubDescription>
</Description>
</root>
}
doc = Nokogiri::XML(str)
doc.xpath("//Description[./ID[text()='1234']]").remove
puts doc
#=> <root>
#=> <Description>
#=> <ID>2222</ID>
#=> <SubDescription>
#=> <subID>4501</subID>
#=> </SubDescription>
#=> <SubDescription>
#=> <subID>4502</subID>
#=> </SubDescription>
#=> </Description>
#=></root>
As you can see, the desired description node is removed.
回答2:
I personally would use the solution by @JustinKo, albeit with the simpler XPath:
doc.xpath("//Description[ID='1234']").remove
However, if crafting XPath isn't your idea of fun, and writing Ruby is, you can lean on Ruby harder (if slightly less efficiently):
doc.css('ID').select{ |el| el.text=="1234" }.map(&:parent).each(&:remove)
That says:
- Find all the elements named
<ID>
- But pare that down do just the ones whose text is
"1234"
- Map this to be the
<Description>
nodes (the result of calling.parent
on each) - And then call
.remove
on each of those.
If you know that there's only ever going to be one match, you can make it simpler with:
doc.css('ID').find{ |el| el.text=="1234" }.parent.remove
回答3:
To find the ID do:
id = doc.xpath("//ID").text
where doc is the Nokogiri object created from loading the xml document
To check if the element id is what you want try:
if id == "1234"
From your xml file this should return true
Finally to remove the entire Description use:
doc.xpath("//Description").remove
What you're looking for is this:
doc = Nokogiri::XML(File.open("test.xml")) #create Nokogiri object from "test.xml"
id = doc.xpath("//ID").text #this will be a string with the id
doc.xpath("//Description").remove if id == "1234" #returns true with your xml document and remove the entire Description element."
来源:https://stackoverflow.com/questions/13825725/how-to-delete-an-xml-element-according-to-value-of-one-of-its-children