使用apply-templates在元素后添加属性与xalan-c和xsltproc的行为不同。什么是正确的?

时间:2013-01-17 08:57:33

标签: xml xslt xalan

我注意到xalan-c和xsltproc之间存在以下差异。哪一个是正确的?规范对此有何看法?

来源xml: -

<a attr="val1">
  <b d="5">
  </b>
  <b d="10">
  </b>
</a>

样式表: -

<xsl:template match="@* | text() | comment() | processing-instruction()">
  <xsl:copy/>
</xsl:template>

<xsl:template match="*">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="a">
  <a>
    <c>
      <xsl:call-template name="gcd">
        <xsl:with-param name="nums" select="./b/@d"/>
      </xsl:call-template>
    </c>
    <xsl:apply-templates select="./@*"/>
  <a>
</xsl:template>

xsltproc给了我: -

<a attr="val1">
  <c>5</c>
</a>

虽然xalan-c给了我: -

<a>
  <c>5</c>
</a>

2 个答案:

答案 0 :(得分:1)

我认为问题可能出在这一行

<xsl:apply-templates select="./@*"/>

特别是它的位置,即在模板中创建 c 元素之后。应在任何子元素之前将属性添加到元素上。实际上,我很惊讶你没有得到错误的&#34;必须在任何子节点之前添加属性节点到元素。&#34;

假设您确实希望将属性添加到 a 元素,请尝试以下

<xsl:template match="a">
  <a>
    <xsl:apply-templates select="@*"/>
    <c>
      <xsl:call-template name="gcd">
        <xsl:with-param name="nums" select="./b/@d"/>
      </xsl:call-template>
    </c>
  <a>
</xsl:template>

然后应该给出一致的结果。

如果您不想要这些属性,只需删除 apply-templates

答案 1 :(得分:0)

xsltproc行为对我来说似乎不对。正如Tim C所说,规范提供了两个选项:忽略属性或发出错误信号。它不允许在适当的位置实际添加属性的选项。但是,对于规范定义“可恢复错误”的这些情况,对错误采取错误的恢复操作并不是真正严重的不合规情况,尤其是当恢复操作要执行用户可能想要的操作时。事实是,样式表是错误的,应该修复。