嵌套元素的模板的XSL顺序

时间:2015-02-02 12:25:39

标签: xml xslt xslt-1.0

我有一个像这样的XML文件:

<text>
  <a>foo1</a>
  <a><b>foo2</b></a>
</text>

我有一个XSL文件,旨在以模板1和2的不同方式处理<a><a><b>

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>

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

  <!-- t1 -->
  <xsl:template match="a">
    <xsl:element name="keep">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

  <!-- t2 -->
  <xsl:template match="a/b" />

</xsl:stylesheet>

我预计这会产生:

<text>
  <keep>foo1</keep>
</text>

因为t2应匹配并且'忽略'<a><b>foo2</a></b>并且我认为它优先于t1(t1和t2匹配<a><b>,但t2稍后在XSL中)。但事实上输出是:

<text>
  <keep>foo1</keep>
  <keep>foo2</keep>
</text>

事实上,如果我拿走t2,输出是相同的,所以显然它甚至不匹配<a><b>。我一定错过了什么:请有人帮忙吗?

1 个答案:

答案 0 :(得分:1)

您正在寻找的是

<xsl:template match="a[b]" />

匹配a元素的模板,如果它们具有名为b的子元素。

模板匹配,如

<xsl:template match="a/b" />

a元素不匹配,它匹配b元素作为其父元素的a元素。但是在原始样式表中,永远不会提示XSLT处理器为b元素找到匹配的模板,这就是为什么此模板中包含的代码(无)永远不会被执行。

通过此更改,输出为

<?xml version="1.0" encoding="UTF-8"?>
<text>
  <keep>foo1</keep>

</text>

正如您所看到的,它几乎您期望的输出。使用您的XSLT处理器MSXSL,空行甚至可能不存在,因为MSXSL剥离了仅空白节点的树。但是要让样式表在任何处理器上产生一致的结果,下面的信息仍然有用。

要删除输出中的空行,请添加xsl:strip-space作为顶级元素。另外,如果事先知道元素名称,请省去键入xsl:element name=...的麻烦。整个样式表:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>

    <xsl:strip-space elements="*"/>

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

  <!-- t1 -->
  <xsl:template match="a">
    <keep>
      <xsl:value-of select="."/>
    </keep>
  </xsl:template>

  <!-- t2 -->
  <xsl:template match="a[b]" />

</xsl:stylesheet>