如何正确使用XSLT if语句?
我创建了一个XSLT样式表,用于查找节点并将其删除。这很有效。我现在想检查某个节点是否存在,然后删除该节点(如果存在) 因此,我尝试添加一条if语句,结果遇到以下错误: 编译错误:文件dt.xls行 10元素模板如何正确使用XSLT if语句?,xslt,compiler-errors,Xslt,Compiler Errors,我创建了一个XSLT样式表,用于查找节点并将其删除。这很有效。我现在想检查某个节点是否存在,然后删除该节点(如果存在) 因此,我尝试添加一条if语句,结果遇到以下错误: 编译错误:文件dt.xls行 10元素模板 元素模板 仅允许作为样式表的子级 我想我理解这个错误,但不知道如何避免它 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output om
元素模板 仅允许作为样式表的子级 我想我理解这个错误,但不知道如何避免它
<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>
通常,当人们第一次尝试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>
为什么这样做有效?简单地说,因为处理器遍历每个元素和节点,然后首先查看最佳匹配的模板。节点
的最佳匹配是不输出任何内容的匹配,因此它会有效地删除它。其他节点不匹配,因此最终会出现在“catch all”模板中
注意1:您收到的错误可能是因为您在另一个元素中错误地添加了
。它只能放在根目录下,而不能放在其他地方
注2:
语句的顺序是不相关的。处理器将使用它们来找到最佳匹配,不管它们放在哪里(只要它们直接位于根目录下)
编辑:有人神奇地检索了你的代码。下面是应用于完整样式表的上面的故事:
<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>
我修复了您的格式,但是您的XSL无效,因为您无法放置@Jim:aha,我只看到XSL:if
,所以我猜到了问题的其余部分。其余的都不见了,因为它不在代码块中。啊,不管怎样,答案应该是一样的;-)学习XSL的关键在于它不是一种命令式编程语言。XSL处理器不使用样式表来驱动处理器;相反,控制流程的是输入XML文档(您正在处理的文档,而不是样式表)。在读取每个标记时,处理器通过搜索XSL以找到最佳匹配的模板来决定要做什么。这有点过于简化了,但学习思考控制中的文档,而不是样式表,是必需的直觉飞跃。@Jim:我想这就是我想说的。我知道这种反向思维是完全正确的,但我注意到学生们很难想到XML(或其他输入)是主导的。这就是为什么我用“规则”来比较。当我使用XSLT时,我编写规则,当我编写规则时,我会问“如果处理器在输入XML中遇到与我的规则匹配的节点,我们应该输出什么?”哇,谢谢,我明白你的说法和你的权利,我是一名c#程序员,我就是这样看待它的。但是,在删除之前,我想检查节点“name ad size”是否存在。我需要这个检查的原因是,有时我需要phy ad宽度,有时我不需要。我的关键是“名称ad大小”,如果存在,那么我想删除phy ad宽度。这就是为什么我认为在这里可以使用if语句。再次感谢您的回答。@kc2scy:忘了这一点,不要用“它是否存在”来思考。为是否存在创建规则。如果不是,它将被忽略。如果必须创建规则,则使用
,该规则将应用于没有
的
。当然,许多其他规则或组合也是可能的。