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" />
Foi útil?

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top