xslt – 统一处理分组的兄弟元素

给出以下
XML文档

<root>
  <a pos="0" total="2"/>
  <a pos="1" total="2"/>

  <a pos="0" total="3"/>
  <a pos="1" total="3"/>
  <a pos="2" total="3"/>

  <a pos="0" total="4"/>
  <a pos="1" total="4"/>
  <a pos="2" total="4"/>
  <a pos="3" total="4"/>
</root>

我需要把它翻译成

<root>
  <group>
    <a pos="0" total="2"/>
    <a pos="1" total="2"/>
  </group>
  <group>
    <a pos="0" total="3"/>
    <a pos="1" total="3"/>
    <a pos="2" total="3"/>
  </group>
  <group>
    <a pos="0" total="4"/>
    <a pos="1" total="4"/>
    <a pos="2" total="4"/>
    <a pos="3" total="4"/>
  </group>
</root>

使用XSLT 1.0样式表.

也就是说,每个< a>文档中@pos属性为0的元素
隐含地启动一个由它和@ total-1组成的组< a>元素.换句话说,为了解释这一点,@ pos表示@total相邻元素组中元素的基于0的索引(位置).

我提出了以下样式表,它有效:

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

    <xsl:output method="xml" indent="yes" />

    <xsl:template match="/">
        <xsl:apply-templates select="root" />
    </xsl:template>

    <xsl:template match="root">
        <xsl:apply-templates select="a[@pos=0]" mode="leader"/>
    </xsl:template>

    <xsl:template match="a" mode="leader">
        <group>
            <xsl:apply-templates select="." />
            <xsl:apply-templates select="following-sibling::a[position() &lt;= current()/@total - 1]" />
        </group>
    </xsl:template>

    <xsl:template match="a">
         <xsl:copy-of select="." />
    </xsl:template>

</xsl:stylesheet>

我对我的解决方案的问题是它使[@ pos = 0]元素“特殊”:进一步处理每个< a>在预期组中的元素,我必须首先将适当的模板首先应用于“组长”元素,然后再应用于组中的其余元素.

换句话说,我非常希望有类似的东西(不正确)

    <xsl:template match="a" mode="leader">
        <group>
            <xsl:apply-templates select=". and following-sibling::a[position() &lt;= current()/@total - 1]" />
        </group>
    </xsl:template>

这将适用于我的< xsl:template match =“a”>一次性模板到组中的所有元素. (重新说明我试图在select表达式中拼写的内容:“选择上下文元素及其后续的兄弟元素匹配…”.)

有没有办法在不诉诸变量和exslt:node-set()的黑客的情况下使用XSLT 1.0获得我想要的东西?可能有更好的方法来进行基于元素计数的分组而不是我想出的那个(这本身就是每个组中的第一个元素特殊)?

我承认这个问题的标题相当薄弱,但我没有想出一个正确反映我问题本质的傻瓜.

最佳答案 你可以这样做:

<xsl:apply-templates select=". | following-sibling::a[position() &lt;= current()/@total - 1]" />

附:使用变量或node-set()函数不符合“hack”的条件.

点赞