W3C

XProc: An XML Pipeline Language

W3C Working Draft 20 September 2007

This Version:
http://www.w3.org/TR/2007/WD-xproc-20070920/
Latest Version:
http://www.w3.org/TR/xproc/
Previous versions:
http://www.w3.org/TR/2007/WD-xproc-20070706/ http://www.w3.org/TR/2007/WD-xproc-20070405/ http://www.w3.org/TR/2006/WD-xproc-20061117/
Editors:
Norman Walsh, Sun Microsystems, Inc.
Alex Milowski, Invited expert
Henry S. Thompson, University of Edinburgh

This document is also available in these non-normative formats: XML


Abstract

This specification describes the syntax and semantics of XProc: An XML Pipeline Language, a language for describing operations to be performed on XML documents.

An XML Pipeline specifies a sequence of operations to be performed on one or more XML documents. Pipelines generally accept one or more XML documents as input and produce one or more XML documents as output. Pipelines are made up of simple steps which perform atomic operations on XML documents and constructs similar to conditionals, loops and exception handlers which control which steps are executed.

Status of this Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document was produced by the XML Processing Model Working Group which is part of the XML Activity. Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This is a Last Call Working Draft. The Working Group considers this specification complete and finished. The review period for this document ends on 24 October 2007. The scope of editorial changes since the last working draft has overwhelmed the utility of a draft with revision markup. Significant changes since the last working draft include:

Please send comments about this document to public-xml-processing-model-comments@w3.org (public archives are available).

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.


Table of Contents

Introduction
Pipeline Concepts
2.1 Steps
2.1.1 Step names
2.2 Inputs and Outputs
2.2.1 External Documents
2.3 Primary Inputs and Outputs
2.4 Options
2.5 Parameters
2.6 Connections
2.6.1 Namespace Fixup on Outputs
2.7 Environment
2.8 XPath Context
2.8.1 Processor XPath Context
2.8.2 Step XPath Context
2.8.3 XProc Extension Functions
Syntax Overview
3.1 XProc Namespaces
3.2 Scoping of Names
3.3 Global Attributes
3.4 Associating Documents with Ports
3.5 Documentation
3.6 Ignored namespaces
3.7 Extension attributes
3.8 Extension elements
3.9 Syntax Summaries
Steps
4.1 p:pipeline
4.2 p:for-each
4.2.1 XPath Context
4.3 p:viewport
4.3.1 XPath Context
4.4 p:choose
4.4.1 p:xpath-context
4.4.2 p:when
4.4.3 p:otherwise
4.5 p:group
4.6 p:try/p:catch
4.6.1 The Error Vocabulary
4.7 Other Steps
4.7.1 Syntactic Shortcut for Option Values
Other pipeline elements
5.1 p:input
5.1.1 Document Inputs
5.1.2 Parameter Inputs
5.2 p:iteration-source
5.3 p:viewport-source
5.4 p:output
5.5 p:log
5.6 p:serialization
5.7 Options and Parameters
5.7.1 p:option
5.7.2 p:parameter
5.7.3 Option and Parameter Namespaces
5.8 p:declare-step
5.9 p:pipeline-library
5.10 p:import
5.11 p:pipe
5.12 p:inline
5.13 p:document
5.14 p:empty
5.15 p:documentation
Errors
6.1 Static Errors
6.2 Dynamic Errors
6.3 Step Errors
Standard Step Library
7.1 Required Steps
7.1.1 Add Attribute
7.1.2 Add xml:base
7.1.3 Compare
7.1.4 Count
7.1.5 Delete
7.1.6 Directory List
7.1.7 Error
7.1.8 Escape Markup
7.1.9 HTTP Request
7.1.10 Identity
7.1.11 Insert
7.1.12 Label Elements
7.1.13 Load
7.1.14 Make Absolute IRIs
7.1.15 Namespace Rename
7.1.16 Pack
7.1.17 Parameters
7.1.18 Rename
7.1.19 Replace
7.1.20 Set Attributes
7.1.21 Sink
7.1.22 Split Sequence
7.1.23 String Replace
7.1.24 Store
7.1.25 Unescape Markup
7.1.26 Unwrap
7.1.27 Wrap
7.1.28 Wrap Sequence
7.1.29 XInclude
7.1.30 XSLT
7.2 Optional Steps
7.2.1 Relax NG Validate
7.2.2 Schematron Validate
7.2.3 XML Schema Validate
7.2.4 XQuery 1.0
7.2.5 XSLT 2.0
7.2.6 XSL Formatter
7.3 Serialization Options

Appendices

1 Introduction

An XML Pipeline specifies a sequence of operations to be performed on a collection of XML input documents. Pipelines take zero or more XML documents as their input and produce zero or more XML documents as their output.

A pipeline consists of steps. Like pipelines, steps take zero or more XML documents as their inputs and produce zero or more XML documents as their outputs. The inputs to a step come from the web, from the pipeline document, from the inputs to the pipeline itself, or from the outputs of other steps in the pipeline. The outputs from a step are consumed by other steps, are outputs of the pipeline as a whole, or are discarded.

There are two kinds of steps: atomic steps and compound steps. Atomic steps carry out single operations and have no substructure as far as the pipeline is concerned, whereas compound steps control the execution of other steps, which they include in the form of one or more subpipelines.

This specification defines a standard library, Section 7, “Standard Step Library”, of steps. Pipeline implementations may support additional types of steps as well.

Figure 1, “A simple, linear XInclude/Validate pipeline” is a graphical representation of a simple pipeline that performs XInclude processing and validation on a document.

A simple, linear XInclude/Validate pipeline
Figure 1. A simple, linear XInclude/Validate pipeline

This is a pipeline that consists of two atomic steps, XInclude and Validate. The pipeline itself has two inputs, “source” (a source document) and “schemas” (a list of W3C XML Schemas). How inputs are connected to XML documents outside the pipeline is implementation-defined. The XInclude step reads the pipeline input “source” and produces a result document. The Validate step reads the pipeline input “schemas” and the output from the XInclude step and produces a result document. The result of the validation, “result”, is the result of the pipeline. How pipeline outputs are connected to XML documents outside the pipeline is implementation-defined.

