1

我正在使用 Saxon 9.4 和 XSLT 2.0

我的样式表中有以下代码片段:-

<xsl:template name="some_template">
  <xsl:param name="some_param" as="xs:integer?"/>
</xsl:template>

这基本上是一个接受可选整数参数的模板。然而,当我尝试这样称呼它时,

<xsl:call-template name="some_template>
  <xsl:with-param name="some_param">
    <xsl:if test="some_condition">
      <xsl:value-of select="xs:integer(./@attr div 20)"/>
    </xsl:if>
  </xsl:with-param>
</xsl:call-template>

我收到一条错误消息:-

Validation error 
  FORG0001: Cannot convert zero-length string to an integer

但是,以下两个样式表不会给我一个错误:-

<xsl:call-template name="some_template>
  <xsl:with-param name="some_param">
    <xsl:value-of select="xs:integer(./@attr div 20)"/>
  </xsl:with-param>
</xsl:call-template>

或者

<xsl:variable name="dummy" as="xs:integer?">
  <xsl:if test="some_condition">
    <xsl:value-of select="xs:integer(./@attr div 20)"/>
  </xsl:if>
</xsl:variable>
<xsl:call-template name="some_template>
  <xsl:with-param name="some_param" select="$dummy"/>
</xsl:call-template>

很明显,类型信息没有在整个块中保留。知道如何让第一件事发挥作用吗?第三个样式表在语义上做了我想要的,但我宁愿不要为了能够做到这一点而四处创建(几个)虚拟变量。

谢谢!

4

3 回答 3

1

我认为当您<xsl:if>的错误意味着没有为您的参数分配值时会出现错误。您可以尝试以下解决方案之一:

默认值

您是否尝试为您的 设置默认值<xsl:param>

<xsl:template name="some_template">
  <xsl:param name="some_param" select="-1" as="xs:integer?" />
</xsl:template>

管理false案例

使用XPath2.0 if-then-else 表达式调用模板时始终设置一个值:

<xsl:call-template name="some_template>
  <xsl:with-param name="some_param" select="
     if (some_condition) 
     then xs:integer(./@attr div 20)
     else -1"
  />
</xsl:call-template>

-1用作false案例的价值。

于 2013-03-04T23:21:08.843 回答
1

这种转变

<xsl:stylesheet version="2.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:call-template name="some_template">
      <xsl:with-param name="some_param" select=
       "if(some_condition)
          then xs:integer(@attr div 20)
          else ()
      "/>
    </xsl:call-template>
 </xsl:template>

 <xsl:template name="some_template">
  <xsl:param name="some_param" as="xs:integer?"/>
  XXX
</xsl:template>
</xsl:stylesheet>

当应用于以下每个 XML 文档时:

<t attr="20">
 <some_condition/>
</t>

,

<t>
 <some_condition/>
</t>

,

<t attr="20">
</t>

<t>
</t>

产生想要的、正确的结果(不引发任何异常):

  XXX
于 2013-03-05T03:12:34.893 回答
1

我并不完全清楚这里发生了什么,但很清楚的是如何改进你的代码,这样它就不会那么混乱了。使用编写的代码,在真实情况下,您正在计算双精度数,将其转换为整数,将整数转换为文本节点,将其包装在文档节点中,将文档节点作为参数传递,将其原子化为无类型在接收端是原子的,因为预期的类型是原子的,然后将无类型的原子值转换为整数。所有这些都应该起作用,但实际上是迂回的,并且很容易通过 xsl:with-param 上的 "as="xs:integer"" 避免。

In the false case, you are passing a document node with no children, and conversion of that to xs:integer? will fail - it won't convert to an empty sequence. So despite what you say, I think it's failing on the false path.

于 2013-03-05T15:33:26.677 回答