2010-06-01 50 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被单独应用于每个报告。

祝你好运!