2012-12-11 50 views
2

我有一个XML元素看起来像这样:如何根据其子元素的值删除XML元素?

<Description> 
    <ID>1234</ID> 
    <SubDescription> 
     <subID>4501</subID> 
    </SubDescription> 
    <SubDescription> 
     <subID>4502</subID> 
    </SubDescription> 
</Description> 

我怎样才能根据其“ID”孩子的值删除整个“说明”元素?

+0

[你尝试过什么(http://whathaveyoutried.com)? –

回答

2

您可以使用以下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> 

正如你可以看到,所需的描述节点被去除。

+0

这是一个不错的解决方案。谢谢。 – drake10k

+1

注意:你的XPath可以做得更简单(如果可能更“神奇”的似乎):'/ Description [ID ='1234']' – Phrogz

+0

谢谢@Phrogz,我不知道你能做到这一点。 –

-3

要查找ID做:

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

您想尝试什么样的文档是从加载XML文档

要检查创建的引入nokogiri对象,如果该元素的ID是:

if id == "1234" 

从XML文件本应返回true

最后删除entir Ë描述】:

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

-1'xpath'将返回一个NodeSet。如果文档中有多个''节点,则所有节点都将返回,并且'text'将返回来自所有节点的内容,这将保持'id ==“1234”'不匹配。同样,'xpath(“// Description”)。remove'将从文档中删除所有''节点。 –

0

我个人会用简单的XPath通过@JustinKo使用该解决方案,虽然:

doc.xpath("//Description[ID='1234']").remove 

但是,如果各具特色XPath是不是你的有趣的想法,并写Ruby是,你可以在红宝石瘦更难(如果略少效率):

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

,上面写着:

  • 找到所有命名为的元素
  • 但削减下来做只是其文本是"1234"
  • 地图这是<Description>节点(主叫每.parent的结果)
  • 然后调用每个那些.remove的人。

如果你知道,有永远只能将是一场比赛,你可以把它用简单:

doc.css('ID').find{ |el| el.text=="1234" }.parent.remove