wrap

Usage

wrap [--namespace expression] [ [--inner] | [--while|:W expression] [--until|:U expression] [--skip-whitespace|:w] [--skip-comments|:c] [--skip-pi|:p] ] expression xpath

Description

For each node matching the xpath argument, this command creates a new element node according to a given expression (in the same way as xinsert does) which replaces the matching node, and moves the matching node into this newly created element. If namespace expression is given, the namespace is applied on the created element. The command returns a node-list consisting of the elements created.

With --inner (or :i) flag the command wraps children nodes of the matching node rather than the node it self the following sense: for each matching node a new element node is created, but this time it is placed into the matching node and all previous children of the matching node are moved into the newly created node. In this mode, all non-element matching nodes are ignored. This flag cannot be used together with --while and --until, which we describe next.

--while (:W) and/or --until (:U) arguments can be provided in order to move a sequence of adjacent siblings following the matching node into the newly created element. In this way the newly created element wraps not just the matching node itself but a range of nodes starting at the matching node and ending either before a first following node matching the expression of --until, or before a first following node not matching the expression of --while, or at the last sibling if neither of the prior apply. Both these expressions are evaluated in the context of the currently tested sibling and prior to the creation of the wrapping element. The context position for these expressions is 1 at the first sibling following the matching node and increases with each tested sibling; the context size is the number of all siblings following the matching node. It is important to mention that siblings wrapped in this way are excluded from further processing by wrap even if included in the node-list produced by the xpath argument. This allows to easily wrap certain adjacent elements without worrying about some elements being wrapped multiple times (for example, wrap :W x y //x wraps each sequence of adjacent elements <x> in a <y>).

--skip-whitespace (:w), --skip-comments (:c), and --skip-pi (:p) can be used in combination with --while (:W) and/or --until (:U) to skip testing the expressions on white-space text nodes, comments, and/or processing instruction, respectively. Such nodes are only included in the wrapped range if followed by a sibling that is to be wrapped.

$scratch/> ls /;
<?xml version="1.0" encoding="utf-8"?>
<scratch/>

$scratch/> wrap 'foo' *;
$scratch/> insert attribute 'bar=baz' into /foo;
$scratch/> insert text 'some text' into //scratch;
$scratch/> wrap --namespace 'http://foo/bar' 'a:A' //@*;
$scratch/> $wrapper := wrap 'text aaa="bbb"' //text();
$scratch/> wrap '<elem ccc=ddd>' //*;
$scratch/> ls /;
<?xml version="1.0" encoding="utf-8"?>
<elem ccc="ddd">
  <foo xmlns:a="http://foo/bar">
    <elem ccc="ddd">
      <scratch>
        <elem ccc="ddd">
          <text aaa="bbb">some text</text>
        </elem>
      </scratch>
    </elem>
    <elem ccc="ddd">
      <a:A xmlns:a="http://foo/bar" bar="baz"/>
    </elem>
  </foo>
</elem>

$scratch/> ls $wrapper;
<text aaa="bbb">some text</text>


$scratch/> wrap --inner bar //foo
$scratch/> ls /;
<?xml version="1.0" encoding="utf-8"?>
<elem ccc="ddd">
  <foo xmlns:a="http://foo/bar">
    <bar>
      <elem ccc="ddd">
        <scratch>
          <elem ccc="ddd">
            <text aaa="bbb">some text</text>
          </elem>
        </scratch>
      </elem>
      <elem ccc="ddd">
        <a:A xmlns:a="http://foo/bar" bar="baz"/>
      </elem>
    </bar>
  </foo>
</elem>

Example 56. Wrapping a range of adjacent nodes

# prepare the test document
$scratch/> rm /scratch/node(); # cleanup the document
$scratch/> set /scratch/li[5]; # create 5 <li> elements
$scratch/> set /scratch/li[3]/following-sibling::li; # add <br/> after the 3rd <li>
$scratch/> for //li set . position(); # number the <li> elements 
$scratch/> ls /
<?xml version="1.0" encoding="utf-8"?>
<scratch>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <br/>
  <li>4</li>
  <li>5</li>
</scratch>
# wrap adjacent elements <li> into an <ol>
$scratch/> wrap --skip-whitespace --while self::li ol //li;
$scratch/> ls /
<?xml version="1.0" encoding="utf-8"?>
<scratch>
  <ol>
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ol>
  <br/>
  <ol>
    <li>4</li>
    <li>5</li>
  </ol>
</scratch>

See Also

xinsert, insert, move, xmove