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'