在XSLT-1.0中对节点集进行双重迭代

时间:2011-11-04 10:56:08

标签: xpath xslt-1.0 exslt

我有一个包含博客文章的XML。每个帖子都包含一个date节点。

我想提取发布帖子的年份列表,并以精美的格式打印出来。我希望每年以非常相似的方式打印活跃月份列表。

外部部件对我来说很好。由于我无法使用原始XSLT-1.0找到实现此目的的方法,因此我使用EXSLT实现了它。我迭代帖子,提取年份,将其放入新的year节点并将其作为临时XML树存储在变量中。然后我使用EXSLT从这个变量创建一个节点集,迭代它并删除重复项。

但是,每当我调用每年的内部模板时,即使我从第一个模板复制并粘贴变量构造代码并将其转储,它也不会生成任何输出。它只是拒绝再次迭代相同的节点集。

我在这里撞墙,我绝对无法理解正在发生的事情。

这就像我设法简化样式表一样::          

<xsl:param name="myparam" select="''" />

<xsl:template match="/">
    <ul>
        <xsl:call-template name="outer" />
    </ul>
</xsl:template>

<xsl:template name="outer">
    <xsl:variable name="years_tree">
        <xsl:for-each select="//post">
            <xsl:sort select="date" />
            <xsl:element name="year"><xsl:value-of select="substring(date, 1, 4)" /></xsl:element>
        </xsl:for-each>
    </xsl:variable>

    <xsl:comment>
        <xsl:copy-of select="$years_tree" />
    </xsl:comment>

    <xsl:for-each select="exsl:node-set($years_tree)/year[not(.=following::year)]">
        <li>
            <xsl:value-of select="." />
            <xsl:if test="starts-with($myparam, string(.))">
                <ul>
                    <xsl:call-template name="inner" />
                </ul>
            </xsl:if>
        </li>
    </xsl:for-each>
</xsl:template>

<xsl:template name="inner">
    <xsl:variable name="years_tree">
        <xsl:for-each select="//post">
            <xsl:sort select="date" />
            <xsl:element name="year"><xsl:value-of select="substring(date, 1, 4)" /></xsl:element>
        </xsl:for-each>
    </xsl:variable>

    <xsl:copy-of select="$years_tree" />
</xsl:template>

</xsl:stylesheet>

这是我的示例输入::

<?xml version="1.0" encoding="UTF-8"?>
<blog>
    <post>
        <date>2011-10-22T22:50:26</date>
    </post>
    <post>
        <date>2011-10-02T17:25:14</date>
    </post>
    <post>
        <date>2011-10-14T11:58:58</date>
    </post>
    <post>
        <date>2011-11-21T11:58:58</date>
    </post>
    <post>
        <date>2010-10-14T11:58:58</date>
    </post>
    <post>
        <date>2011-09-14T11:58:58</date>
    </post>
</blog>

这是我得到的输出::

<?xml version="1.0"?>
<ul>
  <debug>
    <year>2010</year>
    <year>2011</year>
    <year>2011</year>
    <year>2011</year>
    <year>2011</year>
    <year>2011</year>
  </debug>
  <li>2010<ul><debug/></ul></li>
  <li>2011<ul><debug/></ul></li>
</ul>

1 个答案:

答案 0 :(得分:1)

路径/选择当前上下文节点的文档节点,在您的情况下,您正在使用两个文档,即主输入文档和您创建的临时文档。当您调用另一个模板时,上下文节点是临时文档中的year元素,因此您尝试//post尝试在临时文档中查找post元素但您没有该文件中的任何内容。因此,您需要确保存储全局<xsl:variable name="main-doc" select="/"/>,然后当您在主要输入文档中查找post元素时,可以使用$main-doc//post