<?xml version="1.0" encoding="UTF-8"?><specification xmlns="http://docbook.org/ns/docbook" xmlns:cs="http://www.w3.org/XML/XProc/2006/04/components#" xmlns:e="http://www.w3.org/1999/XSL/Spec/ElementSyntax" xmlns:p="http://www.w3.org/ns/xproc" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="steps" class="ed" version="5.0-extension w3c-xproc">
<info>
<title>XProc 3.1: Standard Step Library</title>
<!--
<pubdate>2025-05-30</pubdate>
<bibliomisc role="final-uri">https://spec.xproc.org/3.1/steps/</bibliomisc>
-->
<copyright><year>2018</year><year>2019</year><year>2020</year><year>2021</year><year>2022</year>
<year>2023</year><year>2024</year><year>2025</year>
<holder>the Contributors to the XProc 3.1 Standard Step Library
specifications</holder>
</copyright>

<bibliomisc role="repository">XProc/specification</bibliomisc>
<bibliomisc role="w3c-cg" xlink:href="https://www.w3.org/community/xproc-next/">XProc Next</bibliomisc>

<bibliorelation type="isformatof" xlink:href="specification.xml">XML</bibliorelation>
<!--
<bibliorelation type="isformatof" xlink:href="steps_a4.pdf">PDF (A4)</bibliorelation>
<bibliorelation type="isformatof" xlink:href="steps_letter.pdf">PDF (US Letter)</bibliorelation>
-->
<authorgroup>
  <author>
    <personname>Norman Walsh</personname>
  </author>
  <author>
    <personname>Achim Berndzen</personname>
  </author>
  <author>
    <personname>Gerrit Imsieke</personname>
  </author>
  <author>
    <personname>Erik Siegel</personname>
  </author>
</authorgroup>

<abstract>
  <para>This specification describes the standard step vocabulary of
  <citetitle>XProc 3.1: An XML Pipeline Language</citetitle>.</para>
</abstract>

<legalnotice xml:id="sotd" role="status">
  <para>This specification was published by the
  <link xlink:href="https://www.w3.org/community/xproc-next/">XProc
  Next Community Group</link>. It is not a W3C Standard nor is it on
  the W3C Standards Track. Please note that under the
  <link xlink:href="https://www.w3.org/community/about/agreements/cla/">W3C
  Community Contributor License Agreement (CLA)</link> there is a limited
  opt-out and other conditions apply. Learn more about <link xlink:href="https://www.w3.org/community/">W3C Community and Business
  Groups</link>.
  </para>
 
  <para>If you wish to make comments regarding this document, please
  send them to
  <link xlink:href="mailto:xproc-dev@w3.org">xproc-dev@w3.org</link>.
  (<link xlink:href="mailto:xproc-dev-request@w3.org?subject=subscribe">subscribe</link>,
  <link xlink:href="https://lists.w3.org/Archives/Public/xproc-dev/">archives</link>).
  </para>

<para>This document is derived from
<link xlink:href="https://www.w3.org/TR/2010/REC-xproc-20100511/">XProc:
An XML Pipeline Language</link> published by the W3C.</para>

<para>Changes made since the 3.0 specification was published are listed in
<xref linkend="changelog"/>.</para>
</legalnotice>
</info>

<section xml:id="introduction">
  <title>Introduction</title>

<para>This specification describes the standard, required atomic XProc
steps.
A machine-readable description of these steps may be found in
<link xlink:href="steps.xpl">steps.xpl</link>.
</para>

<para>Many atomic steps are available for <biblioref linkend="xproc31"/>. They are described in several specifications.
This specification describes the general background common to all
steps. A conformant processor <rfc2119>must</rfc2119> implement all of
the steps in this specification. Additional steps may also be
implemented.
</para>

<para>The types given for options should be understood as follows:</para>
<itemizedlist>
  <listitem>
    <para>Types in the XML Schema namespace, identified as QNames with the
    <code>xs:</code> prefix, as per the XML Schema specification with one
    exception. Anywhere an <code>xs:QName</code> is specified,
    an
    <link xlink:href="https://www.w3.org/TR/xquery-30/#doc-xquery30-EQName">EQName</link>
    is allowed.</para>
  </listitem>
  <listitem>
    <para><type>XPathExpression</type>:
    As a string per <biblioref linkend="xmlschema-2"/>, including
    whitespace normalization, and the further requirement to be a
    conformant Expression per <biblioref linkend="xpath31"/>.
    </para>
  </listitem>
  <listitem xml:id="dt-selection-pattern">
    <para><type>XSLTSelectionPattern</type>:
    As a string per <biblioref linkend="xslt30"/> conforming to an XSLT
    <emphasis>selection pattern</emphasis>.</para>
  </listitem>
  <listitem>
    <para><type>XPathSequenceType</type>: An XPath
    <link xlink:href="https://www.w3.org/TR/xpath-31/#id-types">sequence type</link>.
    </para>
  </listitem>
  <listitem>
    <para><type>ContentType</type>: A media type as defined in
    <biblioref linkend="rfc2046"/>.
    </para>
  </listitem>
  <listitem>
    <para><type>ContentTypes</type>:
    As a whitespace separated list of media types as defined in
    <biblioref linkend="rfc2046"/>.
    </para>
  </listitem>
</itemizedlist>

<para>Option values are often expressed using the shortcut syntax. In
these cases, the option shortcuts are generally treated as value
templates. However, for options of type <code>map()</code> or
<code>array()</code>, an expression is <emphasis>required</emphasis>
(there is no non-expression string which can ever be a legal value for
a map or array). Given that every value entered this way will have to
be a value template, and consequently every curly brace contained
within the expression will have to be escaped, values of type map or
array are defined to be expressions directly.</para>

<para>Some aspects of documents are generally unchanged by steps:</para>

<itemizedlist>
<listitem>
<para>When a step in this library produces an output document,
the base URI of the output is the base URI of the step's primary
input document unless the step's process explicitly sets an
<tag class="attribute">xml:base</tag> attribute or the step's
description explicitly states how the base URI is constructed.</para>
</listitem>
<listitem>
<para>Steps are responsible for describing how document properties are
transformed as documents flow through them. Many steps claim that the
specified properties are preserved. Generally, it is the
responsibility of the pipeline author to determine when this is
inapropriate and take corrective action. However, it is the
responsibility of the pipeline processor to assure that the
<code>content-type</code> property is correct. If a step transforms a
document in a manner that is inconsistent with the
<code>content-type</code> property (accepting an XML document on the
source port but producing a text document on the result, for example), the
processor must assure that the <code>content-type</code> property is appropriate.
If a step changes the <code>content-type</code> in this way, it <rfc2119>must</rfc2119> also
remove the <code>serialization</code> property
</para>
</listitem>
</itemizedlist>

<para xml:id="cv.result">Also, in this specification, several steps use this
element for result information:</para>

<e:rng-pattern name="VocabResult"/>

<para>When a step uses an XPath to compute an option value, the XPath
context is as defined in <biblioref linkend="xproc31"/>.</para>

<para>When a step specifies a particular version of a technology,
implementations <rfc2119>must</rfc2119> implement that
version or a subsequent version that is backwards compatible with that
version. At user-option, they may implement other non-backwards
compatible versions.</para>
  
<para>In this specification the words <rfc2119>must</rfc2119>, <rfc2119>must not</rfc2119>,
        <rfc2119>should</rfc2119>, <rfc2119>should not</rfc2119>, <rfc2119>may</rfc2119> and
        <rfc2119>recommended</rfc2119> are to be interpreted as described in <biblioref linkend="rfc2119"/>.</para>

<para>As described in <xspecref spec="xproc" xref="psvi-support"/>,
steps may not produce PSVI output unless that behavior is explicitly
described. In this specification, the steps that may produce PSVI
output are the “identity” steps: <tag>p:identity</tag>,
<tag>p:store</tag>, and <tag>p:split-sequence</tag> (which <rfc2119>must</rfc2119> preserve 
PSVI properties that appear on their inputs). In addition, the
<tag>p:xslt</tag> and <tag>p:xquery</tag> steps <rfc2119>may</rfc2119> return documents with
PSVI annotations.</para>

</section>

<section xml:id="req-steps">
<title>Step library</title>

<para>A conformant processor must support all of these steps.</para>

<section xml:id="c.add-attribute">
<title>p:add-attribute</title>

<para>The <code>p:add-attribute</code> step adds a single attribute to
a set of matching elements. The input document specified on the
  <code>source</code> is processed for matches specified by the 
    <glossterm>selection pattern</glossterm> in the <option>match</option> option. For each of these
matches, the attribute whose name is specified by the
<option>attribute-name</option> option is set to the attribute value
specified by the <option>attribute-value</option> option.
</para>

<para>The resulting document is produced on the <code>result</code>
output port and consists of a exact copy of the input with the
exception of the matched elements. Each of the matched elements is
copied to the output with the addition of the specified attribute
with the specified value.
</para>

<p:declare-step type="p:add-attribute">
  <p:input port="source" content-types="xml html"/>
  <p:output port="result" content-types="xml html"/>
  <p:option name="match" as="xs:string" select="'/*'" e:type="XSLTSelectionPattern"/>
  <p:option name="attribute-name" required="true" as="xs:QName"/>
  <p:option name="attribute-value" required="true" as="xs:string"/>
</p:declare-step>

<para>The value of the <option>match</option> option
<rfc2119>must</rfc2119> be an XSLTSelectionPattern. <error code="C0023">It
is a <glossterm>dynamic error</glossterm> if the <glossterm>selection pattern</glossterm> matches a node
which is not an element.</error></para>

<para>The value of the <option>attribute-value</option> option
<rfc2119>must</rfc2119> be a legal attribute value according to XML.</para>

<para>If an attribute with the same name as the expanded name
from the <option>attribute-name</option> option exists on the matched
element, the value specified in
the <option>attribute-value</option> option is used to set the
value of that existing attribute.  That is, the value of the
existing attribute is changed to the <option>attribute-value</option>
value. </para>

<note xml:id="note-multattr"><para>If multiple attributes need to be set on the same
element(s), the <tag>p:set-attributes</tag> step can be used to set them
all at once.</para>
</note>

<para>This step cannot be used to add namespace declarations.
<error code="C0059">It is a <glossterm>dynamic error</glossterm> if the QName
value in the <option>attribute-name</option> option is “<code>xmlns</code>” or uses the prefix
“<literal>xmlns</literal>”
or any other prefix that resolves to the namespace name
<uri>http://www.w3.org/2000/xmlns/</uri>.
</error> Note, however, that while namespace declarations cannot be
added explicitly by this step, adding an attribute whose name is in a
namespace for which there is no namespace declaration in scope on the
matched element may result in a namespace binding being added by
namespace fixup.</para>

<para>If an attribute named
<tag class="attribute">xml:base</tag> is added or changed, the base URI
of the element <rfc2119>must</rfc2119> also be amended accordingly.</para>

<simplesect>
<title>Document properties</title>
<para feature="add-attribute-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.add-xml-base">

<title>p:add-xml-base</title>

<para>The <code>p:add-xml-base</code> step exposes the base URI via
explicit <code>xml:base</code> attributes. The input document from the
<port>source</port> port is replicated to the <port>result</port> port
with <code>xml:base</code> attributes added to or corrected on each element as specified
by the options on this step.</para>

<p:declare-step type="p:add-xml-base">
   <p:input port="source" content-types="xml html"/>
   <p:output port="result" content-types="xml html"/>
   <p:option name="all" as="xs:boolean" select="false()"/>
   <p:option name="relative" as="xs:boolean" select="true()"/>
</p:declare-step>

 <para>The value of the <option>all</option> option
<rfc2119>must</rfc2119> be a boolean.</para>

 <para>The value of the <option>relative</option> option
<rfc2119>must</rfc2119> be a boolean.</para>

<para><error code="C0058">It is a <glossterm>dynamic error</glossterm>
if the <option>all</option> and <option>relative</option> options are
<emphasis>both</emphasis> <literal>true</literal>.</error></para>

<para>The <tag>p:add-xml-base</tag> step modifies its input as follows:</para>

<itemizedlist>
<listitem>
<para>For every element that is a child of the document node: force the element to have an <tag class="attribute">xml:base</tag>
attribute with the document's [base URI] property's value as its value.</para>
</listitem>
<listitem>
<para>For other elements:</para>
<itemizedlist>
<listitem>
<para>If the <option>all</option> option has the value
<literal>true</literal>, force the element to have an <tag class="attribute">xml:base</tag> attribute with the element's [base
URI] value as its value.</para>
</listitem>
<listitem>
<para>If the element's [base URI] is different from the its parent's
[base URI], force the element to have an <tag class="attribute">xml:base</tag> attribute with the following
value: if the value of the <option>relative</option> option is
<literal>true</literal>, a string which, when resolved against the
parent's [base URI], will give the element's [base URI], otherwise the
element's [base URI].</para>
</listitem>
<listitem>
<para>Otherwise, if there is an <tag class="attribute">xml:base</tag> attribute present, remove it.
</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>

<simplesect>
<title>Document properties</title>
<para feature="add-xml-base-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.archive">

  <title>p:archive</title>

  <para>The <code>p:archive</code> step outputs on its <port>result</port> port an archive (usually
    binary) document, for instance a ZIP file. A specification of the contents of the archive may be
    specified in a manifest XML document on the <port>manifest</port> port. The step produces a
    report on the <port>report</port> port, which contains the manifest, amended with additional
    information about the archiving.</para>

  <p:declare-step type="p:archive">
    <p:input port="source" primary="true" content-types="any" sequence="true"/>
    <p:input port="manifest" content-types="xml" sequence="true">
      <p:empty/>
    </p:input>
    <p:input port="archive" content-types="any" sequence="true">
      <p:empty/>
    </p:input>
    <p:output port="result" primary="true" content-types="any" sequence="false"/>
    <p:output port="report" content-types="application/xml" sequence="false"/>
    <p:option name="format" as="xs:QName" select="'zip'"/>
    <p:option name="relative-to" as="xs:anyURI?"/>
    <p:option name="parameters" as="map(xs:QName, item()*)?"/>
  </p:declare-step>

  <para>The <code>p:archive</code> step can perform several different operations on archives. The
    most common one will likely be creating an archive, but it could also, depending on the archive
    format, provide services like update, freshen or even merge. The only format implementations
      <rfc2119>must</rfc2119> support is <biblioref linkend="zip"/>. <impl>The list of formats
      supported by the <tag>p:archive</tag> step is
      <glossterm>implementation-defined</glossterm>.</impl></para>

  <para>The <code>p:archive</code> step has the following input ports:</para>
  <variablelist>
    <varlistentry>
      <term><port>source</port></term>
      <listitem>
        <para>The (primary) <port>source</port> port is used to provide documents to be archived
          (for instance constructed by other steps). How and which of these documents are processed
          is governed by the document(s) appearing on the other input ports and the combination of
          options and parameters. See below for details. <error code="C0084">It is a
              <glossterm>dynamic error</glossterm> if two or more documents appear on the <code>p:archive</code>
            step's <port>source</port> port that have the same base URI or if any document that
        appears on the <port>source</port> port has no base URI.</error></para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term><port>manifest</port></term>
      <listitem>
        <para>The <port>manifest</port> port can receive a manifest document that tells the step how
          to construct the archive. If no manifest document is provided on this port, a default
          manifest is constructed automatically. See <xref linkend="cv.archive-manifest"/>. <error code="C0100">It is a <glossterm>dynamic error</glossterm> if the document on port
              <port>manifest</port> does not conform to the given schema.</error>
        </para>
        <para><error code="C0112">It is a <glossterm>dynamic error</glossterm> if more than one
            document appears on the port <port>manifest</port>.</error></para>
        <para>The default input for this port is the empty sequence.</para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term><port>archive</port></term>
      <listitem>
        <para>The <port>archive</port> port is used to provide the step with existing archive(s) for
          operations like update, freshen or merge. Handling of ZIP files supports modifying
          archives appearing on the <port>archive</port> port (<xref linkend="cv.archive-zips"/>).
            <impl>The list of archive formats that can be modified by <tag>p:archive</tag> is
              <glossterm>implementation-defined</glossterm>.</impl> For instance an implementation
          that supports archive merging may accept more than one document on the
            <port>archive</port> port.</para>
        <para>The default input for this port is the empty sequence.</para>
      </listitem>
    </varlistentry>
  </variablelist>

  <para>The <code>p:archive</code> step has the following output ports:</para>
  <variablelist>
    <varlistentry>
      <term><port>result</port></term>
      <listitem>
        <para>The (primary) <port>result</port> port will output the resulting archive.</para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term><port>report</port></term>
      <listitem>
        <para>The <port>report</port> port will output a report about the archiving operation. This
          will be the same as the manifest (as provided on the <port>manifest</port> port or
          automatically created if there was no manifest provided), optionally amended with
          additional attributes and/or elements. <impl>The semantics of any additional attributes,
            elements and their values are
          <glossterm>implementation-defined</glossterm>.</impl></para>
      </listitem>
    </varlistentry>
  </variablelist>

  <para>The <code>p:archive</code> step has the following options:</para>
  <variablelist>
    <varlistentry>
      <term><option>format</option></term>
      <listitem>
        <para>The format of the archive can be specified using the <option>format</option> option.
          Implementations <rfc2119>must</rfc2119> support the <biblioref linkend="zip"/> format,
          specified with the value <code>zip</code>. <impl>It is
              <glossterm>implementation-defined</glossterm> what other formats are
          supported.</impl></para>
      </listitem>
    </varlistentry>
    <varlistentry xml:id="archive-parameters">
      <term><option>parameters</option></term>
      <listitem>
        <para>The <option>parameters</option> option can be used to supply parameters to control the
          archiving. Several parameters are defined for processing
          <link linkend="cv.archive-zips">zip archives</link>, but implementations are
          free to use additional parameters and to use parameters for controlling
          how other archive formats are processed.
          <error code="C0079">It is a <glossterm>dynamic error</glossterm> if the map
              <option>parameters</option> contains an entry whose key is defined by the
            implementation and whose value is not valid for that key.</error></para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term><option>relative-to</option></term>
      <listitem>
        <para>The <option>relative-to</option> option is used in creating a manifest when no
          manifest is provided on the <port>manifest</port> port. If a manifest is present this option is
          not used. If the option’s value is a relative URI, it is made absolute against the
          base URI of the element on which it is specified (<tag>p:with-option</tag> or the step in
          case of a syntactic shortcut value). <error code="D0064">It is a <glossterm>dynamic
              error</glossterm> if the base URI is not both absolute and valid according to
              <biblioref linkend="rfc3986"/>.</error></para>
      </listitem>
    </varlistentry>
  </variablelist>

  <para>The format of the archive is determined as follows:</para>
  <itemizedlist>
    <listitem>
      <para>If the <option>format</option> option is specified, this determines the format of the
        archive.
        <error code="C0081">It is a <glossterm>dynamic error</glossterm> if the format of the
          archive does not match the format as specified in the <option>format</option>
          option.</error></para>
    </listitem>
    <listitem>
      <para>If no <option>format</option> option is specified or if its value is the empty sequence,
        the archive's format will be determined by the step, using the <code>content-type</code>
        document-property of the document on the <port>archive</port> port and/or by inspecting its
        contents. <impl>It is <glossterm>implementation-defined</glossterm> how the step determines
          the archive's format.</impl> Implementations <rfc2119>should</rfc2119> recognize archives
        in <biblioref linkend="zip"/> format. </para>
    </listitem>
  </itemizedlist>

  <para><error code="C0085">It is a <glossterm>dynamic error</glossterm> if the format of the archive 
    cannot be understood, determined and/or processed.</error></para>

  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

  <section xml:id="cv.archive-manifest">
    <title>The archive manifest</title>

    <para>An archive manifest specifies which documents will be considered in processing the
    archive. Every entry in the archive must have a corresponding entry in the manifest; if no such
    entry is provided, one will be constructed automatically (see below). If manifest entries are
    provided for documents that <emphasis>are not</emphasis> in the archive, how those are processed
    depends on the archive type and the parameters passed to the step.</para>

    <para>A manifest is represented by a <tag>c:archive</tag> root element:</para>

    <e:rng-pattern name="VocabArchive" xml:id="cv.archive"/>

    <para><impl>The <code>c:archive</code> root element may contain additional
    <glossterm>implementation-defined</glossterm> attributes.</impl></para>

    <para>All entries in the archive must be present as <tag>c:entry</tag> child elements:</para>

    <e:rng-pattern name="VocabEntry" xml:id="cv.entry"/>

    <itemizedlist>
      <listitem>
        <para>The <code>name</code> attribute specifies the name of the entry in the archive.</para>
      </listitem>
      <listitem>
        <para>The <code>href</code> attribute must be a valid URI according to
          <biblioref linkend="rfc3986"/>. If its value is relative, it is made absolute
          against the base URI of the manifest. There are two possible cases:</para>

        <itemizedlist>
        <listitem>
        <para>If the (absolute) <code>href</code> value is exactly the same as the base URI of a
        document appearing on the <port>source</port> port, that document is associated with this
        entry. If this entry is to be added to the archive, the associated document will be used.
        (The <code>serialization</code> document property can be used to provide serialization
        properties.)
        </para>
        </listitem>

        <listitem>
        <para>If no document on the <port>source</port> port has a base URI that is exactly the same
        as the (absolute) <code>href</code> value, the document at the specified URI is associated
        with this entry. These documents are stored in the archive “as is”; they
        <rfc2119>must not</rfc2119> be parsed and re-serialized.</para>
        </listitem>
        </itemizedlist>
      </listitem>

      <listitem>
        <para>The <code>comment</code> attribute specifies a comment associated with the
        entry. If the archive format does not support per-entry comments, the value
        of this attribute is ignored. <impl>If the format imposes constraints on the archive
        comment (character set or length, for example), how the processor coerces the attribute value
        to satisfy those constraints is <glossterm>implementation-dependent</glossterm>.</impl></para>
      </listitem>

      <listitem>
        <para>The <code>method</code> attribute specifies how the entry should be compressed.
            <impl>The default compression method is <glossterm>implementation-defined</glossterm>.
          </impl>Implementations <rfc2119>must</rfc2119> support no compression, specified with the
          value <code>none</code>. <impl>It is <glossterm>implementation-defined</glossterm> what
            other compression methods are supported.</impl></para>
      </listitem>
      <listitem>
        <para>The <code>level</code> attribute specifies the level of compression. <impl>The default
            compression level is <glossterm>implementation-defined</glossterm>. </impl>
          <impl>It is <glossterm>implementation-defined</glossterm> what compression levels are
            supported.</impl></para>
      </listitem>
      <listitem>
        <para>The <code>content-type</code> attribute specifies the content-type of the entry as
          detected by the processor. It will be set by <tag>p:archive-manifest</tag> in constructing
          the manifest. It will be ignored by <tag>p:archive</tag>.</para>
      </listitem>
    </itemizedlist>

    <para>The <code>p:archive</code> step <rfc2119>should</rfc2119> strive to retain the order of
      the <tag>c:entry</tag> elements when constructing the archive. For instance, an e-book in EPUB
      format has a non-compressed entry that must be first in the archive. It should be possible to
      construct such an archive using <code>p:archive</code>.</para>

    <para><impl>The <code>c:entry</code> elements may contain additional
          <glossterm>implementation-defined</glossterm> attributes.</impl></para>

    <para>If no manifest entry is provided for a document appearing on the <port>source</port> port,
      the step will create a manifest entry for the document.
      (If no document arrives on the <port>manifest</port> port at all, a complete manifest
      document will be created.)</para>

    <para>In a constructed manifest entry:</para>

    <itemizedlist>
    <listitem>
    <para>The entry’s <tag class="attribute">href</tag> value is the base URI of the document.
    </para>
    </listitem>
    <listitem>
    <para>The entry’s <tag class="attribute">name</tag> value is derived from the base URI of
    the document and the <option>relative-to</option> option.</para>
    <itemizedlist>
    <listitem>
    <para>First, the value of the <option>relative-to</option> option is made absolute. If the
    initial substring of the base URI is exactly the same as the resulting absolute value, then the
    <tag class="attribute">name</tag> is the portion of the base URI that follows that initial
    substring.
    </para>
    </listitem>
    <listitem>
    <para>If there is no <option>relative-to</option> option or if its value is not the initial
    substring of the base URI of the document, the name is the <emphasis>path</emphasis> portion of
    the URI (per <biblioref linkend="rfc3986"/>). If the path portion begins with an initial slash,
    that slash is removed.
    </para>
    </listitem>
    </itemizedlist>
    </listitem>
    </itemizedlist>
    
    <para>
      <error code="C0100">It is a <glossterm>dynamic error</glossterm> if an archive manifest is
        invalid according to the specification.</error></para>
  </section>

  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

  <section xml:id="cv.archive-zips">
    <title>Handling of ZIP archives</title>

    <para>The format of the archive can be specified using the <option>format</option> option.
      Implementations <rfc2119>must</rfc2119> support the <biblioref linkend="zip"/> format,
      specified with the value <code>zip</code>. </para>

   <para>When ZIP archives are processed, every <tag class="attribute">name</tag> in the
   manifest must be a relative path without a leading slash.</para>

    <para>The <option>parameters</option> option can be used to supply parameters to control the
      archiving. For the <code>zip</code> format, the following parameters <rfc2119>must</rfc2119>
      be supported:</para>

    <variablelist>
      <varlistentry>
        <term><code>command</code></term>
        <listitem>
          <para>Specifies what operation to perform. If not specified, its default value is
              <literal>update</literal>. Implementations must support the values <literal>update</literal>,
              <literal>create</literal>, <literal>freshen</literal>, and <literal>delete</literal>.
              <impl>The <tag>p:archive</tag> step may support additional,
              <glossterm>implementation-defined</glossterm> commands for ZIP files.</impl>
              Unless otherwise specified, exactly zero or one ZIP archive can appear on the
              <port>archive</port> port for the commands described below. If no archive appears,
              a new archive will be created.
          </para>

          <variablelist>
            <varlistentry>
              <term><code>update</code></term>
              <listitem>
                <para>When the <code>command</code> parameter is set to <code>update</code>, the
                ZIP archive will be updated:</para>

                <orderedlist>
                  <listitem>
                    <para>For every entry in the ZIP file:</para>
                    <itemizedlist>
                      <listitem>
                        <para>If the manifest contains a <tag>c:entry</tag> with a matching
                        <tag class="attribute">name</tag>, the entry in the ZIP file is updated with
                        the document identified by the <tag>c:entry</tag> in the manifest.</para>
                      </listitem>
                      <listitem>
                        <para>If the manifest does not contain a matching <tag>c:entry</tag>, the
                        ZIP entry name is resolved against the base URI of the ZIP file.</para>
                        <itemizedlist>
                          <listitem>
                            <para>If a document exists at that URI and either has no timestamp or has a timestamp
                            more than the timestamp in the ZIP file, the entry in the ZIP file will be updated
                            with the document at the resolved URI.</para>
                          </listitem>
                          <listitem>
                            <para>If no document exists at that URI, or the document cannot be accessed,
                            or the document has a timestamp and the timestamp in the ZIP archive is more recent
                            than the timestamp of the document, then the ZIP entry is unchanged.</para>
                          </listitem>
                        </itemizedlist>
                      </listitem>
                    </itemizedlist>
                  </listitem>
                  <listitem>
                    <para>For every <tag>c:entry</tag> in the manifest that does not have a matching
                    entry in the ZIP file, the ZIP file will be updated by adding the document identified
                    by the <tag>c:entry</tag> to the ZIP file.</para>
                  </listitem>
                </orderedlist>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term><code>create</code></term>
              <listitem>
                <para>When the <code>command</code> parameter is set to <code>create</code>,
                the ZIP archive will be created. Creating a ZIP archive behaves exactly like
                <literal>update</literal> except that any timestamps
                are ignored; every ZIP entry will be updated or created if there is a <tag>c:entry</tag> or
                  matching document for it. The document must be obtained by dereferencing the URI in 
                  <option>href</option>. <error code="D0011">It is a <glossterm>dynamic error</glossterm>
                    if the resource referenced by the <option>href</option> option does not exist, cannot be
                    accessed or is not a file.</error></para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term><code>freshen</code></term>
              <listitem>
                <para>When the <code>command</code> parameter is set to <code>freshen</code>,
                existing files in the ZIP archive may be updated, but no new files will be added.
                Freshing a ZIP archive behaves exactly like <literal>update</literal> except that
                only entries that already exist in the ZIP archive are considered.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term><code>delete</code></term>
              <listitem>
                <para>When the <code>command</code> parameter is set to <code>delete</code>,
                exactly one document in ZIP format must appear on the <port>archive</port> port.
                For every entry in the ZIP file:</para>
                <itemizedlist>
                  <listitem>
                    <para>If the manifest contains a <tag>c:entry</tag> with a matching
                    <tag class="attribute">name</tag>, the entry in the ZIP file is removed from
                    the ZIP archive.</para>
                  </listitem>
                </itemizedlist>
                <para>If the manifest contains <tag>c:entry</tag>
                elements which do not have a matching entry in the ZIP
                archive, they are simply ignored.</para>
              </listitem>
            </varlistentry>
          </variablelist>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><code>level</code></term>
        <listitem>
          <para>Specifies the default compression level for files added to or updated in the
            archive. If the <tag class="attribute">level</tag> attribute is specified on a
            <tag>c:entry</tag>, its value takes precedence for that entry.
            Values that must be supported for ZIP files are:
              “<code>smallest</code>”, “<code>fastest</code>”, “<code>default</code>”,
              “<code>huffman</code>”, and “<code>none</code>”.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><code>method</code></term>
        <listitem>
          <para>Specifies the default compression method for files added to or updated in the
            archive. If the <tag class="attribute">method</tag> attribute is specified on a
            <tag>c:entry</tag>, its value takes precedence for that entry.
            Values that must be supported for ZIP files are:
              “<code>none</code>” and “<code>deflated</code>”.</para>
        </listitem>
      </varlistentry>
    </variablelist>

    <para><error code="C0080">It is a <glossterm>dynamic error</glossterm> if the number of
        documents on the <port>archive</port> does not match the expected number of archive input
        documents for the given <code>format</code> and <code>command</code>.</error></para>

    <para>Implementations of other archive formats <rfc2119>should</rfc2119> use the same parameter
      names if applicable. The value spaces for these parameters may be format-specific though.
        <impl>The actual parameter names supported by <tag>p:archive</tag> for a particular format
        are <glossterm>implementation-defined</glossterm>.</impl></para>

  </section>

  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

  <simplesect>
    <title>Document properties</title>
    <para feature="archive-preserves-none">No document properties are preserved.
