我已经从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中,它会导致错误。
答案 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接口为中心。我会尝试一些实验。
select="true()"
)。我再次预测,最初报告的错误不会出现。 testparm
时(包括您现在设置它的方式)在9.0和9.1中会发生什么。调整诊断以适应,并在testparm声明中使用和不使用as="xs:boolean"
进行尝试。如果我已经正确理解了这种情况,我希望当你运行带有<param name="testparm" expression="false"/>
的Ant的测试样式表时,Saxon 9.0会告诉你testparm是一个布尔值,9.1会告诉你字符串“false”不能被强制转换布尔值。前两个实验应该确认世界不是以任意和反复无常的方式运行(我总是喜欢在调试时检查它)并且你的代码是有意义的。第三个实验如果成功,将隔离传入参数的行为变化,并允许您尝试从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表达式。