2012-07-27 86 views
0

我正在尋找可重複使用的從xml文檔獲取所有節點的方法,這些節點是通過id從後代引用的給定節點,但它們本身不是給定節點的後代。例如:獲取所有節點的集合,這些節點由子孫引用,但不是子孫自己

<root> 
    <somenode> 
    <a id="a1"/> 
    <aref ref="a1"/> 
    </somenode> 
    <somenode> 
    <a id="a2"/> 
    <aref ref="a1"/> 
    <aref ref="a2"/> 
    </somenode> 
</root> 

如果給定節點將是/根/ somenode [1],所得到的節點集應該是空的。每個引用的a都是/ root/somenode [1]的子節點。另一方面,如果給定的節點是/ root/somenode [2],則最終的節點集應該包含/ root/somenode [1]/a [1],而不是其他的。

重要的是生成的節點集始終以相同的方式排序。另外一個解決方案應該只使用XSLT的1.0和exlst擴展建設成爲在xsltproc(庫的確切版本:「使用的libxml 20708,的libxslt 10126和libexslt 815」)提前

感謝, 約斯特

回答

1

http://www.exslt.org/set/functions/difference/index.html,支持的libxslt在模板函數這樣做

<xsl:key name="el-by-id" match="*" use="id"/> 

<xsl:variable name="refs" select="set:difference(key('el-by-id', descendant::*/@ref), descendant::*)"/> 

應該做的(與xmlns:set="http://exslt.org/sets"),它作爲上下文節點的節點。

1

的此處提供的解決方案不使用任何擴展函數,並且可以在任何XSLT處理器上100%移植。

使用XSLT功能generate-id()

//*[@id = /*/somenode[1]/aref/@ref 
    and 
    not(generate-id(ancestor::somenode) = generate-id(/*/somenode[1])) 
    ] 

密鑰的使用可以帶來更高的效率,

這也可以表示爲使用Kayessian公式一個XPath 1.0表達式節點集交叉點:

$ns1[count(.|$ns2) = count($ns2)] 

在純XPath 2.0中,將使用is運算符而不是generate-id()

下面是一個完整的演示

<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="/"> 
    "<xsl:copy-of select= 
    "//*[@id = /*/somenode[1]/aref/@ref 
     and 
     not(generate-id(ancestor::somenode) = generate-id(/*/somenode[1])) 
     ]"/>" 
============ 
    "<xsl:copy-of select= 
    "//*[@id = /*/somenode[2]/aref/@ref 
     and 
     not(generate-id(ancestor::somenode) = generate-id(/*/somenode[2])) 
     ]"/>" 
</xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔應用:

<root> 
    <somenode> 
    <a id="a1"/> 
    <aref ref="a1"/> 
    </somenode> 
    <somenode> 
    <a id="a2"/> 
    <aref ref="a1"/> 
    <aref ref="a2"/> 
    </somenode> 
</root> 

中的XPath表達式,並且所述選擇的節點被複制到輸出:

"" 
============ 
    "<a id="a1" />"