【问题标题】:XSLT: xsl:function won't workXSLT: xsl:function 不起作用
【发布时间】:2009-07-14 18:27:13
【问题描述】:

以下对我有用:

<xsl:variable name="core" select="document('CoreMain_v1.4.0.xsd')" />
<xsl:variable name="AcRec" select="document('AcademicRecord_v1.3.0.xsd')" />

<xsl:template match="xs:element">       
  <xsl:variable name="prefix" select="substring-before(@type, ':')" />
  <xsl:variable name="name" select="substring-after(@type, ':')" />

  <xsl:choose>
    <xsl:when test="$prefix = 'AcRec'">             
      <xsl:apply-templates select="$AcRec//*[@name=$name]">
        <xsl:with-param name="prefix" select="$prefix" />
      </xsl:apply-templates>                
    </xsl:when>
    <xsl:when test="$prefix = 'core'">              
      <xsl:apply-templates select="$core//*[@name=$name]">
        <xsl:with-param name="prefix" select="$prefix" />
      </xsl:apply-templates>                
    </xsl:when>             
  </xsl:choose>
</xsl:template>

但我使用相同的逻辑来处理基于前缀的当前或其他文档中的元素查找,匹配样式表中许多位置的节点名称。因此,将样式表版本更改为 2.0 后,我尝试了:

<xsl:template match="xs:element">
  <xsl:value-of select="my:lookup(@type)" />
</xsl:template>

<xsl:function name="my:lookup">
  <xsl:param name="attribute" />

  <!-- parse the attribute for the prefix & name values -->
  <xsl:variable name="prefix" select="substring-before($attribute, ':')" />
  <xsl:variable name="name" select="substring-after($attribute, ':')" />

  <!-- Switch statement based on the prefix value -->
  <xsl:choose>
    <xsl:when test="$prefix = 'AcRec'">             
      <xsl:apply-templates select="$AcRec//*[@name=$name]">
        <xsl:with-param name="prefix" select="$prefix" />
      </xsl:apply-templates>                
    </xsl:when>
    <xsl:when test="$prefix = 'core'">              
      <xsl:apply-templates select="$core//*[@name=$name]">
        <xsl:with-param name="prefix" select="$prefix" />
      </xsl:apply-templates>                
    </xsl:when>             
  </xsl:choose> 
</xsl:function>

在我的阅读中,我只找到了返回文本的函数示例 - 没有调用模板。我的印象是 xsl:function 应该总是返回文本/输出......

经过更多调查,它正在输入 my:lookup 函数并且变量(前缀和名称)正在被填充。所以它确实进入了 xsl:choose 语句,并且在测试时点击了适当的。问题似乎与应用模板有关 - value-of 正在显示子值; copy-of 也可以,我认为这很奇怪(输出不应该包括 xml 元素声明吗?)。如果将模板声明中的代码移到 xsl:function 中,为什么会有不同?

【问题讨论】:

  • 哪个 XSLT 引擎?撒克逊或 Xalan 还是别的什么?请注意,Xalan 不支持 XSLT 2.0,但 Saxon 支持。 Xalan 和 Saxon 都支持函数,但它们在 XSLT 1.0 和 2.0 之间的行为不同。

标签: xslt


【解决方案1】:

自从我做任何严肃的 XSLT 以来已经有一段时间了,但是 IIRC 你的问题不在于函数,而在于你的模板:

<xsl:template match="xs:element">
  <xsl:value-of select="my:lookup(@type)" />
</xsl:template>

value-of 语句不会内联您的函数返回的结果树。相反,它会尝试将结果树缩减为某种字符串,然后将其内联。这就是为什么您看到的是子值而不是元素本身。

要内联函数返回的结果树,您需要使用一些模板将结果树复制到位。

因此,您的主模板需要更改为:

<xsl:template match="xs:element">
  <xsl:apply-templates select="my:lookup(@type)" />
</xsl:template>

并且您需要一些模板来执行递归调用。一个快速的谷歌发现 a good discussion of the identity template 应该可以满足您的需求。

(请原谅任何语法错误,正如我所说,已经有一段时间了......)

【讨论】:

    猜你喜欢
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    相关资源
    最近更新 更多