2012-07-27 80 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" />"