2014-04-29 21 views
0

我遇到了一個有趣的問題,我試圖按順序菊花鏈連接兩個轉換(使用XSLT 2.0),從原始XML中刪除CDATA元素在第一遍中,以便它可以在第二次被解析爲XML。雖然我懷疑它會影響結果,但我在使用Saxon 9 HE中的初始模板參數和collection()函數將多個XML文檔(相同名稱空間)收集到變量中,然後再通過變換。值得注意的是,我現在甚至無法使用這個文檔。在撒克遜菊花鏈接XSLT以在第二次傳遞之前從有效XML中刪除CDATA

我輸入文件(S):

<root> 
    <blah> 
     <![CDATA[<elementA att="A"><elementB att="B">Text</elementB></elementA>]]> 
    </blah> 
</root> 

我的XSLT嘗試:

<!-- Collect all XML files in $input folder for processing --> 
    <xsl:variable name="xml" select="collection(concat($input,'?select=*.*ml;recurse=no;on-error=ignore'))"/> 

    <!-- Initial template is called from the saxon command line using the -it:process option --> 
    <xsl:template name="process"> 
     <!-- First pass --> 
     <xsl:variable name="pass1xml"> 
      <xsl:apply-templates select="$xml" mode="pass1"/> 
     </xsl:variable> 
     <!-- First pass output --> 
     <xsl:result-document href="{concat($output,'\pass1.xml')}" method="xml" indent="yes"> 
      <xsl:copy-of select="$pass1xml"/> 
     </xsl:result-document> 
     <!-- Second pass --> 
     <xsl:apply-templates select="$pass1xml" mode="pass2"/> 
    </xsl:template> 

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

    <!-- First pass: strip CDATA from element --> 
    <xsl:template match="blah" mode="pass1"> 
     <xsl:copy> 
      <xsl:value-of select="." disable-output-escaping="yes"/> 
     </xsl:copy> 
    </xsl:template> 

    <!-- Second pass using $pass1xml variable --> 
    <xsl:template match="root" mode="pass2"> 
     <!-- Second pass output --> 
     <xsl:result-document href="{concat($output,'\pass2.xml')}" method="xml" indent="yes"> 
      <xsl:apply-templates select="descendant::elementA" mode="elementA"/> 
     </xsl:result-document>  
    </xsl:template> 

...etc (continue with second pass)... 
從第一階段所需的輸出

<root> 
    <blah> 
     <elementA att="A"> 
      <elementB att="B">Text</elementB> 
     </elementA> 
    </blah> 
</root> 

我所看到的那一刻在我的pass1.xml(第一次傳遞的結果 - 儘管使用disable-output-escaping =「yes」),是轉義的XML,這顯然不是XP ATHable在PASS2:

<root> 
    <blah> 
     &lt;elementA att="A"&gt;&lt;elementB att="B"&gt;Text&lt;/elementB&gt;&lt;/elementA&gt; 
    </blah> 
</root> 

不幸的是,我不能改變我的源文件刪除CDATA(我很欣賞這樣可以解決我的問題)。 CDATA中的XML也將始終保持良好狀態,所以我毫不猶豫地將其剝離出來。也許我誤解了菊花鏈方法,這意味着我試圖實現的是不可能的 - 無論如何我都渴望學習。

非常感謝您的時間和建議 - 非常感謝!

回答

2

disable-output-escaping是一個序列化功能,因此它不會幫助您將內存節點傳遞到同一樣式表中的第二個轉換步驟,您需要使用兩個樣式表,其中的結果首先在被送到第二個之前序列化。然而,正如你所提到的撒克遜,我會考慮使用商業版本和擴展函數或XSLT/XPath 3.0函數,如[parse-xml][1][parse-xml-fragment][2]來提供簡單地解析和處理內容的例如。

<xsl:template match="blah"> 
    <xsl:apply-templates select="parse-xml-fragment(.)/node()"/> 
</xsl:template> 

作爲一種替代方案,在Saxon 9.1 B中,即使在開源版本中也有擴展功能。

+0

感謝您的回覆,我現在理解這個概念好得多。我給了SaxonB一個鏡頭(對於其他感興趣的人:http://sourceforge.net/projects/saxon/files/Saxon-B/) - 一個絕妙的想法,但對我而言,它缺少命令行上的「-catalog」(批處理文件),所以我會換一個問題換另一個問題。我現在也很想保持開源(需要我可以廣泛分享的東西),所以我會從命令行運行兩個轉換。再次感謝! – Aaron