The pipeline document for this pipeline is shown in Example 1, “A simple, linear XInclude/Validate pipeline”.

Example 1. A simple, linear XInclude/Validate pipeline
<p:pipeline name="pipeline" xmlns:p="http://www.w3.org/ns/xproc">
  <p:input port="source" primary="true"/>
  <p:input port="schemas" sequence="true"/>
  <p:output port="result">
    <p:pipe step="validated" port="result"/>
  </p:output>

  <p:xinclude name="included">
    <p:input port="source">
      <p:pipe step="pipeline" port="source"/>
    </p:input>
  </p:xinclude>

  <p:validate-xml-schema name="validated">
    <p:input port="source">
      <p:pipe step="included" port="result"/>
    </p:input>
    <p:input port="schema">
      <p:pipe step="pipeline" port="schemas"/>
    </p:input>
  </p:validate-xml-schema>
</p:pipeline>

The example in Example 1, “A simple, linear XInclude/Validate pipeline” is very verbose. It makes all of the connections seen in the figure explicit. In practice, pipelines do not have to be this verbose. XProc supports defaults for many common cases. The same pipeline, using XProc defaults, is shown in Example 2, “A simple, linear XInclude/Validate pipeline (simplified)”.

Example 2. A simple, linear XInclude/Validate pipeline (simplified)
<p:pipeline name="pipeline" xmlns:p="http://www.w3.org/ns/xproc">
  <p:input port="source" primary="true"/>
  <p:input port="schemas" sequence="true"/>

  <p:xinclude/>

  <p:validate-xml-schema>
    <p:input port="schema">
      <p:pipe step="pipeline" port="schemas"/>
    </p:input>
  </p:validate-xml-schema>
</p:pipeline>

Figure 2, “A validate and transform pipeline” is a more complex example: it performs schema validation with an appropriate schema and then styles the validated document.

A validate and transform pipeline
Figure 2. A validate and transform pipeline

The heart of this example is the conditional. The “choose” step evaluates an XPath expression over a test document. Based on the result of that expression, one or another branch is run. In this example, each branch consists of a single validate step.

Example 3. A validate and transform pipeline
<p:pipeline xmlns:p="http://www.w3.org/ns/xproc">
  <p:input port="source"/>

  <p:choose>
    <p:when test="/*[@version &lt; 2.0]">
      <p:validate-xml-schema name="val1">
        <p:input port="schema">
          <p:document href="v1schema.xsd"/>
        </p:input>
      </p:validate-xml-schema>
    </p:when>

    <p:otherwise>
      <p:validate-xml-schema name="val2">
        <p:input port="schema">
          <p:document href="v2schema.xsd"/>
        </p:input>
      </p:validate-xml-schema>
    </p:otherwise>
  </p:choose>

  <p:xslt name="xform">
    <p:input port="stylesheet">
      <p:document href="stylesheet.xsl"/>
    </p:input>
  </p:xslt>
</p:pipeline>

This example, like the preceding, relies on XProc defaults for simplicity. It is always valid to write the fully explicit form if you prefer.

2 Pipeline Concepts

[Definition: A pipeline is a set of connected steps, outputs flowing into inputs, without any loops (no step can read its own output, directly or indirectly).] A pipeline is itself a step and must satisfy the constraints on steps.

The result of evaluating a pipeline is the result of evaluating the steps that it contains, in the order determined by the connections between them. A pipeline must behave as if it evaluated each step each time it occurs. Unless otherwise indicated, implementations must not assume that steps are functional (that is, that their outputs depend only on their explicit inputs, options, and parameters) or side-effect free.

2.1 Steps

[Definition: A step is the basic computational unit of a pipeline.] All steps have a name; if the pipeline author does not provide a name for a step, a default name is manufactured automatically.

Steps are either atomic or compound. [Definition: An atomic step is a step that performs a unit of XML processing, such as XInclude or transformation, and has no internal subpipeline.] Atomic steps carry out fundamental XML operations and can perform arbitrary amounts of computation, but they are indivisible. An XSLT step, for example, performs XSLT processing; an XML Schema Validation step validates one input with respect to some set of XML Schemas, etc.

There are many types of atomic steps. The standard library of atomic steps is described in Section 7, “Standard Step Library”, but implementations may provide others as well. What additional step types, if any, are provided is implementation-defined. Each use, or instance, of an atomic step invokes the processing defined by that type of step. A pipeline may contain instances of many types of steps and many instances of the same type of step.

Compound steps, on the other hand, control and organize the flow of documents through a pipeline, reconstructing familiar programming language functionality such as conditionals, iterators and exception handling. They contain other steps, whose evaluation they control.

[Definition: A compound step is a step that contains one or more subpipelines. That is, a compound step differs from an atomic step in that its semantics are at least partially determined by the steps that it contains.] Every compound step contains one or more subpipelines. [Definition: The steps that occur directly inside a compound step are called contained steps.] [Definition: A compound step which immediately contains another step is called its container.]

This simple distinction between atomic and compound steps is occasionally stretched. The immediate children of some compound steps, e.g. p:choose and p:try, are special. In the case of p:choose, the p:when and p:otherwise elements serve as wrappers around different pipelines at most one of which will be processed. In the case of p:try, the p:catch element is a wrapper around a subpipeline that will only be processed if the initial p:group fails. Acknowledging this slight irregularity, we nevertheless treat all compound steps as if they directly contained one or more subpipelines.

[Definition: The steps (and the connections between them) within a compound step form a subpipeline.] [Definition: The last step in a subpipeline is the last step in document order within its container. ]

subpipeline = (p:for-each|p:viewport|p:choose|p:group|p:try|pfx:other-step|p:documentation|ipfx:ignored)*

A compound step can contain one or more subpipelines and it determines how and which of its subpipelines are evaluated.

Note

A p:pipeline, because it defines a subpipeline that can be called from other pipelines, has a somewhat dual nature with respect to the atomic vs. compound distinction. A p:pipeline is a compound step. When it is invoked by name from some other pipeline, its invocation is an atomic step. The “type” of the atomic step is determined by the p:pipeline that defines it.

