web-dev-qa-db-ja.com

スタイルシートとxsltprocでxsltを使用してxmlから要素を削除する方法は?

次のような形式のXMLファイルがたくさんあります。

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

ファイルから削除したいもの。

XSLTスタイルシートとLinuxコマンドラインユーティリティxsltprocを使用して、これをどのように行うことができますか?

スクリプトのこの時点までに、削除したい要素を含むファイルのリストが既にあるので、単一のファイルをパラメーターとして使用できます。


編集:質問はもともと意図に欠けていました。

私が達成しようとしているのは、要素「Element」全体を削除することです(fruit == "Apple" && animal == "cat")。同じドキュメントには、「Element」という名前の要素が多数ありますが、これらが残ることを望みます。そう

<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" />
66
Grundlefleck

最も基本的なXSLT設計パターンの1つを使用して、「 恒等変換 "をオーバーライドすると、次のように記述できます。

 <xsl:stylesheet version = "1.0" 
 xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"> 
 
 <xsl:output exclude-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 note値「Apple」を持つ属性「fruit」を持つ「Element」という名前の要素に対してのみ、2番目のテンプレートがID(1st)テンプレートをオーバーライドする方法値「cat」を持つ属性「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 = 「同じ」> 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

128

@ Dimitre Novatchev による答えは確かに正確でエレガントですが、一般化があります(OPはそれについて尋ねませんでした):フィルターする要素に子要素またはテキストもある場合keepしたいですか?

私はこの小さな変化がそのケースをカバーすると信じています:

<?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 の功績。

2
Sboisen