2010-11-05 15 views
5

me gustaría hacer estacambiar el espacio de nombres de un elemento con XSLT

<hello> 
    <one> 
    <paragraph>p1</paragraph> 
    </one> 
</hello> 

en este

<x:hello y:an_attribute="a value for an_attribute" xmlns:x="some_new_namespace" xmlns:y="other_ns"> 
    <one> 
    <paragraph>p1</paragraph> 
    </one> 
</x:hello> 

esta es la hoja de estilo que se me ocurrió:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:param name="element_localname" select="'hello'"/> 


    <xsl:template match="node()"> 
     <xsl:choose> 
      <xsl:when test="local-name() = $element_localname"> 
       <xsl:element name="{$element_localname}" namespace="some_new_namespace"> 
        <xsl:attribute name="an_attribute" namespace="other_ns">a value for an_attribute</xsl:attribute> 
        <xsl:apply-templates select="node()"/> 
       </xsl:element> 
      </xsl:when> 

      <!-- copy the rest as is --> 
      <xsl:otherwise> 
       <xsl:copy> 
        <xsl:apply-templates select="node()" /> 
       </xsl:copy> 
      </xsl:otherwise> 

     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

pero por alguna extraña razón, el atributo que estoy agregando al elemento tiene el mismo espacio de nombres que el elemento raíz en sí mismo? ¿por qué?

<ns0:hello xmlns:ns0="other_ns" ns0:an_attribute="a value for an_attribute"> 
    <one> 
    <paragraph>p1</paragraph> 
    </one> 
</ns0:hello> 

Gracias por leer.

+0

El funcionamiento de su fuente a través de su transformación en xsltproc me da ' 'para el elemento' hello', que parece ser lo que quieres. Me pregunto si esto es un XSL 1.0 frente a XSL 2.0 cosa? –

+0

Gracias por intentarlo. Estoy usando la construcción eclipse wtp en el procesador xslt. No tengo idea qué implementación usa. – Luca

+0

Buena pregunta, +1. Vea mi respuesta para una solución mucho más simple y corta que la actualmente aceptada. :) –

Respuesta

0

Esta hoja de estilo:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:x="some_new_namespace" 
    xmlns:y="other_ns"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:param name="element_localname" select="'hello'"/> 
    <xsl:template match="node()|@*" name="identity"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="*"> 
     <xsl:choose> 
      <xsl:when test="local-name() = $element_localname"> 
       <xsl:element name="x:{$element_localname}"> 
        <xsl:attribute name="y:an_attribute"> 
         <xsl:text>a value for an_attribute</xsl:text> 
        </xsl:attribute> 
        <xsl:apply-templates select="node()|@*"/> 
       </xsl:element> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:call-template name="identity" /> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

Salida:

<x:hello y:an_attribute="a value for an_attribute" 
     xmlns:y="other_ns" xmlns:x="some_new_namespace"> 
    <one> 
     <paragraph>p1</paragraph> 
    </one> 
</x:hello> 
+0

Gracias, esto funciona. Has resuelto mi problema :) ¿Tienes una idea de por qué mi ejemplo no? – Luca

+0

@Luca: Usted es bienvenido. Esta es la salida del código: ' p1' Entonces , tiene un elemento raíz de espacio de nombres defalut con un atributo bajo un espacio de nombres no nulo (el prefijo se agrega automáticamente mediante Corrección de espacios de nombres) y una declaración predeterminada de espacio de nombres 'xmlns =" ​​"' (En XML 1.1 también se puede resetear la declaración de espacios de nombres prefijados). . En pocas palabras: si quiere un URI de espacio de nombres de prefijo específico vinculante, declare eso en la hoja de estilos. –

4

Esto es mucho más sencillo de lo que parece:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:x="some_new_namespace" xmlns:y="other_ns" 
exclude-result-prefixes="x y"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="/*"> 
    <x:hello y:an_attribute="a value for an_attribute"> 
    <xsl:apply-templates/> 
    </x:hello> 
</xsl:template> 
</xsl:stylesheet> 

Cuando se aplica esta transformación a la prevista Documento XML:

<hello> 
    <one> 
     <paragraph>p1</paragraph> 
    </one> 
</hello> 

el resultado deseado, correcta se produce:

<x:hello xmlns:x="some_new_namespace" xmlns:y="other_ns" y:an_attribute="a value for an_attribute"> 
    <one> 
     <paragraph>p1</paragraph> 
    </one> 
</x:hello> 
Cuestiones relacionadas