Previous Up Next

Chapter 7. Options, Variables, and Parameters

Table of Contents

1. Options
1.1. p:option
1.2. p:with-option
2. Variables
2.1. p:variable
3. Parameters
3.1. Parameter Port Bindings
3.2. p:with-param
3.3. Order and precedence of parameters
3.4. Controlling in-scope namespaces
3.5. p:namespaces

Options, variables, and parameters are all quite similar in one way: they provide a mechanism for the pipeline author to name strings that can be reused. However, despite their apparent similarity, each has a different purpose. In this chapter, we're going to explore what each is for and how they're used.

In broad strokes:

Options and variables are actually quite similar; parameters are something else entirely, so let's look at options and variables first.

1. Options

Steps, and pipelines, are units of processing designed to operate on XML documents. A p:xslt step performs XSLT processing, a p:validate-with-xml-schema step performs schema validation, and so forth. They accept XML inputs and produce XML outputs.

But what about extra information that a step might need: in XSLT, what is the initial mode?; in schema validation, is strict or lax validation requested?; etc.

Those additional settings aren't XML documents, those are simple flags, switches, or strings. Those are options. Consider the “simple” pipeline we saw back in Chapter 1, Introduction:

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                version='1.0'>
      <p:xinclude/>
    
  5   <p:validate-with-relax-ng>
        <p:input port="schema">
          <p:document href="docbook.rng"/>
        </p:input>
      </p:validate-with-relax-ng>
 10 
      <p:xslt>
        <p:input port="stylesheet">
          <p:document href="docbook.xsl"/>
        </p:input>
 15   </p:xslt>
    </p:pipeline>

It applies XInclude, validates against the DocBook RELAX NG grammar, and then styles the result. This works great for DocBook processing. Suppose you also want to do TEI processing. You could write another pipeline:

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                version='1.0'>
      <p:xinclude/>
    
  5   <p:validate-with-relax-ng>
        <p:input port="schema">
          <p:document href="tei.rng"/>
        </p:input>
      </p:validate-with-relax-ng>
 10 
      <p:xslt>
        <p:input port="stylesheet">
          <p:document href="tei.xsl"/>
        </p:input>
 15   </p:xslt>
    </p:pipeline>

And you could write another new pipeline for each new vocabulary that you want to process. The problem with this approach is that it's tedious and results in a lot of redundancy. Suppose after you've got pipelines for five or six vocabularies, you discover that you need to pass different options to the XInclude step, or that you want to perform some other extra-grammatical check on the inputs? You have to edit each of the pipelines to add this new functionality.

Even with only casual inspection, you can see that they're all the same, they just use different names for the schemas and the stylesheets. Instead of making different copies of this pipeline, you could make the schema and stylesheet into options:

Example 7.1. A simple pipeline with options
  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                version='1.0'>
      <p:option name="schema"/>
      <p:option name="stylesheet"/>
  5 
      <p:xinclude name="include"/>
    
      <p:load name="load-schema">
        <p:with-option name="href" select="$schema"/>
 10   </p:load>
    
      <p:load name="load-stylesheet">
        <p:with-option name="href" select="$stylesheet"/>
      </p:load>
 15 
      <p:validate-with-relax-ng>
        <p:input port="source">
          <p:pipe step="include" port="result"/>
        </p:input>
 20     <p:input port="schema">
          <p:pipe step="load-schema" port="result"/>
        </p:input>
      </p:validate-with-relax-ng>
    
 25   <p:xslt>
        <p:input port="stylesheet">
          <p:pipe step="load-stylesheet" port="result"/>
        </p:input>
      </p:xslt>
 30 </p:pipeline>

Admittedly, on the surface, we've made the pipeline more complicated. That's because we have to use the p:load step to load the schema and the stylesheet. But the benefit of this additional complexity is that our new pipeline will work for any RELAX NG grammar and XSLT stylesheet combination, we simply pass the URIs for those documents in as options and the pipeline does the rest[1].

As you can see, options can be referenced like variables in XPath expressions.

If you run this pipeline with docbook.rng and docbook.xsl for the schema and stylesheet options, respectively, you'll get DocBook validation and styling:

  1 $ calabash -isource=dbdoc.xml format.xpl schema=docbook.rng stylesheet=docbook.xsl

If you use tei.rng and tei.xsl, the exact same stylesheet will perform TEI validation and styling:

  1 $ calabash -isource=teidoc.xml format.xpl schema=tei.rng stylesheet=tei.xsl

