XPath 不支持 Let

Let is not supported in XPath

最近我升级了我的服务器,但以下带有 Saxonb-XSLT 的 XSLT 停止工作:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output cdata-section-elements="title"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="title[ends-with(., 'Apple') or ends-with(., 'Samsung') or ends-with(., 'Banana')]">
      <xsl:copy>
          <xsl:value-of select="let $words := tokenize(., '\s+') 
               return (subsequence($words, 1, count($words) - 2), $words[last()], $words[last() - 1])"/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

我收到错误:

  XPST0003: XPath syntax error at char 0 on line 13 in {let $}:
    'let' is not supported in XPath

我还没有升级 saxonb-xslt(来自 Saxonica 的 Saxon 9.1.0.8J)。有人知道为什么它不能正常工作吗?

我认为 let 绑定是 XPath 3 的一部分,因为它在 Saxon 9.8 HE 之前的 XSLT 3.0 中不完全支持,因为这是第一个支持最终 XSLT 3.0 的 Saxon 开源版本与 XPath 3 推荐。您可能会发现使用 version="3.0" 然后使用 let 的 XPath 3 表达式也可以在 9.7 和 9.6 中工作,但在更早的版本中 Saxon(至少是开源版本)是一个带有 XPath 的 XSLT 2.0 处理器2.0 支持和不支持任何 XPath 3 表达式(如 let)。

文字错误消息 'let' is not supported in XPath 可能表明该版本在 XQuery 中对 let 提供了一些支持,但我不记得细节,也没有检查过。

不清楚您在升级之前使用了哪个版本的 Saxon,在升级之后使用了哪个版本,或者您进行了何种“更新”。

您可以通过重写您的模板以使用 XSLT xsl:variable 语句而不是 XPath 3.0 let 语句来绕过对 let 和任何相关版本或许可复杂性的需求:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="#all"
                version="2.0">

  <xsl:output cdata-section-elements="title"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="title[   ends-with(., 'Apple') 
                             or ends-with(., 'Samsung') 
                             or ends-with(., 'Banana')]">
    <xsl:variable name="words" select="tokenize(., '\s+')"/>
    <xsl:copy>
        <xsl:value-of select="subsequence($words, 1, count($words) - 2), 
                              $words[last()], 
                              $words[last() - 1]"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

更新: 我已经替换了 <xsl:mode on-no-match="shallow-copy"/> 使用传统的身份转换来全面减少从 XSLT 3.0 到 XSLT 2.0 的依赖性。感谢 @michael.hor257k 的建议。

您提到来自 Saxonica 的 Saxon 9.1.0.8J。那确实是一个非常老的版本(2009 年),它永远无法 运行 这个样式表。

我担心你的“升级”让你 运行 宁愿使用旧的 Saxon 版本。

当前版本是10.6。