XSLT 2.0 - 循环遍历nodeset变量,但也需要处理循环中的其他元素

时间:2011-10-30 13:48:52

标签: xslt-2.0

我有这样的XML:

<?xml version="1.0" encoding="UTF-8"?>

<nodes>
    <n c="value2"/>
    <n>Has a relation to node with value2</n>
    <n>Has a relation to node with value2</n>
    <n c="value"/>
    <n>Has a relation to node with value</n>
    <n c="value1"/>
    <n>Has a relation to node with value1</n>
</nodes>

我对所有具有变量属性的元素进行排序,然后在 for-each循环中迭代此变量。但是在每个循环结束时,我需要打印那些低于当前处理元素(原始XML)的元素的值,并且没有任何属性。

这意味着:在没有属性的<n>上调用apply-templates,但是“select”attr。在apply-templates中无效,可能是因为我现在处于变量循环

有解决方案吗? 感谢

这是XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="nodes">

        <xsl:variable name="sorted">
            <xsl:for-each select="n[@c]">
                <xsl:sort select="@c"></xsl:sort>
                <xsl:copy-of select="."></xsl:copy-of>
            </xsl:for-each>
        </xsl:variable>

        <xsl:for-each select="$sorted/n">
            <xsl:value-of select="@c"></xsl:value-of>

            <xsl:apply-templates select="/nodes/n[2]"></xsl:apply-templates>
        </xsl:for-each>

    </xsl:template>

    <xsl:template match="n[not(@c)]">
        <xsl:value-of select="."></xsl:value-of>
    </xsl:template>

</xsl:stylesheet>

这只是一个例子,所有这些都是更大项目的一部分:)

具有更复杂XPAth的所需输出(现在即使是简单的XPAth也不起作用)是:

Value
Has a relation to node with value
Value1
Has a relation to node with value1
Value2
Has a relation to node with value2
Has a relation to node with value2

现在有点清楚吗?

1 个答案:

答案 0 :(得分:0)

一些想法:apply-templates没有select处理当前上下文节点的子节点;在您的输入示例中,n元素根本没有任何子元素。此外,在您的变量中,您执行复制 - 意味着您创建与输入样本中的节点无关的新节点。因此,虽然我不确定你想要在for-each中使用apply-templates实现你的构造是没有意义的,考虑到你发布的输入样本和你使用的变量。

我怀疑你可以使用XSLT 2.0 for-each-group group-starting-with,如

<xsl:template match="nodes">
  <xsl:for-each-group select="n" group-starting-with="n[@c]">
    <xsl:sort select="@c"/>
    <xsl:value-of select="@c"/>
    <xsl:apply-templates select="current-group() except ."/>
  </xsl:for-each-group>
</xsl:template>

如果这没有帮助,那么考虑发布一个带有样本数据的小输入样本和您想用XSLT 2.0创建的相应输出样本,然后我们就如何实现这一点提出建议。

[edit]现在你已经发布了一个输出样本,我发布了我之前建议的增强版本:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<xsl:output method="text"/>

<xsl:template match="nodes">
  <xsl:for-each-group select="n" group-starting-with="n[@c]">
    <xsl:sort select="@c"/>
    <xsl:value-of select="@c"/>
    <xsl:text>&#10;</xsl:text>
    <xsl:apply-templates select="current-group() except ."/>
  </xsl:for-each-group>
</xsl:template>

<xsl:template match="n[not(@c)]">
   <xsl:value-of select="."/>
   <xsl:text>&#10;</xsl:text>
</xsl:template>

</xsl:stylesheet>

当我使用Saxon 9.3并针对最新的输入样本运行样式表时,结果如下:

value
Has a relation to node with value
value1
Has a relation to node with value1
value2
Has a relation to node with value2
Has a relation to node with value2

这就是你所要求的我认为所以尝试用更复杂的实际输入方法。