简体   繁体   English

如何根据子元素之一的值删除XML元素?

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

I have an xml element looking something like this: 我有一个看起来像这样的xml元素:

<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? 如何根据“ ID”子元素的值删除整个“描述”元素?

You can use the following xpath to select Description nodes that contain an ID node with value 1234: 您可以使用以下xpath选择包含ID值为1234的ID节点的Description节点:

//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. 如您所见,所需的描述节点已删除。

I personally would use the solution by @JustinKo, albeit with the simpler XPath: 我个人将使用@JustinKo的解决方案,尽管使用了更简单的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): 但是,如果制作XPath并不是您的乐趣所在,而编写Ruby就是您的主意,那么您可以更加依赖Ruby(如果效率略低):

doc.css('ID').select{ |el| el.text=="1234" }.map(&:parent).each(&:remove)

That says: 说的是:

  • Find all the elements named <ID> 查找所有名为<ID>的元素
  • But pare that down do just the ones whose text is "1234" 但是请尽量减少那些文字为"1234"
  • Map this to be the <Description> nodes (the result of calling .parent on each) 将此映射为<Description>节点(在每个节点上调用.parent的结果)
  • And then call .remove on each of those. 然后对每个调用.remove

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

To find the ID do: 要查找ID,请执行以下操作:

id = doc.xpath("//ID").text

where doc is the Nokogiri object created from loading the xml document 其中doc是通过加载xml文档创建的Nokogiri对象

To check if the element id is what you want try: 要检查元素ID是否是您想要的,请尝试:

if id == "1234"

From your xml file this should return true 从您的xml文件中应返回true

Finally to remove the entire Description use: 最后删除整个Description使用:

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."

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM