XProc tips and tricks
Maybe it’s time to start collecting “tips and tricks” for XProc pipelines? Perhaps I should revamp exproc.org? Tip: how can I make an empty sequence into an empty document?
Regardless of whether it’s time to start collecting “tips and tricks” or what I should do with exproc.org, I have a tip. Or a trick. Something.
Suppose you’re selecting items from a document and passing them to a step that does something with them:
<p:identity>
<p:with-input select="/path/to/something"/>
</p:identity>
<ex:my-step-that-does-a-thing/>
If the primary input port of ex:my-step-that-does-a-thing
doesn’t accept a
sequence, then you’ll get an error if /path/to/something
doesn’t select anything.
Suppose instead that you want to pass an empty document to the step. It’s not that difficult to imagine scenarios where that would be easier than dealing with a sequence (especially if you want to the processor to reject sequences of more than one document for you).
Here’s one way to do that:
<p:identity>
<p:with-input select="/path/to/something"/>
</p:identity>
<p:if test="empty(collection())" collection="true">
<p:identity>
<p:with-input>
<p:inline content-type="text/plain"></p:inline>
</p:with-input>
</p:identity>
</p:if>
<ex:my-step-that-does-a-thing/>
The semantics of p:if
are that it returns the result of its subpipeline if the
test expression is true and otherwise passes its inputs through unchanged.
Setting collection
to true means that the default collection will contain all
of the documents that appeared as inputs to p:if
. If that collection is empty, there
were no documents.
So, if there are inputs, they are passed through unchanged, but if there
aren’t any inputs, the result is a single text/plain
document containing
an empty text node. Obviously, you could produce something else as the default just by
changing the inline.
It’s concise and useful, but it took me a good few minutes to figure it out the first time I needed it.