Previous Up Next


p:wrap

p:wrap — Adds a wrapper around matching nodes.

Synopsis

<p:declare-step type="p:wrap">
     <p:input port="source"/>
     <p:output port="result"/>
     <p:option name="wrapper" required="true"/>                    <!-- QName -->
     <p:option name="wrapper-prefix"/>                             <!-- NCName -->
     <p:option name="wrapper-namespace"/>                          <!-- anyURI -->
     <p:option name="match" required="true"/>                      <!-- XSLTMatchPattern -->
     <p:option name="group-adjacent"/>                             <!-- XPathExpression -->
</p:declare-step>

Description

In the simple case, the p:wrap step adds a wrapper element around matching nodes in the document; it creates a new element and inserts the content of each match into that element. In the not so simple case, the group-adjacent expression can be used to group adjacent nodes together.

The name of the wrapper is computed from the wrapper, wrapper-prefix, and wrapper-namespace options. If the wrapper value contains a colon, then its value is interpreted as a QName and there must be an in-scope namespace declaration for that prefix in the pipeline document. It is an error in this case to specify either a wrapper-prefix or wrapper-namespace.

The group-adjacent option can be used to group adjacent nodes. For each matching node, the group-adjacent expression is evaluated with that node as the context. Whenever two or more adjacent nodes yield the same value for the group-adjacent option, they are wrapped together. Two matching nodes are considered adjacent 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.

Errors

Error Description
err:D0034 Occurs if either wrapper-namespace or wrapper-prefix are specified when the wrapper name contains a colon.
err:C0023 Occurs if the match pattern matches anything other than document, element, text, processing instruction, and comment nodes.

Examples

Here we use p:wrap to wrap each p in a div.

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                xmlns:h="http://www.w3.org/1999/xhtml"
                version="1.0">
    
  5   <p:wrap match="h:p" wrapper="div"
              wrapper-namespace="http://www.w3.org/1999/xhtml"/>
    </p:pipeline>
Input Output
1 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some Document</title>
</head>
5 <body>
<p>Some text.</p>
<pre>Some example pre text.</pre>
<p>Some more text.</p>
<p>Yet even more text.</p>
10 </body>
</html>
 
1 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some Document</title>
</head>
5 <body>
<div>
<p>Some text.</p>
</div>
<pre>Some example pre text.</pre>
10 <div>
<p>Some more text.</p>
</div>
<div>
<p>Yet even more text.</p>
15 </div>
</body>
</html>

Using group-adjacent we can group elements together. Notice how it's the value of the group-adjacent option that matters. The expression local-name(.) will be the same for both p elements, so they match.

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                xmlns:h="http://www.w3.org/1999/xhtml"
                version="1.0">
    
  5   <p:wrap match="h:p" wrapper="div"
              wrapper-namespace="http://www.w3.org/1999/xhtml"
              group-adjacent="local-name(.)"/>
    </p:pipeline>
Input Output
1 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some Document</title>
</head>
5 <body>
<p>Some text.</p>
<pre>Some example pre text.</pre>
<p>Some more text.</p>
<p>Yet even more text.</p>
10 </body>
</html>
 
1 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some Document</title>
</head>
5 <body>
<div>
<p>Some text.</p>
</div>
<pre>Some example pre text.</pre>
10 <div>
<p>Some more text.</p>
<p>Yet even more text.</p>
</div>
</body>
15 </html>

The first and second paragraphs are not adjacent because a pre intervenes.

In this example, we use a more complex expression to group all paragraphs except the first.

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                xmlns:h="http://www.w3.org/1999/xhtml"
                version="1.0">
    
  5   <p:wrap match="h:p" wrapper="div"
              wrapper-namespace="http://www.w3.org/1999/xhtml"
              group-adjacent="count(preceding-sibling::h:p) &gt; 1"/>
    </p:pipeline>
Input Output
1 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some Document</title>
</head>
5 <body>
<p>Some text.</p>
<pre>Some example pre text.</pre>
<p>Some more text.</p>
<p>Yet even more text.</p>
10 <p>A third paragraph.</p>
</body>
</html>
 
1 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some Document</title>
</head>
5 <body>
<div>
<p>Some text.</p>
</div>
<pre>Some example pre text.</pre>
10 <div>
<p>Some more text.</p>
</div>
<div>
<p>Yet even more text.</p>
15 <p>A third paragraph.</p>
</div>
</body>
</html>

This is close to what we want, we're successfully grouping all the paragraphs except the first, but if the goal was to only wrap the non-first paragraphs, we're getting extra wrappers.

That's because each “first paragraph” forms its own group where the value of the group-adjacent option is “false”.

We can jump this last hurdle by changing the match option so that it doesn't even consider first paragraphs.

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                xmlns:h="http://www.w3.org/1999/xhtml"
                version="1.0">
    
  5   <p:wrap match="h:p[count(preceding-sibling::h:p) &gt; 1]"
              wrapper="div"
              wrapper-namespace="http://www.w3.org/1999/xhtml"
              group-adjacent="count(preceding-sibling::h:p) &gt; 1"/>
    </p:pipeline>
Input Output
1 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some Document</title>
</head>
5 <body>
<p>Some text.</p>
<pre>Some example pre text.</pre>
<p>Some more text.</p>
<p>Yet even more text.</p>
10 <p>A third paragraph.</p>
</body>
</html>
 
1 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some Document</title>
</head>
5 <body>
<p>Some text.</p>
<pre>Some example pre text.</pre>
<p>Some more text.</p>
<div>
10 <p>Yet even more text.</p>
<p>A third paragraph.</p>
</div>
</body>
</html>

You might think that the more complex match expression was sufficient, but it isn't. See what happens when we remove the group-adjacent?

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                xmlns:h="http://www.w3.org/1999/xhtml"
                version="1.0">
    
  5   <p:wrap match="h:p[count(preceding-sibling::h:p) &gt; 1]"
              wrapper="div"
              wrapper-namespace="http://www.w3.org/1999/xhtml"/>
    </p:pipeline>
Input Output
1 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some Document</title>
</head>
5 <body>
<p>Some text.</p>
<pre>Some example pre text.</pre>
<p>Some more text.</p>
<p>Yet even more text.</p>
10 <p>A third paragraph.</p>
</body>
</html>
 
1 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some Document</title>
</head>
5 <body>
<p>Some text.</p>
<pre>Some example pre text.</pre>
<p>Some more text.</p>
<div>
10 <p>Yet even more text.</p>
</div>
<div>
<p>A third paragraph.</p>
</div>
15 </body>
</html>

Although we still avoid first paragraphs, we no longer get the grouping.