一次访问XSLT中的所有拆分字符串

时间:2013-08-29 20:24:49

标签: html xml xslt

我将逗号分隔的字符串拆分如下:

<xsl:call-template name="SimpleStringLoop">
    <xsl:with-param name="input" select="'1,2,3,4,'"/>
</xsl:call-template>

<xsl:template name="SimpleStringLoop">
    <xsl:param name="input"/>
    <xsl:if test="string-length($input) &gt; 0">
      <xsl:variable name="v" select="substring-before($input, ',')"/>
      <xsl:value-of select="$v"/>
      <xsl:call-template name="SimpleStringLoop">
        <xsl:with-param name="input" select="substring-after($input, ',')"/>
      </xsl:call-template>
    </xsl:if> 
</xsl:template>

如何在数组中访问所有提取的值? 我需要访问它们中的每一个并在xslt过滤中使用它们。 调用SimpleStringLoop时,$ v第一次保持值1,另一次保持2,依此类推。但有没有办法利用$ v就像在$ v [1],$ v [2]

等数组中使用索引一样

所以我有$v[1]=1, $v[2] =2 etc..

或者我是如此愚蠢,以至于我根本不理解这个递归过程?

2 个答案:

答案 0 :(得分:3)

正如Michael Kay所说,XSLT 2.0将成为你的朋友,因为它可以轻松处理序列。事实上,你甚至不需要递归模板,因为你可以使用方便的tokenize函数来分割你的字符串

<xsl:variable name="fields" select="tokenize($input, ',')" />

然后,例如,要获得第二个字段,您可以执行此操作

<xsl:value-of select="$fields[2]"/>

但是如果你坚持使用XSLT 1.0,你将会做一些额外的工作。目前,您的所有递归模板都在输出一系列字符。这些构成了结果树的一部分,因此XSLT最初无法访问它们。但是,此时您需要做的是输出元素。

  <xsl:variable name="v" select="substring-before($input, ',')"/>
  <field>
    <xsl:value-of select="$v"/>
  </field>

接下来,您需要将现有的 xsl:call-template 包装在变量中,这样您就可以开始访问模板调用的结果。

<xsl:variable name="fields">
  <xsl:call-template name="SimpleStringLoop">
    <xsl:with-param name="input" select="'1,2,3,4,'"/>
  </xsl:call-template>
</xsl:variable>

目前,字段变量此时包含“结果树片段”,但您希望能够访问其中的节点。这是扩展函数的用武之地。有一个扩展可以将结果树片段转换为节点集,因此您可以在其上使用XSLT函数。这在很大程度上取决于处理器你使用的命名空间,但最终它会允许你写这样的东西:

 <xsl:value-of select="msxml:node-set($fields)/field[2]"/>

以此XSLT为例。注意,我在这里使用Mircosoft的XSLT处理器。其他XSLT处理器可用....

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxml="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxml">
  <xsl:template match="/*">
    <xsl:variable name="fields">
      <xsl:call-template name="SimpleStringLoop">
        <xsl:with-param name="input" select="'1,2,3,4,'"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:value-of select="msxml:node-set($fields)/field[2]"/>
  </xsl:template>

  <xsl:template name="SimpleStringLoop">
    <xsl:param name="input"/>
    <xsl:if test="string-length($input) &gt; 0">
      <xsl:variable name="v" select="substring-before($input, ',')"/>
      <field>
        <xsl:value-of select="$v"/>
      </field>
      <xsl:call-template name="SimpleStringLoop">
        <xsl:with-param name="input" select="substring-after($input, ',')"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

有关节点集的更多信息,请尝试以此链接作为开头:

http://www.xml.com/pub/a/2003/07/16/nodeset.html

答案 1 :(得分:2)

您需要XSLT 2.0。在XSLT 1.0中,没有数据类型来处理字符串序列。您可以创建一个包含变量中字符串的节点集,如果您有exslt:node-set()扩展,那么您可以处理节点集,但它是一个糟糕的替代品。升级时间。