我知道在xslt中没有break语句而且不知道如何解决我的问题。
实施例
<tag name="param" />
<tag name="Token" />
<tag name="Token" />
<tag name="Token" />
<tag name="param" />
<tag name="Token" />
<tag name="param" />
<tag name="Token" />
<tag name="Token" />
<tag name="Token" />
<tag name="return"/>
参数必须在下一个参数之前与所有标记分组。我怎么能这样做?
输出必须是这样的:
param
Token
Token
Token
param
Token
param
Token
Token
Token
答案 0 :(得分:5)
实现这一目标的另一种方法是匹配“非参数”元素的关键,将它们按第一个最前面的参数元素分组
<xsl:key
name="params"
match="tag[@name!='param']"
use="generate-id(preceding-sibling::tag[@name='param'][1])" />
然后,您将首先匹配您的“param”元素
<xsl:apply-templates select="tag[@name='param']" />
对于您匹配的每一个,您可以使用键
在组中选择关联的标签<xsl:apply-templates select="key('params', generate-id())" />
尝试以下XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:key name="params" match="tag[@name!='param']" use="generate-id(preceding-sibling::tag[@name='param'][1])" />
<xsl:template match="/*">
<xsl:apply-templates select="tag[@name='param']" />
</xsl:template>
<xsl:template match="tag[@name='param']">
<xsl:text>param </xsl:text>
<xsl:apply-templates select="key('params', generate-id())" />
</xsl:template>
<xsl:template match="tag">
<xsl:value-of select="concat(' - ', @name, ' ')" />
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML(假设根元素)时,输出以下内容
param
- Token
- Token
- Token
param
- Token
param
- Token
- Token
- Token
- return
如果你不想要“return”元素,你可以添加另一个模板来匹配它,然后忽略它。
答案 1 :(得分:3)
在XSLT 2.0中,这很容易,使用for-each-group
,但在XSLT 1.0中,它不那么简单。区分组的一种方法是计算以下兄弟param
标签:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:apply-templates select="*/tag[@name = 'param']" />
</xsl:template>
<xsl:template match="tag[@name = 'param']">
<xsl:text>param
</xsl:text>
<xsl:apply-templates select="following-sibling::tag[@name = 'Token']
[count(following-sibling::tag[@name='param'])
= count(current()/following-sibling::tag[@name='param'])]" />
</xsl:template>
<xsl:template match="tag[@name = 'Token']">
<xsl:text>	Token
</xsl:text>
</xsl:template>
</xsl:stylesheet>
此处,我们选择的Token
代码与我们开始的param
代码具有相同数量的param
代码,即在下一个参数之前发生的代码。请注意,这是非常低效的,标签数量为O(N 2 )。一种更有效的方法是使用尾递归模板,让每个令牌“向前看”以查看它是否是下一个参数之前的最后一个令牌:
<xsl:template match="tag[@name = 'param']">
<xsl:text>param
</xsl:text>
<xsl:apply-templates select="following-sibling::tag[1][@name = 'Token']" />
</xsl:template>
<xsl:template match="tag[@name = 'Token']">
<xsl:text>	Token
</xsl:text>
<xsl:apply-templates select="following-sibling::tag[1][@name = 'Token']" />
</xsl:template>
此处param
模板将模板应用于令牌后的第一个,并且令牌模板检查其第一个后续兄弟是否是另一个令牌,如果是,则递归应用模板。