2010-07-17 89 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