But what if you don't specify any options?

If you run the pipeline in Example 7.1, “A simple pipeline with options” without any options, it will fail badly (the load step will fail with an error along the lines of “undeclared variable in XPath expression”):

  1 $ calabash -isource=doc.xml format.xpl
    SEVERE: format.xpl:8:30:err:XD0023:Undeclared variable in XPath expression: $schema
    SEVERE: It is a dynamic error if an XPath expression is encountered which cannot be
    evaluated (because it is syntactically incorrect, contains references to unbound
  5 variables or unknown functions, or for any other reason).

As the pipeline author, there are two ways that you can fix this: you can make the options required or you can give them default values.

The required attribute is used to make them required:

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                version='1.0'>
      <p:option name="schema" required="true"/>
      <p:option name="stylesheet" required="true"/>
  5 
    

If you make them required, the pipeline will not run without the options (and the error will be something more comprehensible like “required option not provided”):

  1 $ calabash -isource=doc.xml format.xpl
    SEVERE: format-optreq.xpl:3:44:err:XS0018:No value provided for required option "schema"
    SEVERE: If an option is required, it is a static error to invoke the step without
    specifying a value for that option.

If you give them default values, then the specified default value will be used if the caller doesn't provide a value.

In this case, because we used to get DocBook processing without specifying any options, it probably makes sense to make those the defaults.

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                version='1.0'>
      <p:option name="schema" select="'docbook.rng'"/>
      <p:option name="stylesheet" select="'docbook.xsl'"/>
  5 
    

The following sections describe the option elements in more detail.

Before we go on, however, we should point out that there's one other possibility when dealing with options. Sometimes it makes sense to require them, sometimes it makes sense to give them defaults, but sometimes you'd like to do something more sophisticated. In those cases, you can use the p:value-available function to test whether or not values were provided and respond accordingly. For more information about p:value-available and other extension functions, see Chapter 4, XPath Expressions and XProc Functions.

1.1. p:option

The p:option element is used when you are declaring a step to specify what options are allowed, whether or not they are required and what default values they have, if any.

The p:option element can occur as a child of p:pipeline (or p:declare-step) to declare that the pipeline has an option. In the simplest case, the p:option simply specifies the name of the option:

<pfx:atomic-step />

Options are not often placed in a namespace, but they are QNames, so you can if you want to. You can not, however, put them in the XProc namespace. That's not allowed.

It may also specify that the option is required. If the required attribute is not specified, it has the same effect as explicitly setting it to false.

All options in XProc are simple string values, so there's no provision for specifying any additional information about the option, such as its type.

Tip

XML Calabash has an option which enables options, variables, and parameters to hold arbitrary values. Using this option makes XML Calabash a non-conforming processor.

It's also possible for the p:option to specify a default value to be used when the caller does not provide a value for the option. This is done with the select attribute:

<pfx:atomic-step />

The default value is an XPath expression. It can refer to preceding options but the context node is undefined.

In summary:

<p:option name=”oname”/>

Specifies an option named “oname”. The option is not required and has no default value. If the caller doesn't specify a value, it will be an error to attempt to refer to it in the pipeline.

<p:option name=”oname” required=”false”/>

Specifies an option named “oname”. The option is not required and has no default value. Just like the preceding example.

<p:option name=”oname”/ required=”true”>

Specifies an option named “oname”. The option is required. If the caller does not provide a value, the step will fail at runtime.

<p:option name=”oname” select=”'some default value'/>

Specifies an option named “oname” with the default value “some default value”. If the caller doesn't specify a value, it will be exactly as if they specified the value “some default value”. (The pipeline cannot tell if an option's value was explicitly provided or provided by default.)

<p:option name=”oname” select=”'some default value'” required=”true”/>

This is an error. It makes no sense to provide a default value for a required option so the specification does not allow it. A pipeline that contains this will be statically rejected.

It is also an error to attempt to declare more then one option with the same name.

1.2. p:with-option

The p:with-option element is used when you are calling a step to specify a value for that option. You must specify the option name and a select attribute containing an XPath expression to provide its value. You may also specify an explicit binding in order to set the context node.

<pfx:atomic-step />

If you do not specify an explicit binding, the binding comes from the default readable port, if there is one. If there's no explicit binding and no default readable port, then the context is undefined (and it's an error to refer to it).

This example passes the value “5” to the option “depth”:

<p:with-option name=”depth” select=”5”/>

