我正试图弄清楚<;和lt。
假设XML如下所示:
<root>
<field time="PT22M00.000S" value="red" number="22"/>
<field2 time="PT23M00.000S" value="blue" number="23"/>
</root>
对于每个表达式,我将得到以下结果:
- 比较日期:
if (xs:dayTimeDuration(/root/field/@time) lt xs:dayTimeDuration(/root/field2/@time)) then (/root/field/@value) else (/root/field2/@value)
结果是";红色">
- 比较数字:
if (/root/field/@number < /root/field2/@number) then (/root/field/@value) else (/root/field2/@value)
结果是";红色">
- 使用<比较日期:
if (xs:dayTimeDuration(/root/field/@time) < xs:dayTimeDuration(/root/field2/@time)) then (/root/field/@value) else (/root/field2/@value)
结果是";蓝色">
这两者之间的区别有什么解释吗?谢谢
- 使用<比较日期:
if (xs:dayTimeDuration(/root/field/@time) < xs:dayTimeDuration(/root/field2/@time)) then (/root/field/@value) else (/root/field2/@value)
结果是";蓝色">
这两者之间的区别有什么解释吗?谢谢
简短回答:
上面的结果是在应用XSLT1.0(<xsl:stylesheet version="1.0" ...>
(转换时产生的。将版本属性的值替换为";2.0〃;或更大,则所有结果将是"0";红色";正如预期的那样。
长答案:
当XSLT2.0处理器执行XSLT1.0转换时,这是在XPath1.0兼容模式中完成的。
特别是,这里是XPath 1.0兼容模式下的一般比较(包括<
(的语义定义:
如果XPath 1.0兼容模式为true,则一般比较为通过应用以下规则按顺序进行评估:
如果任一操作数是作为xs:boolean,则通过将另一个操作数转换为xs:boollean取其有效布尔值。
原子化应用于每个操作数。雾化后操作数是原子值的序列。
如果比较运算符是<lt;=>,或者>=,然后两者中的每个项目的操作数序列转换为类型xs:double应用fn:number函数。(请注意,fn:number返回值NaN,如果其操作数无法转换为数字。(
这正是发生的事情。
这两个日期被转换为数字,这在两种情况下都会产生NaN
。
根据定义,NaN < NaN
是false()
要证明这一点,请运行以下XSLT转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:sequence select=
"if (xs:dayTimeDuration(/root/field/@time)
lt xs:dayTimeDuration(/root/field2/@time))
then string(/root/field/@value)
else string(/root/field2/@value)"/>
<xsl:sequence select=
"if (/root/field/@number < /root/field2/@number)
then string(/root/field/@value)
else string(/root/field2/@value)"/>
<xsl:sequence select=
"if (xs:dayTimeDuration(/root/field/@time)
< xs:dayTimeDuration(/root/field2/@time))
then string(/root/field/@value)
else string(/root/field2/@value)"/>
===============================================
<xsl:sequence select="xs:dayTimeDuration(/root/field/@time)
< xs:dayTimeDuration(/root/field2/@time)"/>
<xsl:variable name="v1" select="data(xs:dayTimeDuration(/root/field/@time))"/>
<xsl:sequence select="$v1"/>
<xsl:variable name="v2" select="data(xs:dayTimeDuration(/root/field2/@time))"/>
<xsl:sequence select="$v2"/>
<xsl:sequence select="$v1 < $v2"/>
================================================
<xsl:sequence select="number($v1)"/>
<xsl:sequence select="number($v2)"/>
</xsl:template>
</xsl:stylesheet>
当此转换应用于所提供的XML文档时:
<root>
<field time="PT22M00.000S" value="red" number="22"/>
<field2 time="PT23M00.000S" value="blue" number="23"/>
</root>
结果是:
red red blue
===============================================
false PT22M PT23M false
================================================
NaN NaN
正如上面的解释一样。
我们还从Saxon那里得到了这一点,本质上告诉我们确实使用了XPath1.0兼容模式:
SaxonicJava 1.8.0_191版本的Saxon 9.1.0.1J警告:在xxxx第2行第46列的xsl:stylesheet处。xsl:
使用XSLT 2.0处理器运行XSLT 1.0样式表
现在,在相同的转换中将version="1.0"
属性替换为";version="2.0"
并运行转换。
现在的结果是:
red red red
===============================================
true PT22M PT23M true
================================================
NaN NaN
只是因为XSLT处理器将转换作为真正的XSLT2.0执行!