2013-10-28 129 views
2

我想將一個大的XML書分成多個文件(按章節)。此沙箱XML:XSLT 2.0結果文檔

<?xml version="1.0" encoding="UTF-8"?> 
<book> 
    <chapter id='1'>Chapter 1</chapter> 
     <p>Highly random content.</p> 
     <div>foo</div> 
     <blockquote>Bar</blockquote> 
    <chapter id='2'>Chapter 2</chapter> 
     <div> 
      <p>p in <i>italicized div</i>!</p> 
     </div> 
     <p>Content.</p> 
    <chapter id='3'>Chapter 3</chapter> 
     <blockquote>foo</blockquote> 
     <p>foo</p> 
    <chapter id='4'>Chapter 4</chapter> 
     <p>foo</p> 
     <p>end of book</p> 
</book> 

變換通過此XSLT期望:

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" /> 
<xsl:strip-space elements="*"/>  
<xsl:template match="book"> 
    <xsl:for-each-group select="*" group-starting-with="chapter"> 
     <xsl:result-document href="{concat('/home/paul/t',@id,'.xhtml')}"> 
      <xsl:for-each select="current-group()[self::*]"> 
       <xsl:copy-of select="."/> 
      </xsl:for-each> 
     </xsl:result-document> 
    </xsl:for-each-group> 
</xsl:template> 

問題。當我將XSLT應用於更復雜的生產文檔時,它不起作用。我會把源文件放在這裏..但它太大了,客戶可能不喜歡那樣。

我很困惑,爲什麼它不工作。而不是像沙箱測試一樣每章創建一個文件,它會創建一個大文件。懷疑問題可能與文件名中的@id有關。在生產文檔中,@id爲空。結果文件名爲t.xhtml,其中有整本書,當我真的想要多個文件t --id of the chapter-- .xhtml

任何提示在哪裏看?有沒有一種方法可以讓代碼更加符合不同文檔的複雜性(我認爲這是我的問題...從簡單概念轉移到生產已經引入了一些我不太感興趣的東西,也許一些更緊密的代碼會有所幫助) 。

+1

我們確實需要看到導致問題的示例,而不是簡單地按預期工作的示例。你確定你試圖與'group-starting-with =「章節」'模式匹配的'chapter'元素不在某個命名空間嗎?如果結果是單個文件,那麼它看起來好像分組創建單個組,並且如果模式根本不匹配,就會發生這種情況。 –

+0

正如@Martin所示,如果當前組不是'',則會發生錯誤。如果文檔不包含任何章節,或者在下有其他標籤,但是在第一個「」之前,則會發生這種情況。這些將被選爲一個沒有「@ ID」的組。至少這就是撒克遜人爲您的輸入文件插入額外的前置標籤所做的。我第二@Martin:我們需要一些(至少縮短的)逼真的輸入。 –

+0

感謝您的反饋意見。我還沒有完全解決這個問題,但是你的想法已經指出了問題出現的方向(我認爲)。我不擅長調試。 – Paulb

回答

1

至於你如何使你的代碼更具彈性,你可以嘗試檢查輸入文件最明顯的錯誤,這將使你的XSLT的過程中發生了錯誤,或者至少產生無用輸出問題:

  • 檢查第一<chapter>
  • 檢查<chapter>之前其他標籤不@id
  • 檢查<chapter>的帶有非唯一@id

以下XSLT將執行這些檢查併發出警告。否則它會產生輸出文件。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" /> 

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

    <xsl:template match="book"> 

     <xsl:variable name="chapter_ids" > 
     <xsl:for-each-group select="chapter" group-by="@id"> 
      <count_me/> 
     </xsl:for-each-group> 
     </xsl:variable> 

     <xsl:choose> 

     <xsl:when test="name(*[1]) != 'chapter'"> 
      <xsl:message>The book does not start with chapter! --- Aborting</xsl:message> 
     </xsl:when> 

     <xsl:when test="count(chapter[normalize-space(@id) = '']) > 0"> 
      <xsl:message>The book contains chapters without chapter ids! - Aborting</xsl:message> 
     </xsl:when> 

     <xsl:when test="count(chapter) &gt; count($chapter_ids/count_me)"> 
      <xsl:message>The book has more chapters (<xsl:value-of select="count(chapter)"/>) than chapter ids (<xsl:value-of select="count($chapter_ids/count_me)"/>)! - Aborting</xsl:message> 
     </xsl:when> 

     <xsl:otherwise> 

      <xsl:for-each-group select="*" group-starting-with="chapter"> 
      <xsl:result-document href="{concat('./t',@id,'.xhtml')}"> 
       <xsl:for-each select="current-group()[self::*]"> 
       <xsl:copy-of select="."/> 
       </xsl:for-each> 
      </xsl:result-document> 
      </xsl:for-each-group> 

     </xsl:otherwise> 

     </xsl:choose> 

    </xsl:template> 
</xsl:stylesheet> 
0

您遇到的行爲表示XPath group-starting-with="chapter"未選擇任何內容。我相信真正的內容包含標籤名稱的差異。將單詞chapter修改爲任意文字可以使問題在樣本數據上重現。