给出以下
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() <= 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() <= 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() <= current()/@total - 1]" />
附:使用变量或node-set()函数不符合“hack”的条件.