2012-04-11 111 views
3

我使用微軟的XSLT處理器(1.0只)多個命名空間1.0

XML開場白:

<?xml version="1.0" encoding="utf-8"?> 
<Header xmlns="http:\\OldNameSpace.com"> 
    <Detail> 

有以下XSLT模板拿起我的文檔的<Header>元素並更改其名稱空間。

<xsl:template match="*"> 
    <xsl:element name="{name()}" xmlns="http:\\NewNameSpace.com"> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates /> 
    </xsl:element> 
</xsl:template> 

果然<Header xmlns="http:\\OldNameSpace.com">進入<Header xmlns="http:\\NewNameSpace.com">

不過,我現在需要第二個命名空間添加到這個讓我得到以下輸出:

<Header xmlns="NewNameSpace.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

我已經嘗試使用:

<xsl:template match="*"> 
    <xsl:element name="{name()}" xmlns="NewNameSpace.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates /> 
    </xsl:element> 
</xsl:template> 

但是我仍然只得到相同的輸出t作爲原始的XSLT模板。

任何人都可以啓發我,爲什麼這是?

回答

5

這種轉變

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:old="http:\\OldNameSpace.com" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    exclude-result-prefixes="old xsi"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:param name="pNewNamespace" select="'http:\\NewNameSpace.com'"/> 

<xsl:variable name="vXsi" select="document('')/*/namespace::*[name()='xsi']"/> 

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

    <xsl:template match="old:*"> 
     <xsl:element name="{local-name()}" namespace="{$pNewNamespace}"> 
      <xsl:copy-of select="$vXsi"/> 
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates /> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

當下面的XML文檔應用:

<Header xmlns="http:\\OldNameSpace.com"> 
    <Detail/> 
</Header> 

產生(我猜是)通緝,正確的結果

<Header xmlns="http:\\NewNameSpace.com" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <Detail/> 
</Header> 
+0

Dimitre你永遠不會失望,謝謝。 – Mike 2012-04-11 12:28:51

+0

@Mike:不客氣。你的問題很容易解決,因爲要添加的命名空間是靜態的。當命名空間要動態生成時,它變得更有趣(在XSLT 1.0中)。大衛卡萊爾和邁克爾凱在這個更具挑戰性的案例中暗示瞭解決方案。最近我使用這種特殊的XSLT 1.0技術給出了答案 - 它還需要使用'xxx:node-set()'擴展函數。 – 2012-04-11 12:33:56

+0

@Mike:更具挑戰性的問題的解決方案:http://stackoverflow.com/a/9937128/36305 – 2012-04-11 12:40:02

2

的xsl:元素(不像文字結果元素)確實都在範圍的命名空間副本的結果,只是9either隱含從它的名字或與命名空間參數指定)的元素名稱所需的命名空間。

xslt2增加一個xsl:命名空間指令針對這種情況,但在xslt1最容易做的事情是

凡祖先

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

的地方(例如,在XSL:樣式表)

這會將一個僞造的xsi:tmp=""添加到輸出中,而且還會添加一個名稱空間聲明 如果您實際上需要此名稱空間中的屬性,例如xsi:type,則在上面使用該屬性而不是tmp,然後完成。如果你不介意xsi命名空間中額外的,可能無效的屬性,那麼你就完成了。否則,請在變量中執行上述操作,然後使用msxsl:node-set查詢變量並刪除虛假的額外屬性。

+0

您是否介意進一步澄清這是如何實現的,因爲它不是xslt最有經驗的。在xsl:stylesheet聲明中實現'xmlns:xsi =「http://www.w3.org/2001/XMLSchema-instance」'似乎對我的輸出沒有任何影響 – Mike 2012-04-11 09:08:04

+0

試試http://fgeorges.blogspot。 co.uk/2007/01/creating-namespace-nodes-in-xslt-10.html – 2012-04-11 09:10:45

+0

我們很快就會看到更多的博客,它看起來是我閱讀過的很好的一篇文章,現在正在查詢第二版因爲我沒有看到它允許我們在這種情況下沒有意義的三件事情有任何用處。當我知道它是否需要時,將刪除/繼續此線程 – Mike 2012-04-11 09:42:00

2

如果您靜態知道要生成的命名空間,那麼在XSLT 1.0中最簡單的方法是使用xsl:copy-of。創建源文檔<dummy xmlns:xsi="http://whatever"/>, ,然後在xsl:element的調用中執行<xsl:copy-of select="document('dummy.xml')/*/namespace::xsi"/>