获取所有节点的集合,这些节点由子体引用,但本身不是子体



我正在搜索一种可重复使用的方法,以从xml文档中获取所有节点,这些节点是从给定节点的后代引用的(通过id),但它们本身不是给定节点的后裔。例如:

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

如果给定的节点是/root/somenode[1],则生成的节点集应该为空。每个引用的a都是/root/somenode[1]的子级。另一方面,如果给定的节点是/root/somenode[2],则生成的节点集应该包含/root/ssomenode[1]/a[1],而不包含其他内容。

重要的是,生成的节点集始终以相同的方式进行排序。此外,解决方案应该只使用xslt-1.0和xsltproc中内置的exlst扩展(库的确切版本:"使用libxml 20708、libxslt 10126和libexslt 815")

提前感谢,Jost

根据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"),将您的节点作为上下文节点。

此处提供的解决方案不使用任何扩展函数,并且在任何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" />"

相关内容

  • 没有找到相关文章

最新更新