我有一个分隔的字符串(在下面的例子中用空格分隔),我需要对它进行标记,排序,然后重新连接在一起,我需要使用XSLT 1.0完成所有这些操作。我该怎么办?我知道我需要以某种方式使用xsl:sort
,但到目前为止我尝试的所有内容都给了我一些错误。
例如,如果我在此帖子的底部运行代码,我会得到:
草莓蓝莓橙子覆盆子 柠檬柠檬
如果我想要这样做,我该怎么办?:
蓝莓柠檬石灰橙色覆盆子 草莓
请注意,我正在使用XSLT 1.0。
以下是代码,它基于代码Jeni Tennison。
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="tokenize1.xsl"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:call-template name="tokenize">
<xsl:with-param name="string" select="'strawberry blueberry orange raspberry lime lemon'" />
</xsl:call-template>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="string" />
<xsl:param name="delimiter" select="' '" />
<xsl:choose>
<xsl:when test="$delimiter and contains($string, $delimiter)">
<token>
<xsl:value-of select="substring-before($string, $delimiter)" />
</token>
<xsl:text> </xsl:text>
<xsl:call-template name="tokenize">
<xsl:with-param name="string"
select="substring-after($string, $delimiter)" />
<xsl:with-param name="delimiter" select="$delimiter" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<token><xsl:value-of select="$string" /></token>
<xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:4)
这是一个低效的纯版本1解决方案:
<!-- Sort the tokens -->
<xsl:template name="sortTokens">
<xsl:param name="tokens" select="''"/> <!-- The list of tokens -->
<xsl:param name="separator" select="' '"/> <!-- What character separates the tokens? -->
<xsl:param name="pivot" select="''"/> <!-- A pivot word used to divide the list -->
<xsl:param name="lessThan" select="''"/> <!-- Accumulator for tokens less than the pivot (with leading separator) -->
<xsl:param name="moreThan" select="''"/> <!-- Accumulator for tokens more than the pivot (with leading separator) -->
<xsl:param name="leadWith" select="''"/> <!-- If set, output this before sorting -->
<xsl:param name="trailWith" select="''"/> <!-- If set, output this after sorting -->
<!-- The first token -->
<xsl:variable name="firstToken" select="substring-before(concat($tokens,$separator),$separator)"/>
<!-- Is the first token more or less than the pivot? -->
<xsl:variable name="pivotVsFirstToken">
<xsl:call-template name="compareStrings">
<xsl:with-param name="a" select="$pivot"/>
<xsl:with-param name="b" select="$firstToken"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<!-- No input, no output -->
<xsl:when test="$tokens = '' and $pivot = ''"></xsl:when>
<!-- At the outset, the first token becomes the pivot -->
<xsl:when test="$pivot = ''">
<xsl:value-of select="$leadWith"/>
<xsl:call-template name="sortTokens">
<xsl:with-param name="separator" select="$separator"/>
<xsl:with-param name="tokens" select="substring-after($tokens,$separator)"/>
<xsl:with-param name="pivot" select="$firstToken"/>
</xsl:call-template>
<xsl:value-of select="$trailWith"/>
</xsl:when>
<!-- When all tokens are in a bucket, output the pivot between sorted buckets -->
<xsl:when test="$tokens = ''">
<xsl:call-template name="sortTokens">
<xsl:with-param name="separator" select="$separator"/>
<xsl:with-param name="tokens" select="substring-after($lessThan,$separator)"/>
<xsl:with-param name="trailWith" select="$separator"/>
</xsl:call-template>
<xsl:value-of select="$pivot"/>
<xsl:call-template name="sortTokens">
<xsl:with-param name="separator" select="$separator"/>
<xsl:with-param name="tokens" select="substring-after($moreThan,$separator)"/>
<xsl:with-param name="leadWith" select="$separator"/>
</xsl:call-template>
</xsl:when>
<!-- If the first token is less than the pivot, put it in the lessThan bucket -->
<xsl:when test="number($pivotVsFirstToken) = 1">
<xsl:call-template name="sortTokens">
<xsl:with-param name="separator" select="$separator"/>
<xsl:with-param name="tokens" select="substring-after($tokens,$separator)"/>
<xsl:with-param name="pivot" select="$pivot"/>
<xsl:with-param name="lessThan" select="concat($separator,$firstToken,$lessThan)"/>
<xsl:with-param name="moreThan" select="$moreThan"/>
</xsl:call-template>
</xsl:when>
<!-- If the first token is more than the pivot, put it in the moreThan bucket -->
<xsl:otherwise>
<xsl:call-template name="sortTokens">
<xsl:with-param name="separator" select="$separator"/>
<xsl:with-param name="tokens" select="substring-after($tokens,$separator)"/>
<xsl:with-param name="pivot" select="$pivot"/>
<xsl:with-param name="lessThan" select="$lessThan"/>
<xsl:with-param name="moreThan" select="concat($separator,$firstToken,$moreThan)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Quote an apostrophe -->
<xsl:variable name="apos" select=""'""/>
<!-- The comparison order of the characters -->
<xsl:variable name="characterOrder" select="concat(' !"#$%&',$apos,'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')"/>
<!-- Return -1 if string a is less, 1 if string b is less, or 0 if they are equal -->
<xsl:template name="compareStrings">
<xsl:param name="a" select="''"/>
<xsl:param name="b" select="''"/>
<xsl:choose>
<xsl:when test="$a = '' and $b = ''">0</xsl:when>
<xsl:when test="$a = ''">-1</xsl:when>
<xsl:when test="$b = ''">1</xsl:when>
<xsl:when test="substring($a,1,1) = substring($b,1,1)">
<xsl:call-template name="compareStrings">
<xsl:with-param name="a" select="substring($a,2)"/>
<xsl:with-param name="b" select="substring($b,2)"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains(substring-after($characterOrder,substring($a,1,1)),substring($b,1,1))">-1</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:template>
答案 1 :(得分:0)
如果您的处理器支持EXSLT,则最好使用str:tokenize
为了排序,为什么不使用xsl:sort?
<xsl:template match="/">
<xsl:variable name="tokens">
<xsl:call-template name="tokenize">
<xsl:with-param name="string" select="'strawberry blueberry orange raspberry lime lemon'" />
</xsl:call-template>
</xsl:variable>
<xsl:for-each select="$tokens">
<xsl:sort select="text()" />
<xsl:value-of select="." />
<xsl:if test="not(last())">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
请注意,您可能需要exsl:node-set do到迭代。