Informal step type checking algorithm for Appendix G

Henry S. Thompson
4 Aug 2009

1. Handling Circular and Re-entrant Library Imports

Define the step type exports of an XProc element, against the background of a set of URIs Visited of resources already visited, as follows:

p:pipeline, p:declare-step
A singleton bag containing the type of the element
p:library
The bag-merger* of the step type exports of all the element's children
p:import
Let RU be the actual resolved URI of the resource identified by the href of the element. If RU is a member of Visited, then an empty bag, otherwise update Visited by adding RU to it, and return the step type exports of the document element of the retrieved representation
all other elements
An empty bag

The changes to Visited mandated by the p:import case above are persistent, not scoped. That is, not only the recursive processing of the imported resource but also subsequent processing of siblings and ancestors must be against the background of the updated value. In practice this means either using a side-effected global variable, or not only passing Visited as an argument to any recursive or iterative processing, but also returning its updated value for subsequent use, along with the bag of step types.

Given a pipeline library document with actual resolved URI DU, it is an error (err:XS0036) if the step type exports of the document element of the retrieved representation, against the background of a singleton set containing DU, contains any duplicates.

Given a top-level pipeline document with actual resolved URI DU, it is an error (err:XS0036) if the bag-merger of the step type exports of the document element of the retrieved representation with the step type exports of its children, against the background of a singleton set containing DU, contains any duplicates.

Given a non-top-level p:pipeline or p:declare-step element, it is an error (err:XS0036) if the bag-merger of the step type exports of its parent with the step type exports of its children, against the background of a copy of the Visited set of its parent, contains any duplicates.

The phrase "a copy of the Visited set" in the preceding paragraph is meant to indicate that checking of non-top-level p:pipeline or p:declare-step elements does not have a persistent impact on the checking of its parent. The contrast is that whereas changes to Visited pass both up and down through p:import, they pass only down through p:pipeline and p:declare-step.

2. Footnote

* The bag-merger of two or more bags (where a bag is an unordered lists or, equivalently, something like a set except that it may contain duplicates) is a bag constructed by starting with an empty bag and adding each member of each of the input bags in turn to it. It follows that the cardinality of the result is the sum of the cardinality of all the input bags.