2013-07-08 89 views
2

我有一個包含805個模板的大型XSLT文件,這取決於系統和環境,因堆棧溢出而失敗。XslCompiledTransform失敗,堆棧溢出

開發環境是Windows 7,InfoPath 2010和C#。儘管安裝了.NET 4.0,但此版本的InfoPath使用.NET 2.0。

使用的例程被是:

private void TransformXML(String inputFileName, String transformFileName, String outputFileName) 
{ 
    CorralLog(String.Concat("Transform with ", transformFileName, ": ", inputFileName, " -> ", outputFileName)); 

    using (XmlReader inputFile = XmlReader.Create(inputFileName, null)) 
    { 
     XslCompiledTransform transform = new XslCompiledTransform(true); 
     XsltSettings settings = new XsltSettings(true, false); 

     transform.Load(transformFileName, settings, null); 

     using(XmlWriter outputFile = XmlWriter.Create(outputFileName)) 
     { 
      filesToDelete.Add(outputFileName); 
      transform.Transform(inputFile, outputFile); 
     } 
    } 
} 

我可以看到一些可能性:

  1. 增加可用的存儲器的「transform.Load」命令
  2. 開始與更多的單獨的線程內存
  3. 啓動一個單獨的線程並使用'msxsl.exe'執行轉換(始終有效)
  4. 將XSLT文件拆分爲更小的部分並進行多次轉換

有沒有人有關於選擇哪個選項的建議?還是有其他建議?

保羅


有問題的XLST文件需要一些元素從一個XML文件,對一些元素更名,併產生另一個XML文件。大約有800個元素,每個元素都有自己的模板。

此代碼顯示了XSLT文件開始處的三個模板和兩個用於複製元素的模板:一個用於按原樣複製元素,另一個用於更改元素的名稱。所有後續的模板都以這兩種方式之一格式化。

此語法是否導致遞歸,或者是導致堆棧溢出的模板數量。 (我們已經避免了這個問題,但也許不就解決了,通過運行這個變換一個新的線程。)

<?xml version="1.0"?> 

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
       xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2011-03-16T10:53:27"> 

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

    <xsl:template match="/"> 
     <xsl:apply-templates select="*"/> 
    </xsl:template> 

    <xsl:template match="/*"> 
     <xsl:copy> 
      <xsl:apply-templates select="*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*"> 
     <xsl:apply-templates select="*"/> 
    </xsl:template> 

    <xsl:template match="/SAN/ClientProfiles/ClientProfile"> 
     <xsl:copy> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="/SAN/ClientProfiles/ClientProfile/Name"> 
     <CompanyName> 
      <xsl:apply-templates/> 
     </CompanyName> 
    </xsl:template> 
+1

缺少大量信息。它在什麼特定的條件下失敗?你有沒有嘗試過自己呢(如果沒有,爲什麼不)?如果你給它足夠的內存(比如說12GB),它是否總能成功運行?根據迄今爲止提供的信息,任何答案都將是瘋狂的猜測。 –

+0

不知道爲什麼你說「多次執行轉換」與「將XSLT文件拆分爲更小的塊」有關。這是一個多階段轉型嗎? – LarsH

+0

由於每種工作類型的不同,我們已經有五次轉換。因此,製作較大的一個可能會有所幫助,可以通過一次以上的轉換來完成。但是我們似乎已經成功地將轉換轉換爲單獨的線程。 –

回答

1

堆棧溢出的最可能的原因是在你的XSLT代碼深遞歸。我會查看相關的模板,看看它們是否可以用其他方式編寫,例如要使用分而治之遞歸而不是頭尾遞歸,或者可能要利用XSLT 2.0--還有一些適用於.NET的XSLT 2.0處理器。

+0

我希望在XSLT代碼中沒有遞歸。因爲我們只從源XML獲取一些元素,所以我們有805個模板將這個元素複製到目標XML中。大量的模板會導致遞歸嗎? –

+1

誰知道?邁克爾凱在他的發言中是正確的。你還沒有提供你的XSL的一點甚至診斷,但你的解決方案的想法是問增加內存和這樣的...你的XSLT是更有可能的問題,但你沒有提出要求其他人來評估可能的問題 –

+0

我之前沒有發佈XSLT代碼,因爲我認爲這是Windows或.NET問題。鑑於原因可能是XSLT文件的錯誤設計,我已經將XSLT代碼添加到了我的問題中。 –

1
+0

MSDN文章非常好。儘管我們沒有使用提到的特定結構,但是可以通過更改XSLT文件來解決大部分堆棧溢出問題。 在我們的案例中,我們已經啓動了一個新的線程來完成這個轉換,並且這似乎是有效的。從長遠來看,如果可能的話,更改XSLT可能是一個好主意。 –

+0

馬丁,感謝您的參考。它表明魔鬼的細節;我當然不會期望僅僅擁有數千個模板規則就足以導致堆棧溢出。 –