Wraps a sequence of documents in an element.
<p:declare-step type="p:wrap-sequence"> <input port="source" primary="true" content-types="text xml html" sequence="true"/> <output port="result" primary="true" content-types="application/xml" sequence="true"/> <option name="wrapper" as="xs:QName" required="true"/> <option name="group-adjacent" as="xs:string?" required="false" select="()"/> </p:declare-step>
The p:wrap-sequence
step takes a sequence of documents on its source
port and wraps these in a wrapper element. The result appears on
the result
port. It can also group the source document(s) before wrapping, based on an XPath expression.
Ports:
Port | Type | Primary? | Content types | Seq? | Description |
---|---|---|---|---|---|
|
|
|
|
| The document(s) to wrap. |
|
|
|
|
| The resulting wrapped document(s) |
Options:
Basic usage of the p:wrap-sequence
step is to wrap an element around a sequence of text, XML or HTML documents. This action turns the sequence into
a single XML document. See Basic usage for how this works. This example is however not very useful. A much more common
scenario, wrapping the results of a p:for-each
loop, is shown in the Wrapping the results of a for-each loop example.
The group-adjacent
option of p:wrap-sequence
allows you to group documents together and wrap each group in the same wrapper
element. The value of this option must a valid XPath expression. It is evaluated for every document in the input sequence. Documents with an
equal result value are bundled together, resulting in a sequence of documents on the result
port.
For all documents appearing on the source
port:
The document becomes the context item (accessible with the dot .
operator).
The expression in the group-adjacent
option is evaluated.
During this evaluation, the position()
and last()
functions are available to get the position of the
document in the sequence and the size of the sequence.
Two values computed by the XPath expression are considered equal if the XPath function deep-equal()
returns
true
for them. In most cases this simply means that values are equal when you intuitively expect them to be.
All documents with equal values for the XPath expression, that are adjacent in the sequence, are wrapped in an element named by the
wrapper
option.
For an example see Grouping and wrapping.
The source
port here receives a sequence of 4 <fruit>
documents, by default. p:wrap-sequence
wraps this into a
<fruits>
element, turning the four separate documents into a single one.
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0"> <p:input port="source" sequence="true"> <fruit name="banana" color="yellow"/> <fruit name="orange" color="orange"/> <fruit name="carrot" color="orange"/> <fruit name="lemon" color="yellow"/> </p:input> <p:output port="result"/> <p:wrap-sequence wrapper="fruits"/> </p:declare-step>
Result document:
<fruits> <fruit color="yellow" name="banana"/> <fruit color="orange" name="orange"/> <fruit color="orange" name="carrot"/> <fruit color="yellow" name="lemon"/> </fruits>
A very common scenario in which p:wrap-sequence
is used, is in wrapping the results of a p:for-each
loop. Such a loop usually results
in a sequence of documents (one for each iteration). It’s often easier to turn this (back) into a single document before continuing. The
following example shows this. It has a p:for-each
loop over all yellow fruit elements that adds an attribute
delivery="special"
. The resulting documents are wrapped in a <yellow-fruits>
element, resulting in a single result
document.
Source document:
<fruits> <fruit name="banana" color="yellow"/> <fruit name="orange" color="orange"/> <fruit name="carrot" color="orange"/> <fruit name="lemon" color="yellow"/> </fruits>
Pipeline document:
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0"> <p:input port="source" sequence="true"/> <p:output port="result"/> <p:for-each> <p:with-input select="/*/*[@color eq 'yellow']"/> <p:add-attribute attribute-name="delivery" attribute-value="special"/> </p:for-each> <p:wrap-sequence wrapper="yellow-fruits"/> </p:declare-step>
Result document:
<yellow-fruits> <fruit delivery="special" color="yellow" name="banana"/> <fruit delivery="special" color="yellow" name="lemon"/> </yellow-fruits>
Like Basic usage, the source
port here receives a sequence of 4 <fruit>
documents. The first
p:wrap-sequence
step groups these, using the color
attribute, and wraps these groups in a <fruits-by-color>
element. This results
in a sequence of 3 documents, which is wrapped again, to enable showing it as a single document.
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0"> <p:input port="source" sequence="true"> <fruit name="banana" color="yellow"/> <fruit name="orange" color="orange"/> <fruit name="carrot" color="orange"/> <fruit name="lemon" color="yellow"/> </p:input> <p:output port="result" sequence="true"/> <p:wrap-sequence wrapper="fruits-by-color" group-adjacent="/*/@color"/> <p:wrap-sequence wrapper="groups"/> </p:declare-step>
Result document:
<groups> <fruits-by-color> <fruit color="yellow" name="banana"/> </fruits-by-color> <fruits-by-color> <fruit color="orange" name="orange"/> <fruit color="orange" name="carrot"/> </fruits-by-color> <fruits-by-color> <fruit color="yellow" name="lemon"/> </fruits-by-color> </groups>
You might have expected that the result would group all fruits together by color, resulting in two documents: one for
banana
+lemon
and one for orange
+carrot
. But p:wrap-sequence
groups documents that are
adjacent to each other only. It does not do what would be called “group by”: all
documents with the same value for the XPath expression together in a single group. If you need this, you will have to sort the documents
first. But unfortunately, XProc does not have anything on board for that. For more complex grouping, the advice is to use XSLT or XQuery.
No document-properties of the source document(s) survive.
The resulting document(s) have no base-uri
property.
This description of the p:wrap-sequence
step is for XProc version: 3.1. This is a required step (an XProc 3.1 processor must support this).
The formal specification for the p:wrap-sequence
step can be found here.
The p:wrap-sequence
step is part of categories:
The p:wrap-sequence
step is also present in version:
3.0.