Pergunta

Eu tenho alguns XML que declara um namespace que é usado apenas para atributos, como este:

<?xml version="1.0" encoding="UTF-8"?>
<a xmlns:x="http://tempuri.com">
    <b>
        <c x:att="true"/>
        <d>hello</d>
    </b>
</a>

Eu quero usar XSL para criar uma cópia de nós selecionados e seus valores - Livrar-se dos atributos. Assim, a minha saída desejada é:

<?xml version="1.0" encoding="UTF-8"?>
<b>
    <c />
    <d>hello</d>
</b>

Eu tenho alguns XSL que quase faz isso, mas eu não consigo pará-lo colocando a declaração de namespace no elemento de nível superior da saída. Meu XSL é:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <xsl:apply-templates select="/a/b"/>
    </xsl:template>

    <xsl:template match="node()">
        <xsl:copy>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

O primeiro elemento da saída é <b xmlns:x="http://tempuri.com"> vez de <b>. Eu tentei declarar o namespace na XSL e colocando o prefixo na lista exclude-result-prefixes, mas isso não parece ter qualquer efeito. O que estou fazendo de errado?

UPDATE: Eu descobri que ao declarar o namespace na XSL e usando as obras de atributos extension-element-prefixes, mas isso não parece certo! Eu acho que eu poderia usar isso, mas eu gostaria de saber por que o exclude-result-prefixes não funciona!

UPDATE:. Na verdade, parece que esta solução extension-element-prefixes só funciona com XMLSpy de built-in motor de XSLT, não com MSXML

Foi útil?

Solução

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:x="http://tempuri.com">
    <xsl:template match="/">
        <xsl:apply-templates select="/a/b"/>
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="{local-name(.)}">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:copy/>
    </xsl:template>

    <!-- This empty template is not needed.
Neither is the xmlns declaration above:
    <xsl:template match="@x:*"/> -->
</xsl:stylesheet>

Eu encontrei uma explicação aqui .

Michael Kay escreveu:
excluem-resultado-prefixos afeta apenas os namespaces copiados do estilo por um elemento resultado literal, não afetam a cópia de namespaces de documentos de origem.

Outras dicas

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:x="http://tempuri.com"
  exclude-result-prefixes="x"
>

  <!-- the identity template copies everything 1:1 -->
  <xsl:template match="@* | node()">
     <xsl:copy>
      <xsl:apply-templates select="@* | node()" />
    </xsl:copy>
  </xsl:template>

  <!-- this template explicitly cares for namespace'd attributes -->
  <xsl:template match="@x:*">
    <xsl:attribute name="{local-name()}">
      <xsl:value-of select="." />
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

Tente isto (note a copy-namespaces='no' atributo):

<xsl:template match="node()">
    <xsl:copy copy-namespaces="no">
            <xsl:apply-templates select="node()"/>
    </xsl:copy>
</xsl:template>

Isto irá remover o x namespace de saída.

<xsl:namespace-alias result-prefix="#default" stylesheet-prefix="x" />

Lembre-se de fazer duas coisas quando você lida com um namespace padrão. Primeiro mapeá-lo em algo na tag de estilo, e depois removê-lo usando um namespace-alias.

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