2012-09-24 70 views
0

我有一個結構有點像這樣的XML文檔: -XSL轉換隻能元素一定的命名空間

<catalog xmlns="format_old" xmlns:final="format_new"> 
    <final:book> 
    <final:title>blah</final:title> 
    <final:author>more blah</final:author> 
    </final:book> 
    <book> 
    <description title="blah2"/> 
    <writer name="more blah2"/> 
    </book> 
</catalog> 

顯然,這是問題的一個簡化版本。我想要做的是將其轉換成類似: -

<catalog xmlns="format_new"> 
    <book> 
    <title>blah</title> 
    <author>more blah</author> 
    </book> 
    <book> 
    <title>blah2</title> 
    <author>more blah2</author> 
    </book> 
</catalog> 

,我現在所擁有的樣式表是這樣的: -

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:orig="format_old" 
    xmlns="format_new"/> 

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

<xsl:template match="//orig:book"> 
    <xsl:element name="title"> 
    <xsl:value-of select="./orig:description/@title" /> 
    </xsl:element> 
    <xsl:element name="author"> 
    <xsl:value-of select="./orig:writer/@name" /> 
    </xsl:element> 
</xsl:template> 

</xsl:stylesheet> 

這給了我一個輸出,如: -

<catalog xmlns="format_old"> 
    <book xmlns="format_new"> 
    <title>blah</title> 
    <author>more blah</author> 
    </book> 
    <book xmlns:orig="format_old" xmlns="format_new"> 
    <title>blah2</title> 
    </author>more blah2</author> 
    </book> 
</catalog> 

有兩個問題與這個樣式表: -

1)(重大問題)根的Elemen t被複制而不是更改根元素的默認名稱空間。所以基本上,目錄元素仍然位於名稱空間format_old中。

2)(小問題)這將元素轉換爲: -

<book xmlns:orig="format_old" xmlns="format_new"> 
    ... 
</book> 

,而不是從根元素拿起命名爲保持它作爲

<book> 
    ... 
</book> 

我是什麼在這裏失蹤?我正在使用Xalan-C。

回答

2

我認爲有以下應該做的:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns="format_new" 
    xmlns:ns1="format_old" 
    exclude-result-prefixes="ns1" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="@* | text() | comment() | processing-instruction()"> 
    <xsl:copy/> 
</xsl:template> 

<xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
    <xsl:apply-templates select="@* | node()"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="ns1:book/ns1:description[@title]"> 
    <title> 
    <xsl:value-of select="@title"/> 
    </title> 
</xsl:template> 

<xsl:template match="ns1:book/ns1:writer[@name]"> 
    <author> 
    <xsl:value-of select="@name"/> 
    </author> 
</xsl:template> 

</xsl:stylesheet> 

撒克遜6.5.5將您輸入

<?xml version="1.0" encoding="utf-8"?><catalog xmlns="format_new"> 
    <book> 
    <title>blah</title> 
    <author>more blah</author> 
    </book> 
    <book> 
    <title>blah2</title> 
    <author>more blah2</author> 
    </book> 
</catalog> 
+0

謝謝。在我的實際場景中試試這個... – owagh

1

你靠近。您的默認模板正在挑選您沒有其他模板的所有內容。

你的第一個問題是,他們正在拾取orig:catalog元素並將其寫出來,結果不是你想要的。簡單的修復:爲它添加一個模板。

你的第二個問題是管理輸出中的名稱空間聲明。在這裏,幾種技術可以幫助:

  • 仔細閱讀的XSL文件:排除對結果前綴的規範或你最喜歡的XSLT參考;用它來告訴你的處理器,你不需要爲舊命名空間命名空間聲明。

  • 如果要利用字面結果元素的輸出始終包含樣式表中LRE中找到的所有inscope名稱空間前綴這一事實,請使用xsl:element構造函數而不是文字結果元素。有關更多詳情,請參見this SO question

  • 在SAX或您最喜歡的編輯器中編寫一個簡單的過濾器,讓您完全控制聲明命名空間的位置以及如何執行。 (XSLT的設計認爲你應該很擔心命名空間的聲明,結果很難控制它們。)

  • 如果你的輸出有一些額外的命名空間聲明,那麼訓練你自己不要太在意,並且只要所有東西都綁定正確,就編寫你的下游消費者去做正確的事情,這樣他們就不會被多餘的名稱空間聲明困擾。

不同的人對這些不同的技術有不同的成功程度;我自己,我發現最後一個特別有效,而我只在其他人失望時擔心。