搜索XML并将节点的子集作为XML

时间:2010-07-17 20:57:26

标签: ruby xml search xpath nokogiri

给定一个搜索词,如何搜索XML中节点的属性,并返回仅包含与该词一起匹配的节点及其父节点一直跟踪到根节点的XML。

以下是输入XML的示例:

<root>
  <node name = "Amaths"> 
    <node name = "Bangles"/> 
  </node>
  <node name = "C">
    <node name = "Dangles">
      <node name = "E"> 
        <node name = "Fangles"/> 
      </node>
    </node>
    <node name = "Gdecimals" />
  </node>
  <node name = "Hnumbers"/> 
  <node name = "Iangles"/> 
</root>

输出我正在寻找搜索词“角度”:

<root>
  <node name = "Amaths"> 
    <node name = "Bangles"/> 
  </node>
  <node name = "C">
    <node name = "Dangles">
      <node name = "E"> 
        <node name = "Fangles"/> 
      </node>
    </node>
  </node>
  <node name = "Iangles"/> 
</root>

我用来搜索xml的XPath是“// * [contains(@ name,'angles')]”

我在Ruby中使用Nokogiri来搜索XML,它为我提供了与该术语匹配的所有节点的NodeSet。我无法弄清楚如何从那组节点构造回来的XML。

谢谢!

编辑:修复了本应该的例子。谢谢Dimitre。

编辑2:再次修复了xml的格式良好。

1 个答案:

答案 0 :(得分:2)

首先,请注意所呈现的所需输出不正确,并且后面的元素在文档后面没有结束标记:

<node name = "C">

评估XPath表达式的结果可以是XML文档中的一组节点,但XPath 不能更改这些注释。

此XPath表达式选择

  

与该术语匹配的节点   他们的父母一直追踪到   根节点

//*[contains(@name,'angles') and not(node())]/ancestor::*

但是,节点不会更改,并且它们包含所有子节点,这意味着以Root为根的完整子树仍然是返回结果中Root的子树。

如果要获取与原始XML文档结构不同的新文档(节点集),则必须使用托管XPath的其他语言。有许多这样的语言,例如XSLT,XQuery和任何具有XML DOM实现的语言。

这是一个XSLT转换,产生想要的结果

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="*[not(descendant-or-self::*[contains(@name, 'angles')])]"/>
</xsl:stylesheet>

将此转换应用于提供的XML文档(更正为格式良好)

<root>
  <node name = "Amaths">
    <node name = "Bangles"/>
  </node>
  <node name = "C">
    <node name = "Dangles">
      <node name = "E">
        <node name = "Fangles"/>
      </node>
      <node name = "Gdecimals" />
    </node>
  </node>
  <node name = "Hnumbers"/>
  <node name = "Iangles"/>
</root>

生成所需(正确)结果

<root>
   <node name="Amaths">
      <node name="Bangles"/>
   </node>
   <node name="C">
      <node name="Dangles">
         <node name="E">
            <node name="Fangles"/>
         </node>
      </node>
   </node>
   <node name="Iangles"/>
</root>