The archive has no <property>base-uri</property>.</para>
  </simplesect>

</section>
<section xml:id="c.archive-manifest">

  <title>p:archive-manifest</title>

  <para>The <code>p:archive-manifest</code> creates an XML manifest file describing the contents of
    the archive appearing on its <port>source</port> port.</para>

  <p:declare-step type="p:archive-manifest">
    <p:input port="source" primary="true" content-types="any" sequence="false"/>
    <p:output port="result" primary="true" content-types="application/xml" sequence="false"/>
    <p:option name="format" as="xs:QName?"/>
    <p:option name="parameters" as="map(xs:QName, item()*)?"/>
    <p:option name="relative-to" as="xs:anyURI?"/>
    <p:option name="override-content-types" as="array(array(xs:string))?"/>
  </p:declare-step>

  <para>The <code>p:archive-manifest</code> step inspects the archive appearing on its
      <port>source</port> port and outputs a manifest describing the contents of the archive on its
      <port>result</port> port. </para>

  <para>The format of the archive is determined as follows:</para>
  <itemizedlist>
    <listitem>
      <para>If the <option>format</option> option is specified, this determines the format of the
        archive. Implementations <rfc2119>must</rfc2119> support the <biblioref linkend="zip"/>
        format, specified with the value <code>zip</code>. <impl>It is
            <glossterm>implementation-defined</glossterm> what other formats are supported.</impl>
        <error code="C0081">It is a <glossterm>dynamic error</glossterm> if the format of the
          archive does not match the format as specified in the <option>format</option>
          option.</error>
      </para>
    </listitem>
    <listitem>
      <para>If no <option>format</option> option is specified or if its value is the empty sequence,
        the archive's format will be determined by the step, using the <code>content-type</code>
        document-property of the document on the <port>source</port> port and/or by inspecting its
        contents. <impl>It is <glossterm>implementation-defined</glossterm> how the step determines
          the archive's format.</impl> Implementations <rfc2119>should</rfc2119> recognize archives
        in <biblioref linkend="zip"/> format. </para>
    </listitem>
  </itemizedlist>

  <para><error code="C0085">It is a <glossterm>dynamic error</glossterm> if the format of the
      archive cannot be understood, determined and/or processed.</error></para>

  <para>The <option>parameters</option> option can be used to supply parameters to control the
    archive manifest generation. <impl>The semantics of the keys and the allowed values for these
      keys are <glossterm>implementation-defined</glossterm>.</impl>
    <error code="C0079">It is a <glossterm>dynamic error</glossterm> if the map
        <option>parameters</option> contains an entry whose key is defined by the implementation and
      whose value is not valid for that key.</error></para>

  <para>The <option>relative-to</option> option, when present, is used in creating the value of the
    manifest's <code>c:entry/@href</code> attribute. If the option is relative, it is made absolute
    against the base URI of the element on which it is specified (<tag>p:with-option</tag> or the
    step in case of a syntactic shortcut value). <error code="D0064">It is a <glossterm>dynamic
        error</glossterm> if the base URI is not both absolute and valid according to <biblioref linkend="rfc3986"/>.</error></para>

  <para>The generated manifest has the format as described in <xref linkend="cv.archive-manifest"/>.
    Implementations <rfc2119>must</rfc2119> supply an <tag>c:entry</tag> element and its
      <code>name</code> and <code>content-type</code> attributes for every entry in the archive. The
    value of the generated manifest's <code>c:entry/@href</code> attribute will be determined in the
    same way as a base URI of an unarchived document by <xref linkend="c.unarchive"/>. <error code="C0120">It is a <glossterm>dynamic error</glossterm> if the <option>relative-to</option>
      option is not present and the document on the <port>source</port> port does not have a base
      URI.</error>
    <impl>Additional information provided for entries in <tag>p:archive-manifest</tag> is
        <glossterm>implementation-defined</glossterm>.</impl></para>

  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

  <section xml:id="override-content-type">
    <title>Overriding content types</title>

    <para>The <option>override-content-types</option> option can be used to partially override the
      content-type determination mechanism. If present, it must be an array of arrays, where the
      inner arrays consist of exactly two strings: </para>
    <itemizedlist>
      <listitem>
        <para>The first member in an inner array <rfc2119>must</rfc2119> be a regular expression as
          specified in <biblioref linkend="xpath31-functions"/>, section 7.61 “<literal>Regular
            Expression Syntax</literal>”. <error code="C0147">It is a <glossterm>dynamic
              error</glossterm> if the specified value is not a valid XPath regular
            expression.</error></para>
      </listitem>
      <listitem>
        <para>The second member in an inner array <rfc2119>must</rfc2119> be a valid a MIME
          content-type. <error code="D0079">It is a <glossterm>dynamic error</glossterm> if a supplied 
            content-type is not a valid media type of the form 
            “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable>+<replaceable>ext</replaceable></literal>” 
            or “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable></literal>”.</error></para>
      </listitem>
    </itemizedlist>

    <para><error code="C0146">It is a <glossterm>dynamic error</glossterm> if the specified value
        for the <option>override-content-types</option> option is not an array of arrays, where the
        inner arrays have exactly two members of type <code>xs:string</code>.</error></para>

    <para>Determining an archive entry's content-type is as follows:</para>
    <itemizedlist>
      <listitem>
        <para>The XPath regular expressions (the first members of the inner arrays) will be matched
          against the path of the entry <emphasis>in</emphasis> the archive. This will be done in
          the order of appearance in the outer array (so order is significant). The matching is done
          unanchored: it is a match if the regular expression matches part of the entry's path.
          Informally: matching behaves like applying the XPath <code>matches#2</code> function, like
          in <code>matches($path-in-archive, $regular-expression)</code>.</para>
        <note>
          <para>Depending on how archives are constructed, the path of an entry in an archive can be
            with or without a leading slash. Usually it will be without. For archives constructed by
              <tag>p:archive</tag> no leading slash will be present.</para>
        </note>
      </listitem>
      <listitem>
        <para>If a match is found, the content-type (the second member of the inner array for which
          the match was found) is used as the entry's content-type.</para>
      </listitem>
      <listitem>
        <para>If no match was found for all inner arrays, the normal
            (implementation-defined) mechanism for determining the
          content-type is used. </para>
      </listitem>
    </itemizedlist>

    <para>For example: setting the <option>override-content-types</option> option to <code>[
        ['.rels$', 'application/xml'], ['^special/', 'application/octet-stream'] ]</code> means that
      all files ending with <code>.rels</code> will get the content-type
        <code>application/xml</code>. All files in the archive's <code>special</code> directory
      (including sub-directories) will get the content-type
      <code>application/octet-stream</code>.</para>

  </section>

  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

  <simplesect>
    <title>Document properties</title>
    <para feature="archive-manifest-preserves-none">No document properties are preserved. The
      manifest has no <property>base-uri</property>.</para>
  </simplesect>
</section>
<section xml:id="c.cast-content-type">
   <title>p:cast-content-type</title>
   
   <para>The <tag>p:cast-content-type</tag> step creates a new document by 
      changing the media type of its input. If the value of the <option>content-type</option>
   option and the current media type of the document on <port>source</port> port are
   the same, this document will appear unchanged on <port>result</port> port.</para>
   
   <p:declare-step type="p:cast-content-type">
      <p:input port="source" content-types="any"/>
      <p:output port="result" content-types="any"/>
      <p:option name="content-type" required="true" as="xs:string"/>
      <p:option name="parameters" as="map(xs:QName,item()*)?"/>
   </p:declare-step>
   
   <para>The input document is transformed from one media type to another.
      <error code="D0079">It is a <glossterm>dynamic error</glossterm> if a supplied content-type is not 
         a valid media type of the form 
         “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable>+<replaceable>ext</replaceable></literal>” 
         or “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable></literal>”.</error>
      <error code="C0071">It is a <glossterm>dynamic
         error</glossterm> if the <tag>p:cast-content-type</tag> step
         cannot perform the requested cast.</error>
   </para>
   
   <para>The <option>parameters</option> can be used to supply parameters to
      control casting. <impl>The semantics of the keys and the allowed values for
         these keys are <glossterm>implementation-defined</glossterm>.</impl>
      <error code="C0079">It is a <glossterm>dynamic error</glossterm> if the map
         <option>parameters</option> contains an entry whose key is defined by the
         implementation and whose value is not valid for that key.</error></para>
   
   <section xml:id="casting-from-xml">
      <title>Casting from an XML media type</title> 
      <itemizedlist>
        <listitem>
          <para>If the input document is a <tag>c:data</tag> document, casting
          decodes the text content of the <tag>c:data</tag> element according to the
          <tag class="attribute">encoding</tag> and processes it according to its content type.
          The resulting document will have the specified content type.
          The serialization property is removed.</para>
          <para><error code="C0052">It is a <glossterm>dynamic error</glossterm> if
          the encoding specified is not supported by the implementation.</error></para>
          <para><error code="C0072">It is a <glossterm>dynamic
          error</glossterm> if the <tag>c:data</tag> contains content is not
          a valid string according to the encoding.</error></para>
          <para><error code="C0073">It is a <glossterm>dynamic
          error</glossterm> if the <tag>c:data</tag> element does not have
          a <tag class="attribute">content-type</tag> attribute.</error></para>
          <para><error code="C0074">It is a <glossterm>dynamic
          error</glossterm> if the <option>content-type</option> is supplied and is
          not the same as the <tag class="attribute">content-type</tag> specified on
          the <tag>c:data</tag> element.</error>
          </para>
        </listitem>
         <listitem>
            <para>If the input document is not a <tag>c:data</tag> document,
            casting from one XML media type to another simply changes the
               “<literal>content-type</literal>” document property.
            </para>
         </listitem>
         <listitem>
            <para>Casting from an XML media type to an HTML media type changes the
               “<literal>content-type</literal>” document property and removes any
               serialization property.
            </para>
         </listitem>
         <listitem>
            <para>Casting from an XML media type to a JSON media type converts
            the XML into JSON. If the input document is an XML representation of
            JSON as defined in <biblioref linkend="xpath31-functions"/>,
            implementations <rfc2119>must</rfc2119> produce the same result as
            <literal>fn:parse-json(fn:xml-to-json())</literal> by default. If
            the input document has a <tag>c:param-set</tag> document element, an
            instance of <literal>map(xs:QName, xs:string)</literal>
            <rfc2119>must</rfc2119> be returned that represents the document's
            <tag>c:param</tag> elements. <impl>It is
            <glossterm>implementation-defined</glossterm> if any additional
            conversions are supported.</impl> The serialization property is
            removed.
            </para>
         </listitem>
         <listitem>
            <para>Casting from an XML media type to a text media type serializes the XML document
               by calling <function>fn:serialize($doc, $param)</function> where <literal>$doc</literal> is
               the document on the <port>source</port> port and <literal>$param</literal> is the serialization
               property of this document. The resulting string is wrapped by a document node and returned
               on the <port>result</port> port. The serialization property is removed.</para>
         </listitem>
         <listitem>
            <para><impl>Casting from an XML media type to any other media type when
               the input document is not a <tag>c:data</tag> document is
               <glossterm>implementation-defined</glossterm>.</impl></para>
         </listitem>
      </itemizedlist>

   <simplesect xml:id="c.param-set">
     <title>Parameter sets</title>

     <para>In XProc 3.1, maps are used for parameters. In XProc 1.0, no maps were
     available, so an XML vocabulary was defined. It is sometimes convenient to generate
     a map this way, so the vocabulary is retained.</para>

     <para>A <tag>c:parameter-set</tag> is a wrapper around zero or more <tag>c:param</tag>
     elements.</para>

     <e:rng-pattern name="VocabParamSet" xml:id="cv.param-set"/>

     <para><error code="D0018">It is a <glossterm>dynamic error</glossterm> if
     the parameter list contains any elements other than <tag>c:param</tag>.</error></para>

     <para>Any namespace-qualified attribute names that appear on the
     <tag>c:param-set</tag> element are ignored. <error code="D0014">It is a
     <glossterm>dynamic error</glossterm> for any unqualified
     attribute names to appear on a <tag>c:param-set</tag> element.</error></para>
     
     <para xml:id="c.param">A <tag>c:param</tag> is a name/value pair with an optional namespace.</para>

     <e:rng-pattern name="VocabParam" xml:id="cv.param"/>

     <para>The <tag class="attribute">name</tag> attribute of the
     <tag>c:param</tag> must have the lexical form of a QName.</para>

     <para>If the <tag class="attribute">namespace</tag> attribute is specified,
     then the expanded name of the parameter is constructed from the specified
     namespace and the name value. <error code="D0025">It is a
     <glossterm>dynamic error</glossterm> if the <tag class="attribute">namespace</tag> attribute is
     specified, the <tag class="attribute">name</tag> contains a colon, and the specified namespace is not
     the same as the in-scope namespace binding for the specified prefix.</error></para>

     <para>If the <tag class="attribute">namespace</tag> attribute is not
     specified, and the <tag class="attribute">name</tag> contains a colon, then
     the expanded name of the parameter is constructed using the name value and
     the namespace declarations in-scope on the <tag>c:param</tag> element.</para>

     <para>If the <tag class="attribute">namespace</tag> attribute is not
     specified, and the <tag class="attribute">name</tag> does not contain a
     colon, then the expanded name of the parameter is in no namespace.</para>

     <para>If the <tag>c:param</tag> element has a <tag class="attribute">value</tag>
     attribute, the element <rfc2119>must</rfc2119> be empty. If it does not have a
     <tag class="attribute">value</tag> attribute, the content of the element is
     the value. In either case, the type of the value may be specified with a
     sequence type in the
     <tag class="attribute">as</tag> attribute. <error code="D0081">It is a
     <glossterm>dynamic error</glossterm> if the <tag>c:param</tag> element has a
     <tag class="attribute">value</tag> attribute and is not empty.</error>
     <error code="D0082">It is a <glossterm>dynamic error</glossterm> if the
     <tag>c:param</tag> specifies a sequence type and the value does not
     satisfy that type.</error></para>

     <para>Any namespace-qualified attribute names that appear on the
     <tag>c:param</tag> element are ignored. <error code="D0014">It is a
     <glossterm>dynamic error</glossterm> for any unqualified attribute names
     other than those specified here to appear on a <tag>c:param</tag> element.</error></para>
   </simplesect>
   </section>
   <section xml:id="casting-from-html">
      <title>Casting from an HTML media type</title>
      <itemizedlist>
         <listitem>
            <para>Casting from an HTML media type to an XML media type changes
               “<literal>content-type</literal>” document property and removes any
               serialization property. </para>
         </listitem>
         <listitem>
            <para>Casting from an HTML media type to another HTML media type
               changes “<literal>content-type</literal>” document property.</para>
         </listitem>
         <listitem>
            <para><impl>Casting from an HTML media type to a JSON media type is 
               <glossterm>implementation-defined</glossterm>.</impl></para>
         </listitem>
         <listitem>
            <para>Casting an an HTML media type to a text media type serializes the HTML document
               by calling <function>fn:serialize($doc, $param)</function> where <literal>$doc</literal> is
               the document on the <port>source</port> port and <literal>$param</literal> is the serialization
               property of this document. The resulting string is wrapped by a document node and returned
               on the <port>result</port> port. The serialization property is removed.</para>
         </listitem>
         <listitem>
            <para><impl>Casting from an HTML media type to any other media type is
               <glossterm>implementation-defined</glossterm>.</impl></para>
         </listitem>
      </itemizedlist>
   </section>
   <section xml:id="casting-from-json">
      <title>Casting from a JSON media type</title>
      <itemizedlist>
         <listitem>
            <para>Casting from a JSON media type to an XML media type converts the
               JSON into XML. An implementation <rfc2119>must</rfc2119> support the format
               specified in section “XML Representation of JSON” of <biblioref linkend="xpath31-functions"/>
               as default for the resulting XML. <impl>It is <glossterm>implementation-defined</glossterm> whether
                  other result formats are supported.</impl> The serialization property is removed.</para>
         </listitem>
         <listitem>
            <para><impl>Casting from a JSON media type to an HTML media type is
               <glossterm>implementation-defined</glossterm>.</impl></para>
         </listitem>
         <listitem>
            <para>Casting from a JSON media type to another JSON media type
               changes “<literal>content-type</literal>” document property.</para>
         </listitem>
         <listitem>
            <para>Casting from a JSON media type to a text media type serializes the JSON document
               by calling <function>fn:serialize($doc, $param)</function> where <literal>$doc</literal> is
               the document on the <port>source</port> port and <literal>$param</literal> is the serialization
               property of this document. The resulting string is wrapped by a document node and returned
               on the <port>result</port> port. The serialization property is removed.</para>
         </listitem>
         <listitem>
            <para><impl>Casting from a JSON media type to any other media type is
               <glossterm>implementation-defined</glossterm>.</impl></para>
         </listitem>
      </itemizedlist>
   </section>
   <section xml:id="casting-from-text">
      <title>Casting from a text media type</title>
      <itemizedlist>
         <listitem>
            <para>Casting from a text media type to an XML media type parses the text value
               of the document on <port>source</port> port by calling <function>fn:parse-xml</function>.
               <error code="D0049">It is a <glossterm>dynamic error</glossterm> if the text value is not
                  a well-formed XML document</error>. The serialization property is removed.</para>
         </listitem>
         <listitem>
            <para>Casting from a text media type to an HTML media type parses the text value
               of the document on <port>source</port> port into an XPath data model document that 
               contains a tree of elements, attributes, and other nodes. <impl>The precise way in which 
                  text documents are parsed into the XPath data model is 
                  <glossterm>implementation-defined</glossterm>.</impl> <error code="D0060">It is a 
                     <glossterm>dynamic error</glossterm> if the text document can not be converted into
                     the XPath data model</error>. The serialization property is removed.</para> 
         </listitem>
         <listitem>
            <para>Casting from a text media type to a JSON media type parses the text value 
               of the document on <port>source</port> port by calling <function>fn:parse-json($doc, $par)</function>
               where <literal>$doc</literal> is the text document and <literal>$par</literal> is the 
               <option>parameter</option> option. <error code="D0057">It is a <glossterm>dynamic
                  error</glossterm> if the text document does not conform to the JSON grammar, unless the 
                  parameter liberal is true and the processor chooses to accept the deviation.</error>
               <error code="D0058">It is a <glossterm>dynamic error</glossterm> if the parameter duplicates is 
                  reject and the text document contains a JSON object with duplicate keys.</error>
               <error code="D0059">It is a <glossterm>dynamic error</glossterm> if the parameter map contains 
                  an entry whose key is defined in the specification of <function>fn:parse-json</function> and 
                  whose value is not valid for that key, or if it contains an entry with the key fallback 
                  when the parameter <literal>escape</literal> with <literal>true()</literal> is also 
                  present.</error> The serialization property is removed.
            </para>
         </listitem>
         <listitem>
            <para>Casting from a text media type to another text media type changes 
               “<literal>content-type</literal>” document property.</para>
         </listitem>
         <listitem>
            <para><impl>Casting from a text media type to any other media type is
               <glossterm>implementation-defined</glossterm>.</impl></para>
         </listitem>
      </itemizedlist>
   </section>
   <section xml:id="casting-from-other">
      <title>Casting from any other media type</title>
      <itemizedlist>
         <listitem xml:id="c.data">
            <para>Casting from a non-XML media type to an XML media type produces an
               XML document with a <tag>c:data</tag> document element. The original
               media type will be preserved in the
               <tag class="attribute">content-type</tag> attribute on the
               <tag>c:data</tag> element.</para>
            
            <e:rng-pattern name="VocabData"/>
            
            <para>The content of the <tag>c:data</tag> element is the base64 encoded
               representation of the non-XML content. The serialization property is removed.</para>
         </listitem>
         <listitem>
            <para><impl>Casting from any other media type to a HTML media type, a JSON media type
               or a text document is <glossterm>implementation-defined</glossterm>.</impl></para>
         </listitem>
         <listitem>
            <para><impl>Casting from any other media type to any other media type is 
               <glossterm>implementation-defined</glossterm>.</impl></para>
         </listitem>
      </itemizedlist>
   </section>
   <simplesect>
      <title>Document properties</title>
      <para feature="cast-content-type-preserves-some">All document
         properties are preserved except the <code>content-type</code> property
         which is updated accordingly and the <code>serialization</code> property
         which is removed by some casting methods.</para>
   </simplesect>
