reemplace el espacio de nombres uri usando XSLT en mensaje SOAP
xslt-1.0 exslt (2)
Este tipo de procesamiento es fácil en XSLT 2.0, pero bastante complicado en XSLT 1.0 :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pTarget" select="''OLDSTRING''"/>
<xsl:param name="pRepl" select="''NEWSTRING''"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[starts-with(namespace-uri(), ''urn:schemas'')
or
namespace::*[starts-with(., ''urn:schemas'')]
]">
<xsl:variable name="vNS" select="namespace-uri()"/>
<xsl:variable name="vNewNS">
<xsl:choose>
<xsl:when test="not(contains($vNS, $pTarget))">
<xsl:value-of select="$vNS"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($vNS, $pTarget)"/>
<xsl:value-of select="$pRepl"/>
<xsl:value-of select="substring-after($vNS, $pTarget)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="{name()}" namespace="{$vNewNS}">
<xsl:copy-of select=
"namespace::*
[not(. = $vNS
or
starts-with(., ''urn:schemas'')
and
contains(., $pTarget)
)
]"/>
<xsl:for-each select=
"namespace::*
[starts-with(., ''urn:schemas'')
and
contains(., $pTarget)
]">
<xsl:variable name="vNewNSUri" select=
"concat(substring-before(., $pTarget),
$pRepl,
substring-after(., $pTarget)
)
"/>
<xsl:variable name="vPrefix" select="name()"/>
<xsl:variable name="vPref">
<xsl:if test="$vPrefix">
<xsl:value-of select="concat($vPrefix, '':'')"/>
</xsl:if>
</xsl:variable>
<xsl:variable name="vrtfDoc">
<xsl:element name="{$vPref}dummy"
namespace="{$vNewNSUri}"/>
</xsl:variable>
<xsl:copy-of select=
"ext:node-set($vrtfDoc)/*/namespace::*[. = $vNewNSUri]"/>
</xsl:for-each>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
cuando esta transformación se aplica en el documento XML proporcionado :
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:schemas-OLDSTRING-com:VARIABLESTRING">
<soapenv:Header/>
<soapenv:Body>
<requestMessage xmlns="urn:schemas-OLDSTRING-com:VARIABLESTRING">
<merchantID>TESTID</merchantID>
</requestMessage>
</soapenv:Body>
</soapenv:Envelope>
el resultado deseado y correcto se produce :
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:schemas-NEWSTRING-com:VARIABLESTRING">
<soapenv:Header />
<soapenv:Body>
<requestMessage xmlns="urn:schemas-NEWSTRING-com:VARIABLESTRING">
<merchantID>TESTID</merchantID>
</requestMessage>
</soapenv:Body>
</soapenv:Envelope>
Tengo un mensaje de entrada de jabón, tratando de reemplazar parte del espacio de nombres uri con una cadena diferente. Puedo reemplazar URI completo con un URI diferente, pero no puedo modificar el URI existente. Necesito buscar ''OLDSTRING'' y reemplazarlo por ''NEWSTRING''. La cadena VARIABLESTRING varía en cada entrada xml, por lo que debería mantener como está en el xml de salida
XML de entrada:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:schemas-OLDSTRING-com:VARIABLESTRING">
<soapenv:Header/>
<soapenv:Body>
<requestMessage xmlns="urn:schemas-OLDSTRING-com:VARIABLESTRING">
<merchantID>TESTID</merchantID>
</requestMessage>
</soapenv:Body>
</soapenv:Envelope>
OUTPUT XML:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:schemas-NEWSTRING-com:transaction-data-1.69">
<soapenv:Header/>
<soapenv:Body>
<requestMessage xmlns="urn:schemas-NEWSTRING-com:VARIABLESTRING">
<merchantID>TESTID</merchantID>
</requestMessage>
</soapenv:Body>
</soapenv:Envelope>
He intentado el siguiente XSL y he podido cambiar el URI del espacio de nombres, pero quiero reemplazar solo ''OLDSTRING'' por ''NEWSTRING'' y mantener el resto de la cadena tal como está.
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|*|text()" />
</xsl:copy>
</xsl:template>
<xsl:template match="//*[namespace-uri()=''urn:schemas-OLDSTRING-com:VARIABLESTRING'']">
<xsl:element name="{local-name()}" namespace="urn:schemas-NEWSTRING-com:VARIABLESTRING" >
<xsl:apply-templates select="@*|*|text()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
¿Hace esto lo que quieres?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|*|text()" />
</xsl:copy>
</xsl:template>
<xsl:template match="//*[namespace-uri()=''urn:schemas-OLDSTRING-com:VARIABLESTRING'']">
<xsl:element name="{local-name()}" namespace="{replace(namespace-uri(), ''OLDSTRING'', ''NEWSTRING'')}" >
<xsl:apply-templates select="@*|*|text()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>