This example passes the string value of the version attribute on the document element as the value of the “version” option:

<p:with-option name=”version” select=”/*/@version”/>

In order to evaluate this expression, the processor must have a document to use as the context. As specified, the context will come from the default readable port. You can specify an alternate context, most often this is the output from some other step:

  1 <p:with-option name=”version” select=”/*/@version”>
      <p:pipe step=”preceding” port=”result”/>
    </p:with-option/>

Here the context will be the document that appears on the result port of the step with the name “preceding”.

XPath expressions are evaluated in the context of a single document. If a sequence of more than one document appears in the context of a p:with-option, that will raise an error. If you need to use a document from a step that generates a sequence as the context, you can use p:split-sequence to extract exactly the document you want to use.

You can only pass one value for an option. It is an error to use two or more p:with-options on a single instance of a step if they have the same option name.

2. Variables

Variables are very similar to options. The principal difference is that variables are entirely local to the pipeline, they're something that the pipeline author uses to organize or simplify the pipeline. Callers cannot change, or even see, the names or values of variables.

2.1. p:variable

When you declare a variable, you must specify the variable's name and a select expression to provide its value. You may also specify an explicit binding in order to set the context node.

<pfx:atomic-step />

If you do not specify an explicit binding, the binding comes from the default readable port, if there is one. If there's no explicit binding and no default readable port, then the context is undefined (and it's an error to refer to it).

Like options, variables may be in a namespace but may not be in the XProc namespace.

This example specifies the value “5” for the variable “depth”:

<p:variable name=”depth” select=”5”/>

This example computes the “uri” value by resolving the value of some preceding option or variable named “href” against the base URI of a particular document:

<p:variable name=”uri” select=”resolve-uri($href, base-uri(/))”/>

In order to evaluate this expression, the processor must have a document to use as the context. As specified, the context will come from the default readable port. You can specify an alternate context, most often this is the output from some other step:

  1 <p:variable name=”uri” select=”resolve-uri($href, base-uri(/))”>
      <p:pipe step=”preceding” port=”result”/>
    </p:variable/>

Here the context will be the document that appears on the result port of the step with the name “preceding”.

XPath expressions are evaluated in the context of a single document. If a sequence of more than one document appears in the context of a p:variable, that will raise an error. If you need to use a document from a step that generates a sequence as the context, you can use p:split-sequence to extract exactly the document you want to use.

2.1.1. Variable placement

There's one oddity about variables: they can only occur at the beginning of a compound step. In other words, you can't do this:

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                version='1.0'>
      <p:option name="href"/>
    
  5   <p:variable name="abshref" select="resolve-uri($href, 'http://example.com/')"/>
    
      <p:load>
        <p:with-option name="href" select="$abshref"/>
      </p:load>
 10 
      <p:variable name="version" select="/*/@version"/>
    
      ...
    </p:pipeline>

You can't put a variable declaration between two steps. This may seem like an odd restriction, but it's motivated by the fact that the order of the steps in your pipeline document is not necessarily the order in which they will be evaluated.

If variable declarations were allowed between two steps, and the order of those steps was changed, the variable declaration might also have to be moved. In order to determine where it could go (if the resulting pipeline was even valid), the processor would have to examine the content of all the XPath expressions used on all the steps in order to find out where the variable was used (and consequently which steps it must precede).

No where else in XProc is the processor required to analyze the XPath expressions (implementations can simply pass them off to an underlying processor, without having to parse them directly). The working group was unwilling to impose this additional burden on implementors just to satisfy this single case.

Instead, it made two observations:

  1. If variables are only allowed before the first step, then this problem cannot arise.

  2. The pipeline author can always insert a new p:group if the value of a variable needs to be computed based on the output of some step.

So our earlier invalid pipeline can be written as follows:

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                version='1.0'>
      <p:option name="href"/>
    
  5   <p:variable name="abshref" select="resolve-uri($href, 'http://example.com/')"/>
    
      <p:load>
        <p:with-option name="href" select="$abshref"/>
      </p:load>
 10 
      <p:group>
        <p:variable name="version" select="/*/@version"/>
    
        ...
 15   </p:group>
    </p:pipeline>

This is perfectly valid. There's no question that this is a surprising state of affairs, but it doesn't actually impact the kinds of processing that XProc can perform.

2.1.2. Variable shadowing

It's an error to have more than one declaration for the same variable name at the same level, in other words for their declarations to be siblings in the XML sense.

