2013-04-22 32 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