xml - node - XSLT para cambiar el prefijo del espacio de nombres
xpath xml (2)
En vista de sus aclaraciones en los comentarios, sugeriría:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://my.ns.uri">
<xsl:output method="xml" version="1.0" omit-xml-declaration="yes" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="ns:{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[@*]">
<xsl:element name="ns:{local-name()}">
<xsl:element name="ns:{local-name()}">
<xsl:apply-templates/>
</xsl:element>
<xsl:apply-templates select="@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:element name="ns:{local-name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
¿Cual es la diferencia?
Cuando se aplica a la siguiente entrada de ejemplo:
XML
<lm:GetInvoiceList xmlns:lm="http://www.w3.org">
<lm:Response>
<lm:Bill>
<lm:BillPropertyA subPropertyA="first subproperty">first property</lm:BillPropertyA>
<lm:BillPropertyB subPropertyB="second subproperty"/>
<lm:BillPropertyC>second property</lm:BillPropertyC>
</lm:Bill>
</lm:Response>
</lm:GetInvoiceList>
el resultado será:
<ns:GetInvoiceList xmlns:ns="http://my.ns.uri">
<ns:Response>
<ns:Bill>
<ns:BillPropertyA>
<ns:BillPropertyA>first property</ns:BillPropertyA>
<ns:subPropertyA>first subproperty</ns:subPropertyA>
</ns:BillPropertyA>
<ns:BillPropertyB>
<ns:BillPropertyB/>
<ns:subPropertyB>second subproperty</ns:subPropertyB>
</ns:BillPropertyB>
<ns:BillPropertyC>second property</ns:BillPropertyC>
</ns:Bill>
</ns:Response>
</ns:GetInvoiceList>
Opuesto a:
<ns:GetInvoiceList xmlns:ns="http://my.ns.uri">
<ns:Response>
<ns:Bill>
<ns:BillPropertyA>
<ns:subPropertyA>first subproperty</ns:subPropertyA>
<ns:BillPropertyA>first property</ns:BillPropertyA>
</ns:BillPropertyA>
<ns:BillPropertyB>
<ns:subPropertyB>second subproperty</ns:subPropertyB>
</ns:BillPropertyB>
<ns:BillPropertyC>
<ns:BillPropertyA>second property</ns:BillPropertyA>
</ns:BillPropertyC>
</ns:Bill>
</ns:Response>
</ns:GetInvoiceList>
lo que coloca incorrectamente el nodo de texto "segunda propiedad" en otra instancia de ns:BillPropertyA
y lo convierte en un elemento secundario de ns:BillPropertyC
.
Notas :
Si desea cambiar el espacio de nombre de un nodo, no puede usar
xsl:copy
, ya que eso también copiará el espacio de nombres existente;Puede (y debería) declarar el espacio de nombres una vez, luego usar el enlace ya existente donde sea necesario.
Estoy tratando de convertir atributos en elementos, junto con esto, quiero cambiar el prefijo del espacio de nombres de mi código XML. Código XML:
<lm:GetInvoiceList xmlns:lm="http://www.w3.org">
<lm:Response>
<lm:Bill>
<lm:BillStatusCode typecode="1">type description</lm:BillStatusCode>
<lm:EBillProcessStatusCode typecode="2">type description</lm:EBillProcessStatusCode>
<lm:BillCycleCode typecode="1">type description</lm:BillCycleCode>
<lm:BillActivityCode typecode="3">type description</lm:BillActivityCode>
<lm:ToDate>...</lm:ToDate>
</lm:Bill>
</lm:Response>
</lm:GetInvoiceList>
Tengo este código XSLT:
<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()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@*]">
<xsl:copy>
<xsl:element name="ns:{name()}">
<xsl:apply-templates select="node()"/>
</xsl:element>
<xsl:apply-templates select="@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*|*[@*]">
<xsl:element name="ns:{local-name()}" namespace="http://my.ns.uri">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:element name="ns:{name()}" namespace="http://my.ns.uri">
<xsl:copy-of select="namespace::*"/>
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Pero no estoy obteniendo el resultado deseado.
Rendimiento esperado:
<ns:GetInvoiceList xmlns:ns="http://my.ns.uri">
<ns:Response>
<ns:Bill>
<ns:BillStatusCode>
<ns:BillStatusCode>type description</ns:BillStatusCode>
<ns:typecode>1</ns:typecode>
</ns:BillStatusCode>
<ns:EBillProcessStatusCode>
<ns:EBillProcessStatusCode>type description</ns:EBillProcessStatusCode>
<ns:typecode>2</ns:typecode>
</ns:EBillProcessStatusCode>
<ns:BillCycleCode>
<ns:BillCycleCode>type description</ns:BillCycleCode>
<ns:typecode>1</ns:typecode>
</ns:BillCycleCode>
<ns:BillActivityCode>
<ns:BillActivityCode>type description</ns:BillActivityCode>
<ns:typecode>3</ns:typecode>
</ns:BillActivityCode>
<ns:ToDate>...</ns:ToDate>
</ns:Bill>
</ns:Response>
</ns:GetInvoiceList>
Salida real:
<ns:GetInvoiceList xmlns:ns="http://my.ns.uri">
<ns:Response>
<ns:Bill>
<ns:BillStatusCode>
<ns:typecode>1</ns:typecode>type description</ns:BillStatusCode>
<ns:EBillProcessStatusCode>
<ns:typecode>2</ns:typecode>type description</ns:EBillProcessStatusCode>
<ns:BillCycleCode>
<ns:typecode>1</ns:typecode>type description</ns:BillCycleCode>
<ns:BillActivityCode>
<ns:typecode>3</ns:typecode>type description</ns:BillActivityCode>
<ns:ToDate>...</ns:ToDate>
</ns:Bill>
</ns:Response>
</ns:GetInvoiceList>
Apreciaría cualquier ayuda en esto!
Prueba este XSLT:
<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="*">
<xsl:element name="ns:{local-name()}" namespace="http://my.ns.uri">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<xsl:element name="ns:{local-name(../../*)}" namespace="http://my.ns.uri">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:element name="ns:{local-name()}" namespace="http://my.ns.uri">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Salida:
<ns:GetInvoiceList xmlns:ns="http://my.ns.uri">
<ns:Response>
<ns:Bill>
<ns:BillStatusCode>
<ns:typecode>1</ns:typecode>
<ns:BillStatusCode>type description</ns:BillStatusCode>
</ns:BillStatusCode>
<ns:EBillProcessStatusCode>
<ns:typecode>2</ns:typecode>
<ns:BillStatusCode>type description</ns:BillStatusCode>
</ns:EBillProcessStatusCode>
<ns:BillCycleCode>
<ns:typecode>1</ns:typecode>
<ns:BillStatusCode>type description</ns:BillStatusCode>
</ns:BillCycleCode>
<ns:BillActivityCode>
<ns:typecode>3</ns:typecode>
<ns:BillStatusCode>type description</ns:BillStatusCode>
</ns:BillActivityCode>
<ns:ToDate>
<ns:BillStatusCode>...</ns:BillStatusCode>
</ns:ToDate>
</ns:Bill>
</ns:Response>
</ns:GetInvoiceList>