XPath:从函数返回的节点集中进行选择
XPath: Selecting from a nodeset returned from a function
我刚刚开始使用 XSLT,请多多包涵。我正在处理一个相当复杂的文档,其结构类似于下面的文档。它分为两部分,data
和 meta
。对于每个 data/item
我需要在相应的 meta/item
.
中查找 "actual" class
<root>
<data>
<item id="i1">
<h3 id="p2">akkakk</h3>
<p id="p3">osijaoid</p>
<p id="p4">jqidqjwd</p>
<item>
</data>
<meta>
<item ref="i1">
<p ref="p2" class="heading"/>
<p ref="p3" class="heading"/>
<p ref="p4" class="body"/>
</item>
</meta>
</root>
我需要根据 class 属性对 meta
中相邻的 p
元素进行分组。我认为辅助函数可以使它更干净一些:
<xsl:function name="fn:node-groups" as="node()*">
<xsl:param name="parent"/>
<xsl:variable name="nodeRefs" select="root($parent)//meta/item[@ref = $parent/@id]/p"/>
<xsl:for-each-group select="$nodeRefs" group-adjacent="@class">
<group class="{@class}">
<xsl:for-each select="current-group()">
<node ref="{@ref}"/>
</xsl:for-each>
</group>
</xsl:for-each-group>
</xsl:function>
然后在处理数据节点时使用它,像这样。我的问题是我无法 select 远离函数返回的节点集。
<xsl:template match="//data/item">
<!-- works -->
<xsl:variable name="test1" select="fn:node-groups(.)"/>
<!-- works -->
<xsl:variable name="test2" select="fn:node-groups(.)/*"/>
<!-- does not work -->
<xsl:variable name="test3" select="fn:node-groups(.)/group[@class = 'heading']"/>
</xsl:template>
我 可以 像 test2
那样写一颗星,这会给我所有 node
个节点。但其他任何东西只会给我一个空的节点集。或者至少看起来是这样,但在这一点上我真的不知道了。
我想你的样式表有一个 xmlns="http://example.com/foo"
函数的命名空间声明范围,它将结果元素放入该命名空间的函数中,然后显然 fn:node-groups(.)/group
不会 select 它们作为它 select 是一个没有命名空间的 group
元素。因此,请确保您的函数使用 <xsl:for-each-group select="$nodeRefs" group-adjacent="@class" xmlns="">
.
覆盖该命名空间
另一个原因可能是您的样式表定义了 xpath-default-namespace
.
我还认为你的第三个变量需要是 <xsl:variable name="test3" select="mf:node-groups(.)/node"/>
因为显然你的函数返回的节点序列已经是一个 group
元素的序列,如果你想过滤那个序列然后使用<xsl:variable name="test3" select="fn:node-groups(.)[@class = 'heading']"/>
我刚刚开始使用 XSLT,请多多包涵。我正在处理一个相当复杂的文档,其结构类似于下面的文档。它分为两部分,data
和 meta
。对于每个 data/item
我需要在相应的 meta/item
.
<root>
<data>
<item id="i1">
<h3 id="p2">akkakk</h3>
<p id="p3">osijaoid</p>
<p id="p4">jqidqjwd</p>
<item>
</data>
<meta>
<item ref="i1">
<p ref="p2" class="heading"/>
<p ref="p3" class="heading"/>
<p ref="p4" class="body"/>
</item>
</meta>
</root>
我需要根据 class 属性对 meta
中相邻的 p
元素进行分组。我认为辅助函数可以使它更干净一些:
<xsl:function name="fn:node-groups" as="node()*">
<xsl:param name="parent"/>
<xsl:variable name="nodeRefs" select="root($parent)//meta/item[@ref = $parent/@id]/p"/>
<xsl:for-each-group select="$nodeRefs" group-adjacent="@class">
<group class="{@class}">
<xsl:for-each select="current-group()">
<node ref="{@ref}"/>
</xsl:for-each>
</group>
</xsl:for-each-group>
</xsl:function>
然后在处理数据节点时使用它,像这样。我的问题是我无法 select 远离函数返回的节点集。
<xsl:template match="//data/item">
<!-- works -->
<xsl:variable name="test1" select="fn:node-groups(.)"/>
<!-- works -->
<xsl:variable name="test2" select="fn:node-groups(.)/*"/>
<!-- does not work -->
<xsl:variable name="test3" select="fn:node-groups(.)/group[@class = 'heading']"/>
</xsl:template>
我 可以 像 test2
那样写一颗星,这会给我所有 node
个节点。但其他任何东西只会给我一个空的节点集。或者至少看起来是这样,但在这一点上我真的不知道了。
我想你的样式表有一个 xmlns="http://example.com/foo"
函数的命名空间声明范围,它将结果元素放入该命名空间的函数中,然后显然 fn:node-groups(.)/group
不会 select 它们作为它 select 是一个没有命名空间的 group
元素。因此,请确保您的函数使用 <xsl:for-each-group select="$nodeRefs" group-adjacent="@class" xmlns="">
.
另一个原因可能是您的样式表定义了 xpath-default-namespace
.
我还认为你的第三个变量需要是 <xsl:variable name="test3" select="mf:node-groups(.)/node"/>
因为显然你的函数返回的节点序列已经是一个 group
元素的序列,如果你想过滤那个序列然后使用<xsl:variable name="test3" select="fn:node-groups(.)[@class = 'heading']"/>