SaxonB 9.0与SaxonB 9.1.0.8和xs:boolean与xs:字符串类型错误

时间:2013-06-22 19:41:02

标签: java xml xslt ant saxon

我已经从SaxonB(XSLT 2.0处理器)版本9.0升级到9.1.0.8,我的程序(XML Web Generator)停止工作。

使用Ant执行XSLT转换。萨克森现在抱怨说:

 [xslt] .../stránka.xsl:37: Fatal Error! Required type is xs:boolean; supplied value has type xs:string
 [xslt] Failed to process null

但是在该XSLT文件的第37行上有:

<xsl:include href="stránka-společné.xsl"/>

这可能不是问题。它可能在第47行,我在&lt; xsl中使用了一个属性(从Ant设置):if test =“$ someProperty”/&gt;

该属性在包含的XSL文件中声明:

<xsl:param name="someProperty" select="false()" as="xs:boolean"/>

我在属性名称中使用unicode字符,但它应该可以工作,不应该吗? (至少它在9.0中工作)。我试图使用ASCII,它没有帮助。

它也不是关于Ant或Java版本,因为它是否有效取决于JAR文件的路径(9.0与9.1.0.8)。

我想使应用程序与9.1.0.8兼容。 (或者它是SaxonB中的一个错误?)

我使用的版本(SHA-256):

3cb7336b154eabfb0d78a1b9b5f7c70e15a9c790193676803fa4391b60de7ebb  saxonb-9.0.jar (working)
dc09c0e3d03609ff3c11b1e19446ca82a5f7f1bc364173b7910f2267312bd7d5  saxonb-9.1.0.8.jar (error described above)

可以找到文件,例如在package.ubuntu.com里面.deb文件 - 清单(9.0)或raring(9.1.0.8)中的包libsaxonb-java

更新#1

如果我删除了这个有问题的属性(XSLT中的变量)的用法,我得到了不同的错误:

 [xslt] Failed to process null

BUILD FAILED
…/build.xml:39: ; SystemID: file:…/šablona/makra/diagramy.xsl; Line#: 63; Column#: -1
net.sf.saxon.instruct.TerminationException: Processing terminated by xsl:message at line 89 in diagramy.xsl
    at net.sf.saxon.instruct.Message.processLeavingTail(Unknown Source)
    at net.sf.saxon.instruct.Choose.processLeavingTail(Unknown Source)
    at net.sf.saxon.expr.LetExpression.processLeavingTail(Unknown Source)
    …

这也是特定于版本9.1.0.8(使用9.0我没有错误)。在diagramy.xsl的第63行,有:

<xsl:variable name="souborDiagramu" select="j:vytvořDiagram(
    $zadání, 
    @orientace = 'vodorovně', 
    $kompletní,
    tokenize(base-uri(), '/')[last()],
    @src
    )"/>

源文档中缺少@orientace@src(在9.0中,此类属性作为vytvořDiagram(…)参数传递给Java方法null。)

更新#2

我在Java中编写了一个函数来获取属性的类型:

public static String zjistiTyp(Object o) {
    if (o == null) {
        return "null";
    } else {
        return o.getClass().getName();
    }
}

使用9.0版本

<xsl:message>Typ proměnné $podporaZaostalýchProhlížečů = <xsl:value-of select="j:zjistiTyp($podporaZaostalýchProhlížečů)"/></xsl:message>

成功打印:

 [xslt] Typ proměnné $podporaZaostalýchProhlížečů = java.lang.Boolean

但是使用9.1.0.8我得到了错误Required type is xs:boolean; supplied value has type xs:string即使我删除了任何其他障碍(此属性的用法),如果我删除它的最后一次使用,转换仍在继续:<xsl:message>Typ proměnné…(但是我找不到属性的类型。)

所以看起来字符串false(或true)可以从Ant传递给XSLT,甚至可以使用这种结构在XSLT中声明属性:

<xsl:param name="podporaZaostalýchProhlížečů" select="false()" as="xs:boolean"/>

但它无法使用 - 这种属性的使用会导致错误(但仅在9.1.0.8中 - 在9.0中有效)。

更新#3

我找到了问题的一部分的解决方法。

<xsl:param name="someParameterUncasted"/>
<xsl:variable name="someParameter" select="$someParameterUncasted cast as xs:boolean"/>

但这很难看,因为我需要一个参数的两个名字 - 在Ant中不同,在XSLT中不同。有没有办法如何将布尔类型的参数从Ant传递给XSLT?为什么这个在Saxon 9.1.0.8中停止工作,虽然它在9.0中工作?

并且还存在9.0 / 9.1.0.8问题的第二部分:当将一些缺失属性的值传递给Java方法时,在9.0中它起作用并且Java简单地为空。在9.1.0.8中,它会导致错误。

3 个答案:

答案 0 :(得分:2)

我相信Ant总是将样式表参数的值作为字符串提供。撒克逊当然无法控制这一点。从你的证据(我还没有考虑到这一点来证实这一点),Saxon 9.0将提供的值转换为所需的参数类型,而当前版本(可能从9.1开始)使用用于函数调用的类型转换规则,比铸造弱。

