Saxon:无法调用静态方法,期望来自XSLT的带xs:string参数的String

时间:2012-07-12 08:58:48

标签: java xslt saxon

我试图从我的XSLT样式表中调用静态Java方法:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:digest="java:org.apache.commons.codec.digest.DigestUtils">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>

<xsl:template match="user">
  <user>
    <firstname>
      <xsl:value-of select="value[@type='firstname'][1]" />
    </firstname>
    <lastname>
      <xsl:value-of select="value[@type='name'][1]" />
    </lastname>
    <password>
      <xsl:variable name="password" select="string(value[@type='password'][1])" />
      <xsl:value-of select="digest:md5Hex($password)"
                    disable-output-escaping="yes" />
    </password>
  </user>
</xsl:template>

找到DigestUtils类和静态md5Hex方法[1]。问题是,有三种可能的方法来调用该方法,即使用byte [],InputStream或String。鉴于“password”变量的类型为xs:string,我认为Saxon会自动选择最后一个选项。但相反,它坚持使用byte [] - 方法并相应地失败:

[...]
Loading org.apache.commons.codec.digest.DigestUtils
Looking for method md5Hex in Java class class org.apache.commons.codec.digest.DigestUtils
Number of actual arguments = 1
[...]
Trying method md5Hex: name matches
Method is static
Method has 1 argument; expecting 1
Found a candidate method:
    public static java.lang.String org.apache.commons.codec.digest.DigestUtils.md5Hex(byte[])
Trying method md5Hex: name matches
Method is static
Method has 1 argument; expecting 1
Found a candidate method:
    public static java.lang.String org.apache.commons.codec.digest.DigestUtils.md5Hex(java.io.InputStream) throws java.io.IOException
Trying method md5Hex: name matches
Method is static
Method has 1 argument; expecting 1
Found a candidate method:
    public static java.lang.String org.apache.commons.codec.digest.DigestUtils.md5Hex(java.lang.String)
[...]
Finding best fit method for arguments
Trying option 0: public static java.lang.String org.apache.commons.codec.digest.DigestUtils.md5Hex(byte[])
Conversion preferences are [24]
Trying option 1: public static java.lang.String    org.apache.commons.codec.digest.DigestUtils.md5Hex(java.io.InputStream) throws java.io.IOException
Conversion preferences are [80]
Trying option 2: public static java.lang.String org.apache.commons.codec.digest.DigestUtils.md5Hex(java.lang.String)
Conversion preferences are [80]
Eliminating option 1
Eliminating option 2
Number of candidate methods remaining: 1
Error at xsl:template on line 14 column 30 of migrate_users.xsl:
  Cannot convert from xs:string to byte
Failed to compile stylesheet. 1 error detected.

有没有办法迫使Saxon使用String-method?

[1] http://commons.apache.org/codec/api-release/org/apache/commons/codec/digest/DigestUtils.html#md5Hex(java.lang.String

- 更新:一位同事刚刚找到了该公司的Saxon 9.4PE许可证密钥。不幸的是错误仍然存​​在,唯一改变的是byte [] - 方法的转换首选项从24变为31。

2 个答案:

答案 0 :(得分:3)

您需要输入变量:

<xsl:variable as="xs:string" name="password" select="string(value[@type='password'][1])" />

或将其投入电话:

<xsl:value-of select="digest:md5Hex(xs:string($password))"
                disable-output-escaping="yes" />

将xs名称空间定义为:

xmlns:xs="http://www.w3.org/2001/XMLSchema"

答案 1 :(得分:3)

Saxon根据对所提供参数类型的静态分析,尝试决定在编译时使用哪种方法。如果推断的静态类型允许一个序列(与单例不同),那么期望数组或集合的方法总是会胜过需要单例的方法:所以期望byte []的方法首选的事实意味着撒克逊无法确定所提供的价值是单身人士。很明显,强制转换为字符串足以实现此推理。

令人失望的是,向变量声明添加类型信息是不够的。其原因在于,在将类型信息从变量声明传播到变量引用之前,在编译过程中过早地决定使用哪种方法。我将在未来的版本中考虑改进这一点的可能性。