</section>
<section xml:id="c.compare">
<title>p:compare</title>

<para>The <code>p:compare</code> step compares two documents for
equality.</para>

<p:declare-step type="p:compare">
   <p:input port="source" primary="true" content-types="any"/>
   <p:input port="alternate" content-types="any"/>
   <p:output port="result" primary="true" content-types="application/xml"/>
   <p:output port="differences" content-types="any" sequence="true"/>
   <p:option name="parameters" as="map(xs:QName,item()*)?"/>
   <p:option name="method" as="xs:QName?"/>
   <p:option name="fail-if-not-equal" as="xs:boolean" select="false()"/>
</p:declare-step>

<para>This step takes single documents on each of two ports and
compares them. If <option>method</option> is not specified, or if
<code>deep-equal</code> is specified, the comparison
uses <function>fn:deep-equal</function>
(as defined in <biblioref linkend="xpath31-functions"/>). <impl>Implementations of <tag>p:compare</tag>
<rfc2119>must</rfc2119> support the <code>deep-equal</code> <option>method</option>;
other supported methods are <glossterm>implementation-defined</glossterm>.</impl>
<error code="C0076">It is a <glossterm>dynamic error</glossterm> if
the comparison <option>method</option> specified in <tag>p:compare</tag>
is not supported by the implementation.</error>
<error code="C0077">It is a <glossterm>dynamic error</glossterm> if
the media types of the documents supplied are incompatible with the
comparison <option>method</option>.</error>
</para>

<para><error code="C0019">It is a <glossterm>dynamic error</glossterm>
if the documents are not equal according to the specified comparison
<option>method</option>, and the value of the
<option>fail-if-not-equal</option> option is
<literal>true</literal>.</error> If the documents are equal, or if the
value of the <option>fail-if-not-equal</option> option is
<literal>false</literal>, a <tag>c:result</tag> document is produced
with contents <literal>true</literal> if the documents are equal,
otherwise <literal>false</literal>.</para>

<para><impl>If
<option>fail-if-not-equal</option> is <code>false</code>, and the
documents differ, an <glossterm>implementation-defined</glossterm>
summary of the differences between the two documents may appear on the
<port>differences</port> port.</impl></para>

<simplesect>
<title>Document properties</title>
<para feature="compare-preserves-none">No document properties are preserved.
The comparison document has no <property>base-uri</property>.</para>
</simplesect>
</section>
<section xml:id="c.compress">

  <title>p:compress</title>

  <para>The <tag>p:compress</tag> step serializes the document appearing on its <port>source</port>
    port and outputs a compressed version of this on its <port>result</port> port.</para>

  <p:declare-step type="p:compress">
    <p:input port="source" primary="true" content-types="any" sequence="false"/>
    <p:output port="result" primary="true" content-types="any" sequence="false"/>
    <p:option name="format" as="xs:QName" select="'gzip'"/>
    <p:option name="serialization" as="map(xs:QName,item()*)?"/>
    <p:option name="parameters" as="map(xs:QName, item()*)?"/>
  </p:declare-step>

  <para>The <tag>p:compress</tag> step first serializes the document appearing on its
      <port>source</port>. It then compresses the outcome of this serialization and outputs the
    result on its <port>result</port> port.</para>

  <para>The <tag>p:compress</tag> step has the following options:</para>
  <variablelist>
    <varlistentry>
      <term><option>format</option></term>
      <listitem>
        <para>The format of the compression can be specified using the <option>format</option>
          option. Implementations <rfc2119>must</rfc2119> support the <biblioref linkend="gzip"/>
          format, specified with the value <code>gzip</code>. <impl>It is
              <glossterm>implementation-defined</glossterm> what other formats are supported.</impl>
          <error code="C0202">It is a <glossterm>dynamic error</glossterm> if the compression
              format cannot be understood, determined and/or processed.</error>
        </para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term><option>parameters</option></term>
      <listitem>
        <para>The <option>parameters</option> option can be used to supply parameters to control the
          compression. <impl>The semantics of the keys and the allowed values for these keys are
              <glossterm>implementation-defined</glossterm>.</impl>
          <error code="C0079">It is a <glossterm>dynamic error</glossterm> if the map
              <option>parameters</option> contains an entry whose key is defined by the
            implementation and whose value is not valid for that key.</error></para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term><option>serialization</option></term>
      <listitem>
        <para>The <option>serialization</option> option is provided to control the serialization of
          content before compression takes place. If the document to be stored has a
            <code>serialization</code> property, the serialization is controlled by the merger of
          the two maps where the entries in the <code>serialization</code> property take precedence.
          Serialization is described in <biblioref linkend="xproc31"/>.</para>
      </listitem>
    </varlistentry>
  </variablelist>

  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

  <simplesect>
    <title>Document properties</title>
    <para feature="compress-preserves-some">All document properties are preserved, except for the
        <code>content-type</code> property which is updated accordingly and the
        <code>serialization</code> property which is removed.</para>
  </simplesect>

</section>
<section xml:id="c.count">
<title>p:count</title>

<para feature="p-count">The <code>p:count</code> step counts the number of documents in
the <code>source</code> input sequence and returns a single document
on <code>result</code> containing that number. The generated document
contains a single <tag>c:result</tag> element whose contents is the
string representation of the number of documents in the
sequence.</para>

<p:declare-step type="p:count">
   <p:input port="source" content-types="any" sequence="true"/>
   <p:output port="result" content-types="application/xml"/>
   <p:option name="limit" as="xs:integer" select="0"/>
</p:declare-step>

<para>If the <tag feature="p-count-limit" class="attribute">limit</tag> option is specified
and is greater than zero, the <tag>p:count</tag> step will count at most
that many documents. This provides a convenient mechanism to discover,
for example, if a sequence consists of more than 1 document, without
requiring every document to be counted.</para>

<simplesect>
<title>Document properties</title>
<para feature="count-preserves-none">No document properties are preserved.
The count document has no <property>base-uri</property>.</para>
</simplesect>
</section>
<section xml:id="c.delete">
<title>p:delete</title>

<para>The <code>p:delete</code> step deletes items specified by a <glossterm>selection pattern</glossterm> from the
<code>source</code> input document and produces the resulting document,
with the deleted items removed, on the <port>result</port> port.</para>

<p:declare-step type="p:delete">
   <p:input port="source" content-types="xml html"/>
   <p:output port="result" content-types="text xml html"/>
   <p:option name="match" required="true" as="xs:string" e:type="XSLTSelectionPattern"/>
</p:declare-step>

<para>The value of the <option>match</option> option <rfc2119>must</rfc2119> be an
XSLTSelectionPattern. A <glossterm>selection pattern</glossterm> may match multiple items to be
deleted.</para>

<para>If an element is selected by the <option>match</option> option, the
entire subtree rooted at that element is deleted.</para>

<para><error code="C0023">It is a <glossterm>dynamic error</glossterm> if the
<option>match</option> option matches the document node.</error></para>

<para>This step cannot be used to remove namespaces. <error code="C0062">It is a <glossterm>dynamic error</glossterm> if the
<option>match</option> option matches a namespace node.</error>
Also, note that deleting an attribute named
<tag class="attribute">xml:base</tag> does not change the base URI
of the element on which it occurred.</para>

<simplesect>
<title>Document properties</title>
   <para feature="delete-preserves-partially">If the resulting document contains exactly one text node,
      the <literal>content-type</literal> property is changed to <literal>text/plain</literal> and the 
      <literal>serialization</literal> property is removed, while all other document properties are 
      preserved. In all other cases, all document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.encode">
<title>p:encode</title>

<para>The <code>p:encode</code> step encodes an input document, for example with base64 encoding.
</para>

<p:declare-step type="p:encode">
  <p:input port="source"/>
  <p:output port="result" content-types="application/xml"/>
  <p:option name="encoding" as="xs:string" select="'base64'"/>
  <p:option name="serialization" as="map(xs:QName,item()*)?"/>
</p:declare-step>

<para>The encode step produces an XML document by encoding its input. The
encoding value “<literal>base64</literal>” <rfc2119>must</rfc2119> be supported.
<impl>An implementation may support encodings other than
<literal>base64</literal>, but these encodings and their names are
<glossterm>implementation-defined</glossterm>.</impl> <error code="C0052">It is
a <glossterm>dynamic error</glossterm> if the encoding specified is not supported
by the implementation.</error>
</para>

<para>If the input document is a binary document, its content is encoded
directly, otherwise the content is first serialized and the serialized
representation is encoded. The <option>serialization</option> option is provided
to control the serialization of content when it is stored. If the document to be
stored has a “serialization” property, the serialization is controlled by the
merger of the two maps where the entries in the “serialization” property take
precedence. Serialization is described in <biblioref linkend="xproc31"/>.</para>

<para>The result of encoding is a <tag>c:data</tag> element.</para>

<e:rng-pattern name="VocabData"/>
            
<para>The content of the <tag>c:data</tag> element is the encoded representation
of the content.</para>

<note>
<para>There is no <code>p:decode</code> step. Decoding is performed by the
<tag>p:cast-content-type</tag> step if the input is a <tag>c:data</tag>
document.</para>
</note>

<simplesect>
<title>Document properties</title>
<para feature="encode-preserves-none">No document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.error">
<title>p:error</title>

<para>The <code>p:error</code> step generates a
<glossterm role="unwrapped">dynamic error</glossterm> using the input provided to the
step.</para>

<p:declare-step type="p:error">
    <p:input port="source" sequence="true" content-types="text xml"/>
    <p:output port="result" sequence="true" content-types="any"/>
    <p:option name="code" required="true" as="xs:QName"/>
</p:declare-step>

<para>The <tag>p:error</tag> step always fails. It generates a single error with the
error code specified in the 
<option>code</option> option. It also produces a <tag>c:errors</tag> document that
will be visible on the error port inside a <tag>p:catch</tag>.
(The error vocabulary is described in <biblioref linkend="xproc31"/>.)
</para>

<para>This step <rfc2119>should</rfc2119> include the content of the document
that appears on the <port>source</port> port in the error. If more than one
document appears on the <port>source</port> port of the <tag>p:error</tag> step, all
of the documents <rfc2119>must</rfc2119> be added to a single <tag>c:error</tag>
element.</para>

<para>For authoring convenience, the <tag>p:error</tag> step is declared with a
single, primary output port. With respect to connections, this port behaves like
any other output port even though nothing can ever appear on it since the step
always fails.</para>

<para>For example, given the following invocation:</para>
<programlisting language="xml">&lt;p:error xmlns:my="http://www.example.org/error"
         name="bad-document" code="my:unk12"&gt;
   &lt;p:with-input port="source"&gt;
     &lt;message&gt;The document element is unknown.&lt;/message&gt;
   &lt;/p:with-input&gt;
&lt;/p:error&gt;</programlisting>

<para>The errors document generated on the error output port might be:</para>

<programlisting language="xml">&lt;c:errors xmlns:c="http://www.w3.org/ns/xproc-step"
          xmlns:p="http://www.w3.org/ns/xproc"
          xmlns:my="http://www.example.org/error"&gt;
 &lt;c:error name="bad-document" type="p:error"
          code="my:unk12"&gt;&lt;message
          &gt;The document element is unknown.&lt;/message&gt;
&lt;/c:error&gt;
&lt;/c:errors&gt;</programlisting>

<para>The <tag class="attribute">href</tag>,
<tag class="attribute">line</tag> and <tag class="attribute">column</tag>,
or <tag class="attribute">offset</tag>, might also be present on the
<tag>c:error</tag> to identify the location of the <tag>p:error</tag>
element in the pipeline.</para>

<simplesect>
<title>Document properties</title>
<para feature="error-preserves-none">No document properties are preserved but
that’s irrelevant as no document is ever produced.</para>
</simplesect>
</section>
<section xml:id="c.filter">
<title>p:filter</title>

<para>The <code>p:filter</code> step evaluates an XPath expression
against the input document.</para>

<p:declare-step type="p:filter">
  <p:input port="source" content-types="xml html"/>
  <p:output port="result" sequence="true" content-types="text xml html json"/>
  <p:option name="select" required="true" as="xs:string" e:type="XPathExpression"/>
</p:declare-step>

<para>This step evaluates the <tag class="attribute">select</tag> expression
against the input document. The result of that evaluation appears on the
<port>result</port> port.</para>

<para>This step is very similar to a <tag>p:with-input</tag> with
a <tag class="attribute">select</tag> expression except that the select
expression is computed dynamically (because it’s a step option in this case).</para>

<simplesect>
<title>Document properties</title>
<para feature="filter-preserves-none">No document properties are preserved. When
portions of the input are selected, the <property>base-uri</property> property
of each document constructed from a selected portion will reflect the base URI
of the selected node(s).
</para>
</simplesect>
</section>
<section xml:id="c.hash">
<title>p:hash</title>

<para>The <tag>p:hash</tag> step generates a hash, or digital “fingerprint”,
for some value and injects it into the <port>source</port> document.</para>

<p:declare-step type="p:hash">
  <p:input port="source" primary="true" content-types="xml html"/>
  <p:output port="result" content-types="text xml html"/>
  <p:option name="parameters" as="map(xs:QName,item()*)?"/>
  <p:option name="value" required="true" as="xs:string"/>
  <p:option name="algorithm" required="true" as="xs:QName"/>
  <p:option name="match" as="xs:string" select="'/*/node()'" e:type="XSLTSelectionPattern"/>
  <p:option name="version" as="xs:string?"/>
</p:declare-step>

<para>The value of the <option>algorithm</option> option must be a QName.
If it does not have a prefix, then it must be one of the following values:
“crc”, “md”, or “sha”.</para>

<para>If a <tag class="attribute">version</tag> is not specified, the
default version is algorithm-defined. For “<literal>crc</literal>” it
is 32, for “<literal>md</literal>” it is 5, for “<literal>sha</literal>”
it is 1.</para>

<para>A hash is constructed from the string specified in the
<option>value</option> option using the specified algorithm and version.
Implementations <rfc2119>must</rfc2119> support
<biblioref linkend="bib.crc"/>,
<biblioref linkend="rfc1321"/>, and <biblioref linkend="bib.sha"/>
hashes. <impl>It is
<glossterm>implementation-defined</glossterm> what other algorithms are
supported.</impl>
The resulting hash <rfc2119>should</rfc2119> be returned as a string of
hexadecimal characters.
</para>

<para>The value of the <option>match</option> option must be an
XSLTSelectionPattern.</para>

<para>The hash of the specified value is computed using the algorithm and
parameters specified. <error code="C0036">It is a
<glossterm>dynamic error</glossterm> if the requested hash algorithm is not
one that the processor understands or if the value or parameters are
not appropriate for that algorithm.</error></para>

<para>The matched nodes are specified with the <glossterm>selection pattern</glossterm> in the
<option>match</option> option. For each matching node, the string
value of the computed hash is used in the output (if more than one node
matches, the <emphasis>same</emphasis> hash value is used in each match).
Nodes that do not
match are copied without change.</para>

<para>If the expression given in the <option>match</option> option
matches an <emphasis>attribute</emphasis>, the hash is used as the new
value of the attribute in the output.
If the attribute is named “<tag class="attribute">xml:base</tag>”, the base URI
of the element <rfc2119>must</rfc2119> also be amended accordingly.</para>

<para>If the document node is matched, the result is a text document.</para>

<para>If the expression matches any
other kind of node, the entire node (and <emphasis>not</emphasis> just
  its contents) is replaced by the hash.</para>

  <simplesect>
    <title>Document properties</title>
    <para feature="hash-preserves-partially">If the resulting document contains exactly one text node,
      the <literal>content-type</literal> property is changed to <literal>text/plain</literal> and the 
      <literal>serialization</literal> property is removed, while all other document properties are 
      preserved. For other document types, all document properties are preserved.</para>
  </simplesect>
</section>
<section xml:id="c.http-request">
<title>p:http-request</title>

<para>The <code>p:http-request</code> step allows authors to interact
with resources over HTTP or related protocols. Implementations
<rfc2119>must</rfc2119> support the <literal>http</literal> and
<literal>https</literal> protocols.
</para>

<p:declare-step type="p:http-request">
  <p:input port="source" content-types="any" sequence="true"/>
  <p:output port="result" primary="true" content-types="any" sequence="true"/>
  <p:output port="report" content-types="application/json"/>
  <p:option name="href" as="xs:anyURI" required="true"/>
  <p:option name="method" as="xs:string?" select="'GET'"/>
  <p:option name="serialization" as="map(xs:QName,item()*)?"/>
  <p:option name="headers" as="map(xs:string, xs:string)?"/>
  <p:option name="auth" as="map(xs:string, item()+)?"/>
  <p:option name="parameters" as="map(xs:QName, item()*)?"/>
  <p:option name="assert" as="xs:string" select="'.?status-code lt 400'"/>
</p:declare-step>

<para>The <tag>p:http-request</tag> step performs the HTTP request specified by
the <option>method</option> option against the URI specified in the
<option>href</option> option. In simple cases, for example, a GET request on an
unauthenticated URI, nothing else is necessary to form a complete request.
(Implementors are encouraged to support as many protocols as practical. In
particular, pipeline authors may attempt to use <tag>p:http-request</tag> to
load documents with computed URIs using the <literal>file:</literal> scheme.)
</para>

<para>If the method, for example, POST, supports a body, the request
body is constructed using the document(s) appearing on the
<port>source</port> port. For the convenience of pipeline authors,
documents may appear on the <port>source</port> port even when the
request method (such as GET or HEAD) does not define the semantics of
a payload. If the semantics are undefined, the documents are
ignored when constructing the request unless the
<option>parameters</option> option specifies
“<literal>send-body-anyway</literal>” as <code>true()</code>.</para>

<para>The headers for the request come from the
<option>headers</option> option (see below). If exactly one document
appears on the <port>source</port> port, its document properties also
contribute to the overall request headers.</para>

<para>The response from the HTTP request appears on the
<port>result</port> and <port>report</port> ports. Any documents
contained in the response body will appear on the <port>result</port>
port. Each document in the response will be parsed according to
its content-type (but see “<literal>override-content-type</literal>”
in the <option>parameters</option> option).
Details about the outcome of the request will appear as a map on
the <port>report</port> port. The map will always contain:
</para>

<variablelist>
<varlistentry>
  <term><literal>status-code</literal> (an <code>xs:integer</code>)</term>
  <listitem>
    <para>This is the HTTP status code returned for the request.</para>
  </listitem>
</varlistentry>
<varlistentry>
  <term><literal>base-uri</literal> (an <code>xs:anyURI</code>)</term>
  <listitem>
    <para>This is the URI of the last request made and is always
    available in the report even when the request does not return any
    documents. In the case of HTTP redirection, the base URI returned
    may be different from the original request URI.
    </para>
  </listitem>
</varlistentry>
<varlistentry>
  <term><literal>headers</literal> (a <code>map(xs:string, xs:string)</code>)</term>
  <listitem>
    <para>These are the HTTP headers returned for the request. The map may be
empty. Header names are converted to lowercase.</para>
  </listitem>
</varlistentry>
</variablelist>

<para>The <tag>p:http-request</tag> step has the following options:</para>
<variablelist>
<varlistentry>
  <term><option>href</option></term>
<listitem>
  <para>The <option>href</option> option specifies the request’s IRI.
  Relative values are resolved against the base URI of the element on
  which the option is specified (the relevant <tag>p:with-option</tag>
  or the step element in the case of a syntactic shortcut value).</para>

  <para>Fragment identifiers are removed before making the request.
  Query parameters are passed through unchanged.
  <error code="C0128">It is a <glossterm>dynamic error</glossterm> if the
  URI’s scheme is unknown or not supported.</error> It is the pipeline
  author’s responsibility to escape problematic UTF-8 characters in the
  <option>href</option> value, for example with <function>escape-html-uri()</function>.
  </para>
</listitem>
</varlistentry>
<varlistentry>
  <term><option>method</option></term>
<listitem>
  <para>The <option>method</option> specifies the HTTP request method.
  The value is implicitly turned into an uppercase string if
  necessary. <impl>It is <glossterm>implementation-defined</glossterm>
  which HTTP methods are supported.</impl> An implementation
  <rfc2119>should</rfc2119> implement at least the methods
  <literal>GET</literal>, <literal>POST</literal>,
  <literal>PUT</literal>, <literal>DELETE</literal>, and
  <literal>HEAD</literal> (for HTTP and HTTPS).
  <error code="C0122">It is a <glossterm>dynamic error</glossterm> if
  the given method is not supported.</error></para>
</listitem>
</varlistentry>
<varlistentry>
  <term><option>serialization</option></term>
<listitem>
  <para>The <option>serialization</option> option is used to control
  the serialization of documents for the request body. If a document
  has a “<literal>serialization</literal>” document property, the
  effective value of the serialization options is the union of the two
  maps, where the entries in the “<literal>serialization</literal>”
  document property take precedence.</para>
</listitem>
</varlistentry>
<varlistentry>
  <term><option>headers</option></term>
<listitem>
  <para>The key/value pairs in the <option>headers</option> map are
  used to construct the request headers. Each map key is used as a
  header name and the value associated with that key in the map is
  used as the header value.</para>

  <para>If a single document appears on the <port>source</port> port,
  then document properties on that document may be added as additional
  headers. For XML, HTML, and text documents with a 
  <literal>serialization</literal> document property having an 
    <literal>encoding</literal> key, a <literal>charset</literal> is
    appended to the created <literal>content-type</literal> header of
    the HTTP request.
  Properties in the <code>http://www.w3.org/ns/xproc-http</code>
  namespace will be added to the headers, using the local-name of the
  property QName as the header name. These properties are only copied
  if they are not specified in the <option>header</option> map. In
  other words, if the same header name appears in both places, the
  value from the map is used and the value from the document
  properties is ignored. (Header names are case-insensitive, so a case-insensitive
  comparison must be performed.) If multiple documents appear on the
  <port>source</port> port, none of their properties are used in the
  request headers.</para>

  <para>The behavior of the <tag>p:http-request</tag> depends on the
  headers specified. In particular:</para>

  <variablelist>
  <varlistentry>
    <term><literal>content-type</literal></term>
    <listitem>
      <para>If a <literal>content-type</literal> header is provided,
      it will be used. For a single document request, this overrides
      the content type value of the document. If the content type
      specified begins with “<literal>multipart/</literal>”, a
      multipart request will be sent to the server.</para>
      <para><error code="D0079">It is a <glossterm>dynamic error</glossterm> if a supplied content-type is not 
        a valid media type of the form 
        “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable>+<replaceable>ext</replaceable></literal>” 
        or “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable></literal>”.</error></para>
    </listitem>
  </varlistentry>
  <varlistentry>
    <term><literal>transfer-encoding</literal></term>
    <listitem>
      <para>If a <literal>transfer-encoding</literal> header is provided,
      the request <rfc2119>must</rfc2119> be sent with that encoding.
      <error code="C0131">It is a <glossterm>dynamic error</glossterm> if
      the processor cannot support the requested encoding.</error></para>
    </listitem>
  </varlistentry>
  <varlistentry>
    <term><literal>authorization</literal></term>
    <listitem>
      <para>The <literal>authorization</literal> header is used to
      authenticate a request. If the <option>auth</option>
      <emphasis>option</emphasis> is specified, any key or property
      that would have contributed a header named
      “<literal>authorization</literal>” (irrespective of case) is
      ignored. The authorization header is determined exclusively by
      the <option>auth</option> option when it is present.</para>
    </listitem>
  </varlistentry>
  </variablelist>

  <para>HTTP headers are case-insensitive but keys in maps are not;
  be careful when specifying the request headers.
  <error code="C0127">It is a <glossterm>dynamic error</glossterm> if
  the <option>headers</option> map contains two keys that are the same
  when compared in a case-insensitive manner.</error>
  (That is, when <code>fn:uppercase($key1) = fn:uppercase($key2)</code>.)
  </para>
</listitem>
</varlistentry>
<varlistentry>
  <term><option>auth</option></term>
