Comment supprimer des éléments de xml en utilisant xslt avec stylesheet et xsltproc?
Question
J'ai beaucoup de fichiers XML qui ont quelque chose de la forme:
<Element fruit="apple" animal="cat" />
Ce que je veux 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é en tant que paramètre.
MODIFIER: la question manquait initialement d'intention.
Ce que je cherche à faire est de supprimer l’élément entier " Élément " où (fruit == "pomme" & & amp; & animal == "chat"). Dans le même document, il y a beaucoup d'éléments nommés "Élément", je souhaite qu'ils restent. Donc
<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" />
La solution
Utilisation de l'un des modèles de conception XSLT les plus fondamentaux: "Remplacement de la transformation d'identité" / strong> " 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="Element[@fruit='apple' and @animal='cat']"/> </xsl:stylesheet>
Notez que le deuxième modèle remplace le modèle d'identité (1er) uniquement pour les éléments nommés " Élément " qui ont un attribut " fruit " avec la valeur "pomme" et attribuer " animal " avec 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 correspond).
Lorsque cette transformation est appliquée sur le document XML source suivant:
<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>
le résultat souhaité est généré:
<doc>... <Element name="same">foo</Element>... <Element fruit="pear" animal="cat"/> <Element name="same">baz</Element>... <Element name="same">foobar</Element>... </doc>
Vous trouverez d'autres extraits de code d'utilisation et de substitution du modèle d'identité ici .
Autres conseils
La réponse de @Dimitre Novatchev est certes à la fois correcte et élégante, mais il existe une généralisation (que le ne demande pas): que se passe-t-il si l'élément que vous souhaitez filtrer contient également des éléments enfants ou du texte que vous souhaitez conserver ?
Je crois que cette variante 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 de spécifier d'autres attributs, etc., et vous pouvez utiliser plusieurs modèles de ce type si vous supprimez d'autres éléments.
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>
Nous vous remercions de XSLT Cookbook .