2013-04-22 45 views
3

这里是我的输入XML文档:XSLT 2.0 - 改变命名空间,不丢弃现有的前缀绑定

<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上的关键命名空间绑定已经消失。有什么办法强制所有命名空间绑定的副本到输出?

回答

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> 
+0

正是我在找的东西。谢谢! – 2013-04-22 15:41:58