2012-01-17 51 views
2

我有下面的XML文檔根元素更換多個命名空間XSLT

<a:rootElement xmlns:a="http://a/1" xmlns:b="http://b/1" xmlns:c="http://c/1"> 
<child1 type="b:type"/> 
<child2 type="c:type"/> 
</a:rootElement> 

現在我想改變命名空間的URIs,所以我得到以下結果

<a:rootElement xmlns:a="http://a/2" xmlns:b="http://b/2" xmlns:c="http://c/2"> 
<child1 type="b:type"/> 
<child2 type="c:type"/> 
</a:rootElement> 

不應該有其他更改。我用下面的樣式表試了一下。

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:a="http://a/2" 
xmlns:b="http://b/2" 
xmlns:c="http://c/2" > 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="/*"> 
    <xsl:element name="{name()}" namespace="{namespace-uri()}"> 
     <xsl:copy-of select="document('')/*/namespace::*[name()='a']"/> 
     <xsl:copy-of select="document('')/*/namespace::*[name()='b']"/> 
     <xsl:copy-of select="document('')/*/namespace::*[name()='c']"/> 
     <xsl:copy-of select="node()|@*"/> 
    </xsl:element> 
</xsl:template> 

我碰到下面的錯誤輸出。

<a_0:rootElement xmlns:a_0="http://a/1" xmlns:a="http://a/2" xmlns:b="http://b/2" xmlns:c="http://c/2"> 
<child1 type="b:type" xmlns:a="http://a/1" xmlns:b="http://b/1" xmlns:c="http://c/1"/> 
<child2 type="c:type" xmlns:a="http://a/1" xmlns:b="http://b/1" xmlns:c="http://c/1"/> 
</a_0:rootElement> 

我也嘗試了其他一些方法,但也沒有所需的輸出。用XSLT以這種方式更改名稱空間是否可能?

感謝您的任何意見

+0

是不是有一個原因,你不這樣做在第一行用一個簡單的文本替換?看起來這比嘗試使用XSLT做起來要容易得多。 – Flynn1179 2012-01-17 14:40:03

+0

我必須在XML結構中改變更多,但這是我無法解決的唯一任務。轉型是模型升級的一部分。 – 2012-01-17 14:52:08

+0

你不能兩個都做?用文本替換來更改名稱空間,然後應用XSLT來完成剩下的工作?鑑於您正在有效地更改文檔中大多數(如果不是全部)元素的名稱空間,將其全部集成在一起的XSLT可能會變得更加複雜。 – Flynn1179 2012-01-17 14:54:55

回答

1

這種轉變

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:a1="http://a/1" 
xmlns:b1="http://b/1" 
xmlns:c1="http://c/1" 
xmlns:a="http://a/2" 
xmlns:b="http://b/2" 
xmlns:c="http://c/2" 
> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vDoc" select="document('')/*"/> 

<xsl:variable name="vnsA" select="$vDoc/namespace::*[name()='a1']"/> 
<xsl:variable name="vnsB" select="$vDoc/namespace::*[name()='b1']"/> 
<xsl:variable name="vnsC" select="$vDoc/namespace::*[name()='c1']"/> 
<xsl:variable name="vnsA2" select="$vDoc/namespace::*[name()='a']"/> 
<xsl:variable name="vnsB2" select="$vDoc/namespace::*[name()='b']"/> 
<xsl:variable name="vnsC2" select="$vDoc/namespace::*[name()='c']"/> 

<xsl:template match="*"> 
    <xsl:variable name="vNS" select="namespace-uri()"/> 

    <xsl:variable name="vnewNS"> 
     <xsl:choose> 
      <xsl:when test="$vNS = $vnsA"> 
      <xsl:value-of select="$vnsA2"/> 
      </xsl:when> 
      <xsl:when test="$vNS = $vnsB"> 
      <xsl:value-of select="$vnsB2"/> 
      </xsl:when> 
      <xsl:when test="$vNS = $vnsC"> 
      <xsl:value-of select="$vnsC2"/> 
      </xsl:when> 
     </xsl:choose> 
    </xsl:variable> 

    <xsl:element name="{name()}" namespace="{$vnewNS}"> 
     <xsl:copy-of select= 
     "namespace::*[not(contains('|a|b|c|', concat('|', name(), '|')))] 
     "/> 
     <xsl:copy-of select="namespace::*[name() = 'a' and not(. = $vnsA)]"/> 
     <xsl:copy-of select="namespace::*[name() = 'b' and not(. = $vnsB)]"/> 
     <xsl:copy-of select="namespace::*[name() = 'c' and not(. = $vnsC)]"/> 

     <xsl:if test="namespace::*[name() = 'a' and . = $vnsA]"> 
     <xsl:copy-of select="$vnsA2"/> 
     </xsl:if> 
     <xsl:if test="namespace::*[name() = 'b' and . = $vnsB]"> 
     <xsl:copy-of select="$vnsB2"/> 
     </xsl:if> 
     <xsl:if test="namespace::*[name() = 'c' and . = $vnsC]"> 
     <xsl:copy-of select="$vnsC2"/> 
     </xsl:if> 

     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates select="node()"/> 
    </xsl:element> 
</xsl:template> 

</xsl:stylesheet> 

時所提供的XML文檔應用:

<a:rootElement 
xmlns:a="http://a/1" 
xmlns:b="http://b/1" 
xmlns:c="http://c/1"> 

    <child1 type="b:type"/> 
    <child2 type="c:type"/> 
</a:rootElement> 

產生想要的,正確的結果

<a:rootElement xmlns:a="http://a/2" xmlns:b="http://b/2" xmlns:c="http://c/2"> 
    <child1 type="b:type"/> 
    <child2 type="c:type"/> 
</a:rootElement> 
+0

非常感謝你們兩位。 – 2012-01-18 08:25:53

+0

@ user1154071:不客氣。 – 2012-01-18 12:55:32

0

我覺得Dimitre充分證明了我的觀點,任何XSLT的解決方案將是一個很多比簡單地做一個比較複雜的使用XSLT處理之前對XML文檔的第一行文字替換。

不同名稱空間的元素在技術上是完全不同的元素。因爲XML技術認爲它們是不同的,所以實際上你必須處理和處理每一個,儘管它們在輸出時看起來是相同的。

你究竟是怎麼做的取決於你使用的平臺,但是一個簡單的'找到第一個出現的http://a/1並替換爲http://a/2應該爲每個名稱空間做這項工作。