Como eliminar xmlns = “” entradas produzidas pela transformação XSLT de um documento XML para outro documento XML

StackOverflow https://stackoverflow.com/questions/1844476

  •  12-09-2019
  •  | 
  •  

Pergunta

Ok, eu vi inúmeras variações sobre esta questão, mas nenhum exatamente responder o que eu estou tentando resolver e talvez eu sou muito denso para ver como aplicar uma das outras respostas para o que estou tentando fazer.

Eu tenho alguns XML que é algo como o seguinte:

<?xml version="1.0" encoding="utf-8"?>
<message>
  <cmd id="api_info">
    <api-version>1.0</api-version>
    <api-build>1.0.0.0</api-build>
  </cmd>
</message>

Agora eu tenho uma transformação XSLT que eu estou aplicando a este XML. O XSLT é semelhante ao seguinte:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:fn="http://www.w3.org/2005/xpath-functions"
                version="2.0">

    <xsl:output method="xml" version="1.0" indent="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates select="message"/>
    </xsl:template>

    <xsl:template match="message">
        <xsl:element name="message" xmlns="http://www.companyname.com/schemas/product/Version001">
            <xsl:apply-templates select="/message/cmd/@id"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="/message/cmd/@id">
        <xsl:variable name="_commandType" select="/message/cmd/@id"/>
        <xsl:element name="messageHeader">
            <xsl:element name="cmdType">
                <xsl:value-of select="$_commandType"/>
            </xsl:element>
        </xsl:element>

        <xsl:element name="messageBody">
            <xsl:choose>
                <xsl:when test="$_commandType = 'api_info'">
                    <xsl:element name="apiInfoBody">
                        <xsl:element name="apiVersion">
                            <xsl:value-of select="/message/cmd/api-version"/>
                        </xsl:element>
                        <xsl:element name="apiBuild">
                            <xsl:value-of select="/message/cmd/api-build"/>
                        </xsl:element>
                    </xsl:element>
                </xsl:when>
                <xsl:when test="$_commandType = 'communicationError'">
                    <xsl:element name="communicationErrorBody">
                        <xsl:element name="errorCode">
                            <xsl:value-of select="error-code"/>
                        </xsl:element>
                        <xsl:element name="badCmd">
                            <xsl:value-of select="bad-cmd"/>
                        </xsl:element>
                    </xsl:element>
                </xsl:when>
            </xsl:choose>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

A saída que eu vejo é basicamente o que eu quero e parece com o seguinte:

<?xml version="1.0" encoding="UTF-8"?>
<message xmlns="http://www.companyname.com/schemas/product/Version001">
    <messageHeader xmlns="">
        <cmdType>api_info</cmdType>
    </messageHeader>
    <messageBody xmlns="">
        <apiInfoBody>
            <apiVersion>1.0</apiVersion>
            <apiBuild>1.0.0.0</apiBuild>
        </apiInfoBody>
    </messageBody>
</message>

Mas o que eu não quero é o xmlns = "" atributos do e elementos.

Agora eu descobri que se eu especificar explicitamente o namespace no XSLT para esses elementos, então o atributo indesejado é empurrado para baixo um nível para as crianças desses atributos.

Eu poderia simplesmente passar por todo o meu XSLT e explicitamente adicionar o xmlns = "" http : //www.companyname.com/schemas/product/Version001 " atributo para cada um dos meus elemento xsl: definições, mas eu sei que deve haver um mais elegante caminho. Nós programadores são muito preguiçoso para não ter um atalho para este tipo de absurdo. Se o meu XSLT não consistem em algo tão simples como o exemplo encurtado, eu ser tentados a fazê-lo dessa maneira. Mas eu sei que deve haver uma maneira melhor.

Alguém sabe o que eu sinto falta aqui?

Obrigado,

AlarmTripper

Foi útil?

Solução

Use excluem-resultado-prefixos no xsl: tag de estilo com o prefixo "#default"

A referência no W3C para isso é AQUI

