2010-07-17 92 views
2

给定一个搜索项,如何搜索XML中节点的属性并返回只包含那些与该项匹配的节点及其父母的XML方式跟踪到根节点。搜索一个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> 

中的XPath,我用它来搜索XML是“包含(@ name,'angles')]”

我在Ruby中使用Nokogiri来搜索XML,它为我提供了一个与所有匹配术语。我无法弄清楚如何从这组节点构建XML。

谢谢!

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

编辑2:修正了格式良好的xml。

+1

好问题(+1)。查看我的答案以获取解释和简单的XSLT解决方案。 – 2010-07-17 23:41:15

回答

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> 
+0

@Dimitre:谢谢!关于输出中的错误,我已经解决了这个问题。将尝试你的解决方案,并让你知道。再次感谢。 – 2010-07-18 09:54:14

+0

@ Vijay-Dev:XML文档仍然是非格式良好的。我已经改变了我的答案,以包含您最新的XML文档(更正为格式良好)和新结果。 – 2010-07-18 14:32:50

+0

@Dimitre:谢谢你指出错误。修复! – 2010-07-18 16:48:21