<在XSLT中比较值时使用lt

  • 本文关键字:比较 XSLT amp date xslt
  • 更新时间 :
  • 英文 :


我正试图弄清楚<和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 &lt; /root/field2/@number) then (/root/field/@value) else (/root/field2/@value)

结果是";红色">

  • 使用<比较日期:if (xs:dayTimeDuration(/root/field/@time) &lt; xs:dayTimeDuration(/root/field2/@time)) then (/root/field/@value) else (/root/field2/@value)

结果是";蓝色">

这两者之间的区别有什么解释吗?谢谢

  • 使用<比较日期:if (xs:dayTimeDuration(/root/field/@time) &lt; 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,则一般比较为通过应用以下规则按顺序进行评估:

  1. 如果任一操作数是作为xs:boolean,则通过将另一个操作数转换为xs:boollean取其有效布尔值。

  2. 原子化应用于每个操作数。雾化后操作数是原子值的序列。

  3. 如果比较运算符是<lt;=>,或者>=,然后两者中的每个项目的操作数序列转换为类型xs:double应用fn:number函数。(请注意,fn:number返回值NaN,如果其操作数无法转换为数字。(

这正是发生的事情。

这两个日期被转换为数字,这在两种情况下都会产生NaN

根据定义,NaN < NaNfalse()

要证明这一点,请运行以下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 &lt; /root/field2/@number)
then string(/root/field/@value)
else string(/root/field2/@value)"/>
<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="xs:dayTimeDuration(/root/field/@time) 
&lt; 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 &lt; $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执行!