p:run (3.0) 

Runs a dynamically loaded pipeline.

Summary

The p:run step executes a dynamically loaded pipeline within the current pipeline.

Description

In using XProc, there are cases where it is useful to be able to run a dynamically loaded pipeline. The p:run step makes this possible. For instance:

  • Assume you have an XProc pipeline that processes/executes some DSL (Domain Specific Language). This language refers to XProc pipelines (by URI) that need to be executed as part of the DSL processing.

  • Your pipeline gets so complicated that it becomes easier to dynamically construct another pipeline and run this as part of your main pipeline.

Without p:run, all this wouldn’t be possible. Unfortunately, because various requirements surrounding dynamic pipeline execution, the p:run step is very different from other steps: it has a totally different set of child elements. Therefore, the step will be explained as if it was a separate XML element:

<p:run name? = xs:NCName >
  ( <p:with-input> |
    <run-input>* |
    <run-option>* |
    <output>*  )
</p:run>

 

Attribute

#

Type

Description

name

?

xs:NCName

The standard XProc step name attribute.

 

Child element

#

Description

p:with-input

1

Anonymous input port that receives the pipeline to run. This is not the step’s primary port!

Its attributes and child elements are similar to the standard XProc <p:with-input> element, except that, since the port is anonymous, it does not have a port attribute.

See also Details specifying the pipeline to run.

run-input

1

Element for connecting the input ports of the pipeline being run.

Its attributes and child elements are similar to the standard XProc <p:with-input> element, except that it has an additional boolean primary attribute.

See also Details connecting input ports.

run-option

1

Element for passing options to the pipeline being run.

Its attributes and child elements are similar to the standard XProc <p:with-option> element, except that it has an additional boolean static attribute.

See also Details specifying options.

output

1

Element that declares an output port of the pipeline being run.

See also Details specifying output ports.

In handling all this, there are quite a few details involved, which are discussed in the sections below. However, in the vast majority of cases, using p:run is not very difficult. You may want to look at the examples before diving into the details.

Details specifying the pipeline to run

The pipeline to run (the dynamically executed pipeline) must be provided on the anonymous input port of p:run (its “pipeline” port). This must of course be a valid XProc pipeline and it must have a version attribute.

You connect this anonymous “pipeline” port by adding a single <p:with-input> child element to the p:run, without a port attribute. For example, assume there is a step in my pipeline, named pipeline-generating-step, that produces a pipeline on its primary result port. To execute this pipeline using p:run, I would have to write:

<p:run>
  <p:with-input pipe="result@pipeline-generating-step"/>
  …
</p:run>

Take care: this anonymous “pipeline” port is not the primary port of p:run. So you must always connect it, even if the pipeline to run flows out of the primary output port of the step right before (in XProc terms: even if it is the DRP, the Default Readable Port).

Details connecting input ports

The <p:run-input> element is used to connect the input ports of the dynamically executed pipeline. Its attributes and child elements are almost similar to the standard XProc <p:with-input> element.

For example, to connect the primary source input port of the dynamically executed pipeline to some document on disk, you could write:

<p:run>
  <p:with-input href="my-dynamic-pipeline.xpl"/>
  <p:run-input port="source" href="doc.xml"/>
  …
</p:run>

There are a few things you need to keep in mind when connecting the input ports of the dynamically executed pipeline:

  • The additional boolean primary attribute of <p:run-input> can be used to declare that this port in the dynamically executed pipeline is primary. Its default value depends:

    • If there is a single <p:run-input> element, its default value is true.

    • If there are multiple <p:run-input> elements, its default value is false.

  • If the primary input port of the pipeline to run is not explicitly connected to somewhere (in its <p:run-input> element), it gets connected to the default readable port of p:run.

  • The name of the primary input port, as declared by the <p:run-input> element of p:run, must be the same as the name of the primary input port of the dynamically executed step. If not, error XC0206 is raised.

  • Any input ports of the dynamically executed step for which there is no corresponding <p:run-input> element receive an empty connection (<p:empty/>).

  • Any input ports mentioned in <p:run-input> elements that do not exist in the dynamically executed pipeline are silently ignored.

Details specifying options

Options for the dynamically executed pipeline can be specified using one or more <p:run-option> elements. Its attributes and child elements are almost similar to the standard XProc <p:with-option> element.

There are a few additional details to reckon with:

  • The <p:run-option> element has an additional boolean attribute static, which defaults to false. Using static="true" allows you to specify static options for the pipeline to run.

  • Any options of the dynamically executed pipeline that are not specified using <p:run-option> are handled as expected: if they are required, an error will be raised, and if not, their default value applies.

  • Any options set by <p:run-option> that do not exist in the dynamically executed pipeline are silently ignored.

Details specifying output ports

To be able to access the output ports of the dynamically executed pipeline, you have to declare these ports on the p:run invocation using <p:output> elements. For example, if your dynamic pipeline has a primary result output port and you want to access what comes out of this port in the pipeline that does the p:run, you must write something like:

<p:run>
  <p:with-input href="my-dynamic-pipeline.xpl"/>
  <p:output port="result" primary="true"/>
  …
</p:run>