<listitem>
  <para>Many web services are only available to authenticated users,
  that is, to users who have “logged in”. The <option>auth</option>
  option allows the pipeline author to specify information that may be
  required to generate an “<literal>Authorization</literal>” header.
  The standard values support HTTP “Basic” and “Digest”
  authentication, but other authentication methods are allowed.</para>

  <para>The following standard keys are defined:</para>

  <variablelist>
  <varlistentry><term><literal>username</literal> (<code>xs:string</code>)</term>
  <listitem>
  <para>The username.</para>
  </listitem>
  </varlistentry>
  <varlistentry><term><literal>password</literal> (<code>xs:string</code>)</term>
  <listitem>
  <para>The password associated with the username.</para>
  </listitem>
  </varlistentry>
  <varlistentry><term><literal>auth-method</literal> (<code>xs:string</code>)</term>
  <listitem>
  <para>The authentication method. Appropriate values for the
  “<literal>auth-method</literal>” key are “<literal>Basic</literal>”
  or “<literal>Digest</literal>” but other values are allowed. If the
  authentication method is “<literal>Basic</literal>” or
  “<literal>Digest</literal>”, authentication is handled as per
  <biblioref linkend="rfc2617"/>. <impl>The interpretation of values
  associated with the “<literal>auth-method</literal>” key other than
  “<literal>Basic</literal>” or “<literal>Digest</literal>” is
  <glossterm>implementation-defined</glossterm>.</impl></para>
  </listitem>
  </varlistentry>
  <varlistentry><term><literal>send-authorization</literal> (<code>xs:boolean</code>)</term>
  <listitem>
  <para>The “<literal>send-authorization</literal>” key can be used to
  attempt to allow the request to avoid an authentication challenge.
  If the “<literal>send-authorization</literal>” key is
  “<literal>true()</literal>”, and the authentication method specified
  by the value associated with the “<literal>auth-method</literal>”
  key supports generation of an “<literal>Authorization</literal>”
  header without a challenge, then the header is generated and sent on
  the first request. If the “<literal>send-authorization</literal>”
  key is absent or does not have the value “<literal>true</literal>”,
  the first request is sent without an
  “<literal>Authorization</literal>” header.</para>
  </listitem>
  </varlistentry>
  </variablelist>

  <para><impl>Other key value pairs in map “<literal>auth</literal>”
  are <glossterm>implementation-defined</glossterm>.</impl> <error code="C0123">It is a <glossterm>dynamic error</glossterm> if any key
  in the “<literal>auth</literal>” map is associated with a value that
  is not an instance of the required type.</error></para>

  <para>If the initial response to the request is an authentication
  challenge, the values provided in the <literal>auth</literal> map
  and any relevant data from the challenge are used to generate an
  “<literal>Authorization</literal>” header and the request is sent
  again. If that authorization fails, the request is not
  retried.</para>

  <para><error code="C0003">It is a <glossterm>dynamic
  error</glossterm> if a “<literal>username</literal>” or a
  “<literal>password</literal>” key is present without specifying a
  value for the “<literal>auth-method</literal>” key, if the requested
  <literal>auth-method</literal> isn't supported, or the
  authentication challenge contains an authentication method that
  isn't supported.</error> All implementations <rfc2119>must</rfc2119>
  support “Basic” and “Digest” authentication per <biblioref linkend="rfc2617"/>.</para>

</listitem>
</varlistentry>
<varlistentry>
  <term>parameters</term>
  <listitem>
    <para>The <option>parameter</option> option can be used to provide
    values for fine tuning the construction of the request and/or
    handling of the server response. A number of parameters are
    defined in this specification. <impl>It is
    <glossterm>implementation-defined</glossterm> which other
    key/value pairs in the <option>parameters</option> option are
    supported.</impl></para>

    <variablelist>
      <varlistentry>
        <term>override-content-type (<code>xs:string</code>)</term>
      <listitem>
      <para>Ordinarily, the value of the
      <literal>content-type</literal> header provided in the server
      response controls the interpretation of any body in the
      response. If the “<literal>override-content-type</literal>”
      parameter is provided, then its value is used to interpret the
      body. The content-type header that appears on the
        <port>report</port> port is not changed. 
        <error code="D0079">It is a <glossterm>dynamic error</glossterm> if a supplied content-type is not 
          a valid media type of the form 
          “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable>+<replaceable>ext</replaceable></literal>” 
          or “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable></literal>”.</error> <error code="C0030">It
      is a <glossterm>dynamic error</glossterm> if the response body cannot
      be interpreted as requested (e.g. <literal>application/json</literal>
      to override <literal>application/xml</literal> content).</error></para>
      </listitem>
      </varlistentry>
      <varlistentry>
        <term>http-version (<code>xs:string</code>)</term>
      <listitem>
        <para>The <literal>http-version</literal> parameter indicates
        which version of HTTP <rfc2119>must</rfc2119> be used for the request.</para>
      </listitem>
      </varlistentry>
      <varlistentry>
        <term>accept-multipart (<code>xs:boolean</code>)</term>
      <listitem>
        <para>If the <literal>accept-multipart</literal> parameter is
        present and explicitly has the value <code>false()</code>, a
        dynamic error will be raised, if a multipart response is
        received from the server. This feature is a convenience for
        pipeline authors as it will raise an error when the multipart
        request is received, rather than having the presence of a
        sequence raise an error further along in the pipeline, or
        simply producing anomalous results. <error code="C0125">It is
        a <glossterm>dynamic error</glossterm> if the key
        “<literal>accept-multipart</literal>” as the value
        <code>false()</code> and a multipart response is
        detected.</error></para>
      </listitem>
      </varlistentry>
      <varlistentry>
        <term>override-content-encoding (<code>xs:string</code>)</term>
        <listitem>
          <para>If the “<literal>override-content-encoding</literal>”
          parameter is present, the response will be treated as if the
          response contained a “<literal>content-encoding</literal>”
          header with the specified value. The content-encoding header
          that appears on the <port>report</port> port is not changed.
          <error code="C0132">It is a <glossterm>dynamic error</glossterm> if
          the override content encoding cannot be supported.</error>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>permit-expired-ssl-certificate (<code>xs:boolean</code>)</term>
        <listitem>
          <para>If “<literal>permit-expired-ssl-certificate</literal>” is true, then the processor
          should not reject responses where the server provides an expired SSL certificate.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>permit-untrusted-ssl-certificate (<code>xs:boolean</code>)</term>
        <listitem>
          <para>If “<literal>permit-untrusted-ssl-certificate</literal>” is true, then the
          processor should not reject response where the server provides an SSL certificate which
          is not trusted, for example, because the certificate authority (CA) is unknown.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>follow-redirect (<code>xs:integer</code>)</term>
        <listitem>
          <para>The “<literal>follow-redirect</literal>” parameter
          allows the pipeline author to specify the step’s behaviour in the case of a redirect
          response. A value of <literal>0</literal> indicates that redirects are not to be followed, 
          <literal>-1</literal> indicates that redirects are to be followed indefinitely, and a
          specific number indicates the maximum number of redirects to follow. <impl>The default
          behaviour in case of a redirect response is <glossterm>implementation-defined</glossterm>.</impl>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>timeout (<code>xs:integer</code>)</term>
        <listitem>
          <para>If a “<literal>timeout</literal>” is specified, it
          <rfc2119>must</rfc2119> be a non-negative integer. It
          controls the time the XProc processor waits for the request
          to be answered. If a value is given, it is taken as the
          number of seconds to wait for the response to be delivered.
          If no response is received after that time, the request is
          terminated and a status-code <literal>408</literal> is
          assumed.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>fail-on-timeout (<code>xs:boolean</code>)</term>
        <listitem>
          <para>If “<literal>fail-on-timeout</literal>” is true, a
          dynamic error is raised if a <literal>408</literal> response
          is received (either as a consequence of setting a value for
          the “<literal>timeout</literal>” parameter or as status code
          returned by a server). <error code="C0078">It is a
          <glossterm>dynamic error</glossterm> if the value associated
          with the “<literal>fail-on-timeout</literal>” is associated
          with <code>true()</code> and a HTTP status code
          <literal>408</literal> is encountered.</error> If “<literal>fail-on-timeout</literal>”
          is true, it prevents any dynamic error with code <literal>C0126</literal> resulting
          from the <option>assert</option> option to be raised for request's timeout.</para>
          <note>
            <title>Note</title>
            <para>Please note that the “<literal>fail-on-timeout</literal>” parameter
            is different from the “<literal>timeout</literal>” option on the
            <tag>p:http-request</tag> step (see <xspecref spec="xproc" xref="timeout"/>).
            If the <emphasis>step</emphasis> does not finish in the specified time,
            <code>D0053</code> is raised. If the <emphasis>request</emphasis> does not finish in time,
            and <literal>fail-on-timeout</literal> is true,
            <code>C0078</code> is raised. The actual
            times after which a timeout is detected may also differ slightly.
            </para>
          </note>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>status-only (<code>xs:boolean</code>)</term>
        <listitem>
          <para>If the “<literal>status-only</literal>” parameter is
          true, this indicates that the pipeline author is only
          interested in the response code. An empty sequence is always
          returned on the <port>result</port> port in this case. The
          implementation may save resources by ignoring the response
          body. The map on the <port>report</port> will contain the
          status code and an empty map for
          “<literal>headers</literal>”.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>suppress-cookies (<code>xs:boolean</code>)</term>
        <listitem>
          <para>If the “<literal>suppress-cookies</literal>” parameter is true,
          the implementation <rfc2119>must not</rfc2119> send any cookies with the request.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>send-body-anyway (<code>xs:boolean</code>)</term>
        <listitem>
          <para>If the “<literal>send-body-anyway</literal>” parameter
          is true, and one or more documents appear on the
          <port>source</port> port, a request body is constructed from
          the documents and sent with the request, even if the
          semantics of sending a body are not specified for the HTTP method in use.
          </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para><error code="C0124">It is a <glossterm>dynamic
        error</glossterm> if any key in the “parameters” map is
        associated with a value that is not an instance of the
        required type.</error></para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term>assert (<code>xs:string</code>)</term>
      <listitem>
        <para>The <option>assert</option> option can be used by
        pipeline authors to raise a dynamic error if the response does
        not fulfill the expectations of the receiver. The option's
        value (if present) is interpreted as an XPath expression which
        will be executed using the map that appears on the
        <port>report</port> port as its context item. If the effective
        boolean value of the expression is <code>false()</code>, a
        dynamic error is raised. <error code="C0126">It is a
        <glossterm>dynamic error</glossterm> if the XPath expression
        in <option>assert</option> evaluates to
        <code>false</code>.</error> Implementations
        <rfc2119>should</rfc2119> provide an XML representation of the
        map used as the context item with the error document to enable
        pipelines to access the error's cause.</para>
      </listitem>
    </varlistentry>
  </variablelist>

<section xml:id="c.http-multipart-request">
<title>Construction of a multipart request</title>

<para>If more than one document appears on the <port>source</port>
port, or if the specified “<literal>content-type</literal>” header
begins “<literal>multipart/</literal>”, a multipart request will be
constructed, per <biblioref linkend="rfc1521"/>. The content type of
the request is derived from the “<literal>content-type</literal>”
header:</para>

<itemizedlist>
<listitem>
<para>If the “<literal>content-type</literal>” header specifies a
multipart content type, that value will be used as the content type. If the
header includes a <literal>boundary</literal> parameter, that value
will be used as the boundary.
<error code="C0203">It is a <glossterm>dynamic error</glossterm>
if the specified boundary is not valid (for example, if it begins with two hyphens “--”).</error>
</para>
</listitem>
<listitem>
<para>If the “<literal>content-type</literal>” header is not specified,
“<literal>multipart/mixed</literal>” will be used.</para>
</listitem>
<listitem>
<para><error code="C0133">It is a <glossterm>dynamic error</glossterm>
if more than one document appears on the <port>source</port> port and
a <literal>content-type</literal> header is present and the content
type specified is not a multipart content type.</error>
</para>
</listitem>
</itemizedlist>

<para>A multipart request must have a boundary marker, if one isn’t
specified in the content type, the implementation
<rfc2119>must</rfc2119> construct one. <impl>It is
<glossterm>implementation-defined</glossterm> how a multipart boundary
is constructed.</impl> Implementations <emphasis>are not</emphasis>
required to guarantee that the constructed value does not appear
accidentally in the multipart data. If it does, the request will be
malformed; pipeline authors must provide a boundary if they wish to
assure that this cannot happen.</para>

<para>Each document in the sequence is serialized. If the document has
a “<literal>serialization</literal>” document property, its values
are used to determine how serialization is performed.</para>

<para>All of the document properties in the
<code>http://www.w3.org/ns/xproc-http</code> namespace will be added
as headers for the part, using the local-name of the property QName as
the header name. In particular, this is how the
“<literal>id</literal>”, “<literal>description</literal>”,
“<literal>disposition</literal>” and other multipart headers can be
provided.</para>
</section>

<section xml:id="c.http-multipart-response">
<title>Managing a multipart response</title>

<para>When a multipart response is received, each part is interpreted
according to its content type and a pipeline document is constructed.
Any additional headers associated with the part are added to the
document properties of the constructed document.</para>

<para>The multipart response is the resulting sequence of documents.</para>

</section>
  
<simplesect>
<title>Document properties</title>
<para feature="http-request-preserves-none">No document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.identity">
<title>p:identity</title>

<para>The <code>p:identity</code> step makes a verbatim copy of its input
available on its output.</para>

<p:declare-step type="p:identity">
  <p:input port="source" sequence="true" content-types="any"/>
  <p:output port="result" sequence="true" content-types="any"/>
</p:declare-step>

<para>If the implementation supports passing PSVI annotations between
steps, the <tag>p:identity</tag> step <rfc2119>must</rfc2119> preserve
any annotations that appear in the input.</para>

<simplesect>
<title>Document properties</title>
<para feature="identity-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.insert">
<title>p:insert</title>

<para>The <code>p:insert</code> step inserts the
<code>insertion</code> port's document into the <port>source</port>
port's document relative to the matching elements in the
<code>source</code> port's document.</para>

<p:declare-step type="p:insert">
   <p:input port="source" primary="true" content-types="xml html"/>
   <p:input port="insertion" sequence="true" content-types="xml html text"/>
   <p:output port="result" content-types="xml html text"/>
   <p:option name="match" as="xs:string" select="'/*'" e:type="XSLTSelectionPattern"/>
   <p:option name="position" values="('first-child','last-child','before','after')" as="xs:string" select="'after'"/>
</p:declare-step>

<para>The value of the <option>match</option> option
<rfc2119>must</rfc2119> be an XSLTSelectionPattern. <error code="C0023">It
is a <glossterm>dynamic error</glossterm> if that pattern matches
an attribute or a namespace node.</error>
Multiple matches are
allowed, in which case multiple copies of the <port>insertion</port>
documents will occur. If no elements match, then the document is
unchanged.</para>

<para>The value of the <option>position</option> option <rfc2119>must</rfc2119> be an NMTOKEN in
the following list:
</para>

<itemizedlist>
<listitem>
<para>“<literal>first-child</literal>” - the insertion is made as the first child of the match;</para>
</listitem>
<listitem>
<para>“<literal>last-child</literal>” - the insertion is made as the last child of the match;</para>
</listitem>
<listitem>
<para>“<literal>before</literal>” - the insertion is made as the immediate preceding sibling of the match;</para>
</listitem>
<listitem>
<para>“<literal>after</literal>” - the insertion is made as the immediate following sibling of the match.</para>
</listitem>
</itemizedlist>

<para><error code="C0025">It is a <glossterm>dynamic error</glossterm>
if the <glossterm>selection pattern</glossterm> matches anything other than an element or a document
node and the value of the <option>position</option> option is
“<literal>first-child</literal>” or
“<literal>last-child</literal>”.</error> <error code="C0024">It is a
<glossterm>dynamic error</glossterm> if the <glossterm>selection pattern</glossterm> matches a document
node and the value of the <option>position</option> is “<literal>before</literal>” or
“<literal>after</literal>”.</error></para>

<para>As the inserted elements are part of the output of the step they
are not considered in determining matching elements. If an empty sequence
appears on the <port>insertion</port> port, the result will be the same
as the source.</para>

<simplesect>
<title>Document properties</title>
<para feature="insert-preserves-all">All document properties on the
<port>source</port> port are preserved. The document properties on the
<port>insertion</port> port are not preserved or present in the result document.</para>
</simplesect>
</section>
<section xml:id="c.json-join" version="5.0-extension w3c-xproc">
<title>p:json-join</title>

<para>The <code>p:json-join</code> step joins the sequence of documents on port <port>source</port>
into a single JSON document (an array) appearing on port <port>result</port>. If the sequence on
port <code>source</code> is empty, the empty sequence is returned on
port <code>result</code>.</para>

<p:declare-step type="p:json-join">
  <p:input port="source" sequence="true" content-types="any"> </p:input>
  <p:output port="result" content-types="application/json"/>
  <p:option name="flatten-to-depth" as="xs:string?" select="'0'"/>
</p:declare-step>

<para>The step inspects the documents on port <port>source</port> in turn to create the
  resulting array:</para>
<itemizedlist>
  <listitem>
    <para>If the document under inspection is a JSON document representing an array, the array is copied 
     to the resulting array according to the setting of option <option>flatten-to-depth</option>.</para>
  </listitem>
  <listitem>
    <para>For every other type of JSON document, for XML documents, HTML documents, or text
    documents, their XDM representation is appended to the resulting array.</para>
  </listitem>
  <listitem>
    <para><impl>It is <glossterm>implementation-defined</glossterm> if <code>p:json-join</code> is
      able to process document types not mentioned yet, i.e. types of binary documents.</impl> If a processor
      supports a given type of documents, an entry is created as described above. <error code="C0111">
        It is a <glossterm>dynamic error</glossterm> if a document of an unsupported document type appears on 
        port <port>source</port> of <code>p:json-join</code>.</error>
    </para>  </listitem>
</itemizedlist>
  
<para>The option <option>flatten-to-depth</option> controls whether and to which
depth members of an array appearing on port <port>source</port> are flattened.
<error code="C0119">It is a <glossterm>dynamic error</glossterm> if <option>flatten</option> is
neither “<literal>unbounded</literal>”, nor a string that may be cast to a non-negative integer.</error>
An integer value of <literal>0</literal>, which is the default, means that no 
flattening takes place, so the array appearing on port <port>source</port> will
be contained as an array in the resulting array. An integer value of <literal>1</literal>
means that an array on port <port>source</port> is flattened, i.e. the members
of that array will appear as individual members in the resulting array. Any value greater
than <literal>1</literal> means that the flattening is applied recursively to arrays in
arrays up to the given depth. A value of “<literal>unbounded</literal>” means that all
arrays in arrays will be flattened. As a consequence, the resulting array appearing on
port <port>result</port> will not have any arrays as members. </para>


<simplesect>
  <title>Document properties</title>
  <para feature="json-join-preserves-none">No document properties are preserved.
The joined document has no <property>base-uri</property>.
</para>
</simplesect>
</section>
<section xml:id="c.json-merge" version="5.0-extension w3c-xproc">
<title>p:json-merge</title>

<para>The <tag>p:json-merge</tag> step merges the sequence of appearing
on port <port>source</port> into a single JSON object appearing on port
<port>result</port>. If the sequence on
port <port>source</port> is empty, the empty sequence is returned on
port <port>result</port>.</para>

<p:declare-step type="p:json-merge">
  <p:input port="source" sequence="true" content-types="any"> </p:input>
  <p:output port="result" content-types="application/json"/>
  <p:option name="duplicates" as="xs:string" values="('reject', 'use-first', 'use-last', 'use-any', 'combine')" select="'use-first'"/>
  <p:option name="key" as="xs:string" select="'concat(&#34;_&#34;,$p:index)'" e:type="XPathExpression"/>
</p:declare-step>

<para>The step inspects the documents on port <port>source</port> in turn to create the resulting
  map:</para>
<itemizedlist>
  <listitem>
    <para>If the document under inspection is a JSON document representing a map,
    all key-value pairs are copied into the result map unless this map already contains
    an entry with the given key. In this case the value of option <option>duplicates</option>
    determines the policy for handling duplicate keys as specified for function <code>map:merge</code>
      in <biblioref linkend="xpath31-functions"/>.  
      <error code="C0106">It is a <glossterm>dynamic error</glossterm> if duplicate keys are encountered and 
      option <option>duplicates</option> has value “<literal>reject</literal>”.</error></para>
  </listitem>
  <listitem>
    <para>For every other type of JSON document, for XML documents, HTML documents, or text documents a
    new key-value pair is created and put into the resulting map. The key is created by evaluating
    the XPath expression in option <option>key</option> with the inspected document as context item. If the
      evaluation result is a single atomic value, it is taken as key. If the evaluation result is a node, its
      string value is taken as key. <error code="C0110">It is a <glossterm>dynamic error</glossterm> if the
      evaluation of the XPath expression in option <option>key</option> for a given item returns either a
      sequence, an array, a map, or a function.</error> Duplicate
    keys are handled as described above. The XDM representation of the inspected document is taken as value of
    the key-value pair.</para>
  </listitem>
  <listitem>
    <para><impl>It is <glossterm>implementation-defined</glossterm> if <code>p:json-merge</code> is
    able to process document types not mentioned yet, i.e. types of binary documents.</impl> If a processor
    supports a given type of documents, the key-value pair is created as described above. <error code="C0107">
    It is a <glossterm>dynamic error</glossterm> if a document of a not supported document type appears on 
      port <port>source</port> of <code>p:json-merge</code>.</error>
    </para>
  </listitem>
</itemizedlist> 
  <para>An implementation must bind the variable “<code>p:index</code>” in the static context of 
    each evaluation of the XPath expression to the position of the document in the sequence 
    of documents on port <port>source</port>, starting with “<literal>1</literal>”.
    </para>
  <simplesect>
    <title>Document properties</title>
    <para feature="json-merge-preserves-none">No document properties are preserved.
The merged document has no <property>base-uri</property>.
</para>
  </simplesect>
</section>
<section xml:id="c.label-elements">
<title>p:label-elements</title>

<para>The <code>p:label-elements</code> step generates a label for each matched
element and stores that label in the specified attribute.</para>

<p:declare-step type="p:label-elements">
  <p:input port="source" content-types="xml html"/>
  <p:output port="result" content-types="xml html"/>
  <p:option name="attribute" as="xs:QName" select="'xml:id'"/>
  <p:option name="label" as="xs:string" select="'concat(&#34;_&#34;,$p:index)'" e:type="XPathExpression"/>
  <p:option name="match" as="xs:string" select="'*'" e:type="XSLTSelectionPattern"/>
  <p:option name="replace" as="xs:boolean" select="true()"/>
</p:declare-step>

<para>The value of the <option>label</option> option is an XPath
expression used to generate the value of the attribute label.</para>

<para>The value of the <option>match</option> option
<rfc2119>must</rfc2119> be an XSLTSelectionPattern. <error code="C0023">It
is a <glossterm>dynamic error</glossterm> if that expression matches
anything other than element nodes.</error></para>

<para>The value of the <option>replace</option>
<rfc2119>must</rfc2119> be a boolean value and is used to indicate
whether existing attribute values are replaced.</para>

<para>This step operates by generating attribute labels for each
element matched. For every matched element, the expression is
evaluated with the context node set to the matched element. An
attribute is added to the matched element using the attribute name is
specified the <option>attribute</option> option and the string value
of result of evaluating the expression. If the attribute already
exists on the matched element, the value is replaced with the string
value only if the <option>replace</option> option has the value of
<literal>true</literal>.</para>

<para>If this step is used to add or change the value
of an attribute named “<literal>xml:base</literal>”, the base URI
of the element <rfc2119>must</rfc2119> also be amended accordingly.</para>

<para>An implementation must bind the variable
“<literal>p:index</literal>” in the static context of each evaluation
of the XPath expression to the position of the element in the sequence
of matched elements. In other words, the first element (in document
order) matched gets the value “<literal>1</literal>”, the second gets
the value “<literal>2</literal>”, the third, “<literal>3</literal>”,
etc.</para>

<para>The result of the p:label-elements step is the input document with the
attribute labels associated with matched elements.  All other non-matching content
remains the same.</para>

<simplesect>
<title>Document properties</title>
<para feature="label-elements-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.load">
<title>p:load</title>

<para>The <code>p:load</code> step has no inputs but produces as its
result a document specified by an IRI.</para>

<p:declare-step type="p:load">
  <p:output port="result" content-types="any"/>
  <p:option name="href" required="true" as="xs:anyURI"/>
  <p:option name="parameters" as="map(xs:QName,item()*)?"/>
  <p:option name="content-type" as="xs:string?"/>
  <p:option name="document-properties" as="map(xs:QName, item()*)?"/>
</p:declare-step>

  <para>If the <option>href</option> is relative, it is made absolute against the base URI of the element on
    which it is specified (<tag>p:with-option</tag> or <tag>p:load</tag> in the case of a syntactic
    shortcut value). <error code="D0064">It is a <glossterm>dynamic 
      error</glossterm> if the base URI is not both absolute and valid according to <biblioref linkend="rfc3986"/>.</error></para>

<para>The document identified by the
<option>href</option> URI is loaded and returned. If the URI protocol
supports redirection, then redirects <rfc2119>must</rfc2119> be
followed.</para>

<para><error code="D0011">It is a <glossterm>dynamic error</glossterm>
if the resource referenced by a <code>p:load</code> element does not exist,
cannot be accessed, or if the access reports error (for example, an HTTP 404 error).</error></para>

<para>The behavior of this step depends on the content type of the
document loaded. The content type of a document is
determined as follows:</para>

<orderedlist>
<listitem>
<para>If a <property>content-type</property> property is specified
in <option>document-properties</option> or <option>content-type</option> is present,
then the document <rfc2119>must</rfc2119> be interpreted according to
that content type.
  <error code="D0079">It is a <glossterm>dynamic error</glossterm> if a supplied content-type is not 
    a valid media type of the form 
    “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable>+<replaceable>ext</replaceable></literal>” 
    or “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable></literal>”.</error> 
