我应该如何正确使用XSLT if语句?

时间:2010-08-04 16:20:52

标签: xslt compiler-errors

我创建了一个XSLT样式表,用于查找节点并将其删除。这非常有效。我现在想检查是否存在某个节点,然后删除该节点(如果存在)。

所以我试图添加一个if语句,那就是我遇到了以下错误:

  

编译错误:文件dt.xls行   10元素模板
  元素模板   仅允许作为样式表的子项

我想我理解错误但不确定如何绕过它。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="Ad">
    <xsl:template match="node()|@*">

      <xsl:if test="name-ad-size">
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:if>

    </xsl:template>
  </xsl:template>


  <xsl:template match="phy-ad-width"/>
  <xsl:strip-space elements="*"/>
  <xsl:preserve-space elements="codeListing sampleOutput"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:5)

通常,当人们第一次尝试XSLT时,他们认为它是一种语言,就像C#,Java,PHP一样。所有这些语言都用于告诉计算机该做什么。但是使用XSLT则相反,您可以根据规则告诉处理器您期望的输出。

有时,使用xsl:if是好的。更常见的是,这是一个错误的迹象。 删除节点,元素或文本的技巧是创建一个不输出任何内容的匹配模板。像这样:

<!-- starting point -->
<xsl:template match="/">
    <xsl:apply-templates select="root/something" />
</xsl:template>

<xsl:template match="name-ad-size">
   <!-- don't do anything, continue processing the rest of the document -->
   <xsl:apply-templates select="node() | @*" />
</xsl:template>

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

为什么这样做?简单地说,因为处理器遍历每个元素和节点,并首先查看最匹配的模板。节点<name-ad-size>的最佳匹配是不输出任何内容的匹配,因此它会有效地删除它。其他节点不匹配,因此最终出现在“全部捕获”模板中。

注1:您收到的错误可能是因为您错误地将<xsl:template>添加到另一个元素中。它只能放在根<xsl:stylesheet>下,而不能放在其他地方。

注2:<xsl:template>语句的顺序无关紧要。处理器将使用所有这些来找到最佳匹配,无论它们放在何处(只要它们直接位于根目录下)。


编辑:有人神奇地检索了你的代码。以上是适用于完整样式表的故事:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:preserve-space elements="codeListing sampleOutput"/>

  <!-- NOTE: it is better to have a starting point explicitly -->
  <xsl:template match="/">
    <xsl:apply-templates select="root/something" />
  </xsl:template>

  <!-- I assume now that you meant to delete the <Ad> elements -->
  <xsl:template match="Ad">
     <xsl:apply-templates select="node()|@*"/>
  </xsl:template>

  <!-- NOTE: here you were already deleting <phy-ad-width> and everything underneath it -->
  <xsl:template match="phy-ad-width"/>

  <!-- NOTE: copies everything that has no matching rule elsewhere -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>