1

我知道在 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   
4

2 回答 2

5

实现这一点的另一种方法是匹配“非参数”元素的键,按第一个最前面的参数元素对它们进行分组

<xsl:key 
  name="params" 
  match="tag[@name!='param']" 
  use="generate-id(preceding-sibling::tag[@name='param'][1])" />

然后,您将首先匹配您的“参数”元素

<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&#10;</xsl:text> 
      <xsl:apply-templates select="key('params', generate-id())" />
   </xsl:template>

   <xsl:template match="tag">
      <xsl:value-of select="concat(' - ', @name, '&#10;')" />
   </xsl:template>
</xsl:stylesheet>

当应用于您的示例 XML(假设根 lelement)时,输出以下内容

param
 - Token
 - Token
 - Token
param
 - Token
param
 - Token
 - Token
 - Token
 - return

如果你不想要“return”元素,你可以添加另一个模板来匹配它,然后忽略它。

于 2012-10-01T22:45:19.167 回答
3

在 XSLT 2.0 中这很容易,使用for-each-group. 区分组的一种方法是计算以下兄弟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&#x0a;</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>&#x09;Token&#x0a;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

在这里,我们选择与我们开始时具有Token相同数量的后续param标签的标签param,即出现在下一个参数之前的标签。请注意,这是相当低效的,标签数量为 O(N 2 )。一种更有效的方法是使用尾递归模板,让每个 Token “向前看”以查看它是否是下一个参数之前的最后一个 Token:

<xsl:template match="tag[@name = 'param']">
  <xsl:text>param&#x0a;</xsl:text>
  <xsl:apply-templates select="following-sibling::tag[1][@name = 'Token']" />
</xsl:template>

<xsl:template match="tag[@name = 'Token']">
  <xsl:text>&#x09;Token&#x0a;</xsl:text>
  <xsl:apply-templates select="following-sibling::tag[1][@name = 'Token']" />
</xsl:template>

这里param模板将模板应用到后面的一个 Token,并且 Token 模板检查它的第一个后面的兄弟是否是另一个 Token,如果是,则递归应用模板。

于 2012-10-01T22:00:07.297 回答