<error code="D0062">It is a <glossterm>dynamic error</glossterm>
if the <tag class="attribute">content-type</tag> is specified and the
document-properties has a “<code>content-type</code>” that is not the
same.</error>
</para>
</listitem>
<listitem>
<para>If the document is retrieved with a URI protocol that specifies
a content type (for example, <literal>http:</literal>), then the document
<rfc2119>must</rfc2119> be interpreted according to that content type.
</para>
</listitem>
<listitem>
<para><impl>In the absence of an explicit type, the content
type is <glossterm>implementation-defined</glossterm></impl>.</para>
</listitem>
</orderedlist>

<para>The <option>parameters</option> map contains additional, optional
parameters that may influence the way that content is loaded. The interpretation
of this map varies according to the content type. Parameter names that are in
no namespace are treated as strings using only the local-name where appropriate.</para>

<para>Broadly speaking, there are five categories of data that might
be loaded:
<link linkend="c.load.xml">XML</link>,
<link linkend="c.load.text">text</link>,
<link linkend="c.load.json">JSON</link>,
<link linkend="c.load.html">HTML</link>,
and “other”
<link linkend="c.load.binary">binary</link> data.</para>

<section xml:id="c.load.xml">
<title>Loading XML data</title>

<para>For an XML media type, the content is loaded and parsed as XML.</para>

<para><error code="D0049">It is a <glossterm>dynamic error</glossterm> if
the loaded content is not a well-formed XML document.</error></para>

<para>If the <option>dtd-validate</option> parameter is <literal>true</literal>,
then DTD validation must be performed when parsing the document.
<error code="D0023">It is a <glossterm>dynamic error</glossterm> if a DTD validation
is performed and either the document is not valid or no DTD is found.</error>
<error code="D0043">It is a <glossterm>dynamic error</glossterm>
if the <option>dtd-validate</option> parameter is <literal>true</literal> and
the processor does not support DTD validation.</error></para>

<para><impl>Additional XML parameters are <glossterm>implementation-defined</glossterm>.
</impl></para>
</section>

<section xml:id="c.load.text">
<title>Loading text data</title>
<para>For a text media type, the content is loaded as a text document. (A text
document is an XPath data model document consisting of a single text node.)</para>

<para><error code="D0060">It is a <glossterm>dynamic error</glossterm> if the
<option>content-type</option> specifies a charset (sometimes called the
character encoding) that is not supported by the processor.</error></para>

<para><impl>Text parameters are <glossterm>implementation-defined</glossterm>.
</impl></para>

<section xml:id="text-bom">
<title>Byte order marks</title>

<para>UTF-8 and UTF-16 inputs can begin with a byte order mark. The byte order
mark is not considered part of the text and is not included in the text
document.</para>

<para>In order to identify the byte order mark, it is first necessary to
identify the charset that is being
used. The charset of an external resource is determined as follows:</para>

<orderedlist>
<listitem>
<para>external charset information is used if available (for example, if the
resource is loaded with HTTP or HTTPS and the server provided a charset), otherwise
</para>
</listitem>
<listitem>
<para>the charset from the content type if specified, otherwise
</para>
</listitem>
<listitem>
<para>the processor may use implementation-defined heuristics to determine the
likely charset, otherwise
</para>
</listitem>
<listitem>
<para>UTF-8 is assumed.</para>
</listitem>
</orderedlist>

<para>Processors <rfc2119>must</rfc2119> support UTF-8 and UTF-16. <impl>Support
for other charsets is <glossterm>implementation-defined</glossterm>.</impl></para>

<para>If the encoding is UTF-8, UTF-16, UTF-16LE, or UTF-16BE, a byte order mark
may be present. (For any other encoding, there is no byte order mark and all of the text
is returned.)</para>

<itemizedlist>
<listitem>
<para>If the encoding is UTF-8 and the document begins with the bytes 
EF BB BF, those bytes are the byte order mark. They are discarded.</para>
</listitem>
<listitem>
<para>If the encoding is UTF-16 and the document begins with the bytes 
FE FF or FF FE, those bytes are the byte order mark. They are discarded.</para>
</listitem>
<listitem>
<para>If the encoding is UTF-16LE and the document begins with the bytes 
FF FE, those bytes are the byte order mark. They are discarded.</para>
</listitem>
<listitem>
<para>If the encoding is UTF-16BE and the document begins with the bytes 
FE FF, those bytes are the byte order mark. They are discarded.</para>
</listitem>
<listitem>
<para>If the encoding isn’t specified, but the file begins with a byte
order mark (FE FF or FF FE), treat the charset as UTF-16 and
discard the byte order mark.</para>
</listitem>
<listitem>
<para>Otherwise, there is no byte order mark, nothing is discarded.
</para>
</listitem>
</itemizedlist>

</section>
</section>

<section xml:id="c.load.json">
<title>Loading JSON data</title>

<para>For a JSON media type, the content is loaded and parsed as JSON
<biblioref linkend="rfc8259"/>.</para>

<para>The parameters specified for the <code>fn:parse-json</code> function
in <biblioref linkend="xpath31-functions"/>
<rfc2119>must</rfc2119> be supported.
<impl>Additional JSON parameters are <glossterm>implementation-defined</glossterm>.
</impl></para>
<para><error code="D0057">It is a <glossterm>dynamic error</glossterm> if the loaded content
does not conform to the JSON grammar, unless the parameter <option>liberal</option> is
<literal>true</literal> and the processor chooses to accept the deviation.</error></para>

<para><error code="D0058">It is a <glossterm>dynamic error</glossterm> if the parameter
<option>duplicates</option> is <literal>reject</literal> and the value of
loaded content contains a JSON object with duplicate keys.</error></para>

<para><error code="D0059">It is a <glossterm>dynamic error</glossterm> if the parameter
map contains an entry whose key is defined in the specification of
<code>fn:parse-json</code> and whose value is not valid for that key, or if it contains
an entry with the key fallback when the parameter <option>escape</option> with
<literal>true()</literal> is also present.</error></para>

<section xml:id="json-bom">
<title>Byte order mark</title>

<para>JSON data transmitted with the UTF-8 encoding may begin with a byte order
mark. If it does, the byte order mark is discarded before parsing the
input.</para>
</section>

</section>

<section xml:id="c.load.html">
<title>Loading HTML data</title>

<para>For an HTML media type, the content is loaded and parsed into an
XPath data model
document that contains a tree of elements, attributes, and other nodes.</para>

<para><impl>The precise way in which HTML documents are parsed into the
XPath data model is <glossterm>implementation-defined</glossterm>.</impl>
</para>

<para><error code="D0078">It is a <glossterm>dynamic error</glossterm>
if the loaded document cannot be represented as an HTML document in
the XPath data model.</error></para>

<para><impl>HTML parameters are <glossterm>implementation-defined</glossterm>.
</impl></para>
</section>

<section xml:id="c.load.binary">
<title>Loading binary data</title>

<para>An XProc processor may load other, arbitrary data types. <impl>How a
processor interprets other media types is <glossterm>implementation-defined</glossterm>.
</impl>
</para>

<para><impl>Parameters for other media types
are <glossterm>implementation-defined</glossterm>.
</impl></para>
</section>

<simplesect>
<title>Document properties</title>
<para>The properties specified in <option>document-properties</option> are applied.
If the properties do not specify a <property>base-uri</property>, the 
<property>base-uri</property> property will reflect the base URI of the loaded document.
</para>
</simplesect>
</section>
<section xml:id="c.make-absolute-uris">
<title>p:make-absolute-uris</title>

<para>The <code>p:make-absolute-uris</code> step makes an element or
attribute's value in the source document an absolute IRI value in the
result document.</para>

<p:declare-step type="p:make-absolute-uris">
  <p:input port="source" content-types="xml html"/>
  <p:output port="result" content-types="xml html"/>
  <p:option name="match" required="true" as="xs:string" e:type="XSLTSelectionPattern"/>
  <p:option name="base-uri" as="xs:anyURI?"/>
</p:declare-step>

<para>The value of the <option>match</option> option <rfc2119>must</rfc2119> be an
XSLTSelectionPattern.
<error code="C0023">It is a <glossterm>dynamic error</glossterm> if
the pattern matches anything other than element or attribute
nodes.</error></para>

<para>The value of the <option>base-uri</option> option
<rfc2119>must</rfc2119> be an <type>anyURI</type>. It is interpreted
as an IRI reference. If it is relative, it is made absolute against
the base URI of the element on which it is specified
(<tag>p:with-option</tag> or <tag>p:make-absolute-uris</tag> in the case of
  a syntactic shortcut value). <error code="D0064">It is a <glossterm>dynamic 
    error</glossterm> if the base URI is not both absolute and valid according to <biblioref linkend="rfc3986"/>.</error></para>

<para>For every element or attribute in the input document which
matches the specified pattern, its XPath string-value is resolved
against the specified base URI and the resulting absolute IRI is used
as the matched node's entire contents in the output.</para>

<para>The base URI used for resolution defaults to the matched
attribute's element or the matched element's base URI unless the
<option>base-uri</option> option is specified. When the
<option>base-uri</option> option is specified, the option value is
used as the base URI regardless of any contextual base URI value in
the document. This option value is resolved against the base URI of
the <tag>p:option</tag> element used to set the option.</para>

<para><impl>If the IRI reference specified by the <option>base-uri</option> option
on <tag>p:make-absolute-uris</tag> is absent and the input document has no base URI,
the results are <glossterm>implementation-dependent</glossterm>.</impl>
</para>

<simplesect>
<title>Document properties</title>
<para feature="make-absolute-uris-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.message">
<title>p:message</title>

<para>The <code>p:message</code> step conditionally produces a message.</para>

<p:declare-step type="p:message">
  <p:input port="source" sequence="true"/>
  <p:output port="result" sequence="true"/>
  <p:option name="test" as="xs:boolean" select="true()"/>
  <p:option name="select" as="item()*" required="true"/>
</p:declare-step>

<para>Steps that produce messages offer one way for an author to keep track of
the progress of a pipeline. The <tag class="attribute">[p:]message</tag>
attribute can be added to any step to display a message when it runs.</para>

<para>Status and debugging messages that are appropriate during pipeline
development may be distracting when the pipeline is running “in production”.
Existing mechanisms for conditional compilation can be used to mediate between
“development” and “production” runs, but they are a bit heavyweight. Adding many
steps with <tag class="attribute">[p:]use-when</tag> attributes and managing the
connections between steps that may be conditionally removed can make pipelines
harder to read and understand.</para>

<para>The <tag>p:message</tag> step can be used to achieve much the same effect
and is considerably less verbose.</para>

<para>If the <tag class="attribute">test</tag> attribute is
  “<literal>true</literal>”, the result of evaluating the <tag class="attribute">select</tag> option is
serialized and made available. (As with the <link xlink:href="https://spec.xproc.org/master/head/xproc/#messages">message
attribute</link>, this is intentionally vague. <impl>Precisely what “made
available” means is <glossterm>implementation-defined</glossterm>.</impl>
Often it means “printed on the console”.)</para>

<para>Irrespective of the value of the <tag class="attribute">test</tag>
attribute, the <tag>p:message</tag> passes all of the documents that appear on
its <port>source</port> port through to the <port>result</port> port,
unchanged and in the same order.</para>

<para>If exactly one document appears on the <port>source</port> port, it is the
context item when the <tag class="attribute">test</tag> and <tag class="attribute">select</tag> expressions are evaluated. In all other cases,
the context item is undefined.</para>

<note>
<para>If it can be determined statically that <tag class="attribute">test</tag> expression is
<emphasis>always</emphasis> “<literal>false</literal>”, the processor may remove the 
step from the pipeline entirely, although it must guarantee that all of the connections
are preserved.</para>
</note>

<simplesect>
  <title>Document properties</title>
  <para feature="message-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.namespace-delete">
<title>p:namespace-delete</title>

<para>The <tag>p:namespace-delete</tag> step deletes all of the namespaces identified by the specified 
      prefixes from the document appearing on port <port>source</port>.</para>

<p:declare-step type="p:namespace-delete">
   <p:input port="source" content-types="xml html"/>
   <p:output port="result" content-types="xml html"/>
   <p:option name="prefixes" required="true" as="xs:string"/>
</p:declare-step>

<para>The value of option <option>prefixes</option> is taken as a space separated list of
prefixes. <error code="C0108">It is a <glossterm>dynamic error</glossterm> if any
prefix is not in-scope at the point where the <code>p:namespace-delete</code> occurs.</error></para>

<para>For any prefix the associated namespace is removed from the elements and 
attributes in the document appearing on port <port>source</port>. The respective
elements or attributes in the document appearing on port <port>result</port> will be
in no namespace.</para>

<para><error code="C0109">It is a <glossterm>dynamic error</glossterm> if
a namespace is to be removed from an attribute and the element already has an attribute
with the resulting name.</error></para>

<simplesect>
<title>Document properties</title>
<para feature="namespace-delete-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.namespace-rename">
<title>p:namespace-rename</title>

<para>The <code>p:namespace-rename</code> step renames any namespace declaration or
use of a namespace in a document to a new IRI value.</para>

 <p:declare-step type="p:namespace-rename">
   <p:input port="source" content-types="xml html"/>
   <p:output port="result" content-types="xml html"/>
   <p:option name="from" as="xs:anyURI?"/>
   <p:option name="to" as="xs:anyURI?"/>
   <p:option name="apply-to" select="'all'" as="xs:string" values="('all','elements','attributes')"/>
</p:declare-step>

<para>The value of the <option>from</option> option
<rfc2119>must</rfc2119> be an <type>anyURI</type>. It
<rfc2119>should</rfc2119> be either empty or absolute, but will not be
resolved in any case.</para>

<para>The value of the <option>to</option> option
<rfc2119>must</rfc2119> be an <type>anyURI</type>. It
<rfc2119>should</rfc2119> be empty or absolute, but will not be
resolved in any case.</para>

<para>The value of the <option>apply-to</option> option
<rfc2119>must</rfc2119> be one of “<literal>all</literal>”,
“<literal>elements</literal>”, or “<literal>attributes</literal>”.
If the value is “<literal>elements</literal>”, only elements will be
renamed, if the value is “<literal>attributes</literal>”, only attributes
will be renamed, if the value is “<literal>all</literal>”, both elements
and attributes will be renamed.</para>