If however, you use the same option name inside nested compound steps, the inner values shadow the outer values. In other words, within any given compound step, the nearest ancestor declaration is the one that holds.

3. Parameters

Parameters suck. They make XProc more complicated, they introduce a number of odd defaulting rules that the language would be cleaner without, they use an input port in a very odd way, and they're bound to cause all sorts of confusion. If the working group could have thought of a way to get rid of them, it probably would have.

Parameters exist to solve a particular problem exemplified by (but not unique to) XSLT. Consider that pipeline back up in Example 7.1, “A simple pipeline with options”. Suppose that it's used to process a document with the DocBook XSL Stylesheets. The DocBook stylesheets have more than 600 parameters: there are parameters for chunking, profiling, table formating, refentry formatting, cross reference, bibliography, and glossary styling, and on and on.

These parameters exist to allow users to control aspects of behavior without having to edit the stylesheets. Now suppose you want to run that pipeline and pass a parameter (or two, or ten) to XSLT? What are the options?

You can't.

It's simple, but it's not very satisfying. Given the success and popularity of XSLT, it's likely that a lot of pipelines will use it. Preventing any of them from using stylesheet parameters doesn't seem like a good idea.

You have to pass them explicitly on the XSLT step.

That means writing a different pipeline for every combination of stylesheet options and values that you want to pass to XSLT. I guess that's better than not being able to do it at all, but not by much.

Use options.

In many ways using options would be the cleanest answer. Except that using options means every pipeline that includes XSLT will have to provide a p:option for every possible parameter for every possible stylsheet that it might run. I don't think very many pipeline authors are going to want to put thousands of p:option elements in each pipeline that uses XSLT and then thousands of p:with-option elements on each call to p:xslt.

Given that none of those alternatives are practical, a new “parameters” mechanism was invented. In many ways parameters are like options, except that their names are not known in advance to the pipeline author.

In the simplest case, it just works. Any parameters passed to the pipeline are automatically passed to any step that expects parameters. Under the covers there's quite a bit of magic going on. Let's take a closer look. The descriptions that follow describe what an XProc processor does in principle; an implementation is free to choose a more efficient implementation in practice as long as it behaves as if it did the steps described here.

Recall that a p:pipeline is just syntactic sugar for a particular form of p:declare-step. Example 7.2, “Explicit parameter pipeline” shows the simplest XSLT pipeline using the fully explicit syntax.

Example 7.2. Explicit parameter pipeline
  1 <p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
                    version='1.0'>
      <p:input port="source"/>
      <p:input port="parameters" kind="parameter"/>
  5   <p:output port="result"/>
    
      <p:xslt>
        <p:input port="stylesheet">
          <p:document href="docbook.xsl"/>
 10     </p:input>
      </p:xslt>
    </p:declare-step>

The first thing to observe is that it has a special “parameter” input port. XProc's greatest strength is its ability to process XML documents; to take advantage of this strength, parameters are mapped onto a special kind of input port.

Suppose we run this pipeline as follows:

  1 $ calabash -isource=dbdoc.xml -pbody.font.family=sans-serif param-decl.xpl

where we've passed the parameter named “body.font.family” to the pipeline with the value “sans-serif”.

The first thing the server does is create a c:param-set document containing all the parameters passed to the pipeline:

  1 <c:param-set>
      <c:param name="body.font.family" value="sans-serif"/>
    </c:param-set>

This document is sent to the pipeline on the “parameters” port.

It is not an error to specify more than one value for the same parameter; if more than one value is provided for the same parameter name, the last value provided is used. All earlier values are silently ignored.

The p:xslt step also has a parameter input port. When I said the pipeline in Example 7.2, “Explicit parameter pipeline” was fully explicit, I left out a few details. The fully explicit version is in Example 7.3, “Fully explicit parameter pipeline”.

Example 7.3. Fully explicit parameter pipeline
  1 <p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
                    name="main" version='1.0'>
      <p:input port="source"/>
      <p:input port="parameters" kind="parameter"/>
  5   <p:output port="result">
        <p:pipe step="style" port="result"/>
      </p:output>
    
      <p:xslt name="style">
 10     <p:input port="stylesheet">
          <p:document href="docbook.xsl"/>
        </p:input>
        <p:input port="parameters">
          <p:pipe step="main" port="parameters"/>
 15     </p:input>
      </p:xslt>
    </p:declare-step>

