XSLT为同一个XSL获取相同输入XML的两个不同输出

时间:2014-02-08 00:57:02

标签: xslt saxon

我一直在在线工具[ XSLT 1.0处理器]中尝试我的XSLT代码:

http://www.freeformatter.com/xsl-transformer.html

最近,我不得不使用xs:dateTime,因此开始使用使用 XSLT 2.0处理器的工具, http://xsltransform.net/

现在,当我试图解决问题时,我发现在这两个处理器中,我得到了相同输入XML的不同输出。这里发布的代码不是我正在处理的真实代码;这是为了模拟我面临的奇怪输出。

XML:

<?xml version="1.0" encoding="UTF-8"?>
<items>
    <book> 
        <title></title>
    </book>
    <phone>apple</phone>
</items>

XSLT:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" version="1.0" encoding="UTF-8"
        indent="yes" />

    <xsl:template match="/">
        <items><xsl:apply-templates select="items/*" /></items>
    </xsl:template>

    <!-- ignore empty elements -->
    <xsl:template match="*[not(normalize-space())]" />


    <xsl:template match="book">
      <newbook><xsl:apply-templates /></newbook>
    </xsl:template>

    <xsl:template match="title">
      <newtitle><xsl:apply-templates /></newtitle>
    </xsl:template>

    <xsl:template match="phone">
      <newphone><xsl:apply-templates /></newphone>
    </xsl:template>

</xsl:stylesheet>

http://xsltransform.net/的输出: [输出1]

<?xml version="1.0" encoding="UTF-8"?>
<items>
   <newbook> 
        <newtitle/>
    </newbook>
   <newphone>apple</newphone>
</items>

http://www.freeformatter.com/xsl-transformer.html的输出: [输出2]

<?xml version="1.0" encoding="UTF-8"?>
<items>
   <newphone>apple</newphone>
</items>

预期输出XML为output 2

知道为什么这种不同的输出行为?

注意:我查看了另一个问题:Generating two different outputs for the same XSL file?,但情况有所不同。

修改

为了更清楚地说明哪个工具产生了哪个输出:

http://xsltransform.net/制作了output 1

http://www.freeformatter.com/xsl-transformer.html制作了output 2

更新[02/10/2014] - 关于解决方案

由于Jim Garrison首先提供了正确答案,因此标记为答案。然而,正如其他人所指出的那样,还有其他重要的观点,因此我在这里结束了所有这些。

<xsl:template match="*[not(normalize-space())]" />

上述模板消除了XSLT1和XSLT2中的空节点。因此输出2是正确的

*从工具中获取输出1 的原因 - http://xsltransform.net/:*

  1. 正如@ michael.hor257k所指出的,有两个模板与<book>元素相匹配。
  2. 该工具使用的是Saxon-HE 9.5.1.3,输出1 行为可能是最新维护版本中修复的错误[@Michael Kay在他的回答中解释得很清楚]
  3. 正如@Ian Roberts在他的回答中提到的,有一个默认优先级的概念被分配给不同类型的模板。 将模板语法更改为: <xsl:template match="*[not(normalize-space())]" priority="2"/> 无论Saxon版本如何,两个工具都会产生相同的输出,因为我们明确定义了模板的优先级。

4 个答案:

答案 0 :(得分:3)

输出2是正确的。我使用XSLT1和XSLT2在Oxygen / XML中运行了您的示例,并为两者获得了正确的结果。你的模板

<xsl:template match="*[not(normalize-space())]" />

消除了XSLT1和XSLT2中的空节点。

因此,唯一可能的结论是产生输出1的在线工具存在错误。

答案 1 :(得分:3)

我使用Saxon-EE 9.5.1.4运行正确的结果; xsltransform站点运行Saxon-HE 9.5.1.3。它可能是我们在最新维护版本中修复的错误;我会做一些追逐,看看能否指责它。

答案 2 :(得分:2)

请注意,空<book>元素与您的两个模板匹配:

<xsl:template match="*[not(normalize-space())]" />

和:

<xsl:template match="book">
  <newbook><xsl:apply-templates /></newbook>
</xsl:template>

同样的事情适用于空的<title>元素。必须使用XSLT规范中指定的优先级由XSLT处理器解决此类冲突。

您从http://xsltransform.net/报告的结果由Saxon 9.5.1(XSLT 2.0引擎)生成。如果切换到XSLT 1.0引擎(Saxon 6.5或Xalan 2.7.1),您将获得不同的结果(在同一站点上)。

我不知道XSLT 2.0中的冲突解决规则是否与XSLT 1.0相比有所改变;当我使用Saxon 8.9时,我自己得到了不同的结果 - 也是一个XSLT 2.0处理器。也许我们很幸运能听到Michael Kay关于这种差异的消息(我已经在你的问题中添加了一个Saxon标签以引起他的注意)..

答案 3 :(得分:1)

根据您在问题中提供的样式表的1.0和2.0 XSLT规范,输出2绝对是正确的。但是你说这与你的真实样式表相比是简化的。

使其有效的是分配给不同类型模板的default priorities。这些在两个XSLT版本中都是相同的,并且涉及谓词的匹配模式将否决仅仅是单个元素名称测试的匹配模式。

但是,涉及层次结构的匹配(例如match="items/book")或任何比单个元素名称更复杂的匹配将默认获得与*[....]规则相同的优先级 - 0.5。如果你在真正的XSLT中有这些类型的模式,那么你需要在“blank-suppressor”模板中添加一个高于0.5的显式优先级。

<xsl:template match="*[not(normalize-space())]" priority="2"/>