无法为 xsi:type 属性动态创建命名空间节点
Cannot dynamically create namespace node for xsi:type attribute
假设
<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>
假设
<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>