EDIT: OK, eu deveria ter estudado o seu XSL com mais cuidado. Mova os xmlns na marca da mensagem até a marca de estilo. Isto irá colocar todos os elementos resultar no mesmo namespace e resultar em um atributo namespace na tag mensagem. Eu corri isso em oxigênio / XML e tem a saída desejada.

Outras dicas

Ok, eu descobri-lo.

O XSLT Eu quero parecido com este:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:fn="http://www.w3.org/2005/xpath-functions"
                exclude-result-prefixes="xsl fo xs fn">

    <xsl:output method="xml" version="1.0" indent="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates select="message"/>
    </xsl:template>

    <xsl:template match="message">
        <message namespace="http://www.companyname.com/schemas/product/Version001">
            <xsl:apply-templates select="/message/cmd/@id"/>
        </message>
    </xsl:template>

    <xsl:template match="/message/cmd/@id">
        <xsl:variable name="_commandType" select="/message/cmd/@id"/>

        <xsl:element name="messageHeader">
            <xsl:element name="cmdType">
                <xsl:value-of select="$_commandType"/>
            </xsl:element>
        </xsl:element>

        <xsl:element name="messageBody">
            <xsl:choose>
                <xsl:when test="$_commandType = 'api_info'">
                    <xsl:element name="apiInfoBody">
                        <xsl:element name="apiVersion">
                            <xsl:value-of select="/message/cmd/api-version"/>
                        </xsl:element>
                        <xsl:element name="apiBuild">
                            <xsl:value-of select="/message/cmd/api-build"/>
                        </xsl:element>
                    </xsl:element>
                </xsl:when>
                <xsl:when test="$_commandType = 'communicationError'">
                    <xsl:element name="communicationErrorBody">
                        <xsl:element name="errorCode">
                            <xsl:value-of select="error-code"/>
                        </xsl:element>
                        <xsl:element name="badCmd">
                            <xsl:value-of select="bad-cmd"/>
                        </xsl:element>
                    </xsl:element>
                </xsl:when>
            </xsl:choose>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

A mudança que fixa era para adicionar o excluir-resultado-prefixos atributo para o e a seção de mudança que foi:

    <xsl:template match="message">
        <xsl:element name="message" xmlns="http://www.companyname.com/schemas/product/Version001">
            <xsl:apply-templates select="/message/cmd/@id"/>
        </xsl:element>
    </xsl:template>

para ser o seguinte em vez disso:

    <xsl:template match="message">
        <message namespace="http://www.companyname.com/schemas/product/Version001">
            <xsl:apply-templates select="/message/cmd/@id"/>
        </message>
    </xsl:template>

E agora eu sou feliz outra vez.

Existem provavelmente melhores maneiras de fazer isso, mas isso está funcionando para mim. Quaisquer futuras sugestões ainda são bem-vindos.

resposta (atualizado) de Jim Garrison é tudo que você deveria ter necessário. Mas a folha de estilo são atualizadas você postou saídas um atributo "namespace" no resultado, então eu não tenho certeza do que bom que faz você.

A principal coisa a entender é como o namespace padrão funciona. Não pense em xmlns como um atributo que você pode produzir com o resultado. Em vez disso, pense nisso como um detalhe lexical de sua folha de estilo, cujo objetivo é definir o namespace padrão para tudo abaixo dela (o próprio elemento e cada um de seus descendentes até substituído). (Por sua vez, ele tem a mesma função no XML resultado, que tem uma estrutura muito diferente do que o próprio estilo.)

elementos resultado literal na sua folha de estilo (por exemplo, ), bem como instruções (por exemplo, ) doesn tanto assumir o namespace padrão quando o nome fornecido 't usar um prefixo. Se você quiser todas deles para assumir esse mesmo espaço, então você precisa colocar um namespace padrão no topo da sua folha de estilo, como Jim Garrison sugeriu.

Caso contrário, você vai acabar com alguns elementos que não estão em que namespace, razão pela qual o resultado contido xmlns = "" (desactivação do espaço de nomes para os elementos).

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