Xslt 1.0 使用xsl:for-each访问谓词中的当前节点

Xslt 1.0 使用xsl:for-each访问谓词中的当前节点,xslt-1.0,xpath-1.0,Xslt 1.0,Xpath 1.0,我一直在寻找如何在使用xsL:for each遍历节点集合的同时访问当前节点。这是我的XML: <events> <event> <date> <year>2012</year> <month>July</month> </date> <description>...</descr

我一直在寻找如何在使用
xsL:for each
遍历节点集合的同时访问当前节点。这是我的XML:

<events>
    <event>
        <date>
            <year>2012</year>
            <month>July</month>
        </date>
        <description>...</description>
    </event>
    <!-- more events -->
</events>
非常感谢


PS:必须使用XPath和XSLT 1.0。

此转换:

<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:key name="kYear" match="year" use="."/>

 <xsl:key name="kEventByMonthYear" match="event"
  use="string(date)"/>

 <xsl:key name="kMonthByMonthYear" match="month"
  use="string(..)"/>

 <xsl:key name="kMonthByYear" match="month"
 use="../year"/>

 <xsl:template match="/*">
  <xsl:for-each select=
    "*/date/year
            [generate-id() = generate-id(key('kYear', .)[1])]
    ">
   <h2><xsl:value-of select="."/></h2>
   <dl>
      <xsl:apply-templates select=
      "key('kMonthByYear', current())
           [generate-id()
           =
            generate-id(key('kMonthByMonthYear',
                             string(..)
                         )[1]
                     )
            ]"/>
      </dl>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="month">
    <dt><xsl:value-of select="."/></dt>

    <xsl:for-each select=
    "key('kEventByMonthYear', string(current()/..))">
     <dd><xsl:value-of select="description"/></dd>
    </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

应用于以下XML文档时:

<events>
    <event>
        <date>
            <year>2012</year>
            <month>January</month>
        </date>
        <description>Jan1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>January</month>
        </date>
        <description>Jan2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>March</month>
        </date>
        <description>Mar1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>March</month>
        </date>
        <description>Mar2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>March</month>
        </date>
        <description>Mar3</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>July</month>
        </date>
        <description>Jul1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>July</month>
        </date>
        <description>Jul2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>September</month>
        </date>
        <description>Sep1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>October</month>
        </date>
        <description>Oct1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>October</month>
        </date>
        <description>Oct2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>November</month>
        </date>
        <description>Nov1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>November</month>
        </date>
        <description>Nov2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>December</month>
        </date>
        <description>Dec1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>December</month>
        </date>
        <description>Dec2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>December</month>
        </date>
        <description>Dec3</description>
    </event>
    <event>
        <date>
            <year>2013</year>
            <month>January</month>
        </date>
        <description>Jan1</description>
    </event>
    <event>
        <date>
            <year>2013</year>
            <month>January</month>
        </date>
        <description>Jan2</description>
    </event>
</events>
<h2>2012</h2>
<dl>
   <dt>January</dt>
   <dd>Jan1</dd>
   <dd>Jan2</dd>
   <dt>March</dt>
   <dd>Mar1</dd>
   <dd>Mar2</dd>
   <dd>Mar3</dd>
   <dt>July</dt>
   <dd>Jul1</dd>
   <dd>Jul2</dd>
   <dt>September</dt>
   <dd>Sep1</dd>
   <dt>October</dt>
   <dd>Oct1</dd>
   <dd>Oct2</dd>
   <dt>November</dt>
   <dd>Nov1</dd>
   <dd>Nov2</dd>
   <dt>December</dt>
   <dd>Dec1</dd>
   <dd>Dec2</dd>
   <dd>Dec3</dd>
</dl>
<h2>2013</h2>
<dl>
   <dt>January</dt>
   <dd>Jan1</dd>
   <dd>Jan2</dd>
</dl>

2012
一月
1月1日
2012
一月
1月2日
2012
前进
Mar1
2012
前进
Mar2
2012
前进
三月三日
2012
七月
七月一日
2012
七月
七月二日
2012
九月
九月一日
2012
十月
十月一日
2012
十月
十月二日
2012
十一月
11月1日
2012
十一月
11月2日
2012
十二月
十二月一日
2012
十二月
十二月二日
2012
十二月
十二月三日
2013
一月
1月1日
2013
一月
1月2日
生成所需的正确结果:

