ChatGPT解决这个技术问题 Extra ChatGPT

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

我有很多具有以下形式的 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" />

D
Dimitre Novatchev

使用最基本的 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”的元素覆盖标识(第一个)模板,这些元素具有属性“fruit”的值为“apple”,属性“animal”的值为“cat”。这个模板的主体是空的,这意味着匹配的元素被简单地忽略(匹配时什么都不产生)。

当此转换应用于以下源 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 可以找到更多使用和覆盖身份模板的代码片段。


尽管我什至没有问正确的问题,但你已经回答了我应该问的问题! :)
那你为什么不把这篇文章标记为正确答案呢?然后它会从未解决的问题列表中消失。
不得不等到我确认它有效,并且今天没有机会工作。不过现在完成了,谢谢 Dimitre。
你能告诉我这个 xpath 表达式 /bookstore/book[position() = 1 or position() = 3]/@* 的缩写版本是什么吗?
@Babai,/*/book[position() = 1 or position() = 3]/@*。在 XPath 2.0 中:/*/book[position() = (1,3)]/@*
S
Sboisen

@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