How to delete an XML element according to value of one of its children?

╄→гoц情女王★ 提交于 2021-02-10 07:20:06

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!