A few details to consider:

  • The <p:output> child element of p:run has the same definition as a normal <p:output> element, but here it may not establish a connection to another port/step in the pipeline. In other words: you cannot use the pipe attribute or a child <p:pipe> element.

  • The name of the primary output port, as declared by the <p:output> element of p:run, must be the same as the name of the primary output port of the dynamically executed step. If not, error XC0207 is raised.

  • If the dynamically executed pipeline has output ports that are not declared in <p:output> elements of p:run, their outputs will be silently discarded.

  • If the p:run step declares additional output ports that are not present in the dynamically executed pipeline, their outputs will be empty (<p:empty/>).

Examples

Basic usage

Suppose we have some kind of XML content in which we want to dynamically generate other content using XProc pipelines. For example:

<body>
  <p>Let's do some additions:</p>
  <ul>
    <li>
      <generate href-pipeline="add-them.xpl" a="1" b="1"/>
    </li>
    <li>
      <generate href-pipeline="add-them.xpl" a="7" b="3"/>
    </li>
  </ul>
</body>

The <generate> elements invokes another pipeline (named in its href-pipeline attribute) using p:run:

  • The input to these generator pipelines, on their primary source port, is the <generate> element itself (so it can access any attributes/child elements).

  • The output of these generator pipelines, on their primary result port, is inserted back into the original document, replacing the <generate> element.

For this example, we only use one generator pipeline, called add-them.xpl. This simply adds the attributes a and b and reports about this:

<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="3.0" exclude-inline-prefixes="#all">

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

  <p:variable name="a" as="xs:integer" select="xs:integer(/*/@a)"/>
  <p:variable name="b" as="xs:integer" select="xs:integer(/*/@b)"/>
  
  <p:identity>
    <p:with-input>
      <p>Adding {$a} to {$b} results in {$a + $b}!</p>
    </p:with-input>
  </p:identity>

</p:declare-step>

The main pipeline and its output are as follows:

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

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

  <p:viewport match="generate">
    <p:run>
      <p:with-input href="{/*/@href-pipeline}"/>
      <p:run-input port="source"/>
      <p:output port="result"/>
    </p:run>
  </p:viewport>

</p:declare-step>

Result document:

<body>
   <p>Let's do some additions:</p>
   <ul>
      <li>
         <p>Adding 1 to 1 results in 2!</p>
      </li>
      <li>
         <p>Adding 7 to 3 results in 10!</p>
      </li>
   </ul>
</body>

Using options

Building on the Basic usage example, we’re going to add and use an option that specifies the language of the generator output. For now this will only accept nl for Dutch. Any other language will default to English.

The extended version of the generator pipeline, called add-them-extended.xpl, looks like this:

<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="3.0" exclude-inline-prefixes="#all">

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

  <p:option name="language" as="xs:string" required="true"/>

  <p:variable name="a" as="xs:integer" select="xs:integer(/*/@a)"/>
  <p:variable name="b" as="xs:integer" select="xs:integer(/*/@b)"/>

  <p:choose>
    <p:when test="$language eq 'nl'"> 
      <p:identity>
        <p:with-input>
          <p>Als we {$a} optellen bij {$b} krijgen we {$a + $b}!</p>
        </p:with-input>
      </p:identity>
    </p:when>
    <p:otherwise>
      <!-- Default language is English: -->
      <p:identity>
        <p:with-input>
          <p>Adding {$a} to {$b} results in {$a + $b}!</p>
        </p:with-input>
      </p:identity>
    </p:otherwise>
  </p:choose>

</p:declare-step>

Let’s generate a Dutch version of our output:

Source document:

<body>
   <p>Laten we optellen:</p>
   <ul>
      <li>
         <generate href-pipeline="add-them-extended.xpl" a="1" b="1"/>
      </li>
      <li>
         <generate href-pipeline="add-them-extended.xpl" a="7" b="3"/>
      </li>
   </ul>
</body>

Pipeline document:

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

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

  <p:viewport match="generate">
    <p:run>
      <p:with-input href="{/*/@href-pipeline}"/>
      <p:run-input port="source"/>
      <p:run-option name="language" select="'nl'"/>
      <p:output port="result"/>
    </p:run>
  </p:viewport>

</p:declare-step>

Result document:

<body>
   <p>Laten we optellen:</p>
   <ul>
      <li>
         <p>Als we 1 optellen bij 1 krijgen we 2!</p>
      </li>
      <li>
         <p>Als we 7 optellen bij 3 krijgen we 10!</p>
      </li>
   </ul>
</body>

Additional details

  • What happens with any document-properties depends entirely on how the dynamically executed pipeline handles these.

Errors raised

Error code

Description

XC0200

It is a dynamic error if the pipeline input to the p:run step is not a valid pipeline.

XC0206

It is a dynamic error if the dynamically executed pipeline implicitly or explicitly declares a primary input port with a different name than implicitly or explicitly specified in the p:run invocation.

XC0207

It is a dynamic error if the dynamically executed pipeline implicitly or explicitly declares a primary output port with a different name than implicitly or explicitly specified in the p:run invocation.

Reference information

This description of the p:run step is for XProc version: 3.0. This is a non-required step (an XProc 3.0 processor does not have to support this).

The formal specification for the p:run step can be found here.

The p:run step is part of category: XProc dynamic pipeline execution steps.

The p:run step is also present in version: 3.1.