需要在使用XSLT从XML文件接收数字时添加备用数字,例如,如果我正在接收123456789,则需要使用XSLT函数从最右边计算备用数字总和,我可以对此有任何建议吗?备用数字之和(XML/XSL)
感谢, Laxmikanth.S
需要在使用XSLT从XML文件接收数字时添加备用数字,例如,如果我正在接收123456789,则需要使用XSLT函数从最右边计算备用数字总和,我可以对此有任何建议吗?备用数字之和(XML/XSL)
感谢, Laxmikanth.S
这是非常容易使用XSLT 2.0(实际上只是一个XPath 2.0表达式)做:
以下XSLT转换:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:sequence select=
"sum(for $n in reverse(string-to-codepoints('123456789'))
[position() mod 2 eq 1]
return
$n - string-to-codepoints('0')
)
"/>
</xsl:template>
</xsl:stylesheet>
上的任何XML文档(没有应用。查阅全文时使用),产生正确的结果:
请注意使用的XPath 2.0中的功能:string-to-codepoints(),codepoints-to-string()和reverse()。
UPDATE: 类似,但有点简单的表达式是:
sum(for $n in reverse(string-to-codepoints('123456789'))
[position() mod 2 eq 1]
return
xs:integer(codepoints-to-string($n))
)
为了这个表达式编译时,XS前缀必须绑定到命名空间: “http://www.w3.org/2001/XMLSchema”
是;不要为此使用XSLT或XML,这是没有意义的。
如果您有EXSL扩展名(http://exslt.org),则可以执行如下操作:
sum(str:tokenize($x,'')[position() mod 2 = 0])
如果不是,您可以通过循环使用子字符串函数来做类似的事情。
如果您无法使用XSLT 2.0,则仍然可以使用XSLT 1.0。一种方法可以递归调用命名模板:
<xsl:template match="number">
<xsl:call-template name="sumdigits">
<xsl:with-param name="number" select="." />
</xsl:call-template>
</xsl:template>
<xsl:template name="sumdigits">
<xsl:param name="number" />
<xsl:param name="runningtotal">0</xsl:param>
<xsl:choose>
<xsl:when test="string-length($number) = 0">
<xsl:value-of select="$runningtotal" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="lastdigit" select="substring($number, string-length($number), 1)" />
<xsl:variable name="newrunningtotal" select="number($runningtotal) + number($lastdigit)" />
<xsl:call-template name="sumdigits">
<xsl:with-param name="number" select="substring($number, 1, string-length($number) - 2)" />
<xsl:with-param name="runningtotal" select="$newrunningtotal" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
它的工作原理是让最后的数字输入,将其添加到一个“运行总计”和递归调用带的最后两位数字的命名模板输入被删除。当没有剩余数字时,可以返回运行总数。
这XSLT片断假定输入是在XML命名为“数字”
<number>123456789</number>
结果应该是25.正如你所看到的,在XSLT2.0做这将是更加美好的元素中。
对于XSLT 1.0解决方案,我将使用FXSL。
这种转变首先反转的字符串,使用“str-reverse”模板,然后执行两次调用“str-foldl”模板,做的工作:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dvc-foldl-func="dvc-foldl-func"
exclude-result-prefixes="xsl dvc-foldl-func"
>
<xsl:import href="str-foldl.xsl"/>
<xsl:import href="strReverse.xsl"/>
<dvc-foldl-func:delEven/>
<dvc-foldl-func:add/>
<xsl:variable name="vFoldlDelEven"
select="document('')/*/dvc-foldl-func:delEven[1]"/>
<xsl:variable name="vFoldlAdd"
select="document('')/*/dvc-foldl-func:add[1]"/>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:variable name="vReversed">
<xsl:call-template name="strReverse">
<xsl:with-param name="pStr" select="'123456789'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vOddDigits">
<xsl:call-template name="str-foldl">
<xsl:with-param name="pFunc" select="$vFoldlDelEven"/>
<xsl:with-param name="pStr" select="$vReversed"/>
<xsl:with-param name="pA0" select="''"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="str-foldl">
<xsl:with-param name="pFunc" select="$vFoldlAdd"/>
<xsl:with-param name="pStr" select="$vOddDigits"/>
<xsl:with-param name="pA0" select="0"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="dvc-foldl-func:add">
<xsl:param name="arg1" select="0"/>
<xsl:param name="arg2" select="0"/>
<xsl:value-of select="$arg1 + $arg2"/>
</xsl:template>
<xsl:template match="dvc-foldl-func:delEven">
<xsl:param name="arg1"/>
<xsl:param name="arg2"/>
<xsl:copy-of select=
"concat($arg1,
$arg2 * (string-length($arg1) mod 2 = 0)
)
"/>
</xsl:template>
</xsl:stylesheet>
当上述改造应用于任何源XML(忽略),获得所需结果:
请注意:
万一你这样做,因为你需要计算Luhn (mod 10) checksum的东西,这是发布在IBM developerWorks。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:tns="http://www.example.org/tns" xmlns:dp="http://www.datapower.com/extensions" extension-element-prefixes="dp" exclude-result-prefixes="dp regexp" xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<xsl:template match="/">
<xsl:call-template name="recLuhn">
<xsl:with-param name="index" select="1"/>
<xsl:with-param name="parity" select="string-length(CreditCard) mod 2"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="recLuhn">
<xsl:param name="index"/>
<xsl:param name="parity"/>
<xsl:choose>
<xsl:when test="$index <= string-length(CreditCard) ">
<xsl:variable name="sum">
<xsl:call-template name="recLuhn">
<xsl:with-param name="index" select="$index + 1"/>
<xsl:with-param name="parity" select="$parity"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="thisSum">
<xsl:choose>
<xsl:when test="$index mod 2 != $parity">
<xsl:choose>
<xsl:when test="substring(CreditCard, $index, 1)*2 > 9">
<xsl:value-of select="(number(substring(CreditCard, $index, 1)) * 2) - 9"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number(substring(CreditCard, $index, 1)) * 2"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number(substring(CreditCard, $index, 1))"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$thisSum + $sum"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="0"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
即使它是固定长度的数字,我的意思是10位数字? – 2009-08-15 03:41:50
我正在使用撒克逊分析器,它具有撒克逊扩展,但我很新这个解析器,有什么建议吗? – 2009-08-15 03:50:39
不是我已经提供的。也许别人会对你有一些评论。 – 2009-08-15 03:51:38