【问题标题】:Validate IBAN using XSLT 2.0?使用 XSLT 2.0 验证 IBAN?
【发布时间】:2011-06-05 04:35:57
【问题描述】:

是否可以编写一个可以进行基本 IBAN Mod-97 检查的 XSLT 函数?

来自维基百科:
1.将四个初始字符移动到字符串的末尾。
2. 将字符串中的每个字母替换为两位数字,从而扩展字符串,其中 A=10, B=11, ..., Z=35。
3. 将字符串解释为十进制整数并计算该数字除以 97 后的余数。

如果余数为 1,则通过校验位测试并且 IBAN 可能有效。

谢谢。

【问题讨论】:

  • 好问题,+1。请参阅我的答案以获得完整且简单的解决方案。 :)

标签: xslt xpath xslt-2.0 xpath-2.0 iban


【解决方案1】:

只是为了好玩(我没有看到@Dimitre 已经回答了它)

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:local="http://localhost/">
    <xsl:template match="IBAN[local:validate(.)]">
        <xsl:text>Validated IBAN</xsl:text>
    </xsl:template>
    <xsl:function name="local:validate">
        <xsl:param name="pIBAN" as="xs:string"/>
        <xsl:sequence select="xs:integer(
                                 codepoints-to-string(
                                    for $n in string-to-codepoints(
                                                 concat(
                                                    substring(
                                                       $pIBAN,
                                                       5
                                                    ),
                                                    substring(
                                                       $pIBAN,
                                                       1,
                                                       4
                                                    )
                                                 )
                                              )
                                    return if ($n > 64)
                                           then string-to-codepoints(
                                                   string(
                                                      $n - 55
                                                   )
                                                )
                                           else $n
                                 )
                              ) mod 97 eq 1"/>
    </xsl:function>
</xsl:stylesheet>

有了这个输入:

<IBAN>GB82WEST12345698765432</IBAN>

输出:

Validated IBAN

编辑:更好的一个班轮。

【讨论】:

  • +1 以获得好的答案。为了更好的可读性,我故意没有生成一个表达式。
  • @Dimitre:顺便说一句,我喜欢for 表达式中的 XPath 2.0“变量声明”... ;)
  • @Alejandro:是的,这是我将几乎所有 XSLT 2.0 编写为(通常是单个)XPath 表达式的基本武器。您仍然必须使用&lt;xsl:variable&gt; 的唯一情况是当变量的值是一个序列时。在 XPath 3.0 中,这个限制消失了,因为它允许在 XPath 中使用 let 子句。
【解决方案2】:

这种转变

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:my="my:my">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:variable name="vCaps" select=
     "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

 <xsl:template match="text()">
  <xsl:sequence select="my:isIBAN(.)"/>
 </xsl:template>

 <xsl:function name="my:isIBAN" as="xs:boolean">
  <xsl:param name="pString" as="xs:string"/>

  <xsl:variable name="vDigits" select=
   "string-join(
                (for $vStarting4 in substring($pString, 1,4),
                     $vRest in substring($pString, 5),
                     $vNewString in concat($vRest,$vStarting4),
                     $vLen in string-length($vNewString),
                     $i in 1 to $vLen
                   return
                     my:code(substring($vNewString,$i,1))
                 ),
                 ''
                 )
   "/>

   <xsl:sequence select="xs:integer($vDigits) mod 97 eq 1"/>
 </xsl:function>

 <xsl:function name="my:code" as="xs:string">
  <xsl:param name="pChar" as="xs:string"/>

  <xsl:sequence select=
  "if(string-length($pChar) ne 1 or not(contains($vCaps, $pChar)))
     then $pChar
     else
      xs:string
         (string-to-codepoints($pChar) - string-to-codepoints('A') +10)
  "/>
 </xsl:function>
</xsl:stylesheet>

应用于此 XML 文档时

<t>GB82WEST12345698765432</t>

产生想要的正确结果

true

注意:函数my:isIBAN() 可以实现为单个XPath 2.0 表达式。出于可读性的原因,我没有提供它。

【讨论】:

  • +1 好答案。 (看起来我们都阅读了相同的 Wiki 文章,ja!)
猜你喜欢
  • 2016-11-08
  • 2019-04-06
  • 2014-01-25
  • 2015-11-19
  • 1970-01-01
  • 2014-03-22
  • 2017-10-03
  • 1970-01-01
  • 2012-01-12
相关资源
最近更新 更多