我是XSLT的新手,但有人向我建议它是完成特定任务的一种方式。我有一堆xhtml文件,我想从中删除边栏。边栏包含在<div class =“ foo”>元素中。
我可以使用此答案中的说明成功执行身份转换:如何使用带有样式表和xsltproc的xslt从xml中删除元素?但我似乎无法匹配我要删除的元素。也许是因为它们不是像我发现的这种设计模式的每个示例中那样的顶级元素?
有人可以解释从身份转换中删除<div class =“ foo”>及其所有子级的正确方法吗?
您的问题很可能是由于源XHTML文件中存在默认(xhtml)名称空间而引起的(您尚未向我们显示此文件,因此充其量只是一种猜测)。
有人可以解释从身份转换中删除及其所有子级的正确方法吗?
如果存在默认名称空间,请执行以下操作:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="xhtml:div[@class='foo']"/>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
在以下XHTML文档上应用此转换时:
<html xmlns="http://www.w3.org/1999/xhtml">
<div class="class1">
<p>Text1</p>
</div>
<div class="foo">
<p>Text foo</p>
</div>
<div class="class2">
<p>Text2</p>
</div>
</html>
Run Code Online (Sandbox Code Playgroud)
产生想要的正确结果:
<html xmlns="http://www.w3.org/1999/xhtml">
<div class="class1">
<p>Text1</p>
</div>
<div class="class2">
<p>Text2</p>
</div>
</html>
Run Code Online (Sandbox Code Playgroud)
必须在模板的match表达式中使用名称空间前缀,因为XPath会考虑“ no namespace”中的任何未前缀名称,而具有非前缀名称的match表达式则不匹配任何节点,因为它在“ no namspace”中指定了节点,但是源文档的所有节点都在XHTML命名空间中。
如果源文档中没有默认名称空间,则可以简化转换:
在以下XML文档上应用此转换时(请注意,它没有定义默认的名称空间):
<html>
<div class="class1">
<p>Text1</p>
</div>
<div class="foo">
<p>Text foo</p>
</div>
<div class="class2">
<p>Text2</p>
</div>
</html>
Run Code Online (Sandbox Code Playgroud)
产生想要的正确结果:
<html>
<div class="class1">
<p>Text1</p>
</div>
<div class="class2">
<p>Text2</p>
</div>
</html>
Run Code Online (Sandbox Code Playgroud)
两种转换都使用标识规则来复制文档的任何节点和另一个模板,该模板将覆盖标识规则以匹配节点"div[@class='foo']"
。第二个模板是空的(没有主体),这意味着完全不处理(忽略)匹配的节点和以其为根的子树,因此不会出现在输出中。