如何使用带有样式表和 xsltproc 的 xslt 从 xml 中删除元素?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/321860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to remove elements from xml using xslt with stylesheet and xsltproc?
提问by Grundlefleck
I have a lot of XML files which have something of the form:
我有很多具有以下形式的 XML 文件:
<Element fruit="apple" animal="cat" />
Which I want to be removed from the file.
我想从文件中删除它。
Using an XSLT stylesheet and the Linux command-line utility xsltproc, how could I do this?
使用 XSLT 样式表和 Linux 命令行实用程序 xsltproc,我该怎么做?
By this point in the script I already have the list of files containing the element I wish to remove, so the single file can be used as a parameter.
至此,在脚本中,我已经有了包含要删除的元素的文件列表,因此可以将单个文件用作参数。
EDIT:the question was originally lacking in intention.
编辑:这个问题最初缺乏意图。
What I am trying to achieve is to remove the entire element "Element" where (fruit=="apple" && animal=="cat"). In the same document there are many elements named "Element", I wish for these to remain. So
我想要实现的是删除整个元素“元素”,其中(水果==“苹果”&动物==“猫”)。在同一个文档中有许多名为“元素”的元素,我希望保留这些元素。所以
<Element fruit="orange" animal="dog" />
<Element fruit="apple" animal="cat" />
<Element fruit="pear" animal="wild three eyed mongoose of kentucky" />
Would become:
会成为:
<Element fruit="orange" animal="dog" />
<Element fruit="pear" animal="wild three eyed mongoose of kentucky" />
回答by Dimitre Novatchev
Using one of the most fundamental XSLT design patterns: "Overriding the identity transformation" one will just write the following:
使用最基本的 XSLT 设计模式之一:“覆盖身份转换”,只需编写以下内容:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Element[@fruit='apple' and @animal='cat']"/>
</xsl:stylesheet>
Do notehow the second template overrides the identity (1st) template only for elements named "Element" that have an attribute "fruit" with value "apple" and attribute "animal" with value "cat". This template has empty body, which means that the matched element is simply ignored (nothing is produced when it is matched).
请注意第二个模板如何仅针对名为“Element”的元素覆盖标识(第一个)模板,这些元素的属性“fruit”值为“apple”,属性“animal”值为“cat”。该模板的主体为空,这意味着匹配的元素将被忽略(匹配时不会产生任何内容)。
When this transformation is applied on the following source XML document:
当此转换应用于以下源 XML 文档时:
<doc>...
<Element name="same">foo</Element>...
<Element fruit="apple" animal="cat" />
<Element fruit="pear" animal="cat" />
<Element name="same">baz</Element>...
<Element name="same">foobar</Element>...
</doc>
the wanted result is produced:
产生了想要的结果:
<doc>...
<Element name="same">foo</Element>...
<Element fruit="pear" animal="cat"/>
<Element name="same">baz</Element>...
<Element name="same">foobar</Element>...
</doc>
More code snippets of using and overriding the identity template can be found here.
更多使用和覆盖身份模板的代码片段可以在这里找到。
回答by Sboisen
The answer by @Dimitre Novatchevis certainly both correct and elegant, but there's a generalization (that the OP didn't ask about): what if the element you want to filter also has child elements or text that you want to keep?
@Dimitre Novatchev的答案当然既正确又优雅,但有一个概括(OP 没有询问):如果要过滤的元素也有要保留的子元素或文本怎么办?
I believe this minor variation covers that case:
我相信这个微小的变化涵盖了这种情况:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.0">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- drop DropMe elements, keeping child text and elements -->
<xsl:template match="DropMe">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
The match condition can be complicated to specify other attributes, etc., and you can use multiple such templates if you're dropping other things.
匹配条件可能很复杂,无法指定其他属性等,如果您要删除其他内容,则可以使用多个此类模板。
So this input:
所以这个输入:
<?xml version="1.0" encoding="UTF-8"?>
<mydocument>
<p>Here's text to keep</p>
<p><DropMe>Keep this text but not the element</DropMe>; and keep what follows.</p>
<p><DropMe>Also keep this text and <b>this child element</b> too</DropMe>, along with what follows.</p>
</mydocument>
produces this output:
产生这个输出:
<?xml version="1.0" encoding="UTF-8"?><mydocument>
<p>Here's text to keep</p>
<p>Keep this text but not the element; and keep what follows.</p>
<p>Also keep this text and <b>this child element</b> too, along with what follows.</p>
</mydocument>
Credit to XSLT Cookbook.
归功于XSLT Cookbook。

![xml 元素不能有字符 [children],因为该类型的内容类型是 element-only](/res/img/loading.gif)