如何使用样式表和xsltproc的xslt从xml中删除元素?

时间:2008-11-26 19:24:57

标签: xml xslt

我有很多XML文件,其格式如下:

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

我想从文件中删除。

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

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


编辑:这个问题原本缺乏意图。

我想要实现的是删除整个元素“Element”,其中(fruit ==“apple”&amp;&amp; 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" />

2 个答案:

答案 0 :(得分:127)

使用最基本的XSLT设计模式之一:“覆盖identity transformation”将只写下以下内容:

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

请注意第二个模板如何仅为名为“Element”的元素覆盖identity(1st)模板,该元素具有值为“apple”的属性“fruit”和属性为“animal”且值为“猫”。这个模板有空体,这意味着匹配元素被简单地忽略(匹配时不会产生任何东西)。

将此转换应用于以下源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>

产生了想要的结果:

<doc>... 
    <Element name="same">foo</Element>...
    <Element fruit="pear" animal="cat"/>
    <Element name="same">baz</Element>...
    <Element name="same">foobar</Element>...
</doc>

可以找到使用和覆盖身份模板的更多代码段 here

答案 1 :(得分:0)

@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