Двойная итерация над набором узлов в XSLT-1.0 - PullRequest
0 голосов
/ 04 ноября 2011

У меня есть 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 Ответ

1 голос
/ 04 ноября 2011

Хорошо, путь / выбирает узел документа текущего узла контекста, и в вашем случае вы работаете с двумя документами, первичным входным документом и временным документом, который вы создаете. Когда вы вызываете другой шаблон, узел контекста является элементом year во временном документе, поэтому ваша попытка с помощью //post пытается найти элементы post во временном документе, а у вас их нет в этом документе. Поэтому вам нужно убедиться, что вы храните глобальный <xsl:variable name="main-doc" select="/"/>, а затем, когда вы ищете post элементов в первичном входном документе, вы можете использовать $main-doc//post.

...