如果您希望从最广泛的环境中调用样式表,我建议您定义接受字符串的样式表参数。我们自己做了同样的事情(也是从Saxon 9.1开始)用于配置参数 - 再次,Ant总是将它们作为字符串提供,因此我们注意确保所有配置参数都可以以字符串形式提供。

有两个参数允许用户选择是完全可以的:

<xsl:param name="use-macros" as="xs:boolean" select="xs:boolean($use-macros-string)"/>
<xsl:param name="use-macros-string" as="xs:string" select="'false'"/>

答案 1 :(得分:1)

[不是一个完整的答案,但可能太过于不适合评论。]

您的困难出现(可能是正确的)以Ant / XSLT和XSLT / Java接口为中心。我会尝试一些实验。

  1. 尝试从Ant调用 not 设置参数podporaZaostalýchProhlížeč......(并恢复测试该参数值的代码)。我预测您不会遇到最初报告的错误。
  2. 出于测试目的,将参数的默认值更改为true(在参数声明中使用select="true()")。我再次预测,最初报告的错误不会出现。
  3. 使用下面显示的简单测试样式表来查看当Ant以各种方式设置参数testparm时(包括您现在设置它的方式)在9.0和9.1中会发生什么。调整诊断以适应,并在testparm声明中使用和不使用as="xs:boolean"进行尝试。如果我已经正确理解了这种情况,我希望当你运行带有<param name="testparm" expression="false"/>的Ant的测试样式表时,Saxon 9.0会告诉你testparm是一个布尔值,9.1会告诉你字符串“false”不能被强制转换布尔值。
  4. 前两个实验应该确认世界不是以任意和反复无常的方式运行(我总是喜欢在调试时检查它)并且你的代码是有意义的。第三个实验如果成功,将隔离传入参数的行为变化,并允许您尝试从Ant设置参数的不同方法。 (但是,对于函数调用遇到的XSLT到Java接口问题,它不会做任何事情。)

    我希望这会有所帮助。

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      version="2.0">
    
      <xsl:param name="testparm" as="xs:boolean"/>
    
      <xsl:template match="/">
        <xsl:choose>
          <xsl:when test="$testparm instance of xs:boolean">
            <xsl:message>Test parameter <xsl:value-of 
              select="$testparm"/> is boolean.</xsl:message>
          </xsl:when>
          <xsl:when test="$testparm instance of xs:string">
            <xsl:message>Test parameter <xsl:value-of 
              select="$testparm"/> is a string.</xsl:message>
          </xsl:when>
          <xsl:when test="$testparm instance of xs:decimal">
            <xsl:message>Test parameter <xsl:value-of 
              select="$testparm"/> is decimal.</xsl:message>
          </xsl:when>
          <xsl:when test="$testparm instance of xs:anyAtomicType">
            <xsl:message>Test parameter <xsl:value-of 
              select="$testparm"/> is of type anyAtomicType.</xsl:message>
          </xsl:when>
          <xsl:when test="$testparm instance of xs:untypedAtomic">
            <xsl:message>Test parameter <xsl:value-of 
              select="$testparm"/> is untypedAtomic.</xsl:message>
          </xsl:when>
        </xsl:choose>
      </xsl:template>
    
    </xsl:stylesheet>
    

    在XSLT中而不是在Java中执行此测试的优点是只涉及Ant / XSLT接口,而不是XSLT调用Java接口。

    如果无法找到从Ant中传递参数的方法,那么在9.0和9.1中都会成功导致布尔值,您可能希望将参数的类型更改为字符串:许多XSLT程序员过着漫长而富有成效的生活使用值“是”和“否”而不是true()和false(),并将其测试编写为test="$parm = 'yes'"。无论好坏,字符串比其他许多类型更好地通过环境边界。

答案 2 :(得分:0)

  

Saxon 9.0将提供的值转换为所需的参数类型,而当前版本(可能从9.1开始)使用用于函数调用的类型转换规则,这些规则比强制转换要弱。

据我所知,如果规范未涵盖自动转换,那就不好了。

  

如果您希望从最广泛的环境中调用样式表,我建议您定义接受字符串的样式表参数。

在这种情况下是的,但我的程序真的是“基于Ant”,所以它不会伤害我。 BTW:例如xsltproc也支持params中的XPath表达式。

  

有两个参数允许用户选择

是完全可以的

它可以工作,但恕我直言,它只是解决方法,XSLT模板代码不是正确的层,其中输入参数的类型转换应该完成 - 对于每个参数,在每个模板中,一次又一次。

我宁愿改进Ant以支持比文本字符串更多的数据类型。任何有兴趣的人都可以关注我的活动

Bug 21525 - XSLT/param@expression used as string instead of as expression as documented

我的补丁增加了对这些类型的支持:字符串,布尔值,int,long,double以及XSLT参数中的XPath表达式。