set

Usage

set xpath [xpath]

Description

This command provides very easy way to create or modify content of a document. It takes two XPath expressions. The first one should be a node location path which specifies the target node, the second is optional and provides new content for the target node. If a node matches the first XPath expression, then its content is replaced with the given value. If no node matches, then XSH2 tries to magically extend the current document by adding nodes in order to add missing steps of the location path so as to make the expression match a node. This node is then populated with a copy of the content value (either text or, if the content xpath results in a node-list and the target node is an element, nodes).

Example 49. Try the following on an empty scratch document

$scratch/> ls /
<scratch/>
$scratch/> set scratch/@say "hallo world"
<scratch say="hello world"/>

$scratch/> set scratch/foo[2]/../foo[1]/following-sibling::bar/baz[3] "HALLO"
$scratch/> ls /
<?xml version="1.0" encoding="utf-8"?>
<scratch>
  <foo/>
    <bar>
      <baz/>
      <baz/>
      <baz>HALLO</baz>
    </bar>
  <foo/>
<scratch/>

Only a limited subset of XPath is currently supported by this command. Namely, the XPath expression must be a location path consisting of a /-separated sequence of one or more location steps along the child, sibling, or attribute axes. The node-test part of the expression cannot be neither a wildcard (*, @*, prefix:*, ...), nor the node() function. If a namespace prefix is used, then either the namespace must already be declared in the document or registered with XSH. Location steps may contain arbitrary predicates (filters), however, only a limited subset is supported for magically created nodes.

In particular, if a filter predicate of a location step specifies a position of a node (e.g. with [4], or [position()>3], etc), then the parser tries to automatically create empty siblings nodes until it finally creates one with for which the predicate is true.

Note, that this command only processes one location step at a time and always picks the first matching node. So, expressions like /root/a/b are treated as /root/a[1]/b[1]. This means that an expression /root/a/b will magically create element <b> in a first matching <a> even if some following <a> already contains a <b>.

To prevent this, either explicitly state that b must exist with e.g. /root/a[b]/b or make the corresponding element <a> the context node and use a relative location path:

for /root/a/b set b 'foo'