我想使用xslt 1.0从逗号分隔的字符串值中找到最大值。以下是我的输入文件示例:
<?xml version="1.0"?>
<product>
<item>1,2.5,3.6,4</item>
</product>
Expected output:
<product>
<item>4</item>
</product>
这样试试:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/product">
<xsl:copy>
<xsl:apply-templates select="item"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<xsl:variable name="items">
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:for-each select="exsl:node-set($items)/item">
<xsl:sort select="." data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="text"/>
<xsl:param name="delimiter" select="','"/>
<xsl:choose>
<xsl:when test="contains($text, $delimiter)">
<item>
<xsl:value-of select="substring-before($text, $delimiter)"/>
</item>
<!-- recursive call -->
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<item>
<xsl:value-of select="$text"/>
</item>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
注意:
如果您的处理器支持EXSLT扩展函数str:tokenze((和/或math:max((,这可以简化。
这里有另一个不使用任何扩展函数的选项。我不确定它的性能,但也许它会有所帮助。
如果您可以使用XSLT2.0(或另一个答案中提到的EXSLT扩展函数(,这将变得非常容易。
XML输入(稍作修改以更改原始排序顺序。(
<product>
<item>1,2.5,4,3.6</item>
</product>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:call-template name="getMax">
<xsl:with-param name="string" select="normalize-space()"/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="getMax">
<xsl:param name="string"/>
<xsl:variable name="firstNbr" select="number(substring-before(concat($string,','),','))"/>
<xsl:variable name="secondNbr">
<xsl:if test="contains($string,',')">
<xsl:value-of select="number(substring-before(concat(substring-after($string,','),','),','))"/>
</xsl:if>
</xsl:variable>
<xsl:variable name="remainingNbrs" select="substring-after(substring-after($string,','),',')"/>
<xsl:variable name="modString">
<xsl:choose>
<xsl:when test="$firstNbr > $secondNbr">
<!--Move $firstNbr to the end.-->
<xsl:value-of select="$remainingNbrs"/>
<xsl:if test="string($remainingNbrs)">,</xsl:if>
<xsl:value-of select="$firstNbr"/>
</xsl:when>
<xsl:otherwise>
<!--Drop $firstNbr.-->
<xsl:value-of select="$secondNbr"/>
<xsl:if test="string($remainingNbrs)">,</xsl:if>
<xsl:value-of select="$remainingNbrs"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="string($secondNbr)">
<xsl:call-template name="getMax">
<xsl:with-param name="string" select="$modString"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$firstNbr"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
XML输出
<product>
<item>4</item>
</product>
感谢您的宝贵回复,我使用以下样式表解决了上述问题。
<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="'125,192,152.50,1600,145,169,170'"/>
</xsl:call-template>
</xsl:variable>
<final>
<xsl:value-of select="msxml:node-set($fields)/field[not(. < msxml:node-set($fields)/field)][1]"/>
</final>
</xsl:template>
<xsl:template name="SimpleStringLoop">
<xsl:param name="input"/>
<xsl:if test="string-length($input) > 0">
<xsl:variable name="v" select="substring-before(concat($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>