Como remover elementos de xml usando XSLT com estilo e xsltproc?
Pergunta
Eu tenho um monte de arquivos XML que têm algo da forma:
<Element fruit="apple" animal="cat" />
O que eu quero ser removido do arquivo.
Usando uma folha de estilo XSLT e linha de comando Linux xsltproc utilidade, como eu poderia fazer isso?
Por este ponto no script eu já tenho a lista de arquivos que contêm o elemento que deseja remover, de modo que o único arquivo pode ser usado como um parâmetro.
EDIT:. a questão foi originalmente falta de intenção
O que eu estou tentando alcançar é para remover todo o elemento "Elemento", onde (fruto == "maçã" && animais == "gato"). No mesmo documento, existem muitos elementos nomeados "Elemento", eu desejo para que estes permanecem. Então
<Element fruit="orange" animal="dog" />
<Element fruit="apple" animal="cat" />
<Element fruit="pear" animal="wild three eyed mongoose of kentucky" />
Quer tornar-se:
<Element fruit="orange" animal="dog" />
<Element fruit="pear" animal="wild three eyed mongoose of kentucky" />
Solução
Usando um dos mais padrões de design XSLT fundamental: "Substituindo o transformação de identidade " um só vai escrever o seguinte:
<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>
Do nota ??strong> como o segundo modelo substitui o modelo de identidade (1º) apenas para elementos nomeados "elemento" que têm um atributo "fruto" com valor "maçã" e atributo "animal" com valor " gato". Este modelo tem corpo vazio, o que significa que o elemento correspondente é simplesmente ignorada (nada é produzido quando é correspondido).
Quando esta transformação é aplicada no seguinte documento XML fonte:
<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>
O resultado queria é produzido:
<doc>... <Element name="same">foo</Element>... <Element fruit="pear" animal="cat"/> <Element name="same">baz</Element>... <Element name="same">foobar</Element>... </doc>
Mais trechos de código de usar e substituir o modelo de identidade pode ser encontrado aqui .
Outras dicas
A resposta por @Dimitre Novatchev é certamente correto e elegante, mas não há uma generalização (que o OP não perguntar sobre): e se o elemento que deseja filtro também tem elementos filhos ou texto que deseja manter ?
Eu acredito que cobre esta variação menor que caso:
<?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>
A condição de correspondência pode ser complicado para especificar outros atributos, etc., e você pode usar vários desses modelos se você está soltando outras coisas.
Assim esta entrada:
<?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>
produz esta saída:
<?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édito para XSLT Cookbook .