EXSLT自定义函数导致样式表返回“太多嵌套的应用模板调用”错误

时间:2013-07-31 09:03:35

标签: xml xslt exslt

我尝试使用EXSLT的func:function元素实现一个“三元运算符”扩展函数,以便在我的样式表中使用。出于兼容性原因,我必须使用XSLT 1.0。我想出了这个:

<func:function name="myext:ternary">
  <xsl:param name="expr" />
  <xsl:param name="ifTrue" />
  <xsl:param name="ifFalse" />

  <func:result>
    <xsl:choose>
      <xsl:when test="boolean($expr)"><xsl:value-of select="$ifTrue"/></xsl:when>
      <xsl:otherwise><xsl:value-of select="$ifFalse" /></xsl:otherwise>
    </xsl:choose>
  </func:result>
</func:function>

无论我在哪里使用它都能正常工作。 然而,我还试图实现一个子串后跟函数(来自here)。这段代码工作正常:

<func:function name="myext:substring-after-last">
  <xsl:param name="string" select="''"/>
  <xsl:param name="delimiter" select="$d" />

  <func:result>
    <xsl:choose>
      <xsl:when test="contains($string, $delimiter)">
        <xsl:value-of select="myext:substring-after-last(substring-after($string, $delimiter), $delimiter)"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$string"/>
      </xsl:otherwise>
    </xsl:choose>
  </func:result>
</func:function>

这种方式也有效:

[…]
  <func:result>
    <xsl:if test="not(contains($string, $delimiter))">
      <xsl:value-of select="$string"/>
    </xsl:if>
    <xsl:if test="not($string='')">
      <xsl:value-of select="myext:substring-after-last(substring-after($string, $delimiter), $delimiter)"/>
    </xsl:if>
  </func:result>
</func:function>

...但是当我尝试使用“三元”函数进行实现时,它不起作用;

这不起作用:

<func:result>
  <xsl:value-of select="myext:ternary(
    contains($string, $delimiter) and not($string = ''),
    myext:substring-after-last(substring-after($string, $delimiter), $delimiter),
    $string
  )"/>
</func:result>

此方法导致我的样式表向我抛出错误

Error at xsl:apply-templates on line 49 of file:/[my_main_file].xsl:
  Too many nested apply-templates calls
Transformation failed: Run-time errors were reported

我尝试使用-Xss16m开关来增加Java的堆栈大小,但这只会导致Saxon抛出OutOfMemoryError(Java堆空间)。我发送给这个函数的数据集相当小,所以我不明白溢出发生的地方以及为什么我甚至需要尝试增加堆栈大小。

我做错了什么?

1 个答案:

答案 0 :(得分:0)

  

我试图实现“三元运算符”扩展函数

使用位置谓词和否定谓词变量check的并集作为else语句:

//var[1] | //var[not //var]

使用互斥表达式的串联作为三元成语:

concat("(",substring(translate(., "()-", ""), 1, 3), ")", substring(translate(., "()-", ""), 4, 3), "-", substring(translate(., "()-", ""), 7, 4)))
  XPath中的

(true())为1,而number(false())为0,当substring()函数的第二个参数大于字符串的实际长度时,返回空字符串。因此,子串($ s1,number(not($ condition))* string-length($ s1)+1)如果$ condition为true则返回$ s1,否则返回空字符串。以互斥的方式连接两个这样的表达式给出了条件字符串表达式。

<强>参考