XProc - 如何重复特定次数的子管道

时间:2015-07-07 19:28:56

标签: xpath xproc

我想重复一次XProc子管道给定次数。 (在我的用例中,subpipeline包含一个exec-step,它在以前创建的.tex文件上运行LaTeX)

我的代码的简化版本如下所示,到目前为止没有结果:

<p:declare-step  version="1.0"
xmlns:p="http://www.w3.org/ns/xproc"
xmlns:c="http://www.w3.org/ns/xproc-step">

<p:option name="latex-exec" select="'uri/latex'"/>
<p:option name="latex-repeat" select="3"/>
<p:option name="tmp-path" select="'uri/tmp/'"/>
<p:option name="tmp-file" select="'tmp'"/>

<!-- pre-processing -->

<p:for-each>
    <p:iteration-source select="(1 to $latex-repeat)"/>

    <p:exec result-is-xml="false">
        <p:with-option name="command" select="$latex-exec"/>
        <p:with-option name="args"    select="string-join(('-interaction=nonstopmode','-halt-on-error','-output-format=pdf',concat('-output-directory=',$tmp-path),concat($tmp-path,$tmp-file,'.tex')),' ')"/>
        <p:input port="source">
            <p:empty/>
        </p:input>
    </p:exec>
</p:for-each>

我不知道p:iteration-source元素中的XPath-2.0表达式是否存在问题。但是,以下工作并给出正确的结果“消息:3”:

<cx:message>
    <p:with-option name="message" select="count((1 to $latex-repeat))"/>
    <p:input port="source">
        <p:empty/>
    </p:input>
</cx:message>

我的exec-step在for-each循环之外进行测试并且有效。我在Oxygen 16.0下与Calabash合作。

1 个答案:

答案 0 :(得分:0)

如VojtěchToman所述,p:for-each循环不能迭代原子值[XD0016]。由于此限制不适用于XSLT 2.0循环等效项,因此我们可以定义自己的p:xslt步骤,以根据所需迭代次数创建XML节点序列。然后,此序列可用作p:for-each的输入。

迭代器步骤如下所示:

<p:declare-step version="1.0"
    xmlns:p="http://www.w3.org/ns/xproc"
    xmlns:c="http://www.w3.org/ns/xproc-step"
    xmlns:my="http://example.org/iterate"
    type="my:iterator">

    <p:option name="iterate" required="true"/>

    <p:input port="source"/>
    <p:output port="result" sequence="true"/>

    <p:xslt name="iterator" template-name="iterator">
        <p:with-param name="iterator" select="$iterate"/>
        <p:input port="stylesheet">
            <p:inline>
                <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
                    <xsl:param name="iterator"/>
                    <xsl:template name="iterator">
                        <xsl:for-each select="(1 to xs:integer($iterator))">
                            <xsl:result-document href="{position()}">
                                <iterate/>
                            </xsl:result-document>
                        </xsl:for-each>
                    </xsl:template>
                </xsl:stylesheet>
            </p:inline>
        </p:input>
        <p:input port="source">
            <p:empty/>
        </p:input>
    </p:xslt>

    <p:sink/>

    <p:identity>
        <p:input port="source">
            <p:pipe port="secondary" step="iterator"/>
        </p:input>
    </p:identity>

</p:declare-step>

使用新迭代器步骤的示例如下所示:

<p:declare-step version="1.0"
    xmlns:p="http://www.w3.org/ns/xproc"
    xmlns:c="http://www.w3.org/ns/xproc-step"
    xmlns:my="http://example.org/iterate">

    <p:import href="iterate.xpl"/>

    <!-- pre-processing -->    

    <my:iterator>
        <p:with-option name="iterate" select="3"/>
    </my:iterator>
    <p:for-each>

        <!-- sub-pipeline -->

    </p:for-each>

</p:declare-step>