这是我的输入XML文档:
<test xmlns="http://www.example.com/v1">
<qnameValue xmlns:foo="http://foo.example.com/">foo:bar</qnameValue>
</test>
我想使用XSLT(2.0)将此文档的命名空间更改为v2,即所需的输出为:
<test xmlns="http://www.example.com/v2">
<qnameValue xmlns:foo="http://foo.example.com/">foo:bar</qnameValue>
</test>
我试图使用这个样式表:
<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:previous='http://www.example.com/v1'>
<xsl:output encoding='UTF-8' indent='yes' method='xml'/>
<!-- Identity transform -->
<xsl:template match='@*|node()'>
<xsl:copy>
<xsl:apply-templates select='@*|node()'/>
</xsl:copy>
</xsl:template>
<!-- Previous namespace -> current. No other changes required. -->
<xsl:template match='previous:*'>
<xsl:element name='{local-name()}' namespace='http://www.example.com/v2'>
<xsl:apply-templates select='@* | node()' />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
不幸的是输出结果为:
<test xmlns="http://www.example.com/v2">
<qnameValue>foo:bar</qnameValue>
</test>
即。关于qnameValue的关键命名空间绑定已经消失了。有没有办法强制将所有命名空间绑定的副本强制输出?
答案 0 :(得分:5)
这应该这样做,并且与XSLT 1.0兼容:
<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:previous='http://www.example.com/v1'>
<xsl:output encoding='UTF-8' indent='yes' method='xml'/>
<!-- Identity transform -->
<xsl:template match='@*|node()'>
<xsl:copy>
<xsl:apply-templates select='@*|node()'/>
</xsl:copy>
</xsl:template>
<!-- Previous namespace -> current. No other changes required. -->
<xsl:template match='previous:*'>
<xsl:element name='{local-name()}' namespace='http://www.example.com/v2'>
<xsl:copy-of select='namespace::*[not(. = namespace-uri(current()))]' />
<xsl:apply-templates select='@* | node()' />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
在样本输入上运行时,结果为:
<test xmlns="http://www.example.com/v2">
<qnameValue xmlns:foo="http://foo.example.com/">foo:bar</qnameValue>
</test>
这是一种类似的方法,通过将旧的uri存储在变量中并从那里访问它可能会更有效:
<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:previous='http://www.example.com/v1'>
<xsl:output encoding='UTF-8' indent='yes' method='xml'/>
<xsl:variable name='oldUri' select='namespace-uri((//previous:*)[1])' />
<!-- Identity transform -->
<xsl:template match='@*|node()'>
<xsl:copy>
<xsl:apply-templates select='@*|node()'/>
</xsl:copy>
</xsl:template>
<!-- Previous namespace -> current. No other changes required. -->
<xsl:template match='previous:*'>
<xsl:element name='{local-name()}' namespace='http://www.example.com/v2'>
<xsl:copy-of select='namespace::*[not(. = $oldUri)]' />
<xsl:apply-templates select='@* | node()' />
</xsl:element>
</xsl:template>
</xsl:stylesheet>