我有一个xml元素看起来像这样:
<Description>
<ID>1234</ID>
<SubDescription>
<subID>4501</subID>
</SubDescription>
<SubDescription>
<subID>4502</subID>
</SubDescription>
</Description>
如何根据其"ID"子元素的值删除整个"描述"元素?
可以使用以下 xpath 选择包含值为 1234 的 ID 节点的描述节点:
//Description[./ID[text()='1234']]
因此,要删除节点,您可以执行以下操作:
doc.xpath("//Description[./ID[text()='1234']]").remove
例:
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>
如您所见,所需的描述节点被删除。
我个人会通过@JustinKo使用该解决方案,尽管使用更简单的XPath:
doc.xpath("//Description[ID='1234']").remove
但是,如果制作 XPath 不是你的想法,而编写 Ruby 是,你可以更努力地依靠 Ruby(如果效率稍微低一点):
doc.css('ID').select{ |el| el.text=="1234" }.map(&:parent).each(&:remove)
这说:
- 查找名为
<ID>
的所有元素
但是,只 - 做那些文本
"1234"
- 将其映射到
<Description>
节点(在每个节点上调用.parent
的结果) - 然后打电话给
.remove
每一个。
如果您知道只有一场比赛,则可以通过以下方式简化:
doc.css('ID').find{ |el| el.text=="1234" }.parent.remove
要查找 ID,请执行以下操作:
id = doc.xpath("//ID").text
其中 doc 是通过加载 xml 文档创建的 Nokogiri 对象
要检查元素 id 是否是您想要的,请尝试:
if id == "1234"
从您的 xml 文件中,这应该返回 true
最后要删除整个描述,请使用:
doc.xpath("//Description").remove
你要找的是这个:
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."