Como eliminar xmlns = “” entradas produzidas pela transformação XSLT de um documento XML para outro documento XML
-
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
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
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
<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,
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).