2010-09-09 38 views
5

全部,將XSLT轉換應用於已轉換的XML

我有一個XML文件,我使用XSLT文檔將其轉換爲另一個XML。

我可以在同一個XSLT文件中定義另一組轉換,應用於第一個轉換的結果XML嗎?

感謝,

MK

+0

你是否希望兩次轉換髮生在一次?如果是這樣,爲什麼不剪掉中間人,直接轉換到預期的輸出? – recursive 2010-09-09 16:07:43

+0

爲什麼你需要這種情況發生在單個XSLT上?爲什麼不能有兩個單獨的文件? – 2010-09-09 16:13:34

+0

我有一個應用程序僅接受一個XSLT文件,但我想將第二個轉換應用於新轉換的文件。 – koumides 2010-09-09 16:14:43

回答

9

是。

I.這XSLT 1.0轉化

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" 
xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vrtfPass1"> 
    <xsl:apply-templates/> 
</xsl:variable> 

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

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

<xsl:template match="num/text()"> 
    <xsl:value-of select="2*."/> 
</xsl:template> 

<xsl:template match="num/text()" mode="pass2"> 
    <xsl:value-of select="1+."/> 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:apply-templates select="ext:node-set($vrtfPass1)/*" mode="pass2"/> 
</xsl:template> 
</xsl:stylesheet> 

當此XML文檔上施加:

<t> 
<num>1</num> 
<num>2</num> 
<num>3</num> 
<num>4</num> 
<num>5</num> 
</t> 

產生

<t> 
    <num>3</num> 
    <num>5</num> 
    <num>7</num> 
    <num>9</num> 
    <num>11</num> 
</t> 

請注意

  1. 兩個轉換的實際執行,二是第一的結果執行。

  2. 第一次轉換的結果是變量$vrtfPass1的內容。

  3. 在XSLT 1.0中,包含動態生成(臨時)XML樹(XML文檔或XML片段)的變量類型爲RTF(結果樹片段)。在RTF上無法進行XPath操作 - 需要使用由絕大多數XSLT 1.0處理器供應商提供的擴展功能xxx:node-set()將其轉換爲常規節點集。在這個例子中,使用了exslt:node-set(),因爲EXSLT由許多不同的供應商實現。

  4. 第二個轉換應用於第一個<xsl:apply-templates select="ext:node-set($vrtfPass1)/*" mode="pass2"/>的結果。使用單獨的mode以便乾淨地分離兩個轉換的代碼。

  5. 第一個轉換將每個num/text()乘以2.第二個轉換每增加num/text()。其結果是2*.+1

II。這XSLT 2.0轉換

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" > 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vPass1"> 
    <xsl:apply-templates mode="pass1"/> 
</xsl:variable> 

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

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

<xsl:template match="num/text()" mode="pass1"> 
    <xsl:value-of select="2*xs:integer(.)"/> 
</xsl:template> 

<xsl:template match="num/text()" mode="pass2"> 
    <xsl:value-of select="1+."/> 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:apply-templates select="$vPass1" mode="pass2"/> 
</xsl:template> 
</xsl:stylesheet> 

當在同一個XML文檔應用,產生同樣的有用和正確的結果

請注意:在XSLT 2.0/XPath 2.0中,RTF類型已被廢除。否需要xxx:node-set()擴展功能。

+0

+1好答案。這說明了爲什麼RTF是來自WG的一個糟糕的設計選擇......另外,當使用擴展功能時,我們是不是必須展示使用'fn:function-available'? – 2010-09-09 20:05:17

+0

@Alejandro:也許使用'fn:function-available'將有助於確定XSLT處理器實現的許多'xxx:node-set()'擴展中的哪一個 - 但這通常是已知的。 – 2010-09-09 20:59:06

+0

太好了。非常感謝Dimitre。 – koumides 2010-09-10 10:07:13