This version shows explicitly the ordinarily implicit binding from the parameters input port on the p:xslt step to the parameters input port on the containing pipeline.

Although this binding is most often implicit, it's important to remember that it can be explicit. In rare circumstances, it may be necessary to have more than one parameter input port. Consider the case, for example where you want to run the p:xslt step twice in a single pipeline but pass entirely separate sets of parameters to each instance.

In this case, you can name multiple parameter input ports and make the bindings explicit as shown in Example 7.4, “Multiple parameter inputs”.

Example 7.4. Multiple parameter inputs
  1 <p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
                    name="main" version='1.0'>
      <p:input port="source"/>
      <p:input port="params1" kind="parameter"/>
  5   <p:input port="params2" kind="parameter"/>
      <p:output port="result"/>
    
      <p:xslt>
        <p:input port="stylesheet">
 10       <p:document href="docbook.xsl"/>
        </p:input>
        <p:input port="parameters">
          <p:pipe step="main" port="params1"/>
        </p:input>
 15   </p:xslt>
    
      <p:xslt>
        <p:input port="stylesheet">
          <p:document href="docbook.xsl"/>
 20     </p:input>
        <p:input port="parameters">
          <p:pipe step="main" port="params2"/>
        </p:input>
      </p:xslt>
 25 </p:declare-step>

The important thing to remember is that most of the defaulting rules only apply when there's a single parameter input port. If you specify multiple parameter input ports, you'll have to make your intentions explicit.

There are some other wrinkles in the default binding story.

3.1. Parameter Port Bindings

A parameter input port is like an ordinary, document input port in the sense that you can make bindings to it explicitly in the normal way. It differs in two ways: it always, and can only, accept a sequence of c:param-set or c:param documents, it's an error to pass anything else to it; and if you don't specify a binding, the default binding rules are different.

If a step has a primary parameter input port without an explicit binding, it will be bound by default to the parameter input port of the pipeline that contains it. In other words, it binds to the primary parameter input port of its nearest ancestor p:pipeline or p:declare-step step.

It is an error if the pipeline does not have a primary parameter input port.

If you want to use a step that has parameters in a pipeline declared with p:declare-step that does not declare a parameter input port, you must provide some explicit binding. That can be a pipe binding to p:empty or it can be one or more p:with-param elements.

3.2. p:with-param

Sometimes you want to construct or specify a parameter value in the pipeline. For this purpose, you can use p:with-param. Like p:with-option, it's used when you are calling a step to specify a value for a particular parameter. (There's no equivalent of p:option because parameters are by definition not declared in the pipeline.)

You must specify the parameter name and a select attribute containing an XPath expression to provide its value. You may also specify an explicit binding in order to set the context node.

<pfx:atomic-step />

If you do not specify an explicit binding, the binding comes from the default readable port, if there is one. If there's no explicit binding and no default readable port, then the context is undefined (and it's an error to refer to it).

This example passes the value “5” to the parameter “depth”:

<p:with-param name=”depth” select=”5”/>

Because there can be multiple parameter input ports, there is also a port attribute. You must specify the port attribute if the step has more than one parameter input port. Otherwise, the default is for the single parameter input port.

This example passes the string value of the version attribute on the document element as the value of the “version” parameter on the params1:

<p:with-param port=”params1” name=”version” select=”/*/@version”/>

In order to evaluate this expression, the processor must have a document to use as the context. As specified, the context will come from the default readable port. You can specify an alternate context, most often this is the output from some other step:

  1 <p:with-param port=”params1” name=”version” select=”/*/@version”>
      <p:pipe step=”main” port=”altparams”/>
    </p:with-param/>

Here the context will be the document that appears on the altparams port of the step with the name “main”.

XPath expressions are evaluated in the context of a single document. If a sequence of more than one document appears in the context of a p:with-param, that will raise an error. If you need to use a document from a step that generates a sequence as the context, you can use p:split-sequence to extract exactly the document you want to use.

One important aspect of p:with-param is that it constitutes a binding for the parameter input port. So if there is no explicit binding for the port, and no default binding is possible, no error will occur.

3.3. Order and precedence of parameters

As mentioned earlier, it is not an error to specify a parameter value multiple times, all but the last value are simply ignored. This raises the question of how the binding to the parameter input port and any explicit p:with-param elements interact.

The answer is that by default p:with-param steps occur after the default binding for the parameter input port. This means that p:with-param values override any values specified through the parameter input port.

