Assume
<myDoc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:js="urn:myJS1"
xmlns:ns="urn:myNS1">
<myElem1 xsi:type="ns:myComplexType"/>
<myElem2 xsi:type="js:myComplexType"/>
</myDoc>
I want to migrate this doc to use version 2 of the namespaces but need to do this dynamically because I can't predict which values of xsi:type are in the instance. Also ideally I want the same prefixes. So I want something like
<myDoc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<myElem1 xmlns:ns="newNs" xsi:type="ns:myComplexType"/>
<myElem2 xmlns:js="newNs" xsi:type="js:myComplexType"/>
</myDoc>
My best effort intercepts the creation of the xsi:type attribute and tries to create a namespace node for the new version. It is not working.
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0">
<xsl:variable name="schemas">
<thing targetNamespace="newNs"/>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@xsi:type">
<xsl:copy copy-namespaces="no">
<xsl:namespace name="{substring-before(.,':')}" select="$schemas/thing/@targetNamespace"/>
<xsl:next-match/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
but this does not result in an instance showing the new namespace nodes.
Although my example is XSLT 2.0, an XSLT 3.0 solution to this is fine.
In the match="@xsi:type"
template, the context node is the @xsi:type
attribute itself, so selecting @xsi:type
is wrong, it should simply be .
.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0">
<xsl:variable name="schemas">
<thing targetNamespace="newNs"/>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@xsi:type">
<xsl:namespace name="{substring-before(.,':')}" select="$schemas/thing/@targetNamespace"/>
<xsl:next-match/>
</xsl:template>
</xsl:stylesheet>