2011-06-30 63 views
4

是否可以從XSLT中刪除xml屬性並使用生成的轉換?從XSLT中刪除屬性並使用結果集

換句話說,我有以下XML:

<?xml version="1.0" encoding="iso-8859-1"?> 
<?xml-stylesheet type="text/xsl" href="XML_TEST.xslt"?> 
<report xmlns="abc123"> 
<book> 
<page id="22"> 

</page> 
<page id="23"> 

</page> 
</book> 
</report> 

我知道我可以使用下面的XSLT剝離的屬性:

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

但是,如果我想讀值,使用以下模板

<xsl:template match="report"> 
    <xsl:for-each select="book/page"> 
     <xsl:value-of select="@id"/> 
    </xsl:for-each> 
</xsl:template> 

我可以將該模板鏈接到前兩個的輸出嗎?

在此先感謝,

-R。

+0

你需要兩個輸出嗎?如果不是,從單個xslt獲取所需內容可能會更容易。你可以添加你試圖獲得的輸出嗎? – cordsen

+0

好問題,+1。請參閱我的答案,瞭解兩個完整,簡短,簡單易行的解決方案。 :) –

+0

對於「_TITLE_」的好問題。 –

回答

1

是否可以從XSLT中刪除xml 屬性並使用 生成的轉換?

是的,只是搜索「多道改造」,你會發現有良好的代碼示例很多答案。

但是,對於你想要做的這樣的轉換鏈是過於複雜和完全不必要的

只需使用:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:x="abc123" > 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="x:page"> 
    <xsl:value-of select="@id"/> 
</xsl:template> 
</xsl:stylesheet> 

而如果XML文檔的默認名稱空間是事先不知道,你仍然可以產生單次想要的結果:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="*[name()='page']"> 
    <xsl:value-of select="@id"/> 
</xsl:template> 
</xsl:stylesheet> 
1

這個問題有些奇怪:我不明白問題的標題與內容的內容相符。

在標題你是要求一個兩通變換,其中第一通必須刪除屬性和第二,要在工作。

在顯示兩個模板的內容中,輸出節點和屬性的本地名稱,然後在另一個模板中顯示,您希望使用屬性獲取它們的值... :)

按@ Dimitre的答案回答你的問題的內容(這並沒有解決一個真正的問題,我認爲)我會盡量回答你的問題,這似乎更有趣的標題(和交代)。


從XSLT刪除屬性...

要刪除的屬性(並獲得無命名空間的變換),您可以用Identity Transformation工作。因爲您需要多遍傳遞,所以您必須在第一遍中將變量的內容複製到變量中。

您可以使用modes來解決第一遍中元素的處理過程。

...和使用結果集

要使用結果集(正式名稱是result tree fragment)工作,你需要使用引用定義的變量,應用模板在第一關。歡迎!這是第二次通過:)

由於XSLT 2.0能夠將模板應用於RTF,所以XSLT 2.0中的兩遍轉換比XSLT 1.0更容易訪問。在XSLT 1.0中,您將需要一個稱爲node-set()的特定擴展函數。


的XSLT 2.0看起來像這樣(純示例):

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:x="abc123" 
    version="2.0"> 

    <xsl:output indent="yes" omit-xml-declaration="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="/"> 
     <xsl:variable name="FirstPass"> 
      <xsl:copy> 
       <xsl:apply-templates select="/" mode="FirstPass"/> 
      </xsl:copy> 
     </xsl:variable> 

     <xsl:apply-templates select="$FirstPass/report/book/page"/> 
    </xsl:template> 

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

    <xsl:template match="page"> 
     <xsl:value-of select="count(@*)"/> 
    </xsl:template> 

</xsl:stylesheet> 

帶結果(塗布在你的輸入例如)

00 

XSLT 1.0看起來非常相似,但變換根元素:

<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:x="abc123" 
xmlns:exslt="http://exslt.org/common" 
version="2.0"> 

第二遍

<xsl:apply-templates select="exslt:node-set($FirstPass)/report/book/page"/> 
+0

通過「屬性」,OP實際上意味着刪除默認名稱空間。 –

+0

@Dimitre:b! LOL –

0

許多變換是最好劃分爲管道,其中管道的每個階段執行一個簡單的任務。

您可以在單個樣式表中進行多階段轉換(通過將結果保存在變量中,尤其是使用XSLT 2.0),或者可以使用多個樣式表執行此操作。您可以使用各種技術(XProc,Coccoon,Orbeon,Ant,xmlsh)或從您自己的Java/C#代碼控制涉及多個樣式表的流水線。使用多個樣式表具有管道組件具有高度可重用性的優點。