Steps have “ports” into which inputs and outputs are connected or “bound”. Each step has a number of input ports and a number of output ports; a step can have zero input ports and/or zero output ports. (All steps have an implicit output port for reporting errors that must not be declared.) The names of all ports on each step must be unique on that step (you can't have two input ports named “source”, nor can you have an input port named “schema” and an output port named “schema”).

Steps have any number of options, all with unique names. A step can have zero options.

Steps have parameter input ports, on which parameters can be passed. The parameters passed on a particular parameter input port must be uniquely named. If multiple parameters with the same name are used, only one of the values will actually be available to the step. A step can have zero parameter input ports, and each parameter port can have zero parameters passed on it.

2.1.1 Step names

The name attribute on any step can be used to give it a name. The name must be unique within its scope, see Section 3.2, “Scoping of Names”.

If the pipeline author does not provide an explicit name, the processor manufactures a default name. All default names are of the form “!n” where “n” is the ordinal number of the step, considering all steps in document order. For example, consider the pipeline in Example 3, “A validate and transform pipeline”. The p:pipeline step has no name, so it gets the default name “!1”; the p:choose gets the name “!2”; the first p:when gets the name “!3”, etc. If the p:choose had had a name, it would not have received a default name, but it would still have been counted and its first p:when would still have been “!3”.

Providing every step in the pipeline with an interoperable name has several benefits:

  1. It provides a simple mechanism for identifying all steps from outside the pipeline, see Appendix C, The XProc Media Type.

  2. It allows implementors to refer to all steps in an interoperable fashion, for example, in error messages.

  3. Pragmatically, we say that readable ports are identified by a step name/port name pair. By manufacturing names for otherwise anonymous steps, we include implicit bindings without changing our model.

In a valid pipeline that runs successfully to completion, the manufactured names aren't visible (except perhaps in debugging or logging output).

Note

The format for defaulted names does not conform to the requirements of an NCName. This is an explicit design decision; it prevents pipelines from using the defaulted names on p:pipe elements. If an explicit connection is required, the pipeline author must provide an explicit name for the step.

2.2 Inputs and Outputs

Although some steps can read and write non-XML resources, what flows between steps through input ports and output ports are exclusively XML documents or sequences of XML documents.

An implementation may make it possible for a step to produce non-XML output (through channels other than a named output port)—for example, writing a PDF document to a URI—but that output cannot flow through the pipeline. Similarly, one can imagine a step that takes no pipeline inputs, reads a non-XML file from a URI, and produces an XML output. But the non-XML data cannot arrive on an input port to a step.

It is a dynamic error (err:XD0001) if a non-XML resource is produced on a step output or arrives on a step input.

The common case is that each step has one or more inputs and one or more outputs. Figure 3, “An atomic step” illustrates symbolically an atomic step with two inputs and one output.

An atomic step with two inputs and one output
Figure 3. An atomic step

All atomic steps are defined by a p:declare-step. The declaration of an atomic step defines the input ports, output ports, and options of all steps of that type. For example, every p:xslt step has two inputs, named “source” and “stylesheet”, and one output named “result” and the same set of options.

The situation is slightly more complicated for compound steps because they don't have separate declarations; each instance of a compound step serves as its own declaration. Compound steps don't have declared inputs, but they do have declared outputs, and unlike atomic steps, on compound steps, the number and names of the outputs can be different on each instance of the step.

Figure 4, “A compound step” illustrates symbolically a compound step with one output. As you can see from the diagram, the output from the compound step comes from one of the outputs of the subpipeline within the step.

A compound step with two inputs and one output
Figure 4. A compound step

[Definition: The input ports declared on a step are its declared inputs.] [Definition: The output ports declared on a step are its declared outputs.] When a step is used in a pipeline, it is connected to other steps through its inputs and outputs.

When a step is used, all of the declared inputs of the step must be connected. Each input can be connected to:

  • The output port of some other step.

  • A fixed, inline document or sequence of documents.

  • A document read from a URI.

  • One of the inputs declared on one of its ancestors.

  • A special port provided by an ancestor compound step, for example, “current” in a p:for-each or p:viewport.

When an input accepts a sequence of documents, the documents can come from any combination of these locations.

The declared outputs of a step may be connected to:

  • The input port of some other step.

  • One of the outputs declared on its container.

The primary output port of a step must be connected, but other outputs can remain unconnected. Any documents produced on an unconnected output port are discarded.

Output ports on compound steps have a dual nature: from the perspective of the compound step's siblings, its outputs are just ordinary outputs and must be connected as described above. From the perspective of the compound step itself, they are inputs into which something must be connected.

Within a compound step, the declared outputs of the step can be connected to:

  • The output port of some contained step.

  • A fixed, inline document or sequence of documents.

  • A document read from a URI.

Each input and output is declared to accept or produce either a single document or a sequence of documents. It is not an error to connect a port that is declared to produce a sequence of documents to a port that is declared to accept only a single document. It is, however, an error if the former step actually produces more than one document at run time.

[Definition: The signature of a step is the set of inputs, outputs, and options that it is declared to accept.] Each atomic step (e.g. XSLT or XInclude) has a fixed signature, declared globally or built-in, which all its instances share, whereas each compound step has its own implicit signature.

[Definition: A step matches its signature if and only if it specifies an input for each declared input, it specifies no inputs that are not declared, it specifies an option for each option that is declared to be required, and it specifies no options that are not declared.] In other words, every input and required option must be specified and only inputs and options that are declared may be specified. Options that aren't required do not have to be specified.

Steps may also produce error, warning, and informative messages. These messages appear on a special “error output” port. The error output port is only bound to an input in the catch clause of a try/catch. Outside of a try/catch, the disposition of error messages is implementation-dependent.

2.2.1 External Documents

It's common for some of the documents used in processing a pipeline to be read from URIs. Sometimes this occurs directly, for example with a p:document element. Sometimes it occurs indirectly, for example if an implementation allows the URI of a pipeline input to be specified on the command line or if an p:xslt step encounters an xsl:import in the stylesheet that it is processing. It's also common for some of the documents produced in processing a pipeline to be written to locations which have, or at least could have, a URI.

The process of dereferencing a URI to retrieve a document is often more interesting than it seems at first. On the web, it may involve caches, proxies, and various forms of indirection. Resolving a URI locally may involve resolvers of various sorts and possibly appeal to implementation-dependent mechanisms such as catalog files.

In XProc, the situation is made even more interesting by the fact that many intermediate results produced by steps in the pipeline have base URIs.Whether or not (and when and how) the intermediate results that pass between steps are ever written to a filesystem is implementation-dependent.

In Version 1.0 of XProc, how (or if) implementers provide local resolution mechanisms and how (or if) they provide access to intermediate results by URI is implementation-defined.

Note

On the one hand, this is a somewhat unsatisfying state of affairs because it leaves room for interoperability problems. On the other, it is not expected to cause such problems very often in practice.

If these problems arise in practice, implementers are encouraged to use the existing extension mechanisms to give users the control needed to circumvent them. Should such mechanisms become widespread, a standard mechanism could be added in some future version of the language.

2.3 Primary Inputs and Outputs

As a convenience for pipeline authors, each step may have one input port designated as the primary input port and one output port designated as the primary output port.

[Definition: If a step has a document input port which is explicitly marked “primary='true'”, or if it has exactly one document input port and that port is not explicitly marked “primary='false'”, then that input port is the primary input port of the step.] If a step has a single input port and that port is explicitly marked “primary='false'”, or if a step has more than one input port and none is explicitly marked as the primary, then the primary input port of that step is undefined.

[Definition: If a step has a document output port which is explicitly marked “primary='true'”, or if it has exactly one document output port and that port is not explicitly marked “primary='false'”, then that output port is the primary output port of the step.] If a step has a single output port and that port is explicitly marked “primary='false'”, or if a step has more than one output port and none is explicitly marked as the primary, then the primary output port of that step is undefined.

The special significance of primary input and output ports is that they are connected automatically by the processor if no explicit binding is given. Generally speaking, if two steps appear sequentially in a subpipeline, then the primary output of the first step will automatically be connected to the primary input of the second.

Additionally, if a p:pipeline has no declared inputs and the first step in its subpipeline has an unbound primary input, then an implicit primary input port (named “source”) will be added to the p:pipeline (and consequently bound to the first step's primary input port). If a compound step has no declared outputs and the last step in its subpipeline has an unbound primary output, then an implicit primary output port (named “result”) will be added to the compound step (and consequently the last step's primary output will be bound to it).

The practical consequence of these rules is that straightforward, linear pipelines are much simpler to read, write, and understand. The following pipeline has a single input which is transformed by the XSLT step; the result of that XSLT step is the result of the pipeline:

<p:pipeline xmlns:p="http://www.w3.org/ns/xproc">
<p:xslt>
  <p:input port="stylesheet">
    <p:document href="docbook.xsl"/>
  </p:input>
</p:xslt>
</p:pipeline>

It is semantically equivalent to this pipeline:

<p:pipeline name="main" xmlns:p="http://www.w3.org/ns/xproc">
<p:input port="source"/>
<p:input port="parameters" kind="parameter"/>
<p:output port="result">
  <p:pipe step="transform" port="result"/>
</p:output>

<p:xslt name="transform">
  <p:input port="source">
    <p:pipe step="main" port="source"/>
  </p:input>
  <p:input port="stylesheet">
    <p:document href="docbook.xsl"/>
  </p:input>
  <p:input port="parameters">
    <p:pipe step="main" port="parameters"/>
  </p:input>
</p:xslt>

</p:pipeline>

(Parameter input ports are a special case discussed in Section 2.5, “Parameters”.)

2.4 Options

Some steps accept options. Options are name/value pairs.

[Definition: An option is a name/value pair where the name is an expanded name and the value must be a string.] If a document, node, or other value is given, its [XPath 1.0] string value is computed and that string is used.

[Definition: The options declared on a step are its declared options.] All of the options specified on an atomic step must have been declared. Option names are always expressed as literal values, pipelines cannot construct option names dynamically.

[Definition: The options on a step which have specified values, either because a p:option element specifies a value or because the declaration included a default value, are its specified options.]

2.5 Parameters

Some steps accept parameters. Parameters are name/value pairs.

[Definition: A parameter is a name/value pair where the name is an expanded name and the value must be a string.] If a document, node, or other value is given, its [XPath 1.0] string value is computed and that string is used.

Unlike options, which have names known in advance to the pipeline, parameters are not declared and their names may be unknown to the pipeline author. Pipelines can dynamically construct sets of parameters. Steps can read dynamically constructed sets on parameter input ports.

[Definition: A parameter input port is a distinguished kind of input port which accepts (only) dynamically constructed parameter name/value pairs.] See Section 5.1.2, “Parameter Inputs”.

Analogous to primary input ports, steps that have parameter inputs may designate at most one parameter input port as a primary parameter input port.

[Definition: If a step has a parameter input port which is explicitly marked “primary='true'”, or if it has exactly one parameter input port and that port is not explicitly marked “primary='false'”, then that parameter input port is the primary parameter input port of the step.] If a step has a single parameter input port and that port is explicitly marked “primary='false'”, or if a step has more than one parameter input port and none is explicitly marked as the primary, then the primary parameter input port of that step is undefined.

Additionally, if a p:pipeline does not declare any parameter input ports, but contains a step which has a primary parameter input port, then an implicit primary parameter input port (named “parameters”) will be added to the pipeline. (If the pipeline declares an ordinary input named “parameters”, the implicit primary parameter input port will be named “parameters1”. If that's not available, then “parameters2”, etc. until an available name is found.)

How an implementation maps parameters specified to the application, or through some API, to parameters accepted by the p:pipeline is implementation-defined.

2.6 Connections

Steps are connected together by their input ports and output ports. It is a static error (err:XS0001) if there are any loops in the connections between steps: no step can be connected to itself nor can there be any sequence of connections through other steps that leads back to itself.

2.6.1 Namespace Fixup on Outputs

What flows between steps are exclusively XML documents. The inputs and outputs can be implemented as sequences of characters, sequences of events, object models, or any other representation that the implementation chooses.

Most steps in this specification manipulate XML documents, or portions of XML documents. In these cases, we speak of changing elements, attributes, or nodes without prejudice to the actual representation used by an implementation. Unless the semantics of a step explicitly says otherwise:

  • The in-scope namespaces associated with a node (even those that are inherited from namespace bindings that appear among its ancestors in the document in which it appears initially) are assumed to travel with it.

  • Changes to one part of a tree (wrapping or unwrapping a node or renaming an element, for example) do not change the in-scope namespaces associated with the descendants of the node so changed.

As a result, some steps can produce XML documents which have no direct serialization (because they include nodes with conflicting or missing namespace declarations, for example). [Definition: To produce a serializable XML document, the XProc processor must sometimes add additional namespace nodes, perhaps even renaming prefixes, to satisfy the constraints of Namespaces in XML. This process is referred to as namespace fixup.]

Implementors are encouraged to perform namespace fixup before passing documents between steps, but they are not required to do so. Conversely, an implementation which does serialize between steps and therefore must perform such fixups, or reject documents that cannot be serialized, is also conformant.

Except where the semantics of a step explicitly require changes, processors are required to preserve the information in the documents and fragments they manipulate. In particular, the information corresponding to the [Infoset] properties [attributes], [base URI], [children], [local name], [namespace name], [normalized value], [owner], and [parent] must be preserved.

The information corresponding to [prefix], [in-scope namespaces], [namespace attributes], and [attribute type] should be preserved, with changes to the first three only as required for namespace fixup. In particular, processors are encouraged to take account of prefix information in creating new namespace bindings, to minimize negative impact on prefixed names in content.

Except for cases which are specifically called out in Section 7, “Standard Step Library”, the extent to which namespace fixup, and other checks for outputs which cannot be serialized, are performed on intermediate outputs is implementation-defined.

Whenever an implementation serializes pipeline contents, for example for pipeline outputs, logging, or as part of steps such as p:store or p:http-request, it is a dynamic error if that serialization could not be done so as to produce a document which is both well-formed and namespace-well-formed, as specified in XML and Namespaces in XML, regardless of what serialization method, if any, is called for.

2.7 Environment

[Definition: The environment of a step is the static information available to each instance of a step in a pipeline.]

The environment consists of:

  1. A set of readable ports. [Definition: The readable ports are the step name/output port name pairs that are visible to the step.] Inputs and outputs can only be connected to readable ports.

  2. A set of in-scope options. [Definition: The in-scope options are the set of options that are visible to a step.] All of the in-scope options are available to the processor for computing option and parameter values. The actual options passed to a step are those that are declared for a step of its type and that have values either provided explicitly with p:option elements on the step or as defaults in the declaration of the step type.

  3. A default readable port. [Definition: The default readable port, which may be undefined, is a specific step name/port name pair from the set of readable ports.]

[Definition: The empty environment contains no readable ports, no in-scope options, and an undefined default readable port. ]

Unless otherwise specified, the environment of a contained step is its inherited environment. [Definition: The inherited environment of a contained step is an environment that is the same as the environment of its container with the standard modifications. ]

The standard modifications made to an inherited environment are:

  • All of the specified options of the container are added to the in-scope options. The value of any option in the environment with the same name as one of the options specified on the container is shadowed by the new value.

    In other words, steps can access the most recently specified value of all of the options specified on any ancestor step.

  • The declared inputs of the container are added to the readable ports.

    In other words, contained steps can see the inputs to their container.

  • The union of all the declared outputs of all of the step's contained steps are added to the readable ports.

    In other words, sibling steps can see each other's outputs in addition to the outputs visible to their container.

  • If there is a preceding sibling step element:

  • If there is not a preceding sibling step element, the default readable port is the primary input port of the container, if it has one, otherwise the default readable port is unchanged.

A step with no parent inherits the empty environment.

2.8 XPath Context

XProc uses [XPath 1.0] as an expression language. XPath expressions can occur in several places: on compound steps, in the expressions used to compute option and parameter values, and in values passed to atomic steps.

Broadly, these can be divided into two classes: expressions evaluated by the XProc processor and expressions evaluated by the implementations of individual steps.

This distinction can be seen in the following example:

<p:option name="home" value="http://example.com/docs"/>

<p:load name="read-from-home">
  <p:option name="href" select="concat($home,'/document.xml')"/>
</p:load>

<p:split-sequence name="select-chapters">
  <p:input port="source" select="//section"/>
  <p:option name="test" value="@role='chapter'"/>
</p:split-sequence>

The href option of the p:load step step is evaluated by the XProc processor. The actual href option received by the step is simply the string literal “http://example.com/docs/document.xml”. (The selection on the source input of the select-chapters step is also evaluated by the XProc processor.)

Conversely, the XPath expression “@role='chapter'” is passed literally to the test option on the p:split-sequence step. That's because the nature of the p:split-sequence is that it evaluates the expression. Only some options on some steps expect XPath expressions.

The XProc processor evaluates all of the XPath expressions in select attributes on steps, options, parameters, and inputs and in test attributes on p:when steps. (XPath expressions in value attributes are passed literally to the step for evaluation.)

2.8.1 Processor XPath Context

When the XProc processor evaluates an XPath expression, unless otherwise indicated by a particular step, it does so with the following context:

context node

The document node of a document. The document is either specified with a binding or is taken from the default readable port. It is a dynamic error (err:XD0008) if a document sequence appears where a document to be used as the context node is expected.

If there is no binding and there is no default readable port then the context node is an empty document node.

context position and context size

The context position and context size are both “1”.

variable bindings

The in-scope options are available as variables.

function library

The [XPath 1.0] core function library and the XProc extension functions.

in-scope namespaces

The namespace bindings in-scope on the element where the expression occurred.

2.8.2 Step XPath Context

When a step evaluates an XPath expression, it does so with the following context:

context node

The document node that appears on the primary input port of the step, unless otherwise specified by the step.

context position and context size

The position and size are both “1”, unless otherwise specified by the step.

variable bindings

None, unless otherwise specified by the step.

function library

The [XPath 1.0] core function library, unless otherwise specified by the step.

in-scope namespaces

The set of namespace bindings provided by the XProc processor. The processor computes this set of bindings by taking a union of the bindings on the step element itself as well as the bindings on any of the options and parameters used in computing values for the step (see Section 5.7.3, “Option and Parameter Namespaces”).

The results of computing the union of namespaces in the presence of conflicting declarations for a particular prefix are implementation-dependent.

2.8.3 XProc Extension Functions

The XProc processor must support a few additional functions in XPath expressions evaluated by the processor.

2.8.3.1 System Properties

XPath expressions within a pipeline document can interrogate the processor for information about the current state of the pipeline. Various aspects of the processor are exposed through the p:system-property function in the pipeline namespace:

Function: String p:system-property(String property)

The property string must have the form of a QName; the QName is expanded into a name using the namespace declarations in scope for the expression. The p:system-property function returns the string representing the value of the system property identified by the QName. If there is no such property, the empty string must be returned.

Implementations must provide the following system properties, which are all in the XProc namespace:

p:episode

Returns a string which should be unique for each invocation of the pipeline processor.

The unique identifier must consist of ASCII alphanumeric characters and must start with an alphabetic character. Thus, the string is syntactically an XML name.

p:product-name

Returns a string containing the name of the implementation, as defined by the implementer. This should normally remain constant from one release of the product to the next. It should also be constant across platforms in cases where the same source code is used to produce compatible products for multiple execution platforms.

p:product-version

Returns a string identifying the version of the implementation, as defined by the implementer. This should normally vary from one release of the product to the next, and at the discretion of the implementer it may also vary across different execution platforms.

p:vendor

Returns a string which identifies the vendor of the processor.

p:vendor-uri

Returns a URI which identifies the vendor of the processor. Often, this is the URI of the vendor's web site.

p:version

Returns the version of XProc implemented by the processor; for processors implementing the version of XProc specified by this document, the value is “1.0”. The value of the version attribute is a token (i.e., an xs:token per [W3C XML Schema: Part 2]).

2.8.3.2 Step Available

The p:step-available function reports whether or not a particular type of step is understood by the processor.

Function: Boolean p:step-available(String step-type)

The step-type string must have the form of a QName; the QName is expanded into a name using the namespace declarations in scope for the expression. The p:step-available function returns true if and only if the processor knows how to evaluate steps of the specified type.

2.8.3.3 Iteration Position

In the context of a p:for-each or a p:viewport, the p:iteration-position function reports the position of the document being processed in the sequence of documents that will be processed. In the context of other standard XProc compound steps, it returns 1.

Function: Integer p:iteration-position()

In the context of an extension compound step, the value returned by p:iteration-position is implementation-defined.

2.8.3.4 Iteration Size

In the context of a p:for-each or a p:viewport, the p:iteration-size function reports the number of documents in the sequence of documents that will be processed. In the context of other standard XProc compound steps, it returns 1.

Function: Integer p:iteration-size()

In the context of an extension compound step, the value returned by p:iteration-size is implementation-defined.

3 Syntax Overview

This section describes the normative XML syntax of XProc. This syntax is sufficient to represent all the aspects of a pipeline, as set out in the preceding sections. [Definition: XProc is intended to work equally well with [XML 1.0] and [XML 1.1]. Unless otherwise noted, the term “XML” refers equally to both versions.] [Definition: Unless otherwise noted, the term Namespaces in XML refers equally to [Namespaces 1.0] and [Namespaces 1.1].] Support for pipeline documents written in XML 1.1 and pipeline inputs and outputs that use XML 1.1 is implementation-defined.

Elements in a pipeline document represent the pipeline, the steps it contains, the connections between those steps, the steps and connections contained within them, and so on. Each step is represented by an element; a combination of elements and attributes specify how the inputs and outputs of each step are connected and how options and parameters are passed.

Conceptually, we can speak of steps as objects that have inputs and outputs, that are connected together and which may contain additional steps. Syntactically, we need a mechanism for specifying these relationships.

Containment is represented naturally using nesting of XML elements. If a particular element identifies a compound step then the step elements that are its immediate children form its subpipeline.

The connections between steps are expressed using names and references to those names.

Six kinds of things are named in XProc:

  1. Step types,
  2. Steps,
  3. Input ports,
  4. Output ports,
  5. Options, and
  6. Parameters

3.1 XProc Namespaces

The XML syntax for XProc uses three namespaces:

http://www.w3.org/ns/xproc

The namespace of the XProc XML vocabulary described by this specification; by convention, the namespace prefix “p:” is used for this namespace.

http://www.w3.org/ns/xproc-step

The namespace used for documents that are inputs to and outputs from several standard and optional steps described in this specification. Some steps, such as p:http-request and p:store, have defined input or output vocabularies. We use this namespace for all of those documents. The conventional prefix “c:” is used for this namespace.

http://www.w3.org/ns/xproc-error

The namespace used for errors. The conventional prefix “err:” is used for this namespace.

3.2 Scoping of Names

The scope of the names of the step types is the union of all the pipelines and pipeline libraries available directly or via p:import.

Step types are:

All the step types in a pipeline must have unique names: it is a static error (err:XS0036) if any step type name is built-in and/or declared or defined more than once in the same scope.

The scope of the names of the steps themselves is determined by the environment of each step. In general, the name of a step, the names of its sibling steps, the names of any steps that it contains directly, the names of its ancestors, and the names of its ancestor's siblings are all in the same scope. All the named steps in the same scope must have unique names: it is a static error (err:XS0002) if two steps with the same name appear in the same scope.

The scope of an input or output port name is the step on which it is defined. The names of all the ports on any step must be unique.

Taken together, these uniqueness constraints guarantee that the combination of a step name and a port name uniquely identifies exactly one port on exactly one in-scope step.

The scope of option names is the step on which they occur and the descendants of that step. The names of all of the options specified on a step must be unique. If a step specifies a value for an option with the same name as some option specified on one of its ancestors, the new value shadows the previous value on the current step and its descendants.

Parameter names are not scoped; they are distinct on each step.

3.3 Global Attributes

The following attributes may appear on any element in a pipeline:

  • The attribute xml:id with the semantics outlined in [xml:id].

  • The attribute xml:base with the semantics outlined in [XML Base].

3.4 Associating Documents with Ports

[Definition: A binding associates an input or output port with some data source.] A document or a sequence of documents can be bound to a port in four ways: by source, by URI, by providing an inline document, or by making it explicitly empty. Each of these mechanisms is allowed on the p:input, p:output, p:xpath-context, p:iteration-source, and p:viewport-source elements.

Specified by URI

[Definition: A document is specified by URI if it is referenced with a URI.] The href attribute on the p:document element is used to refer to documents by URI.

In this example, the input to the p:identity step named “otherstep” comes from “http://example.com/input.xml”.

<p:identity name="otherstep">
  <p:input port="source">
    <p:document href="http://example.com/input.xml"/>
  </p:input>
</p:identity>

It is a dynamic error (err:XD0002) if the processor attempts to retrieve the URI specified on a p:document and fails. (For example, if the resource does not exist or is not accessible with the user's authentication credentials.)

Specified by source

[Definition: A document is specified by source if it references a specific port on another step.] The step and port attributes on the p:pipe element are used for this purpose.

In this example, the “document” input to the p:xinclude step named “expand” comes from the “result” port of the step named “otherstep”.

<p:xinclude name="expand">
  <p:input port="source">
    <p:pipe step="otherstep" port="result"/>
  </p:input>
</p:xinclude>

When a p:pipe is used, the specified port must be in the readable ports of the current environment. It is a static error (err:XS0003) if the port specified by a p:pipe is not in the readable ports of the environment.

Specified inline

[Definition: An inline document is specified directly in the body of the element that binds it.] The content of the p:inline element is used for this purpose.

In this example, the “stylesheet” input to the XSLT step named “xform” comes from the content of the p:input element itself.

<p:xslt name="xform">
  <p:input port="stylesheet">
    <p:inline>
      <xsl:stylesheet version="1.0">
        ...
      </xsl:stylesheet>
    </p:inline>
  </p:input>
</p:xslt>

Inline documents are considered “quoted”. The pipeline processor passes them literally to the port, even if they contain elements from the XProc namespace or ignored namespaces that would have other semantics outside of the p:inline.

Specified explicitly empty

[Definition: An empty sequence of documents is specified with the p:empty element.]

In this example, the “source” input to the XSLT 2.0 step named “generate” is explicitly empty:

<p:xslt2 name="generate">
  <p:input port="source">
    <p:empty/>
  </p:input>
  <p:input port="stylesheet">
    <p:inline>
      <xsl:stylesheet version="2.0">
        ...
      </xsl:stylesheet>
    </p:inline>
  </p:input>
  <p:option name="template-name" value="someName"/>
</p:xslt2>

If you omit the binding on a primary input port, a binding to the default readable port will be assumed. Making the binding explicitly empty guarantees that the binding will be to an empty sequence of documents.

It is inconsistent with the [XPath 1.0] specification to specify an empty binding as the context for evaluating an XPath expression. When an empty binding is specified for an XPath expression, an empty document node must be used instead as the context node.

Note that a p:input or p:output element may contain more than one p:pipe, p:document, or p:inline element. If more than one binding is provided, then the specified sequence of documents is made available on that port in the same order as the bindings.

3.5 Documentation

Pipeline authors may add documentation to their pipeline documents with the p:documentation element. Except when it appears as a descendant of p:inline, the p:documentation element is completely ignored by pipeline processors, it exists simply for documentation purposes. (If a p:documentation is provided as a descendant of p:inline, it has no special semantics, it is treated literally as part of the document to be provided on that port.)

Pipeline processors that inspect the contents of p:documentation elements and behave differently on the basis of what they find are not conformant. Processor extensions must be specified with extension elements.

3.6 Ignored namespaces

In order to facilitate extension elements, the processor can be instructed to ignore elements from selected namespaces. [Definition: Any element in an ignored namespace is an ignorable element.]

If a processor encounters an ignorable element as the child of a p:pipeline or p:pipeline-library then it behaves in an implementation-defined manner if it recognizes the element, otherwise it must behave as if the element (and its content) had not been present.

Syntactically, a pipeline author can specify the set of ignored namespaces with the ignore-prefixes attribute. This attribute can appear on the p:pipeline and p:pipeline-library elements.

The value of the ignore-prefixes attribute is a sequence of tokens, each of which must be the prefix of an in-scope namespace. It is a static error (err:XS0005) if any token specified in the prefix list is not the prefix of an in-scope namespace.

Ignored namespaces specified on a p:pipeline-library are inherited by pipelines that occur within that library.

It is a static error (err:XS0015) to specify as an ignored namespace the XProc namespace, the namespace of any imported p:pipeline, or any namespace in which an atomic step is declared.

3.7 Extension attributes

[Definition: An element from the XProc namespace may have any attribute not from the XProc namespace, provided that the expanded-QName of the attribute has a non-null namespace URI. Such an attribute is called an extension attribute.] Extension attributes are always allowed and do not have to be declared with ignored namespaces.

The presence of an extension attribute must not cause the connections between steps to differ from the connections that any other conformant XProc processor would produce. They must not cause the processor to fail to signal an error that a conformant processor is required to signal. This means that an extension attribute must not change the effect of any XProc element except to the extent that the effect is implementation-defined or implementation-dependent.

A processor which encounters an extension attribute that it does not recognize must behave as if the attribute was not present.

3.8 Extension elements

[Definition: An extension element is any element that is not in the XProc namespace and is not a step.] The presence of an extension element must not cause the connections between steps to differ from the connections that any other conformant XProc processor would produce. They must not cause the processor to fail to signal an error that a conformant processor is required to signal. This means that an extension element must not change the effect of any XProc element except to the extent that the effect is implementation-defined or implementation-dependent.

An element is only an extension element if it is an ignorable element that occurs as a direct child of a p:pipeline or p:pipeline-library.

In other words, elements in a subpipeline are interpreted as follows:

  1. In XProc namespace?
    1. Names a built-in compound step? Check against grammar, interpret per spec.
    2. Names a built-in atomic step? Check against grammar and built-in declaration, intepret per spec.
    3. Otherwise, error.
  2. Is in ignorable namespace?
    1. Is a known extension? Process as appropriate.
    2. Otherwise, ignore.
  3. Names a declared step type? Check against grammer and supplied step declaration, interpret per spec.
  4. Names a defined pipeline? Check against pipeline definition, interpret per spec.
  5. Otherwise, error.

3.9 Syntax Summaries

The description of each element in the pipeline namespace is accompanied by a syntactic summary that provides a quick overview of the element's syntax:

<p:some-element
  some-attribute? = some-type>
    (some |
     elements |
     allowed)*,
    other-elements?
</p:some-element>

For clarity of exposition, some attributes and elements are elided from the summaries:

The types given for attributes should be understood as follows:

  • ID, NCName, NMTOKEN, NMTOKENS, anyURI, boolean, integer, string: As per [W3C XML Schema: Part 2] or its successor(s), including whitespace normalization as appropriate.

  • QName: With whitespace normalization as per [W3C XML Schema: Part 2] and according to the following definition: [Definition: In the context of XProc, a QName is almost always a QName in the Namespaces in XML sense. Note, however, that p:option and p:parameter values can get their namespace declarations in a non-standard way (with p:namespaces) and QNames that have no prefix are always in no-namespace, irrespective of the default namespace.]

  • PrefixList: As a list with [item type] NMTOKEN, per [W3C XML Schema: Part 2], including whitespace normalization.

  • XPathExpression, XSLTMatchPattern: As a string per [W3C XML Schema: Part 2], including whitespace normalization, and the further requirement to be a conformant Expression per [XPath 1.0] or Match pattern per [XSLT 1.0], respectively.

A number of errors apply generally:

If an XProc processor can determine statically that a dynamic error will always occur, it may report that error statically.

4 Steps

This section describes the core steps of XProc.

Every compound step in a pipeline has several parts: a set of inputs, a set of outputs, a set of options, a set of contained steps, and an environment.

Except where otherwise noted, a compound step can have an arbitrary number of outputs, options, and contained steps.

It is a static error (err:XS0027) if a compound step has no contained steps.

4.1 p:pipeline

A pipeline is specified by the p:pipeline element. It encapsulates the behavior of a subpipeline. Its children declare the inputs, outputs, and options that the pipeline exposes and identify the steps in its subpipeline.

A pipeline can declare additional steps (e.g., ones that are provided by a particular implementation or in some implementation-defined way) and import other pipelines. If a pipeline has been imported, it may be invoked as a step within the pipeline that imported it.

<p:pipeline
  name? = NCName
  type? = QName
  ignore-prefixes? = prefix list>
    (p:input |
     p:output |
     p:option |
     p:import |
     p:declare-step |
     p:log |
     p:serialization)*,
    subpipeline
</p:pipeline>

Viewed from the outside, a p:pipeline is a black box which performs some calculation on its inputs and produces its outputs. From the pipeline author's perspective, the computation performed by the pipeline is described in terms of contained steps which read the pipeline's inputs and produce the pipeline's outputs.

The environment inherited by the contained steps of a p:pipeline is the empty environment with these modifications:

If the p:pipeline has a primary output port and that port has no binding, then it is bound to the primary output port of the last step in the subpipeline. It is a static error (err:XS0006) if the primary output port has no binding and the last step in the subpipeline does not have a primary output port.

There are two additional constraints on pipelines:

If the pipeline initially invoked by the processor has inputs or outputs, those ports are bound to documents outside of the pipeline in an implementation-defined manner.

If a pipeline has a type then that type may be used as the name of a step to invoke the pipeline. This most often occurs when the it has been imported into another pipeline, but pipelines may also invoke themselves recursively. If it does not have a type, then its name is used to invoke it as a step.

For pipelines that are part of a p:pipeline-library, see Section 5.9, “p:pipeline-library” for more details on how p:pipeline names are used to compute step names.

4.1.1 Example

A pipeline might accept a document and a stylesheet as input; perform XInclude, validation, and transformation; and produce the formatted document as its output.

Example 4. A Sample Pipeline Document
<p:pipeline name="pipeline" xmlns:p="http://www.w3.org/ns/xproc">
<p:input port="document" primary="true"/>
<p:input port="stylesheet"/>
<p:output port="result" primary="true"/>

<p:xinclude/>

<p:validate-xml-schema>
  <p:input port="schema">
    <p:document href="http://example.com/path/to/schema.xsd"/>
  </p:input>
</p:validate-xml-schema>

<p:xslt>
  <p:input port="stylesheet">
    <p:pipe step="pipeline" port="stylesheet"/>
  </p:input>
</p:xslt>

</p:pipeline>

4.2 p:for-each

A for-each is specified by the p:for-each element. It processes a sequence of documents, applying its subpipeline to each document in turn.

<p:for-each
  name? = NCName>
    (p:iteration-source?,
     (p:output |
      p:option |
      p:log)*,
     subpipeline)
</p:for-each>

When a pipeline needs to process a sequence of documents using a subpipeline that only processes a single document, the p:for-each construct can be used as a wrapper around that subpipeline. The p:for-each will apply that subpipeline to each document in the sequence in turn.

The result of the p:for-each is a sequence of documents produced by processing each individual document in the input sequence. If the p:for-each has one or more output ports, what appears on each of those ports is the sequence of documents that is the concatenation of the sequence produced by each iteration of the loop on the port to which it is connected.

The p:iteration-source is an anonymous input: its binding provides a sequence of documents to the p:for-each step. If no iteration sequence is explicitly provided, then the iteration source is read from the default readable port.

A portion of each input document can be selected using the select attribute. If no selection is specified, the document node of each document is selected.

Each subtree selected by the p:for-each from each of the inputs that appear on the iteration source is wrapped in a document node and provided to the subpipeline.

The processor provides each document, one at a time, to the subpipeline represented by the children of the p:for-each on a port named current.

For each declared output, the processor collects all the documents that are produced for that output from all the iterations, in order, into a sequence. The result of the p:for-each on that output is that sequence of documents.

The environment inherited by the contained steps of a p:for-each is the inherited environment with these modifications:

  • The port named “current” on the p:for-each is added to the readable po