假设
<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>
我想把这个文档迁移到使用第2版命名空间,但需要动态地进行,因为我无法预测实例中xsi:type的哪些值。另外,理想的情况是,我希望使用相同的前缀。 所以,我希望有这样的东西
<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>
我的最大努力是拦截 xsi:type 属性的创建,并试图为新版本创建一个命名空间节点。它没有工作。
<?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>
但这不会导致一个实例显示新的命名空间节点。
虽然我的例子是XSLT 2.0,但XSLT 3.0的解决方案也可以。
在 match="@xsi:type"
模板,上下文节点是 @xsi:type
属性本身,所以选择 @xsi:type
错了,就应该干脆 .
.
<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>