<events>
    <event>
        <date>
            <year>2012</year>
            <month>January</month>
        </date>
        <description>Jan1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>January</month>
        </date>
        <description>Jan2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>March</month>
        </date>
        <description>Mar1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>March</month>
        </date>
        <description>Mar2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>March</month>
        </date>
        <description>Mar3</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>July</month>
        </date>
        <description>Jul1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>July</month>
        </date>
        <description>Jul2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>September</month>
        </date>
        <description>Sep1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>October</month>
        </date>
        <description>Oct1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>October</month>
        </date>
        <description>Oct2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>November</month>
        </date>
        <description>Nov1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>November</month>
        </date>
        <description>Nov2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>December</month>
        </date>
        <description>Dec1</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>December</month>
        </date>
        <description>Dec2</description>
    </event>
    <event>
        <date>
            <year>2012</year>
            <month>December</month>
        </date>
        <description>Dec3</description>
    </event>
    <event>
        <date>
            <year>2013</year>
            <month>January</month>
        </date>
        <description>Jan1</description>
    </event>
    <event>
        <date>
            <year>2013</year>
            <month>January</month>
        </date>
        <description>Jan2</description>
    </event>
</events>
<h2>2012</h2>
<dl>
   <dt>January</dt>
   <dd>Jan1</dd>
   <dd>Jan2</dd>
   <dt>March</dt>
   <dd>Mar1</dd>
   <dd>Mar2</dd>
   <dd>Mar3</dd>
   <dt>July</dt>
   <dd>Jul1</dd>
   <dd>Jul2</dd>
   <dt>September</dt>
   <dd>Sep1</dd>
   <dt>October</dt>
   <dd>Oct1</dd>
   <dd>Oct2</dd>
   <dt>November</dt>
   <dd>Nov1</dd>
   <dd>Nov2</dd>
   <dt>December</dt>
   <dd>Dec1</dd>
   <dd>Dec2</dd>
   <dd>Dec3</dd>
</dl>
<h2>2013</h2>
<dl>
   <dt>January</dt>
   <dd>Jan1</dd>
   <dd>Jan2</dd>
</dl>
2012
一月
1月1日
1月2日
前进
Mar1
Mar2
三月三日
七月
七月一日
七月二日
九月
九月一日
十月
十月一日
十月二日
十一月
11月1日
11月2日
十二月
十二月一日
十二月二日
十二月三日
2013
一月
1月1日
1月2日
说明

<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:key name="kYear" match="year" use="."/>

 <xsl:key name="kEventByMonthYear" match="event"
  use="string(date)"/>

 <xsl:key name="kMonthByMonthYear" match="month"
  use="string(..)"/>

 <xsl:key name="kMonthByYear" match="month"
 use="../year"/>

 <xsl:template match="/*">
  <xsl:for-each select=
    "*/date/year
            [generate-id() = generate-id(key('kYear', .)[1])]
    ">
   <h2><xsl:value-of select="."/></h2>
   <dl>
      <xsl:apply-templates select=
      "key('kMonthByYear', current())
           [generate-id()
           =
            generate-id(key('kMonthByMonthYear',
                             string(..)
                         )[1]
                     )
            ]"/>
      </dl>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="month">
    <dt><xsl:value-of select="."/></dt>

    <xsl:for-each select=
    "key('kEventByMonthYear', string(current()/..))">
     <dd><xsl:value-of select="description"/></dd>
    </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

正确使用组合分组键。

@Dimitre Novatchev的答案更详细,但我发现了另一种可能性,我想与大家分享。它不依赖于
s,因此更加“新手友好”。另一方面,它也不能解决最初的“访问迭代的当前节点”问题:



谢谢!钥匙的使用对我来说又是一件全新的事情。现在我发现了另一种可能性,并将其作为下面的答案发布。只是出于好奇:对于最初的“访问迭代的当前节点”问题,有什么直接的解决方案吗?@hielsnoppe:不客气。请定义“直截了当”:。对我来说,这个解决方案是我所知道的最简单的XSLT 1.0解决方案——否则我会提供另一个解决方案。让我这样说:您的解决方案使我的转换工作,这很好,但没有回答我是否可以访问上述属性的问题(如果是的话,如何访问)。不过没关系,因为它可以工作。:-)@希尔斯诺普:恐怕我不明白“原始问题”。你可能会想出一个更简单更容易解释的例子(尽量避免使用“前面提到的”这样的词),然后用它来问一个新问题。至于当前的问题,这就是众所周知的“分组”,在XSLT1.0中有一个明确、简单且近乎机械的解决方案。在XSLT2.0中,事情变得更加简单。可能您只是需要
current()
函数,但我只能猜测,而不能完全理解这个问题。是的,我可能已经构建了一个更简单的示例。现在我很高兴事情进展顺利,但也许不久我会的
current()
对我不起作用,因为与谓词中的
一样,它指的是要测试的元素,而不是迭代的当前元素。下一次我将确保更精确,让我们就此为止。如果“它有时由于未知的原因而使标记出错,并且也不能解决最初的”访问迭代的当前节点“问题”,那么,恕我直言”,这实际上不是问题的解决方案。