2010-06-01 61 views
1

我有一堆用一個固定的,基於國家的命名架構的XML文件中的變量數XSLT的工作流程:report_en.xmlreport_de.xmlreport_fr.xml等。現在我想寫一個XSLT樣式表,上面寫着每一種文件通過document() XPath函數提取一些值並生成一個帶有摘要的XML文件。我的問題是:如何在不知道要處理的文件的確切名稱的情況下迭代源文件?與源文件

目前我打算生成一個輔助XML文件,其中包含所有文件名,並在我的樣式表中使用輔助XML文件進行迭代。文件列表將使用小型PHP或bash腳本生成。有更好的選擇嗎?

我知道XProc,但是投入大量時間並不是我現在的選擇。也許有人可以發佈XProc解決方案。優選地,解決方案包括工作流程步驟,其中報告以HTML格式下載並整理:

我將使用Saxon作爲我的XSLT處理器,所以如果有我可以使用的特定於撒克遜的擴展,那麼也可以。

+0

好問題(+1)。查看我的答案,找出可能的解決方案 – 2010-06-01 16:51:43

回答

4

您可以使用標準的XPath 2.x的collection()功能,as implemented in Saxon 9.x

撒克遜實現允許在函數的字符串-URI參數中使用的搜索模式,因此你可以在目錄的路徑後面指定任何以report_開頭的文件名的模式,然後再有另外兩個字符,然後以.xml結尾。

該XPath表達式:

collection('file:///c:/?select=report_*.xml') 

選擇駐留在c:\與名稱的文件開始report_然後具有0個或多個字符的每個XML文檔的文檔節點,然後以.xml結尾。

2

Dimitre的答案看起來像你的情況下最快的解決方案。但是既然你問了,這裏是一個XProc的替代品:

<p:declare-step version="1.0" xmlns:p="http://www.w3.org/ns/xproc" xmlns:c="http://www.w3.org/ns/xproc-step" exclude-inline-prefixes="#all" name="main"> 

<!-- create context for p:variable with base-uri pointing to the location of this file --> 
<p:input port="source"><p:inline><x/></p:inline></p:input> 

<!-- any params passed in from outside get passed through to p:xslt automatically! --> 
<p:input port="parameters" kind="parameter"/> 

<!-- configuration options for steering input and output --> 
<p:option name="input-dir" select="'./'"/> 
<p:option name="input-filter" select="'^report_.*\.xml$'"/> 
<p:option name="output-dir" select="'./'"/> 

<!-- resolve any path to base uri of this file, to make sure they are absolute --> 
<p:variable name="abs-input-dir" select="resolve-uri($input-dir, base-uri(/))"/> 
<p:variable name="abs-output-dir" select="resolve-uri($output-dir, base-uri(/))"/> 

<!-- first step: get list of all files in input-dir --> 
<p:directory-list> 
    <p:with-option name="path" select="$abs-input-dir"/> 
</p:directory-list> 

<!-- iterate over each file to load it --> 
<p:for-each> 
    <p:iteration-source select="//c:file[matches(@name, $input-filter)]"/> 
    <p:load> 
     <p:with-option name="href" select="resolve-uri(/c:file/@name, $abs-input-dir)"/> 
    </p:load> 
</p:for-each> 

<!-- wrap all files in a reports element to be able to hand it in to the xslt as a single input document --> 
<p:wrap-sequence wrapper="reports"/> 

<!-- apply the xslt (stylesheet is loaded below) --> 
<p:xslt> 
    <p:input port="stylesheet"> 
     <p:pipe step="style" port="result"/> 
    </p:input> 
</p:xslt> 

<!-- store the result in the output dir --> 
<p:store> 
    <p:with-option name="href" select="resolve-uri('merged-reports.xml', $abs-output-dir)"/> 
</p:store> 

<!-- loading of the stylesheet.. --> 
<p:load href="process-reports.xsl" name="style"/> 

</p:declare-step> 

把上面的例子存儲爲process-reports.xpl。您可以使用XMLCalabash運行它(http://xmlcalabash.com/download/)。你可以像這樣運行:

java -jar calabash.jar process-reports.xpl input-dir=./ output-dir=./ 

上面的代碼假定一個過程reports.xsl,它有一個文件,它包裝的所有報告,並做了一下處理就可以了。您也可以在純XProc中進行處理,但您可能更喜歡這種方式。

您也可以將p:xslt步驟移至p:for-each(位於p:load下方),這將導致xslt被單獨應用於每個報告。

祝你好運!