This site is work in progress and does not yet describe all available steps.

 p:wrap (3.0) 

Wraps nodes in a parent element.

Summary

<p:declare-step type="p:wrap">
  <input port="source" primary="true" content-types="xml html" sequence="false"/>
  <output port="result" primary="true" content-types="application/xml" sequence="false"/>
  <option name="match" as="xs:string" required="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 step wraps matching nodes in the document on the source into a new parent element.

Ports:

Type

Port

Primary?

Content types

Seq?

Description

input

source

true

xml html

false

The document that contains the nodes to wrap.

output

result

true

application/xml

false

The resulting document.

Options:

Name

Type

Req?

Default

Description

match

xs:string (XSLT selection pattern)

true

 

The XSLT match pattern for the nodes to wrap, as a string. This must match either the document-node, an element, a processing-instruction, or a comment. If any other kind of node is matched, error XC0023 is raised.

wrapper

xs:QName

true

 

The name of the wrapping element.

group-adjacent

xs:string? (XPath expression)

false

()

An XPath expression to use for grouping the wrapped elements. See Grouping below.

Description

The p:wrap step takes the XSLT match pattern in the match option and holds this against the document appearing on its source port. This pattern must match the document-node, an element, a processing-instruction, or a comment. The matched node is wrapped in an element, as specified in the wrapper option.

The p:wrap step perform a “deep” wrapping: the children of any matched node are also processed. Wrappers are added to all matching nodes.

Grouping

The group-adjacent option of p:wrap allows you to group adjacent matching nodes in a single wrapper element. The value of this option must a valid XPath expression. It is evaluated for every node in the source document. Adjacent nodes with an equal result value are wrapped together in the same wrapper element.

For all nodes in the document on the source port:

  • The node becomes the context item (accessible with the dot . operator).

  • The expression in the group-adjacent option is evaluated.

  • Two values of sibling nodes, computed by the XPath expression, are considered equal if the XPath function fn:deep-equal() returns true for them. In most cases this simply means that values are equal when you intuitively expect them to be.

  • All sibling nodes with equal values for the XPath expression, that are adjacent, are wrapped together in a wrapper element, as named by the wrapper option.

For an example see Grouping and wrapping.

Examples

Basic usage

The following example wraps every thing element in a <computer-part> element:

Source document:

<things>
   <thing name="laptop"/>
   <thing name="desktop">
      <subthings>
         <thing name="keyboard"/>
         <thing name="mouse"/>
      </subthings>
   </thing>
</things>

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" sequence="true"/>

  <p:wrap match="thing" wrapper="computer-part"/>

</p:declare-step>

Result document:

<things>
   <computer-part>
      <thing name="laptop"/>
   </computer-part>
   <computer-part>
      <thing name="desktop">
         <subthings>
            <computer-part>
               <thing name="keyboard"/>
            </computer-part>
            <computer-part>
               <thing name="mouse"/>
            </computer-part>
         </subthings>
      </thing>
   </computer-part>
</things>

Please notice that the nested <thing> elements (inside the <subthings> element) are also wrapped. This is because p:wrap performs “deep” wrapping.

Grouping and wrapping

This example shows what happens when you use the group-adjacent option. Here we group fruits by color:

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" sequence="true"/>

  <p:wrap match="fruit" wrapper="fruits-by-color" group-adjacent="@color"/>

</p:declare-step>

Result document:

<fruits>
   <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>
</fruits>

You might have expected that the result would group the fruits together by color, resulting in groups of elements, wrapped in <fruits-by-color> elements: one for banana+lemon and one for orange+carrot. But p:wrap groups sibling nodes that are adjacent to each other only. It does not do what would be called “group by”: all sibling nodes with the same value for the XPath expression together in a single group. If you need this, you will have to sort the document first. But unfortunately, XProc does not have anything on board for that. For more complex grouping, the advice is to use XSLT or XQuery.

Replacing comments by elements

This example shows that you can use p:wrap not only to wrap elements, but also other kinds of nodes. Here we use its functionality, together with the p:string-replace step, to change comments into elements. For this, we first wrap every element in a <comment> element and then turn these comments into text nodes using p:string-replace.

Source document:

<examples>
      <!--Comment 1-->
      <!--Another comment…-->
    </examples>

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" sequence="true"/>

  <p:wrap match="comment()" wrapper="comment"/>
  <p:string-replace match="comment/comment()" replace="string(.)"/>

</p:declare-step>

Result document:

<examples>
   <comment>Comment 1</comment>
   <comment>Another comment…</comment>
</examples>

Additional details

  • p:wrap preserves all document-properties of the document(s) appearing on its source port.

Errors raised

Error code

Description

XC0023

It is a dynamic error if the selection pattern matches a wrong type of node.

Reference information

This description of the p:wrap step is for XProc version: 3.0. This is a required step (an XProc 3.0 processor must support this).

The formal specification for the p:wrap step can be found here.

The p:wrap step is part of categories:

The p:wrap step is also present in version: 3.1.