71

我有很多具有以下形式的 XML 文件:

<Element fruit="apple" animal="cat" />

我想从文件中删除。

使用 XSLT 样式表和 Linux 命令行实用程序 xsltproc,我该怎么做?

到目前为止,在脚本中我已经有了包含要删除的元素的文件列表,因此可以将单个文件用作参数。


编辑:这个问题最初缺乏意图。

我想要实现的是删除整个元素“元素” where (fruit=="apple" && animal=="cat")。在同一个文档中有许多名为“元素”的元素,我希望这些元素能够保留。所以

<Element fruit="orange" animal="dog" />
<Element fruit="apple"  animal="cat" />
<Element fruit="pear"   animal="wild three eyed mongoose of kentucky" />

会成为:

<Element fruit="orange" animal="dog" />
<Element fruit="pear"   animal="wild three eyed mongoose of kentucky" />
4

2 回答 2

136

使用最基本的 XSLT 设计模式之一:“重写身份转换”只需编写以下内容:

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

 <xsl:输出省略-xml-declaration="yes"/>

    <xsl:template match="node()|@*">
      <xsl:复制>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:模板>

    <xsl:template match="元素[@fruit='apple' and @animal='cat']"/>
</xsl:样式表>

请注意,第二个模板如何仅针对名为“Element”的元素覆盖标识(第一个)模板,这些元素具有属性“fruit”,值为“apple”,属性“animal”,值为“cat”。这个模板的主体是空的,这意味着匹配的元素被简单地忽略(匹配时什么都不产生)。

当此转换应用于以下源 XML 文档时:

<文档>...
    <Element name="same">foo</Element>...
    <元素水果=“苹果”动物=“猫”/>
    <元素水果="梨" 动物="猫" />
    <Element name="same">baz</Element>...
    <Element name="same">foobar</Element>...
</doc>

产生了想要的结果:

<文档>...
    <Element name="same">foo</Element>...
    <元素水果=“梨”动物=“猫”/>
    <Element name="same">baz</Element>...
    <Element name="same">foobar</Element>...
</doc>

可以在此处找到更多使用和覆盖身份模板的代码片段。

于 2008-11-26T20:44:27.340 回答
3

@Dimitre Novatchev的答案当然既正确又优雅,但有一个概括(OP 没有问):如果您要过滤的元素也有您想要保留的子元素或文本怎么办?

我相信这个微小的变化涵盖了这种情况:

<?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>

指定其他属性等的匹配条件可能很复杂,如果您要删除其他内容,则可以使用多个此类模板。

所以这个输入:

<?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>

产生这个输出:

<?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>

归功于XSLT Cookbook

于 2019-03-08T21:53:57.517 回答