xmlns volver ser qué que puede proyecto primera prefijo parte nombres namespace misma inicial etiqueta espacio elemento ejemplos direccion dentro definir debe xml xslt xml-namespaces

volver - xmlns c#



XSL: ¿Cómo eliminar los espacios de nombres no utilizados de xml de origen? (3)

Tengo un xml con muchos espacios de nombres no utilizados, como este:

<?xml version="1.0" encoding="UTF-8"?> <ns1:Envelope xmlns:ns1="http://www.a.com" xmlns:ns2="http://www.b.com" xmlns:ns3="http://www.c.com" xmlns:ns4="http://www.d.com"> <ns1:Body> <ns2:a> <ns2:b>data1</ns2:b> <ns2:c>data2</ns2:c> </ns2:a> </ns1:Body> </ns1:Envelope>

Me gustaría eliminar los espacios de nombres no utilizados sin tener que especificar en el xslt cuáles eliminar / mantener. El resultado xml debe ser este:

<?xml version="1.0" encoding="UTF-8"?> <ns1:Envelope xmlns:ns1="http://www.a.com" xmlns:ns2="http://www.b.com"> <ns1:Body> <ns2:a> <ns2:b>data1</ns2:b> <ns2:c>data2</ns2:c> </ns2:a> </ns1:Body> </ns1:Envelope>

He buscado en Google pero no he encontrado una solución para este problema en particular. ¿Hay alguna?

Gracias.

PS: No estoy 100% seguro, pero creo que debería ser para XSL 1.0.


Agregando a la respuesta de Dimitre, si esos espacios de nombres deben conservarse y solo ocurren en los valores de los atributos, agregue esta condición: @*[contains(.,concat($vPrefix,'':''))] :

<xsl:if test= "$vtheElem/descendant::* [namespace-uri() = current() and substring-before(name(),'':'') = $vPrefix or @*[substring-before(name(),'':'') = $vPrefix] or @*[contains(.,concat($vPrefix,'':''))] ]">

Esto conservará correctamente el espacio de nombres ns3 debido a attrib="ns3:Header" como en el siguiente ejemplo.

<ns1:Envelope xmlns:ns1="http://www.a.com" xmlns:ns2="http://www.b.com" xmlns:ns3="http://www.c.com" xmlns:ns4="http://www.d.com"> <ns1:Body ns2:x="1"> <ns2:a> <ns2:b atrib="ns3:Header">data1</ns2:b> <ns2:c>data2</ns2:c> </ns2:a> </ns1:Body> </ns1:Envelope>


Bien si usas

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="@* | text() | comment() | processing-instruction()"> <xsl:copy/> </xsl:template> <xsl:template match="*"> <xsl:element name="{name()}" namespace="{namespace-uri()}"> <xsl:apply-templates select="@* | node()"/> </xsl:element> </xsl:template> </xsl:stylesheet>

luego se eliminan los espacios de nombres no utilizados, pero el resultado es más probable que se vea como

<ns1:Envelope xmlns:ns1="http://www.a.com"> <ns1:Body> <ns2:a xmlns:ns2="http://www.b.com"> <ns2:b>data1</ns2:b> <ns2:c>data2</ns2:c> </ns2:a> </ns1:Body> </ns1:Envelope>

de lo que pediste.


A diferencia de la respuesta de @ Martin-Honnen, esta solución produce exactamente el resultado deseado : los nodos de espacio de nombres necesarios permanecen donde están y no se mueven hacia abajo.

Además, esta solución trata correctamente con los atributos que se encuentran en un espacio de nombres :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="node()|@*" priority="-2"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*"> <xsl:element name="{name()}" namespace="{namespace-uri()}"> <xsl:variable name="vtheElem" select="."/> <xsl:for-each select="namespace::*"> <xsl:variable name="vPrefix" select="name()"/> <xsl:if test= "$vtheElem/descendant::* [(namespace-uri()=current() and substring-before(name(),'':'') = $vPrefix) or @*[substring-before(name(),'':'') = $vPrefix] ] "> <xsl:copy-of select="."/> </xsl:if> </xsl:for-each> <xsl:apply-templates select="node()|@*"/> </xsl:element> </xsl:template> </xsl:stylesheet>

cuando esta transformación se aplica en el siguiente documento XML (el documento XML proporcionado con un atributo de espacio de nombre agregado):

<ns1:Envelope xmlns:ns1="http://www.a.com" xmlns:ns2="http://www.b.com" xmlns:ns3="http://www.c.com" xmlns:ns4="http://www.d.com"> <ns1:Body ns2:x="1"> <ns2:a> <ns2:b>data1</ns2:b> <ns2:c>data2</ns2:c> </ns2:a> </ns1:Body> </ns1:Envelope>

Se produce el resultado correcto y deseado :

<ns1:Envelope xmlns:ns1="http://www.a.com" xmlns:ns2="http://www.b.com"> <ns1:Body ns2:x="1"> <ns2:a> <ns2:b>data1</ns2:b> <ns2:c>data2</ns2:c> </ns2:a> </ns1:Body> </ns1:Envelope>