<para><error code="C0014">It is a <glossterm>dynamic error</glossterm>
if the XML namespace (<uri>http://www.w3.org/XML/1998/namespace</uri>)
or the
XMLNS namespace (<uri>http://www.w3.org/2000/xmlns/</uri>) is
the value of either the <option>from</option> option or the
<option>to</option> option.</error></para>

<para>If the value of the <option>from</option> option is the same as
the value of the <option>to</option> option, the input is reproduced
unchanged on the output. Otherwise, namespace bindings, namespace
attributes and element and attribute names are changed as
follows:</para>

<itemizedlist>
  <listitem>
   <para>Namespace bindings:  If the <option>from</option> option is present
and its value is not the empty string,
then every binding of a prefix (or the default namespace) in the input
document whose value is the same as the value of the <option>from</option>
option is</para>
   <itemizedlist>
    <listitem>
     <para>replaced in the output with a binding to the value of the <option>to</option>
option, provided it is present and not the empty string;</para>
    </listitem>
    <listitem>
     <para>otherwise (the <option>to</option> option is
not specified or has an empty string as its value) absent from the output.</para>
    </listitem>
   </itemizedlist>
   <para>If the <option>from</option> option is absent, or its value is the empty string,
then no bindings are changed or removed.</para>
  </listitem>
  <listitem>
   <para>Elements and attributes: If the <option>from</option> option is present
and its value is not the empty string, for every element and attribute,
as appropriate, in the input whose namespace name is the same as the value of the
<option>from</option> option, in the output its namespace name is</para>
   <itemizedlist>
    <listitem>
     <para>replaced with the value of the <option>to</option>
option, provided it is present and not the empty string;</para>
    </listitem>
    <listitem>
     <para>otherwise (the <option>to</option> option is
not specified or has an empty string as its value) changed to have no value.</para>
    </listitem>
   </itemizedlist>
   <para>If the <option>from</option> option is absent, or its value
   is the empty string, then for every element and attribute, as appropriate,
   whose namespace name has no value, in the
   output its namespace name is set to the value of the
   <option>to</option> option.</para>
      <para><error code="C0092">It is a <glossterm>dynamic error</glossterm>
          if as a consequence of changing or removing the namespace of an attribute
          the attribute's name is not unique on the respective element.</error></para>
  </listitem>
  <listitem>
   <para>Namespace attributes:  If the <option>from</option> option is present
and its value is not the empty string, for every namespace attribute in the
input whose value is the same as the value of the <option>from</option> option, in the output</para>
   <itemizedlist>
    <listitem>
     <para>the namespace attribute's value is replaced with the value of the <option>to</option>
option, provided it is present and not the empty string;</para>
    </listitem>
    <listitem>
     <para>otherwise (the <option>to</option> option is
not specified or has an empty string as its value) the namespace attribute is absent.</para>
    </listitem>
   </itemizedlist>
  </listitem>
 </itemizedlist>

<note xml:id="note-apply-to">
<para>The <option>apply-to</option> option is primarily intended to make
it possible to avoid renaming attributes when the <option>from</option> option
specifies no namespace, since many attributes are in no namespace.</para>

<para>Care should be taken when specifying no namespace with the
<option>to</option> option.  Prefixed names in content, for example QNames and
XPath expressions, may end up with no appropriate namespace binding.</para></note>

<simplesect>
<title>Document properties</title>
<para feature="namespace-rename-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.pack">
<title>p:pack</title>

<para>The <code>p:pack</code> step merges two document sequences in a pair-wise
fashion.</para>

<p:declare-step type="p:pack">
   <p:input port="source" content-types="text xml html" sequence="true" primary="true"/>
   <p:input port="alternate" sequence="true" content-types="text xml html"/>
   <p:output port="result" sequence="true" content-types="application/xml"/>
   <p:option name="wrapper" required="true" as="xs:QName"/>
   <p:option name="attributes" as="map(xs:QName, xs:anyAtomicType)?"/>
</p:declare-step>

<para>The step takes each pair of documents, in order, one from the
<port>source</port> port and one from the <port>alternate</port> port,
wraps them with a new element node whose QName is the value specified
in the <option>wrapper</option> option, and writes that element to the
<port>result</port> port as a document.</para>

<para>If the step reaches the end of one input sequence before the
other, then it simply wraps each of the remaining documents in the
longer sequence.</para>

<note xml:id="note-two-docs">
<para>In the common case, where the document element of a document in
the <port>result</port> sequence has two element children, any
comments, processing instructions, or white space text nodes that
occur between them may have come from either of the input documents;
this step does not attempt to distinguish which one.</para>
</note>

<para>If the <option>attributes</option> option is used, a new attribute is
created on the wrapper element for each entry in the map. The attribute name is
taken from the entry's key while the attribute value is taken from the string
value of the entry's value.</para>

<para>Namespace declarations cannot be added
with the <option>attributes</option> option.
<error code="C0059">It is a <glossterm>dynamic error</glossterm> if the name
of any attribute is “<code>xmlns</code>” or uses the prefix
“<literal>xmlns</literal>”
or any other prefix that resolves to the namespace name
<uri>http://www.w3.org/2000/xmlns/</uri>.</error> However,
if the attributes taken from the <option>attributes</option> use namespaces,
prefixes, or prefixes bound to different namespaces, the document produced on the
<port>result</port> output port will require namespace fixup.</para>

<para>If an attribute named <tag class="attribute">xml:base</tag> is added, the
base URI of the element <rfc2119>must</rfc2119> also be amended
accordingly.</para>

<simplesect>
<title>Document properties</title>
<para feature="pack-preserves-none">No document properties are preserved.
The result documents do not have a <property>base-uri</property> property unless
one is specified with the <option>attributes</option> option.
</para>
</simplesect>
</section>
<section xml:id="c.rename">
<title>p:rename</title>

<para>The <code>p:rename</code> step renames elements, attributes, or
processing-instruction targets in a document.</para>

<p:declare-step type="p:rename">
  <p:input port="source" content-types="xml html"/>
  <p:output port="result" content-types="xml html"/>
  <p:option name="match" as="xs:string" select="'/*'" e:type="XSLTSelectionPattern"/>
  <p:option name="new-name" required="true" as="xs:QName"/>
</p:declare-step>

<para>The value of the <option>match</option> option must be an
XSLTSelectionPattern. <error code="C0023">It is a <glossterm>dynamic
error</glossterm> if the pattern matches anything other than element,
attribute, or processing instruction nodes, or if it matches more
than one attribute on a single element.</error></para>

<para>Each element, attribute, or processing-instruction in the input
matched by the <glossterm>selection pattern</glossterm> specified in the <option>match</option>
option is renamed in the output to the name specified by the
<option>new-name</option> option.</para>

<para>If the <option>match</option> option matches an attribute and if
the element on which it occurs already has an attribute whose expanded
name is the same as the expanded name of the specified
<option>new-name</option>, then the results is as if the current
attribute named “<replaceable>new-name</replaceable>” was deleted before
renaming the matched attribute.</para>

<para>With respect to attributes named “<literal>xml:base</literal>”, the
following semantics apply: renaming an <emphasis>from</emphasis>
“<literal>xml:base</literal>” <emphasis>to</emphasis> something else has
no effect on the underlying base URI of the element; however,
if an attribute is renamed <emphasis>from</emphasis> something else
<emphasis>to</emphasis> “<literal>xml:base</literal>”, the base URI
of the element <rfc2119>must</rfc2119> also be amended accordingly.</para>

<para>If the pattern matches processing instructions, then it is the
processing instruction target that is renamed. <error code="C0013">It
is a <glossterm>dynamic error</glossterm> if the pattern matches
a processing instruction and the new name has a non-null namespace.</error>
</para>

<simplesect>
<title>Document properties</title>
<para feature="rename-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.replace">
<title>p:replace</title>

<para>The <code>p:replace</code> step replaces matching nodes in its primary
input with the content of the document that appears on the
<port>replacement</port> port.</para>

<p:declare-step type="p:replace">
   <p:input port="source" primary="true" content-types="xml html"/>
   <p:input port="replacement" content-types="text xml html"/>
   <p:output port="result" content-types="text xml html"/>
   <p:option name="match" required="true" as="xs:string" e:type="XSLTSelectionPattern"/>
</p:declare-step>

<para>The value of the <option>match</option> option
<rfc2119>must</rfc2119> be an XSLTSelectionPattern. <error code="C0023">It
is a <glossterm>dynamic error</glossterm> if that pattern matches
an attribute or a namespace nodes. </error> Multiple matches are allowed, in which case multiple
copies of the <port>replacement</port> document will occur.</para>

<para>Every node in the primary input matching the specified
pattern is replaced in the output by the content
of the <port>replacement</port> document. Only non-nested matches are
replaced. That is, once a node is replaced, its descendants cannot
be matched.</para>

<para>If the document node is matched, and the <port>replacement</port> document is a text document,
the <port>result</port> is a text document.</para>

<simplesect>
<title>Document properties</title>
<para feature="replace-preserves-partially">If the resulting document contains exactly one text node,
the <literal>content-type</literal> property is changed to <literal>text/plain</literal> and the 
   <literal>serialization</literal> property is removed, while all other document properties are 
   preserved. For other document types, all document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.set-attributes">
<title>p:set-attributes</title>

<para>The <tag>p:set-attributes</tag> step sets attributes on
matching elements.</para>

<p:declare-step type="p:set-attributes">
   <p:input port="source" primary="true" content-types="xml html"/>
   <p:output port="result" content-types="xml html"/>
   <p:option name="match" as="xs:string" select="'/*'" e:type="XSLTSelectionPattern"/>
   <p:option name="attributes" required="true" as="map(xs:QName, xs:anyAtomicType)"/>
</p:declare-step>

 <para>The value of the <option>match</option> option <rfc2119>must</rfc2119> be an
 XSLTSelectionPattern. <error code="C0023">It is a <glossterm>dynamic
 error</glossterm> if that pattern matches anything other than element
 nodes.</error></para>

<para>A new attribute is created for each entry in the map appearing
on the <option>attributes</option> option. The attribute name is taken
from the entry's key while the attribute value is taken from the string value of
the entry's value.</para>

<para>If an attribute with the same name as one of the attributes to
be created already exists, the value specified on the
<option>attributes</option> option is used. The result port of
this step produces a copy of the <port>source</port> port's document
with the matching elements' attributes modified.</para>

<para>The matching elements are specified by the <glossterm>selection pattern</glossterm> in the
<option>match</option> option. All matching elements are processed.
If no elements match, the step will not change any elements.</para>

<para>This step cannot be used to add namespace declarations.
<error code="C0059">It is a <glossterm>dynamic error</glossterm> if the name
of any attribute is “<code>xmlns</code>” or uses the prefix
“<literal>xmlns</literal>”
or any other prefix that resolves to the namespace name
<uri>http://www.w3.org/2000/xmlns/</uri>.</error> However,
if the attributes taken from the <option>attributes</option> use namespaces, 
prefixes, or prefixes bound to different namespaces, the document produced on the
<port>result</port> output port will require namespace fixup.</para>

<para>If an attribute named
<tag class="attribute">xml:base</tag> is added or changed, the base URI
of the element <rfc2119>must</rfc2119> also be amended accordingly.</para>

<simplesect>
<title>Document properties</title>
<para feature="set-attributes-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.set-properties">
<title>p:set-properties</title>

<para>The <tag>p:set-properties</tag> step sets document
properties on the source document.</para>

<p:declare-step type="p:set-properties">
   <p:input port="source" content-types="any"/>
   <p:output port="result" content-types="any"/>
   <p:option name="properties" required="true" as="map(xs:QName,item()*)"/>
   <p:option name="merge" select="true()" as="xs:boolean"/>
</p:declare-step>

 <para>The document properties of the document
on the <port>source</port> port are augmented with the values specified
in the <option>properties</option> option. The document produced on
the <port>result</port> port has the same representation but the
adjusted property values.</para>

<para feature="p-set-properties-merge">If the <option>merge</option>
option is true, then the supplied properties are added to the existing
properties, overwriting already existing values for a given key. 
If it is false, the document’s properties are replaced by
the new set.</para>

<para><error code="D0070">It is a <glossterm>dynamic error</glossterm> if a value is 
assigned to the <code>serialization</code> document property that cannot be converted 
into <code>map(xs:QName, item()*)</code> according
to the rules in section “QName handling” of <biblioref linkend="xproc31"/>.</error></para>

<para><error code="C0069">It is a <glossterm>dynamic
error</glossterm> if the <option>properties</option> map contains
a key equal to the string “<literal>content-type</literal>”.</error>
</para>

<para>If the <option>properties</option> map contains a key equal to the string
“<literal>base-uri</literal>” the associated value is taken as the new base URI of
   the resulting document. <error code="D0064">It is a <glossterm>dynamic 
   error</glossterm> if the base URI is not both absolute and valid according 
      to <biblioref linkend="rfc3986"/>.</error></para>

<simplesect>
<title>Document properties</title>
<para feature="set-properties-preserves-some">If <option>merge</option> is true, document 
properties not overridden by settings in the <option>properties</option> map are preserved, 
otherwise the resulting document has only the <literal>content-type</literal> property and the
properties specified in the <option>properties</option> map. In particular, if <option>merge</option> 
is false, the <literal>base-uri</literal> property will not be preserved. This means that the resulting
document will not have a base URI if the <option>properties</option> map does not contain 
a <literal>base-uri</literal> entry.
</para>
</simplesect>
</section>
<section xml:id="c.sink">
<title>p:sink</title>

<para>The <tag>p:sink</tag> step accepts a sequence of documents and
discards them. It has no output.</para>

<p:declare-step type="p:sink">
   <p:input port="source" content-types="any" sequence="true"/>
</p:declare-step>

<simplesect>
<title>Document properties</title>
<para feature="sing-preserves-na">Not applicable.</para>
</simplesect>
</section>
<section xml:id="c.sleep">
<title>p:sleep</title>

<para>The <tag>p:sleep</tag> step introduces a delay.</para>

<p:declare-step type="p:sleep">
  <p:input port="source" sequence="true" content-types="any"/>
  <p:output port="result" sequence="true" content-types="any"/>
  <p:option name="duration" as="xs:string" required="true"/>
</p:declare-step>

<para>The <tag>p:sleep</tag> step copies each of the documents on the
<port>source</port> port to the <port>result</port> port without changing them.
Before copying the documents, it pauses for a period of time not less
than the specified <option>duration</option>.</para>

<para>The duration may be specified as an <code>xs:double</code>, indicating a number of seconds,
or as a duration using a string that satisfies the constraints of an
<code>xs:dayTimeDuration</code>. The duration <rfc2119>must not</rfc2119> be
negative. 
<error code="D0036">It is a <glossterm>dynamic error</glossterm> if the
specified duration is not a positive number or a valid 
<code>xs:dayTimeDuration</code>.</error> The following table summarizes
some example durations:
</para>

<informaltable>
<tgroup cols="3">
<thead>
<row>
  <entry><code>duration</code></entry>
  <entry>Delay</entry>
  <entry>Notes</entry>
</row>
</thead>
<tbody>
<row>
  <entry><code>10</code></entry>
  <entry>10 seconds</entry>
  <entry/>
</row>
<row>
  <entry><code>3.5</code></entry>
  <entry>3.5 seconds</entry>
  <entry/>
</row>
<row>
  <entry><code>0.271</code></entry>
  <entry>271 milliseconds</entry>
  <entry/>
</row>
<row>
  <entry><code>PT3H1M41S</code></entry>
  <entry>3 hours, 1 minute, and 41 seconds</entry>
  <entry/>
</row>
<row>
  <entry><code>-7</code></entry>
  <entry>—</entry>
  <entry>Raises <code>err:XD0036</code></entry>
</row>
<row>
  <entry><code>3H</code></entry>
  <entry>—</entry>
  <entry>Raises <code>err:XD0036</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>

<note>
<para>In multi-threaded implementations, there is no guarantee that this
will pause the execution of more than one thread. However, any steps that
depend on the output of this step will wait for this step to complete.</para>
</note>

<para>Implementations are expected to make a reasonable effort to delay for the
specified duration, but XProc imposes no specific constraints on the precision of
the timer.</para>

<simplesect>
<title>Document properties</title>
<para feature="identity-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.split-sequence">
<title>p:split-sequence</title>

<para>The <tag>p:split-sequence</tag> step accepts a sequence of
documents and divides it into two sequences.</para>

<p:declare-step type="p:split-sequence">
  <p:input port="source" content-types="any" sequence="true"/>
  <p:output port="matched" sequence="true" primary="true" content-types="any"/>
  <p:output port="not-matched" sequence="true" content-types="any"/>
  <p:option name="initial-only" as="xs:boolean" select="false()"/>
  <p:option name="test" required="true" as="xs:string" e:type="XPathExpression"/>
</p:declare-step>

 <para>The value of the <option>test</option> option <rfc2119>must</rfc2119> be an XPathExpression.</para>

<para>The XPath expression in the <option>test</option> option is
applied to each document in the input sequence. If the effective
boolean value of the expression is true, the document is copied to the
<port>matched</port> port; otherwise it is copied to the
<port>not-matched</port> port.</para>

<para>If the <option>initial-only</option> option is true, then when
the first document that does not satisfy the test expression is
encountered, it <emphasis>and all the documents that follow
it</emphasis> are written to the <port>not-matched</port> port.
In other words, it only writes the initial series of matched
documents (which may be empty) to the <port>matched</port> port.
All other documents are written to the <port>not-matched</port> port,
irrespective of whether or not they match.</para>

<para>The XPath context for the
<option>test</option> option changes over time. For each document that
appears on the <code>source</code> port, the expression is evaluated
with that document as the context document. The context position
(<code>position()</code>) is the position of that document within the
sequence and the context size (<code>last()</code>) is the total
number of documents in the sequence. <error code="C0150">It is a 
<glossterm>dynamic error</glossterm> if evaluating the XPath expression
in option <option>test</option> on a context document results
in an error.</error></para>

<note xml:id="note-stream">
<para>In principle, this component cannot stream because it must
buffer all of the input sequence in order to find the context size. In
practice, if the test expression does not use the
<function>last()</function> function, the implementation can stream
and ignore the context size.</para>
</note>

<simplesect>
<title>Document properties</title>
<para feature="split-sequence-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.store">
<title>p:store</title>

<para>The <tag>p:store</tag> step stores (a possibly serialized
version of) its input to a URI. It outputs a reference to the location
of the stored document on the <port>result-uri</port> port.
Aside from these side-effects, it behaves like a <tag>p:identity</tag>
step, copying its input to the <port>result</port> port.</para>

<p:declare-step type="p:store">
  <p:input port="source" content-types="any"/>
  <p:output port="result" content-types="any" primary="true"/>
  <p:output port="result-uri" content-types="application/xml"/>
  <p:option name="href" required="true" as="xs:anyURI"/>
  <p:option name="serialization" as="map(xs:QName,item()*)?"/>
</p:declare-step>

<para>The value of the <option>href</option> option
<rfc2119>must</rfc2119> be an <type>anyURI</type>. If it is relative,
it is made absolute against the base URI of the element on which it is
specified (<tag>p:with-option</tag> or <tag>p:store</tag> in the case
of a syntactic shortcut
value).</para>

<para>The step attempts to store the document to the specified
  URI. If the URI scheme “<literal>file:</literal>” is supported, the processor
 <rfc2119>should</rfc2119> try to create all non existing folders in the URI’s path. 
<error code="C0050">It is a <glossterm>dynamic error</glossterm>
if the URI scheme is not supported or the step cannot store to the
specified location.</error></para>

<para>The output of this step on the <port>result-uri</port> port is a 
document containing a single <tag>c:result</tag> element whose content 
is the absolute URI of the document stored by the step.</para>

<para>The <option>serialization</option> option is provided to control the
serialization of content when it is stored. If the document to be stored
has a “serialization” property, the serialization is controlled by the
merger of the two maps where the entries in the “serialization” property
take precedence. Serialization is described in
<biblioref linkend="xproc31"/>.</para>

<simplesect>
<title>Document properties</title>
<para feature="store-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.string-replace">
<title>p:string-replace</title>

<para>The <tag>p:string-replace</tag> step matches nodes in the
document provided on the <port>source</port> port and replaces them
with the string result of evaluating an XPath expression.</para>

<p:declare-step type="p:string-replace">
   <p:input port="source" content-types="xml html"/>
   <p:output port="result" content-types="text xml html"/>
   <p:option name="match" required="true" as="xs:string" e:type="XSLTSelectionPattern"/>
   <p:option name="replace" required="true" as="xs:string" e:type="XPathExpression"/>
</p:declare-step>

<para>The value of the <option>match</option> option <rfc2119>must</rfc2119> be an
XSLTSelectionPattern.</para>

<para>The value of the <option>replace</option> option <rfc2119>must</rfc2119> be an
XPathExpression.</para>

<para>The matched nodes are specified with the <glossterm>selection pattern</glossterm> in the
<option>match</option> option.
For each matching node, the XPath
expression provided by the <option>replace</option> option is
evaluated with the matching node as the XPath context node.
The string value of the result is used in the output.
Nodes that do not match are copied without change.</para>

<para>If the expression given in the <option>match</option> option
matches an <emphasis>attribute</emphasis>, the string value of the
<option>replace</option>
expression is used as the new value of the attribute in the output.
If the attribute is named “<tag class="attribute">xml:base</tag>”, the base URI
of the element <rfc2119>must</rfc2119> also be amended accordingly.</para>

<para>If the document node is matched, the result is a text document.</para>

<para>If the expression matches any other kind of node, the entire
node (and <emphasis>not</emphasis> just its contents) is replaced by
the string value of the <option>replace</option> expression.</para>

<simplesect>
<title>Document properties</title>
   <para feature="string-replace-preserves-all">If the resulting document contains exactly one text node,
      the <literal>content-type</literal> property is changed to <literal>text/plain</literal> and the 
      <literal>serialization</literal> property is removed, while all other document properties are 
      preserved. For other document types, all document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.text-count">
  <title>p:text-count</title>

  <para>The <code>p:text-count</code> step counts the number of lines in a text document and returns a single XML
    document containing that number.</para>

  <p:declare-step type="p:text-count">
    <p:input port="source" primary="true" sequence="false" content-types="text"/>
    <p:output port="result" primary="true" sequence="false" content-types="application/xml"/>
  </p:declare-step>

  <para>The <tag>p:text-count</tag> step counts the number of lines in the text document appearing on its
      <port>source</port> port. It returns on its <port>result</port> port an XML document containing a single
      <tag>c:result</tag> element whose contents is the string representing this count.</para>

  <para>Lines are identified as described in <link xlink:href="https://www.w3.org/TR/xml/#sec-line-ends">XML, 2.11
      End-of-Line Handling</link>.
For the purpose of identifying lines, if the very last character in the text
document is a newline (&amp;#10;), that newline is ignored. (It is not a separator
between that line and a following line that contains no characters.)
</para>

  <simplesect>
    <title>Document properties</title>
    <para feature="text-count-preserves-none">No document properties are preserved.
The count document does not have a <property>base-uri</property> property.
</para>
  </simplesect>
</section>
<section xml:id="c.text-head">
  <title>p:text-head</title>

  <para>The <code>p:text-head</code> step returns lines from the beginning of a text document.</para>

  <p:declare-step type="p:text-head">
    <p:input port="source" primary="true" sequence="false" content-types="text"/>
    <p:output port="result" primary="true" sequence="false" content-types="text"/>
    <p:option name="count" required="true" as="xs:integer"/>
  </p:declare-step>

  <para>The <tag>p:text-head</tag> step returns on its <port>result</port> port lines from the text document that
    appears on its <port>source</port> port:</para>
  <itemizedlist>
    <listitem>
      <para>If the <option>count</option> option is positive, the <tag>p:text-head</tag> step returns the first
          <option>count</option> lines</para>
    </listitem>
    <listitem>
      <para>If the <option>count</option> option is zero, the <tag>p:text-head</tag> step returns all lines</para>
    </listitem>
    <listitem>
      <para>If the <option>count</option> option is negative, the <tag>p:text-head</tag> step returns all lines except
        the first <option>count</option> lines</para>
    </listitem>
  </itemizedlist>

  <para>Lines are identified as described in <link xlink:href="https://www.w3.org/TR/xml/#sec-line-ends">XML, 2.11
      End-of-Line Handling</link>.
All lines returned by <tag>p:text-head</tag> are terminated with a single
newline (&amp;#10;).</para>

  <simplesect>
    <title>Document properties</title>
    <para feature="add-attribute-preserves-all">All document properties are preserved.</para>
  </simplesect>
</section>
<section xml:id="c.text-join">
  <title>p:text-join</title>
  
  <para>The <code>p:text-join</code> step concatenates text documents.</para>
  
  <p:declare-step type="p:text-join">
    <p:input port="source" sequence="true" content-types="text"/>
    <p:output port="result" content-types="text"/>
    <p:option name="separator" as="xs:string?"/>
    <p:option name="prefix" as="xs:string?"/>
    <p:option name="suffix" as="xs:string?"/>
    <p:option name="override-content-type" as="xs:string?"/>
  </p:declare-step>
  
  <para>The <code>p:text-join</code> step concatenates the text documents appearing on its <port>source</port> port
    into a single document on its <port>result</port> port. The documents will be concatenated in order of appearance. </para>
  <itemizedlist>
    <listitem>
      <para>When the <option>separator</option> option is specified, its value will be inserted in between adjacent
        documents.</para>
    </listitem>
    <listitem>
      <para>When the <option>prefix</option> option is specified, the document appearing on the <port>result</port>
        port will always start with its value (also when there are no documents on the <port>source</port>
        port).</para>
    </listitem>
    <listitem>
      <para>When the <option>suffix</option> option is specified, the document appearing on the <port>result</port>
        port will always end with its value (also when there are no documents on the <port>source</port> port).</para>
    </listitem>
  </itemizedlist>
  <para>When the <option>override-content-type</option> option is specified, the document appearing on the port <port>result</port>
    will have this media type as part of its document properties. <error code="D0079">It is a <glossterm>dynamic 
      error</glossterm> if a supplied content-type is not  a valid media type of the form 
      “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable>+<replaceable>ext</replaceable></literal>” 
      or “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable></literal>”.</error> <error code="C0001">It is a
        <glossterm>dynamic error</glossterm> if the value of option <option>override-content-type</option> 
      is not a text media type.</error>
  </para>

  <para>Concatenating text documents does not require identifying individual
lines in each document, consequently no special end-of-line handling is
performed.</para>

  <simplesect>
    <title>Document properties</title>
    <para feature="text-join-preserves-none">No document properties are preserved.
The joined document has no <property>base-uri</property> property.
</para>
  </simplesect>
</section>
<section xml:id="c.text-replace">
  <title>p:text-replace</title>

  <para>The <code>p:text-replace</code> step replaces all occurrences of substrings in a text document that match a
    supplied regular expression with a given replacement string.</para>

  <p:declare-step type="p:text-replace">
    <p:input port="source" primary="true" sequence="false" content-types="text"/>
    <p:output port="result" primary="true" sequence="false" content-types="text"/>
    <p:option name="pattern" required="true" as="xs:string"/>
    <p:option name="replacement" required="true" as="xs:string"/>
    <p:option name="flags" as="xs:string?"/>
  </p:declare-step>

  <para>The <code>p:text-replace</code> step replaces all occurrences of substrings in the text document appearing on
    its <port>source</port> port that match a supplied regular expression with a given replacement string. The result is
    returned (as another text document) on its <port>result</port> port. </para>
  <para>This step is a convenience wrapper around the XPath <link xlink:href="https://www.w3.org/TR/xpath-functions-31/#func-replace"><function>fn:replace</function></link>
    function to ease text replacements in the document flow of a pipeline.</para>

  <para>The <option>pattern</option>, <option>replacement</option> and <option>flags</option>
    options are specified the same as the parameters with the same names of the <link xlink:href="https://www.w3.org/TR/xpath-functions-31/#func-replace"><function>fn:replace</function></link> function. The <option>pattern</option> option
      <rfc2119>must</rfc2119> be a regular expression as specified in <biblioref linkend="xpath31-functions"/>, section 7.61 “<literal>Regular Expression Syntax</literal>”.
      <error code="C0147">It is a <glossterm>dynamic error</glossterm> if the specified value is not
      a valid XPath regular expression.</error></para>

  <para>Replacing strings in text documents does not require identifying individual
lines in each document, consequently no special end-of-line handling is
performed.</para>

  <simplesect>
    <title>Document properties</title>
    <para feature="add-attribute-preserves-all">All document properties are preserved.</para>
  </simplesect>
</section>
<section xml:id="c.text-sort">
  <title>p:text-sort</title>

  <para>The <code>p:text-sort</code> step sorts lines in a text document.</para>

  <p:declare-step type="p:text-sort">
    <p:input port="source" primary="true" sequence="false" content-types="text"/>
    <p:output port="result" primary="true" sequence="false" content-types="text"/>
    <p:option name="sort-key" as="xs:string" select="'.'" e:type="XPathExpression"/>
    <p:option name="order" as="xs:string" select="'ascending'" values="('ascending', 'descending')"/>
    <p:option name="case-order" as="xs:string?" values="('upper-first', 'lower-first')"/>
    <p:option name="lang" as="xs:language?"/>
    <p:option name="collation" as="xs:string" select="'http://www.w3.org/2005/xpath-functions/collation/codepoint'"/>
    <p:option name="stable" as="xs:boolean" select="true()"/>
  </p:declare-step>

  <para>The <tag>p:text-sort</tag> step sorts the lines in the text document appearing on its <port>source</port> port
    and returns the result as another text document on its <port>result</port> port. The sort key is obtained by applying
    the XPath expression in <option>sort-key</option> to each line in turn.</para>
  <itemizedlist>
    <listitem>
      <para>The <option>sort-key</option> is used to obtain a sort key for each of the lines in the document
       appearing on <port>source</port>. The <code>context item</code> is the line as an instance of <code>xs:string</code>,
       the <code>context position</code> is the number of the line in the document on port <port>source</port>, the
       <code>context size</code> is the number of lines in this document. <error code="C0098">It is a 
       <glossterm>dynamic error</glossterm> if a dynamic XPath error occurred while applying sort-key to a line.</error>
       <error code="C0099">It is a <glossterm>dynamic error</glossterm> if the result of applying <code>sort-key</code>
       to a given line results in a sequence with more than one item.</error>
      </para>
    </listitem>
    <listitem>
     <para>The <option>order</option> option defines whether the lines are processed in ascending or descending order.
        Its value <rfc2119>must</rfc2119> be one of <code>ascending</code> or <code>descending</code>. The default is
          <code>ascending</code>.</para>
    </listitem>
    <listitem>
      <para>The <option>case-order</option> option defines whether upper-case letters are to be collated before or after
        lower-case letters. Its value <rfc2119>must</rfc2119> be one of <code>upper-first</code> or
          <code>lower-first</code>. The default is language-dependent.</para>
    </listitem>

<listitem>
<para>The <option>lang</option> option defines the language whose collating
conventions are to be used.
The <code>xs:language</code> data type represents natural language identifiers
as defined by <biblioref linkend="bcp47"/> (currently
represented by <biblioref linkend="rfc4646"/> and <biblioref linkend="rfc4647"/>
or its successor(s).)
The default depends on the processing environment.
Its value must be a valid language code (e.g. <code>en-EN</code>).
</para>
</listitem>

<listitem>
      <para>The <option>collation</option> option identifies how strings are to be compared with each other. Its value
        must be a valid collation URI. The only collation XProc processors <rfc2119>must</rfc2119> support is the
        Unicode Codepoint Collation <link xlink:href="http://www.w3.org/2005/xpath-functions/collation/codepoint/"><code>http://www.w3.org/2005/xpath-functions/collation/codepoint</code></link>. This is also its default.
        <impl>Support for other collations is <glossterm>implementation-defined</glossterm>.</impl></para>
    </listitem>
    <listitem>
      <para>If the <option>stable</option> option is set to <code>false</code> this indicates that there is no
        requirement to retain the original order of items that have equal values for all the sort keys.</para>
    </listitem>
  </itemizedlist>

  <para>Lines are identified as described in <link xlink:href="https://www.w3.org/TR/xml/#sec-line-ends">XML, 2.11
      End-of-Line Handling</link>.
For the purpose of identifying lines, if the very last character in the text
document is a newline (&amp;#10;), that newline is ignored. (It is not a separator
between that line and a following line that contains no characters.)
All lines returned by <tag>p:text-sort</tag> are terminated with a single
newline (&amp;#10;).</para>

  <para>The sort process performed by this step is the same as the process described in
  <biblioref linkend="xslt30"/> for the
  <link xlink:href="https://www.w3.org/TR/xslt-30/#xsl-sort">xsl:sort</link> element.
  The options <option>lang</option>
  and <option>case-order</option> are considered only if the value
  of the <option>collation</option> option is the empty sequence.</para>

  <simplesect>
    <title>Document properties</title>
    <para feature="text-sort-preserves-all">All document properties are preserved.</para>
  </simplesect>
</section>
<section xml:id="c.text-tail">
  <title>p:text-tail</title>
  
  <para>The <code>p:text-tail</code> step returns lines from the end of a text document.</para>
  
  <p:declare-step type="p:text-tail">
    <p:input port="source" primary="true" sequence="false" content-types="text"/>
    <p:output port="result" primary="true" sequence="false" content-types="text"/>
    <p:option name="count" required="true" as="xs:integer"/>
  </p:declare-step>
  
  <para>The <tag>p:text-tail</tag> step returns on its <port>result</port> port lines from the text document that
    appears on its <port>source</port> port:</para>
  <itemizedlist>
    <listitem>
      <para>If the <option>count</option> option is positive, the <tag>p:text-tail</tag> step returns the last
        <option>count</option> lines</para>
    </listitem>
    <listitem>
      <para>If the <option>count</option> option is zero, the <tag>p:text-tail</tag> step returns all lines</para>
    </listitem>
    <listitem>
      <para>If the <option>count</option> option is negative, the <tag>p:text-tail</tag> step returns all lines except
        the last <option>count</option> lines</para>
    </listitem>
  </itemizedlist>
  
  <para>Lines are identified as described in <link xlink:href="https://www.w3.org/TR/xml/#sec-line-ends">XML, 2.11
    End-of-Line Handling</link>.
All lines returned by <tag>p:text-tail</tag> are terminated with a single
newline (&amp;#10;).</para>
  
  <simplesect>
    <title>Document properties</title>
    <para feature="text-tail-preserves-all">All document properties are preserved.</para>
  </simplesect>
</section>
<section xml:id="c.unarchive">

  <title>p:unarchive</title>

  <para>The <code>p:unarchive</code> step outputs on its <port>result</port> port specific entries
    in an archive (for instance from a zip file).</para>

  <p:declare-step type="p:unarchive">
    <p:input port="source" primary="true" content-types="any" sequence="false"/>
    <p:output port="result" primary="true" content-types="any" sequence="true"/>
    <p:option name="include-filter" as="xs:string*" e:type="RegularExpression"/>
    <p:option name="exclude-filter" as="xs:string*" e:type="RegularExpression"/>
    <p:option name="format" as="xs:QName?"/>
    <p:option name="parameters" as="map(xs:QName, item()*)?"/>
    <p:option name="relative-to" as="xs:anyURI?"/>
    <p:option name="override-content-types" as="array(array(xs:string))?"/>
  </p:declare-step>

  <para>The meaning and interpretation of the <code>p:unarchive</code> step's options is as
    follows:</para>

  <itemizedlist>
    <listitem>
      <para>The format of the archive is determined as follows:</para>
      <itemizedlist>
        <listitem>
          <para>If the <option>format</option> option is specified, this determines the format of
            the archive. Implementations <rfc2119>must</rfc2119> support the <biblioref linkend="zip"/> format, specified with the value <code>zip</code>. <impl>It is
                <glossterm>implementation-defined</glossterm> what other formats are
              supported.</impl></para>
        </listitem>
        <listitem>
          <para>If no <option>format</option> option is specified or if its value is the empty
            sequence, the archive's format will be determined by the step, using the
              <code>content-type</code> document-property of the document on the <port>source</port>
            port and/or by inspecting its contents. <impl>It is
                <glossterm>implementation-defined</glossterm> how the step determines the archive's
              format.</impl> Implementations <rfc2119>should</rfc2119> recognize archives in
              <biblioref linkend="zip"/> format. </para>
        </listitem>
        <listitem><para><error code="C0085">It is a <glossterm>dynamic error</glossterm> if the format of the archive 
          does not match the specified format, cannot be understood, determined and/or processed.</error></para>
        </listitem>
      </itemizedlist>
    </listitem>
    <listitem>
      <para>The <option>parameters</option> option can be used to supply parameters to control the
        unarchiving. <impl>The semantics of the keys and the allowed values for these keys are
            <glossterm>implementation-defined</glossterm>.</impl>
        <error code="C0079">It is a <glossterm>dynamic error</glossterm> if the map
            <option>parameters</option> contains an entry whose key is defined by the implementation
          and whose value is not valid for that key.</error></para>
    </listitem>
    <listitem>
      <para>If present, the value of the <option>include-filter</option> or
          <option>exclude-filter</option> option <rfc2119>must</rfc2119> be a sequence of strings,
        each one representing a regular expressions as specified in <biblioref linkend="xpath31-functions"/>, section 7.61 “<literal>Regular Expression
            Syntax</literal>”. <error code="C0147">It is a <glossterm>dynamic
              error</glossterm> if a specified value is not a valid XPath regular
              expression.</error></para>

      <para>If neither the <option>include-filter</option> option nor the
          <option>exclude-filter</option> option is specified, the <code>p:unarchive</code> step
        outputs on its <port>result</port> port all entries in the archive.</para>

      <para>If the <option>include-filter</option> option or the <option>exclude-filter</option>
        option is specified, the <code>p:archive</code> step outputs on the <port>result</port> port
        the entries from the archive that conform to the following rules:</para>
      <itemizedlist>
        <listitem>
          <para>If any <option>include-filter</option> pattern matches an archive entry's name, the
            entry is included in the output.</para>
        </listitem>
        <listitem>
          <para>If any <option>exclude-filter</option> pattern matches an archive entry's name, the
            entry is excluded in the output.</para>
        </listitem>
        <listitem>
          <para>If both options are provided, the include filter is processed first, then the
            exclude filter. </para>
        </listitem>
        <listitem>
          <para>Names of entries in archives are always relative names. For instance, the name of a
            file called <code>xyz.xml</code> in a <code>specs</code> subdirectory in an archive is
            called in full <code>specs/xyz.xml</code> (and not <code>/specs/xyz.xml</code>).</para>
        </listitem>
      </itemizedlist>
      <para>As a result: an item is included if it matches (at least) one of the
          <option>include-filter</option> values and none of the <option>exclude-filter</option>
        values.</para>
      <para>The regular expressions specified in the <option>include-filter</option> and
          <option>exclude-filter</option> options will be matched against the path of the entry
          <emphasis>in</emphasis> the archive. The matching is done unanchored: it is a match if the
        regular expression matches part of the entry's path. Informally: matching behaves like
        applying the XPath <code>matches#2</code> function, like in <code>matches($path-in-archive,
          $regular-expression)</code>.</para>
      <note>
        <para>Depending on how archives are constructed, the path of an entry in an archive can be
          with or without a leading slash. Usually it will be without. For archives constructed by
            <tag>p:archive</tag> no leading slash will be present.</para>
      </note>
    </listitem>
    <listitem>
      <para>The <option>relative-to</option> option, when present, is used in creating the base URI
        of the unarchived documents. If the option is relative, it is made absolute against the
        base URI of the element on which it is specified (<tag>p:with-option</tag> or the step in
        case of a syntactic shortcut value).</para>
    </listitem>
    <listitem>
      <para>The <option>override-content-types</option> option can be used to partially override the
        content-type determination mechanism, as described in <xref linkend="override-content-type"/>.</para>
    </listitem>
  </itemizedlist>

  <para>The base URI of an unarchived document appearing on the <port>result</port> port is: </para>
  <itemizedlist>
    <listitem>
      <para>If the <option>relative-to</option> option is present: Function <code>p:urify()</code> is
        called with the value of this option as second parameter (<code>$basedir</code>) and
        with the relative path of this document as it was in the archive as first parameter</para>
    </listitem>
    <listitem>
      <para>If the <option>relative-to</option> option is <emphasis>not</emphasis> present: Function
        <code>p:urify()</code>is called with the
        value of the base URI of the archive appended with a “<literal>/</literal>” as second
        parameter (<code>$baseDir</code>) and the relative path of this document as it
        was in the archive as first parameter</para>
    </listitem>
  </itemizedlist>
  
  <para><error code="C0120">It is a <glossterm>dynamic error</glossterm> if the 
    <option>relative-to</option> option is not present and the document on the 
    <port>source</port> port does not have a base URI.</error>
    <error code="D0064">It is a <glossterm>dynamic
    error</glossterm> if the option is not a valid URI according to <biblioref linkend="rfc3986"/>.</error></para>
  
  <para>For instance, the base URI of an unarchived file called <code>xyz.xml</code> that resided in
    the <code>specs</code> subdirectory in an archive with base URI <code>file:///a/b/c.zip</code>
    will become: </para>
  <itemizedlist>
    <listitem>
      <para>With the <option>relative-to</option> option set to <code>file:///x/y/z</code>:
          <code>file:///x/y/z/specs/xyz.xml</code></para>
    </listitem>
    <listitem>
      <para>Without a <option>relative-to</option> option set:
          <code>file:///a/b/c.zip/specs/xyz.xml</code></para>
    </listitem>
  </itemizedlist>
  
  <simplesect>
    <title>Document properties</title>
    <para feature="unarchive-preserves-none">No document properties are preserved.
The <property>base-uri</property> property of each unarchived document is reflective of
the base URI of the document.
</para>
  </simplesect>
</section>
<section xml:id="c.uncompress">

  <title>p:uncompress</title>

  <para>The <tag>p:uncompress</tag> step expects on its <port>source</port> port a compressed
    document. It outputs an uncompressed version of this on its <port>result</port> port.</para>

  <p:declare-step type="p:uncompress">
    <p:input port="source" primary="true" content-types="any" sequence="false"/>
    <p:output port="result" primary="true" content-types="any" sequence="false"/>
    <p:option name="format" as="xs:QName?"/>
    <p:option name="parameters" as="map(xs:QName,item()*)?"/>
    <p:option name="content-type" as="xs:string" select="'application/octet-stream'"/>
  </p:declare-step>

  <para>The compression format of the document appearing on the <port>source</port> port is
    determined as follows:</para>
  <itemizedlist>
    <listitem>
      <para>If the <option>format</option> option is specified, this determines the compression
        format. Implementations <rfc2119>must</rfc2119> support the <biblioref linkend="gzip"/>
        format, specified with the value <code>gzip</code>. <impl>It is
            <glossterm>implementation-defined</glossterm> what other formats are supported.</impl>
         <error code="C0202">It is a <glossterm>dynamic error</glossterm> if the compression
            format cannot be understood, determined and/or processed.</error></para>
    </listitem>
    <listitem>
      <para>If no <option>format</option> option is specified or its value is the empty sequence,
        the compression format will be determined by the step, using the <code>content-type</code>
        document-property of the document on the <port>source</port> port and/or by inspecting its
        contents. <impl>It is <glossterm>implementation-defined</glossterm> how the step determines
          the compression format.</impl> Implementations <rfc2119>should</rfc2119> recognize
        archives in <biblioref linkend="gzip"/> format. </para>
    </listitem>
  </itemizedlist>
  
  <para>The <option>parameters</option> option can be used to supply parameters to control the
    uncompression. <impl>The semantics of the keys and the allowed values for these keys are
      <glossterm>implementation-defined</glossterm>.</impl>
    <error code="C0079">It is a <glossterm>dynamic error</glossterm> if the map
      <option>parameters</option> contains an entry whose key is defined by the
      implementation and whose value is not valid for that key.</error></para>

  <para>Identification of the uncompressed document's content-type is done as follows:</para>
  <orderedlist>
    <listitem>
      <para>If the <option>content-type</option> option is specified, the uncompressed document
        <rfc2119>must</rfc2119> be interpreted according to that content-type. 
        <error code="D0079">It is a <glossterm>dynamic error</glossterm> if a supplied content-type is not 
          a valid media type of the form 
          “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable>+<replaceable>ext</replaceable></literal>” 
          or “<literal><replaceable>type</replaceable>/<replaceable>subtype</replaceable></literal>”.</error>
        <error code="C0201">It is a <glossterm>dynamic error</glossterm> if the
            <tag>p:uncompress</tag> step cannot perform the requested content-type cast.</error>
      </para>
    </listitem>
    <listitem>
      <para>In the absence of an explicit type, the content will be interpreted as content
          type <code>application/octet-stream</code>.</para>
    </listitem>
  </orderedlist>

  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

  <simplesect>
    <title>Document properties</title>
    <para feature="uncompress-preserves-some">All document properties are preserved, except for the
        <code>content-type</code> property which is updated accordingly.</para>
  </simplesect>

</section>
<section xml:id="c.unwrap">
<title>p:unwrap</title>

<para>The <tag>p:unwrap</tag> step replaces matched elements with their
children.</para>

<p:declare-step type="p:unwrap">
   <p:input port="source" content-types="xml html"/>
  <p:output port="result" content-types="text xml html"/>
   <p:option name="match" as="xs:string" select="'/*'" e:type="XSLTSelectionPattern"/>
</p:declare-step>

 <para>The value of the <option>match</option> option <rfc2119>must</rfc2119> be an
 XSLTSelectionPattern. <error code="C0023">It is a <glossterm>dynamic
 error</glossterm> if that pattern matches anything other than the document node
 or element nodes.</error></para>

<para>Every element in the <port>source</port> document that matches
the specified <option>match</option> pattern is replaced by its children,
effectively “unwrapping” the children from their parent. Non-element nodes
and unmatched elements are passed through unchanged.</para>

<note xml:id="note-match-doc">
<para>The matching applies to the entire document, not just the “top-most”
matches. A pattern of the form <literal>h:div</literal> will replace
<emphasis>all</emphasis> <tag>h:div</tag> elements, not just the top-most
ones.</para>
</note>

  <para>This step produces a single document. Special cases:</para> 
  <itemizedlist>
    <listitem>
      <para>If the document element is unwrapped, the result might not be well-formed XML.</para>
      <para>For instance unwrapping the root element of
          <code>&lt;!-- COMMENT --&gt;&lt;root-element/&gt;</code> will result in a document node
        with a single comment node child, which is not well-formed.</para>
    </listitem>
    <listitem>
      <para>If a document consisting of only an empty root element is unwrapped, the result will be
        a document node without children. The result document’s content type will not change.</para>
    </listitem>
    <listitem>
      <para>If a document consisting of a root element containing only text is unwrapped, the result will be
        a document node with a single text node child. The result document’s content type will become
        “<literal>text/plain</literal>”.</para>
    </listitem>
  </itemizedlist>
  
  <para>As specified in the core language specification: if the content type changes, the
      <code>serialization</code> document property, if present, will be removed.</para>
  
<simplesect>
<title>Document properties</title>
  <para feature="unwrap-preserves-partially">If the resulting document contains exactly one text node,
    the <literal>content-type</literal> property is changed to <literal>text/plain</literal> and the 
    <literal>serialization</literal> property is removed, while all other document properties are 
    preserved. In all other cases, all document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.uuid">
<title>p:uuid</title>

<para>The <tag>p:uuid</tag> step generates a
<biblioref linkend="bib.uuid"/> and injects it into
the <port>source</port> document.</para>

<p:declare-step type="p:uuid">
  <p:input port="source" primary="true" content-types="xml html"/>
  <p:output port="result" content-types="text xml html"/>
  <p:option name="match" as="xs:string" select="'/*'" e:type="XSLTSelectionPattern"/>
  <p:option name="version" as="xs:integer?"/>
  <p:option name="parameters" as="map(xs:QName, item()*)?"/>
</p:declare-step>

<para>The value of the <option>match</option> option must be an
XSLTSelectionPattern. The value of the <option>version</option> option
must be an integer.</para>

<para>If the <option>version</option> is specified, that version of
UUID must be computed. <error code="C0060">It is a <glossterm>dynamic
error</glossterm> if the processor does not support the specified
<option>version</option> of the UUID algorithm.</error> <impl>If the
<option>version</option> is not specified, the version of UUID
computed is
<glossterm>implementation-defined</glossterm>.</impl></para>

<para>Implementations <rfc2119>must</rfc2119> support version 4 UUIDs.
<impl>Support for other versions of UUID
is <glossterm>implementation-defined</glossterm>.</impl>
Some UUID schemes require additional parameters which may be provided
in the <option>parameters</option> option.
<impl>The names and values of <option>parameters</option> to <tag>p:uuid</tag>
are <glossterm>implementation-defined</glossterm>.</impl>
</para>

<para>The matched nodes are specified with the <glossterm>selection pattern</glossterm> in the
<option>match</option> option. For each matching node, the generated
UUID is used in the output (if more than one node matches, the
<emphasis>same</emphasis> UUID is used in each match). Nodes that do not
match are copied without change.</para>

<para>If the expression given in the <option>match</option> option
matches an <emphasis>attribute</emphasis>, the UUID is used as the new
value of the attribute in the output. If the attribute is named “<tag class="attribute">xml:base</tag>”, the base URI of the element
<rfc2119>must</rfc2119> also be amended accordingly.</para>

<para>If the document node is matched, the result is a text document.</para>

<para>If the expression matches any
other kind of node, the entire node (and <emphasis>not</emphasis> just
its contents) is replaced by the UUID.</para>

<simplesect>
<title>Document properties</title>
  <para feature="uuid-preserves-partially">If the resulting document contains exactly one text node,
    the <literal>content-type</literal> property is changed to <literal>text/plain</literal> and the 
    <literal>serialization</literal> property is removed, while all other document properties are 
    preserved. For other document types, all document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.wrap">
<title>p:wrap</title>

<para>The <tag>p:wrap</tag> step wraps matching nodes in the
<port>source</port> document with a new parent element.</para>

<p:declare-step type="p:wrap">
   <p:input port="source" content-types="xml html"/>
   <p:output port="result" content-types="application/xml"/>
   <p:option name="wrapper" required="true" as="xs:QName"/>
   <p:option name="match" required="true" as="xs:string" e:type="XSLTSelectionPattern"/>
   <p:option name="group-adjacent" as="xs:string?" e:type="XPathExpression"/>
   <p:option name="attributes" as="map(xs:QName, xs:anyAtomicType)?"/>
</p:declare-step>

<para>The value of the <option>match</option> option
<rfc2119>must</rfc2119> be an XSLTSelectionPattern. <error code="C0023">It
is a <glossterm>dynamic error</glossterm> if the pattern matches
anything other than document, element, text, processing instruction, and comment
nodes.</error>
</para>

<para>The value of the <option>group-adjacent</option> option
<rfc2119>must</rfc2119> be an XPathExpression.</para>

<para>If the node matched is the document node (<code>match="/"</code>),
the result is a new document where the document element is a new
element node whose QName is the value specified in the
<option>wrapper</option> option. That new element contains copies of
all of the children of the original document node.</para>

<para>When the <glossterm>selection pattern</glossterm> does not match the document node,
every node that matches the specified <option>match</option>
pattern is replaced with a new element node whose QName is the value
specified in the <option>wrapper</option> option.
The content of that new element is a copy of the original,
matching node. The <tag>p:wrap</tag> step performs a "deep" wrapping, the children
of the matching node and their descendants are processed and wrappers
are added to all matching nodes.
</para>

<para>The <option>group-adjacent</option> option can be used to group
adjacent matching nodes in a single wrapper element. The specified
XPath expression is evaluated for each matching node with that node
as the XPath context node. Whenever two or more adjacent matching nodes
have the same “group adjacent” value, they are wrapped together in
a single wrapper element. Two “group adjacent” values are the same if the
standard XPath function <code>deep-equal()</code> returns true for them.</para>

<para>Two matching nodes are considered adjacent if and only if they
are siblings and either there are no nodes between them or all
intervening, non-matching nodes are whitespace text, comment, or processing
instruction nodes.</para>

<para>If the <option>attributes</option> option is used, a new attribute is
created on the wrapper element for each entry in the map. The attribute name is
taken from the entry's key while the attribute value is taken from the string
value of the entry's value.</para>

<para>Namespace declarations cannot be added
with the <option>attributes</option> option.
<error code="C0059">It is a <glossterm>dynamic error</glossterm> if the name
of any attribute is “<code>xmlns</code>” or uses the prefix
“<literal>xmlns</literal>”
or any other prefix that resolves to the namespace name
<uri>http://www.w3.org/2000/xmlns/</uri>.</error> However,
if the attributes taken from the <option>attributes</option> use namespaces,
prefixes, or prefixes bound to different namespaces, the document produced on the
<port>result</port> output port will require namespace fixup.</para>

<para>If an attribute named <tag class="attribute">xml:base</tag> is added, the
base URI of the element <rfc2119>must</rfc2119> also be amended
accordingly.</para>

<simplesect>
<title>Document properties</title>
<para feature="wrap-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.wrap-sequence">
<title>p:wrap-sequence</title>

<para>The <tag>p:wrap-sequence</tag> step accepts a sequence of
documents and produces either a single document or a new sequence of
documents.</para>

<p:declare-step type="p:wrap-sequence">
   <p:input port="source" content-types="text xml html" sequence="true"/>
   <p:output port="result" sequence="true" content-types="application/xml"/>
   <p:option name="wrapper" required="true" as="xs:QName"/>
   <p:option name="group-adjacent" as="xs:string?" e:type="XPathExpression"/>
   <p:option name="attributes" as="map(xs:QName, xs:anyAtomicType)?"/>
</p:declare-step>

<para>The value of the <option>group-adjacent</option> option
<rfc2119>must</rfc2119> be an XPathExpression.</para>

<para>In its simplest form, <tag>p:wrap-sequence</tag> takes a
sequence of documents and produces a single, new document by placing
each document in the <port>source</port> sequence inside a new
document element as sequential siblings. The name of the document
element is the value specified in the <option>wrapper</option>
option.</para>

<para>The <option>group-adjacent</option> option can be used to group
adjacent documents.
The XPath context
for the
<option>group-adjacent</option> option changes over time. For each document that
appears on the <code>source</code> port, the expression is evaluated
with that document as the context document. The context position
(<code>position()</code>) is the position of that document within the
sequence and the context size (<code>last()</code>) is the total
number of documents in the sequence.
Whenever
two or more sequentially adjacent documents have the same “group
adjacent” value, they are wrapped together in a single wrapper
element.
Two “group adjacent” values are the same if the
standard XPath function <code>deep-equal()</code> returns true for them.</para>

<para>If the <option>attributes</option> option is used, a new attribute is
created on the wrapper element for each entry in the map. The attribute name is
taken from the entry's key while the attribute value is taken from the string
value of the entry's value.</para>

<para>Namespace declarations cannot be added
with the <option>attributes</option> option.
<error code="C0059">It is a <glossterm>dynamic error</glossterm> if the name
of any attribute is “<code>xmlns</code>” or uses the prefix
“<literal>xmlns</literal>”
or any other prefix that resolves to the namespace name
<uri>http://www.w3.org/2000/xmlns/</uri>.</error> However,
if the attributes taken from the <option>attributes</option> use namespaces,
prefixes, or prefixes bound to different namespaces, the document produced on the
<port>result</port> output port will require namespace fixup.</para>

<para>If an attribute named <tag class="attribute">xml:base</tag> is added, the
base URI of the element <rfc2119>must</rfc2119> also be amended
accordingly.</para>

<simplesect>
<title>Document properties</title>
<para feature="wrap-sequence-preserves-none">No document properties are preserved.
The result documents do not have a <property>base-uri</property> property unless
one is specified with the <option>attributes</option> option.
</para>
</simplesect>
</section>
<section xml:id="c.www-form-urldecode">
<title>p:www-form-urldecode</title>

<para>The <tag>p:www-form-urldecode</tag> step decodes a
<literal>x-www-form-urlencoded</literal> string into a JSON representation.</para>

<p:declare-step type="p:www-form-urldecode">
  <p:output port="result" content-types="application/json"/>
  <p:option name="value" required="true" as="xs:string"/>
</p:declare-step>

<para>A JSON object of the form “<literal>map(xs:string, xs:string+)</literal>” will
appear on <port>result</port> port. The <option>value</option> option is interpreted 
as a string of parameter values encoded using the
<literal>x-www-form-urlencoded</literal> algorithm. Each name/value
pair is represented in the JSON object as key/value entry.
</para>

<para><error code="C0037">It is a
<glossterm>dynamic error</glossterm> if the <option>value</option> provided
is not a properly
<literal>x-www-form-urlencoded</literal> value.</error>
</para>

<para>If any parameter name occurs more than once in the encoded string,
a sequence will be associated with the respective key. The order in the sequence
retains the order of name/value pairs in the encoded string.</para>

<simplesect>
<title>Document properties</title>
<para feature="www-form-urldecode-preserves-none">The resulting JSON document has no properties 
  apart from <property>content-type</property>. In particular, it has no <property>base-uri</property>.</para>
</simplesect>
</section>
<section xml:id="c.www-form-urlencode">
<title>p:www-form-urlencode</title>

<para>The <tag>p:www-form-urlencode</tag> step encodes a set of parameter
values as a <literal>x-www-form-urlencoded</literal> string.</para>

<p:declare-step type="p:www-form-urlencode">
  <p:output port="result" content-types="text/plain"/>
  <p:option name="parameters" required="true" as="map(xs:string,xs:anyAtomicType+)"/>
</p:declare-step>

<para>The map entries of <option>parameters</option> option are encoded as a single
<literal>x-www-form-urlencoded</literal> string of name/value pairs. This
string is returned on the <port>result</port> port as a text document.
</para>

<para>If more than one value is associated with a given key in <option>parameters</option>
option, a name/value pair is created for each value.</para>

<simplesect>
<title>Document properties</title>
<para feature="www-form-urlencode-preserves-none">The resulting text document has no properties 
  apart from <property>content-type</property>. In particular, it has no <property>base-uri</property>.</para>
</simplesect>
</section>
<section xml:id="c.xinclude">
<title>p:xinclude</title>

<para>The <tag>p:xinclude</tag> step applies <biblioref linkend="xinclude"/> processing to the <port>source</port> document.</para>

<p:declare-step type="p:xinclude">
  <p:input port="source" content-types="xml html"/>
  <p:output port="result" content-types="xml html"/>
  <p:option name="fixup-xml-base" as="xs:boolean" select="false()"/>
  <p:option name="fixup-xml-lang" as="xs:boolean" select="false()"/>
</p:declare-step>

<para>The value of the <option>fixup-xml-base</option> option <rfc2119>must</rfc2119> be a
boolean. If it is true, base URI fixup will be performed as per
<biblioref linkend="xinclude"/>.</para>

<para>The value of the <option>fixup-xml-lang</option> option <rfc2119>must</rfc2119> be a
boolean. If it is true, language fixup will be performed as per
<biblioref linkend="xinclude"/>.</para>

<para>The included documents are located with the base URI of the
input document and are not provided as input to the step.</para>

<para><error code="C0029">It is a <glossterm>dynamic error</glossterm>
if an XInclude error occurs during processing.</error> </para>

<simplesect>
<title>Document properties</title>
<para feature="xinclude-preserves-all">All document properties are preserved.</para>
</simplesect>
</section>
<section xml:id="c.xquery">
<title>p:xquery</title>

<para>The <tag>p:xquery</tag> step applies an
XQuery query to the sequence of documents
provided on the <port>source</port> port.</para>

<p:declare-step type="p:xquery">
  <p:input port="source" content-types="any" sequence="true" primary="true"/>
  <p:input port="query" content-types="text xml"/>
  <p:output port="result" sequence="true" content-types="any"/>
  <p:option name="parameters" as="map(xs:QName,item()*)?"/>
  <p:option name="version" as="xs:string?"/>
</p:declare-step>

<para>If a sequence of documents is provided on the
<port>source</port> port, the first document is used as the
initial context item. The whole sequence is also the default
collection. If no documents are provided on the <port>source</port> port,
the initial context item is undefined and the default collection
is empty.</para>

<para>The <port>query</port> port must receive a single document which is either an XML
  document or a text document. A text document <rfc2119>must</rfc2119> be treated as
  the query. For an XML document the following rules apply:</para>
 
<itemizedlist>
  <listitem>
    <para>If the document root element is <tag xml:id="cv.query">c:query</tag>, the text
      descendants of this element are considered the query.</para>
    <e:rng-pattern name="VocabQuery"/>
  </listitem>
  <listitem>
      <para>If the document root element is in the XQueryX namespace, the
        document is treated as an XQueryX-encoded query. <impl>Support for
          XQueryX is <glossterm>implementation-defined</glossterm>.</impl>
      </para>
    </listitem>
    <listitem>
      <para>Otherwise the serialization of the document <rfc2119>must</rfc2119> be treated as
        the query. The document's serialization property (if present) is used.</para>
    </listitem>
</itemizedlist>
 
<para>If the step specifies a <option>version</option>, then that version
of XQuery <rfc2119>must</rfc2119> be used to process the transformation.
<error code="C0009">It is a
<glossterm>dynamic error</glossterm> if the specified XQuery version
is not available.</error> If the step does not specify a version, the
implementation may use any version it has available and may use any means
to determine what version to use, including, but not limited to,
examining the version of the query.<impl>It is <glossterm>implementation-defined</glossterm>
which XQuery version(s) is/are supported.</impl></para>

<para>The name/value pairs in option <option>parameters</option> are used to set the query’s
external variables.</para>
  
<para><error code="C0101">It is a <glossterm>dynamic error</glossterm> if a document
appearing on port <port>source</port> cannot be represented in the XDM version associated with
  the chosen XQuery version, e.g. when a JSON document contains a map and XDM 3.0 is used.</error> 
  <error code="C0102">It is a <glossterm>dynamic error</glossterm> if any key in option 
    <option>parameters</option> is associated to a value that cannot be represented in 
    the XDM version associated with the chosen XQuery version, e.g. with a map, an array, 
    or a function when XDM 3.0 is used.</error></para>

<para><error code="C0103">It is a <glossterm>dynamic error</glossterm> if any error occurs during
    XQuery’s static analysis phase.</error> <error code="C0104">It is a <glossterm>dynamic error</glossterm>
    if any error occurs during XQuery’s dynamic evaluation phase.</error></para>
      
<para>The output of this step
<rfc2119>may</rfc2119> include PSVI annotations.</para>

<para>The static context of the XQuery processor is augmented in the following
way:</para>

<variablelist>
<varlistentry>
<term>Statically known default collection type</term>
<listitem>
<para><literal>document()*</literal></para>
</listitem>
</varlistentry>
<varlistentry>
<term>Statically known namespaces:</term>
<listitem>
<para>Unchanged from the implementation defaults. No namespace declarations
in the XProc pipeline are automatically exposed in the static context.
</para>
</listitem>
</varlistentry>
</variablelist>

<para>The dynamic context of the XQuery processor is augmented in the following
way:</para>

<variablelist>
<varlistentry>
<term>Context item</term>
<listitem>
<para>The first document that appears on the <port>source</port> port.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Context position</term>
<listitem>
<para><literal>1</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Context size</term>
<listitem>
<para><literal>1</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Variable values</term>
<listitem>
<para>Any parameters passed in the <option>parameters</option> option
augment any implementation-defined variable bindings known to the XQuery
processor.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Function implementations</term>
<listitem>
<para>The function implementations provided by the XQuery processor.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Current dateTime</term>
<listitem>
<para><impl>The point in time returned as the current dateTime is
<glossterm>implementation-defined</glossterm>.</impl></para>
</listitem>
</varlistentry>
<varlistentry>
<term>Implicit timezone</term>
<listitem>
<para><impl>The implicit timezone is <glossterm>implementation-defined</glossterm>.
</impl>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Available documents</term>
<listitem>
<para><impl>The set of available documents (those that may be retrieved with a URI)
is <glossterm>implementation-dependent</glossterm>.</impl>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Available collections</term>
<listitem>
<para><impl>The set of available collections
is <glossterm>implementation-dependent</glossterm>.</impl>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Default collection</term>
<listitem>
<para>The sequence of documents provided on the <port>source</port> port.
</para>
</listitem>
</varlistentry>
</variablelist>

<section xml:id="example-xquery" role="tocsuppress">
<title>Example</title>

<para>The following pipeline applies XInclude processing and schema
validation before using XQuery:</para>

<example xml:id="ex.c.xquery">
<title>A Sample Pipeline Document</title>
<programlisting language="xml">&lt;p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
                version="3.1"&gt;
&lt;p:input port="source"/&gt;
&lt;p:output port="result"/&gt;

&lt;p:xinclude/&gt;

&lt;p:validate-with-xml-schema name="validate"&gt;
  &lt;p:with-input port="schema"
                href="http://example.com/path/to/schema.xsd"/&gt;
&lt;/p:validate-with-xml-schema&gt;

&lt;p:xquery&gt;
   &lt;p:with-input port="query" href="countp.xq"/&gt;
&lt;/p:xquery&gt;

&lt;/p:declare-step&gt;
</programlisting>
</example>

<para>Where <filename>countp.xq</filename> might contain:</para>

<programlisting language="xml">&lt;count&gt;{count(.//p)}&lt;/count&gt;</programlisting>

</section>

<section>
<title>Document properties</title>
<para feature="xquery-preserves-none">No document properties are preserved.
The <property>base-uri</property> property of each document will
reflect the base URI specified by the query. If the query does not
establish a base URI, the document will not have one.
</para>
</section>
</section>
<section xml:id="c.xslt">
  <title>p:xslt</title>

  <para>The <tag>p:xslt</tag> step invokes an XSLT stylesheet.</para>
  <p:declare-step type="p:xslt">
    <p:input port="source" content-types="any" sequence="true" primary="true"/>
    <p:input port="stylesheet" content-types="xml"/>
    <p:output port="result" primary="true" sequence="true" content-types="any"/>
    <p:output port="secondary" sequence="true" content-types="any"/>
    <p:option name="parameters" as="map(xs:QName,item()*)?"/>
    <p:option name="static-parameters" as="map(xs:QName,item()*)?"/>
    <p:option name="global-context-item" as="item()?"/>
    <p:option name="populate-default-collection" as="xs:boolean?" select="true()"/>
    <p:option name="initial-mode" as="xs:QName?"/>
    <p:option name="template-name" as="xs:QName?"/>
    <p:option name="output-base-uri" as="xs:anyURI?"/>
    <p:option name="version" as="xs:string?"/>
  </p:declare-step>
  <para>If <option>output-base-uri</option> is relative, it is made absolute against the base URI of
    the element on which it is specified (<tag>p:with-option</tag> or <tag>p:xslt</tag> in the case
    of a syntactic shortcut value).</para>
  <para>If the step specifies a <option>version</option>, then that version of XSLT
    <rfc2119>must</rfc2119> be used to process the transformation. <error code="C0038">It is a
      <glossterm>dynamic error</glossterm> if the specified xslt version is not available.</error> If
    the step does not specify a version, the implementation may use any version it has available and
    may use any means to determine what version to use, including, but not limited to, examining the
    version of the stylesheet. <impl>It is <glossterm>implementation-defined</glossterm> which XSLT
    version(s) is/are supported.</impl></para>
  <para>The XSLT stylesheet provided on the <port>stylesheet</port> port is invoked. <error code="C0093"> It is a <glossterm>dynamic error</glossterm> if a static error occurs during the
    static analysis of the XSLT stylesheet.</error> Any parameters passed in the
    <option>parameters</option> option are used to define top-level stylesheet parameters.</para>
  <para>Parameters passed in the <option>static-parameters</option> option are passed as static
    parameters to the XSLT invocation. <impl>Whether static parameters are supported is
      <glossterm>implementation-defined</glossterm> and depends on the XSLT version (which must be
    3.0 or higher).</impl> If static parameters are not supported the option is ignored.</para>
  <para><error code="C0095">It is a <glossterm>dynamic error</glossterm> if an error occurred during
    the transformation.</error>
    <error code="C0096">It is a <glossterm>dynamic error</glossterm> if the transformation is
      terminated by XSLT message termination.</error>
    <impl>How XSLT message termination errors are reported to the XProc processor is
      <glossterm>implementation-dependent</glossterm>.</impl> Implementations
    <rfc2119>should</rfc2119> raise an error using the error code from the XSLT step (for example,
    the <tag class="attribute">error-code</tag> specified on the <tag>xsl:message</tag> or
    <code>Q{http://www.w3.org/2005/xqt-errors}XTTM9000</code> if no code is provided).</para>
  <para>If XSLT 2.0 or XSLT 3.0 is used, the outputs of this step <rfc2119>may</rfc2119> include
    PSVI annotations.</para>
  <para>The interpretation of the input and output ports as well as for the other options depends on
    the selected XSLT version.</para>
  
  <section>
    <title>Invoking an XSLT 3.0 stylesheet</title>
    <para>The value of <option>global-context-item</option> is used as the global context item for the
      stylesheet invocation. If its value is the empty sequence, the following applies:</para>
    <itemizedlist>
      <listitem>
        <para>If there is a single document on the <port>source</port> port, this document will
          become the value of the <option>global-context-item</option> option.</para>
      </listitem>
      <listitem>
        <para>If there are none or multiple documents on the <port>source</port> port, the
          global context item is absent.</para>
      </listitem>
    </itemizedlist>

    <note>
      <para>As a consequence of these rules, it is not possible for XProc to invoke an XSLT 3.0 stylesheet
      with an <emphasis>empty</emphasis> global context item <emphasis>and simultaneously</emphasis>
      process a single input document.</para>
    </note>

    <para>The <option>populate-default-collection</option> option is used to control whether all
    the documents appearing on <port>source</port> port form the default collection for the XSLT
    transformation.</para>
    <para>If the value of the <option>template-name</option> option is the empty sequence, an “Apply-template
      invocation” is performed. The documents that appear on <port>source</port> are taken to be the
      initial match selection. if <option>populate-default-collection</option> is true, they
      are also the default collection.</para>

    <para>If the value of the <option>initial-mode</option> option is not the
    empty sequence, the option value is used as the initial-mode for the
    invocation. <error code="C0008">It is a <glossterm>dynamic error</glossterm>
    if the stylesheet does not support a given mode.</error> If the value is 
    the empty sequence, no initial-mode is specified and default XSLT 3.0 behavior
    applies.</para>

    <para>If a value is supplied for option <option>template-name</option> a “Call template
      invocation” is performed. The documents on port <port>source</port> are taken as the default
      collection in this case. Option <option>initial-mode</option> is ignored. <error code="C0056">It is a <glossterm>dynamic error</glossterm> if the stylesheet does not provide a given
        template.</error></para>
    <para>Independent of the way the stylesheet is invoked, the principal result(s) will appear on
      output port <port>result</port> while secondary result(s) will appear on output port
      <port>secondary</port>. <impl>The order in which 
        result documents appear on the <port>secondary</port> port is
        <glossterm>implementation-dependent</glossterm>.</impl> 
      Whether the raw results are delivered or a result tree is
      constructed, depends on the (explicit or implicit) setting for attribute
      <literal>build-tree</literal> of in the output-definition for the respective result. If a
      result tree is constructed, the result will be a text document if it is a single text node
      wrapped into a document node. Otherwise it will be either an XML document or an HTML document
      depending on the attribute <literal>method</literal> on the output-definition for the
      respective result. If no result tree is constructed, the stylesheet invocation may
      additionally deliver a sequence of atomic values, maps, or arrays. For each item in this
      sequence a JSON document will be constructed and appear on the steps output port.</para>
    <para>Option <option>output-base-uri</option> sets the base output URI per XSLT 3.0
      specification. If a final result tree is constructed, this URI is used to resolve a relative
      URI reference. If the value of <option>output-base-uri</option> is the empty sequence, the base URI of
      the first document in the <port>source</port> port's sequence is used. If no document is
      supplied on port <port>source</port> the base URI of the document on port <port>stylesheet</port>
      is used. <error code="C0121">It is a <glossterm>dynamic error</glossterm> if a document appearing
        on the <port>secondary</port> port has a base URI that is not both absolute and 
        valid according to <biblioref linkend="rfc3986"/>.</error></para>
    <note>
      <para>If no result tree is constructed for one of secondary results, a sequence of documents
        sharing the same value for attribute <literal>href</literal> may appear on output port
        <port>result</port>.</para>
    </note>
  </section>
  <section>
    <title>Invoking an XSLT 2.0 stylesheet</title>
    <para>If a sequence of documents is provided on the <port>source</port> port, the first document
      is used as the initial context node. The whole sequence is also the default collection. If no
      documents are provided on the <port>source</port> port, the initial context node is undefined
      and the default collection is empty. <error code="C0094">It is a <glossterm>dynamic
        error</glossterm> if any document supplied on the source port is not an XML document, an
        HTML documents, or a Text document if XSLT 2.0 is used.</error></para>
    <para>The <option>populate-default-collection</option> option is used to control whether all
      the documents appearing on <port>source</port> port form the default collection for the XSLT
      transformation.</para>
    <para>The value of option <option>global-context-item</option> is ignored if a stylesheet is
      invoked as per XSLT 2.0. The invocation of the transformation is controlled by the
      <option>initial-mode</option> and <option>template-name</option> options that set the
      initial mode and/or named template in the XSLT transformation where processing begins. <error code="C0007">It is a <glossterm>dynamic error</glossterm> if any key in
        <option>parameters</option> is associated to a value which is not an instance of the XQuery
        1.0 and XPath 2.0 Data Model, e.g. with a map, an array, or a function.</error>
      <error code="C0008">It is a <glossterm>dynamic error</glossterm> if the specified initial mode
        cannot be applied to the specified stylesheet.</error> 
      <error code="C0056">It is a <glossterm>dynamic error</glossterm> if the specified template 
        name cannot be applied to the specified stylesheet.</error>
    </para>
    <para>The primary result document of the transformation, if there is one, appears on the
      <port>result</port> port. At most one document can appear on the <port>result</port> port.
      All other result documents appear on the <port>secondary</port> port. <impl>The order in which 
        result documents appear on the <port>secondary</port> port is
        <glossterm>implementation-dependent</glossterm>.</impl>
    </para>
    <para>The <option>output-base-uri</option> option sets the context's output base URI per the
      XSLT 2.0 specification, otherwise the base URI of the <port>result</port> document is the base
      URI of the first document in the <code>source</code> port's sequence. If no document is
      supplied on port <port>source</port> the base URI of the document on port <port>stylesheet</port>
      is used. <error code="C0121">It is a <glossterm>dynamic error</glossterm> if a document appearing
        on the <port>secondary</port> port has a base URI that is not both absolute and 
        valid according to <biblioref linkend="rfc3986"/>.</error></para>
  </section>
  
  <section>
    <title>Invoking an XSLT 1.0 stylesheet</title>
    <para>The document provided for <port>source</port> is used the transformations source tree.
      <error code="C0039">It is a <glossterm>dynamic error</glossterm> if the source port does not
        contain exactly one XML document or one HTML document if XSLT 1.0 is used.</error> The
      values supplied for options <option>global-context-item</option>,
      <option>initial-mode</option>, and <option>template-name</option> are ignored. If XSLT 1.0
      is used, an empty sequence of documents <rfc2119>must</rfc2119> appear on the
      <port>secondary</port> port. An XSLT 1.0 step <rfc2119>should</rfc2119> use the value of the
      <option>output-base-uri</option> as the base URI of its output, if the option is
      specified.</para>
    <para>The key/value pairs supplied in <option>parameters</option> are used to set top-level
      parameters in the stylesheet. If the value is an atomic value or a node, its string value is
      supplied to the stylesheet. <error code="C0105">It is a <glossterm>dynamic error</glossterm> if an XSLT 1.0
      stylesheet is invoked and option <option>parameters</option> contains a value that is not an atomic value
      or a node.</error>
    </para>
  </section>
  <simplesect>
    <title>Document properties</title>
    <para feature="xslt-preserves-none">No document properties are
    preserved. The <property>base-uri</property> property of each
    document will reflect the base URI specified by the tranformation.
    If the transformation does not establish a base URI, the document
    will not have one.
</para>
  </simplesect>
</section>
</section>

<section xml:id="errors">
<title>Step Errors</title>

<para>Several of the steps in the standard step library can generate
<glossterm role="unwrapped" baseform="dynamic error">dynamic errors</glossterm>.</para>

<para>A <termdef xml:id="dt-dynamic-error">A <firstterm>dynamic
error</firstterm> is one which occurs while a pipeline is being
evaluated.</termdef> Examples of dynamic errors include references to
URIs that cannot be resolved, steps which fail, and pipelines that
exhaust the capacity of an implementation (such as memory or disk
space).</para>

<para>If a step fails due to a dynamic error, failure propagates
upwards until either a <tag>p:try</tag> is encountered or the entire
pipeline fails. In other words, outside of a <tag>p:try</tag>, step
failure causes the entire pipeline to fail.</para>

<para>Dynamic errors raised by steps are divided into two categories:
dynamic errors and step errors. The distinction is largely that “step
errors” tend to be related to a particular step or small group of
steps (e.g., validation error) whereas the “dynamic errors” apply to
many more steps (e.g., URI not available). There is also precedent for some
of the error codes dating back to XProc 1.0.</para>

<?dynamic-error-list?>

<?step-error-list?>

</section>
<appendix xml:id="conformance">
<title>Conformance</title>

<para>Conformant processors <rfc2119>must</rfc2119> implement all of the features
described in this specification except those that are explicitly identified
as optional.</para>

<para>Some aspects of processor behavior are not completely specified; those
features are either <glossterm role="unwrapped">implementation-dependent</glossterm> or
<glossterm role="unwrapped">implementation-defined</glossterm>.</para>

<para><termdef xml:id="dt-implementation-dependent">An
<firstterm>implementation-dependent</firstterm> feature is one where the
implementation has discretion in how it is performed.
Implementations are not required to document or explain
how <glossterm role="unwrapped">implementation-dependent</glossterm> features are performed.</termdef>
</para>

<para><termdef xml:id="dt-implementation-defined">An
<firstterm>implementation-defined</firstterm> feature is one where the
implementation has discretion in how it is performed.
Conformant implementations <rfc2119>must</rfc2119> document
how <glossterm role="unwrapped">implementation-defined</glossterm> features are performed.</termdef>
</para>

<section xml:id="implementation-defined">
<title>Implementation-defined features</title>

<para>The following features are implementation-defined:</para>

<?implementation-defined-features?>
</section>

<section xml:id="implementation-dependent">
<title>Implementation-dependent features</title>

<para>The following features are implementation-dependent:</para>

<?implementation-dependent-features?>
</section>
</appendix>
<appendix xml:id="references" version="5.0-extension w3c-xproc">

<title>References</title>
<section xml:id="normative-references">
  <title>Normative References</title>
  <bibliolist>
    <bibliomixed xml:id="xproc31"/>
    <bibliomixed xml:id="xmlschema-2"/>
    <bibliomixed xml:id="xpath31"/>
    <bibliomixed xml:id="xpath31-functions"/>
    <bibliomixed xml:id="xslt30"/>
    <bibliomixed xml:id="xinclude"/>
    <bibliomixed xml:id="rfc1321"/>
    <bibliomixed xml:id="rfc1521"/>
    <bibliomixed xml:id="rfc2046"/>
    <bibliomixed xml:id="rfc2119"/>
    <bibliomixed xml:id="rfc2617"/>
    <bibliomixed xml:id="rfc3986"/>
    <bibliomixed xml:id="rfc4646"/>
    <bibliomixed xml:id="rfc4647"/>
    <bibliomixed xml:id="rfc8259"/>
    <bibliomixed xml:id="bcp47"/>
    <bibliomixed xml:id="bib.uuid"/>
    <bibliomixed xml:id="bib.sha"/>
    <bibliomixed xml:id="bib.crc"/>
    <bibliomixed xml:id="zip"/>
    <bibliomixed xml:id="gzip"/>
  </bibliolist>
</section>
</appendix>


    <glossary xml:id="glossary">
      <title>Glossary</title>
      <para>Glossary needs to be generated</para>
    </glossary>
  

<appendix version="5.0-extension w3c-xproc" xml:id="ancillary-files">
<title>Ancillary files</title>

<para>This specification includes by reference a number of
ancillary files.</para>

<variablelist>
<varlistentry>
<term><link xlink:href="steps.xpl"/></term>
<listitem>
<para>An XProc step library for the declared steps.
</para>
</listitem>
</varlistentry>
</variablelist>

</appendix>
<appendix version="5.0-extension w3c-xproc" xml:id="credits">
<title>Credits</title>

<para>This document is derived from
<link xlink:href="https://www.w3.org/TR/2010/REC-xproc-20100511/">XProc:
An XML Pipeline Language</link> published by the W3C. It was developed
by the <citetitle>XML Processing Model Working Group</citetitle> and edited by
Norman Walsh, Alex Miłowski, and Henry Thompson.</para>

<para>The editors of this specification extend their gratitude to everyone
who contributed to this document and all of the versions that came before it.</para>
</appendix>

<appendix xml:id="changelog">
<title>Change Log</title>

<para>This appendix summarizes the changes introduced in XProc 3.1.</para>

<section>
<title>Backwards incompatible changes</title>

<itemizedlist>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/659">issue 659</link>
by updating the <tag>p:cast-content-type</tag> step. Added the <tag>p:encode</tag> step.
This is a small backwards incompatibility because it means that you cannot use
<tag>p:cast-content</tag> type to change the content type of a <tag>c:data</tag> element from
<code>application/xml</code> to, for example, <code>application/foo+xml</code>. That seems
like an unlikely scenario because XProc controls the semantics of <tag>c:data</tag>
documents.</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/642">issue 642</link>
by removing the distinction between “has no value” and “the empty sequence” in the
<tag>p:xslt</tag> step. This means it is no longer possible to specify a single document
on the <port>source</port> port and have the global context item be the empty sequence.</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/549">issue 549</link>
by making the <port>result</port> output port on <tag>p:compare</tag> primary.</para>
<para>Although this change is technically backwards incompatible, all known implementations of
XProc 3.0 implemented it this way, so it is unlikely that it will have any significant
consequences.</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/548">issue 548</link>
by correcting the Unicode collation URI in <tag>p:text-sort</tag>.</para>
<para>The value given in XProc 3.0 is incorrect and must be updated. To mitigate
any consequences of this correction, implementations are encouraged to continue
to recognize the incorrect value, perhaps with a warning.
</para>
</listitem>
</itemizedlist>

<section>
<title>Substantive changes</title>
  
<itemizedlist>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/668">issue 668</link>
by clarifying explicitly how the Unicode byte order mark is processed.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/656">issue 656</link>
by adding an <option>attributes</option> option to <tag>p:pack</tag>, <tag>p:wrap</tag>, and
<tag>p:wrap-sequence</tag>.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/647">issue 647</link>
by allowing the value of the <option>duration</option> option on <tag>p:sleep</tag> to be 
either a number of seconds or an <type>xs:dayTimeDuration</type>.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/644">issue 644</link>
by allowing <tag>p:filter</tag> to return non-node results.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/635">issue 635</link>
by clarifying how a text document can be produced from the <tag>p:filter</tag> step.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/623">issue 623</link>
by clarifying the semantics of <tag>p:error</tag>.
</para>
</listitem>
<listitem>
<para>Added a description of <tag>c:parameter-set</tag> documents.</para>
</listitem>
<listitem>
<para>Added the <tag>p:message</tag> step.
</para>
</listitem>
<listitem>
<para>Several error codes were added.</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/587">issue 587</link>
by adding a <option>parameters</option> option to the <tag>p:uuid</tag> step.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/574">issue 574</link>
by adding a <tag>p:sleep</tag> step.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/Vnext/issues/39">V.next issue 29</link> by
allowing the text documents on the <port>insertion</port> port of the <tag>p:insert</tag> step.
Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/583">issue 583</link> by
allowing text documents on the <port>result</port> port.
</para>
</listitem>
</itemizedlist>
</section>

<section>
<title>Editorial changes</title>
  
<itemizedlist>
<listitem>
<para>Added a normative reference to RFC 8259 for the JSON format.</para>
</listitem>
<listitem>
<para>Clarified the relationship between the <tag>p:text-sort</tag> step and the
<tag>xsl:sort</tag> element.</para>
</listitem>
<listitem>
<para>Made editorial improvements to the description of <tag>p:http-request</tag> and
<tag>p:load</tag>.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/678">issue 678</link>
by describing the <tag class="attribute">comment</tag> attribue in the archive manifest.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/639">issue 639</link>
by removing the superflous mention of PSVI annotations in the <tag>p:split-sequence</tag> step.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/580">issue 580</link>
by clarifying what standards apply to the <option>lang</option> option on <tag>p:text-sort</tag>.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/566">issue 566</link>
by clarifying when a text document is produced from the
<tag>p:hash</tag>, <tag>p:replace</tag>, <tag>p:string-replace</tag>, and
<tag>p:uuid</tag> steps.</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/563">issue 563</link>
by clarifying that <code>p:set-attributes</code> cannot add “namespace attributes” to an element.
</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/562">issue 562</link>
by <link linkend="archive-parameters">clarifying</link> that some parameters are defined for
ZIP archives.</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/561">issue 561</link>
and <link xlink:href="https://github.com/xproc/3.0-steps/issues/564">issue 564</link>
by clarifying in the <tag>p:archive</tag> and <tag>p:archive-manifest</tag> steps
that <code>err:XC0081</code> should be raised when the
archive format specified differs from the format of the actual archive and
<code>err:XC0085</code> should be raised when the format of the
archive cannot be determined or processed.</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/560">issue 560</link>
by removing <code>err:XC0118</code> in the <tag>p:archive</tag> step. (It was a duplicate
of <code>err:XC0100</code>.)</para>
</listitem>
<listitem>
<para>Resolved <link xlink:href="https://github.com/xproc/3.0-steps/issues/559">issue 559</link>
by clarifying that <code>err:XC0023</code> in <tag>p:rename</tag> applies
if the match pattern matches more than attribute on a single element.</para>
</listitem>
</itemizedlist>
</section>
</section>
</appendix>

</specification>