web-dev-qa-db-fra.com

Comment supprimer des éléments de XML en utilisant xslt avec feuille de style et xsltproc?

J'ai beaucoup de fichiers XML qui ont quelque chose de la forme:

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

Que je souhaite supprimer du fichier.

À l'aide d'une feuille de style XSLT et de l'utilitaire de ligne de commande Linux xsltproc, comment pourrais-je procéder?

À ce stade du script, j'ai déjà la liste des fichiers contenant l'élément que je souhaite supprimer, de sorte que le fichier unique peut être utilisé comme paramètre.


EDIT: la question manquait initialement d'intention.

Ce que j'essaie de réaliser, c'est de supprimer tout l'élément "Element" où (fruit == "Apple" && animal == "cat"). Dans le même document, il y a beaucoup d'éléments nommés "Element", je souhaite qu'ils restent. Alors

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

Deviendrait:

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

En utilisant l'un des modèles de conception XSLT les plus fondamentaux: "Remplacer la transformation d'identité " on écrira simplement ce qui suit:

 <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 = "Élément [@ fruit = 'Apple' et @ animal = 'cat']" />[.____. diplomatique</ xsl: stylesheet> 

Notez comment le deuxième modèle remplace le modèle d'identité (1er) uniquement pour les éléments nommés "Element" qui ont un attribut "fruit" avec la valeur "Apple" et attribuez "animal" avec la valeur "chat". Ce modèle a un corps vide, ce qui signifie que l'élément correspondant est simplement ignoré (rien n'est produit lorsqu'il est mis en correspondance).

Lorsque cette transformation est appliquée sur le document XML source suivant:

 <doc> ... 
 <Élément name = "same"> foo </Element> ... 
 <Element fruit = "Apple" animal = "cat"/> 
 <Élément fruit = "poire" animal = "chat" />
 <Élément name = "même"> baz </Element> ... 
 <Élément name = "même"> foobar </Element> ... 
 </doc> 

le résultat souhaité est produit:

 <doc> ... 
 <Nom de l'élément = "même"> foo </Element> ... 
 <Élément fruit = "poire" animal = "chat"/> 
 <Nom de l'élément = "même"> baz </Element> ... 
 <Nom de l'élément = "même"> foobar </Element> ... 
 </ doc> 

Plus d'extraits de code d'utilisation et de substitution du modèle d'identité peuvent être trouvés ici.

128
Dimitre Novatchev

La réponse de @ Dimitre Novatchev est certainement à la fois correcte et élégante, mais il y a une généralisation (que l'OP n'a pas posée): que se passe-t-il si l'élément que vous souhaitez filtrer a également des éléments enfants ou du texte qui vous souhaitez conserver ?

Je crois que cette variation mineure couvre ce cas:

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

La condition de correspondance peut être compliquée pour spécifier d'autres attributs, etc., et vous pouvez utiliser plusieurs de ces modèles si vous supprimez d'autres choses.

Donc, cette entrée:

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

produit cette sortie:

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

Crédit à XSLT Cookbook .

2
Sboisen