If you want to reverse this order, if you want your explicit p:with-param to function as a default that the user can override, make the parameter input port binding explicit and put your p:with-param before it:

  1 ...
    <p:xslt>
      <p:with-param name="list-enumeration" select="'arabic,lower-alpha,roman'"/>
      <p:input port="parameters">
  5     <p:pipe step="main" port="parameters"/>
      </p:input>
    </p:xslt>
    ...

Now the stylesheet will see the list enumeration value you specified unless the user provides a different value as a parameter to the pipeline.

3.4. Controlling in-scope namespaces

There's one last wrinkle in this story. And if there's going to be a last wrinkle in an XML story, you can safely bet that it will involve namespaces. And probably QNames-in-content, which is precisely the problem here.

Many steps in XProc accept XSLT match patterns and a few accept strings which are interpreted by the step as XPath expressions. The problem is that the context in which a p:with-option is specified can be entirely different than the context in which the corresponding p:option is declared.

Consider a pipeline that includes a p:rename step where, for some reason, the match pattern and new name are most usefully specified as options to the pipeline.

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                xmlns:html="http://www.w3.org/1999/xhtml"
                xmlns:ex="http://example.com/pipeline/types"
                type="ex:do-stuff-and-rename"
  5             version='1.0'>
      <p:option name="oldname" required="true"/>
      <p:option name="newname" select="'html:div'"/>
    
      <!-- do some stuff -->
 10 
      <p:rename>
        <p:with-option name="match" select="$oldname"/>
        <p:with-option name="new-name" select="$newname"/>
      </p:rename>
 15 
      <!-- do some stuff -->
    </p:pipeline>

The namespace binding for XHTML in this pipeline is “html:”. Now imagine that you import this pipeline into your pipeline, which then wants to call the pipeline shown above:

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                xmlns:ex="http://example.com/pipeline/types"
                version='1.0'>
      <p:import href="do-stuff-and-rename.xpl"/>
  5 
      <!-- do some other stuff -->
    
      <ex:do-stuff-and-rename match="h:body/h:p"/>
    
 10   <!-- do some other stuff -->
    </p:pipeline>

This pipeline doesn't even declare a binding for the XHTML namespace (which is a little odd under the circumstances but will help to reinforce a point later). What happens when this call is made? From the perspective of this pipeline, there's no error because the value of the match attribute is just a string. But that string “h:body/h:p is passed to the ex:do-stuff-and-rename step where it is eventually passed to p:rename.

The p:rename step attempts to interpret the string as an XSLT match pattern using the namespace bindings in-scope for the option. Because there is no binding for the “h:” prefix in this context, the step will fail.

The p:namespaces element allows you to address this problem by passing an explicit set of namespace bindings along with the option. These bindings will then be used by the steps that interpret the option value:

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                xmlns:ex="http://example.com/pipeline/types"
                version='1.0'>
      <p:import href="do-stuff-and-rename.xpl"/>
  5 
      <!-- do some other stuff -->
    
      <ex:do-stuff-and-rename match="h:body/h:p">
        <p:namespaces xmlns:h="http://www.w3.org/1999/xhtml"/>
 10   </ex:do-stuff-and-rename>
    
      <!-- do some other stuff -->
    </p:pipeline>

In the interest of making the bindings as explicit as possible, we show the namespace declaration on the p:namespaces element in this example. In practice, the binding would more likely be on the p:pipeline element and the p:namespaces element would just be an ordinary, empty element.

3.5. p:namespaces

The p:namespaces element provides three methods for establishing namespace bindings.

<pfx:atomic-step />

binding

The binding option can be used to identify the name of another in-scope option or variable. The bindings associated with that option or variable will be used.

element

The element option may be used to provide an XPath expression that selects a single element. The bindings associated with that element will be used. In this case, the context node for the element XPath expression is exactly the same as the context node for the XPath expression that specifies the value.

Its own namespace bindings

If neither the binding or element attributes are present, then the namespace bindings of the p:namespaces element itself are used. In this case the ordinary, in-scope namespace rules apply.

If except-prefixes is used, it specifies a list of namespace prefixes (that are in-scope for this p:namespaces element) that should not be made part of the context.

The p:namespaces element is probably something you will use very rarely, but it is sometimes necessary. As XProc libraries grow and become popular, it may become more common (if those libraries are or are treated as read-only).


[1]Alternatively, you could make the grammar and the stylesheet into pipeline inputs; that's an equally reasonable approach, but it doesn't illustrate the point I'm trying to make here.