<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE recdescent-xml SYSTEM "recdescent.dtd" [
<!ENTITY IDre "[a-zA-Z_][a-zA-Z0-9_]*">
<!ENTITY XSH "XSH2">
]>
<recdescent-xml>
<doc>
<title>&XSH;</title>
<shortdesc>XML Editing Shell (generation 2)</shortdesc>
<description>
<para>
&XSH; acts as a command interpreter. Individual commands must
be separated with a semicolon.
In the interactive shell, backslash may be used at the end of a line to
indicate that a command continues on the next line.
Output redirection can be used to pipe output of some XSH <xref
linkend="command"/> to some external program, or to capture the output
to a variable. See <xref linkend="Redirection"/> for more info.
</para>
<para>
&XSH; command <xref linkend="help_command"/> provides a complete
reference, instantly from the command-line:
</para>
<para>
<literal>help command</literal>
gives a list of all &XSH; <link linkend="command">commands</link>.
</para>
<para>
<literal>help type</literal> gives a
list of all argument types.
</para>
<para>
<literal>help topic</literal> followed by
documentation chapter gives more information on a given topic.
</para>
<para>
<literal>help toc</literal> displays the table of contents.
</para>
</description>
<section id="Documents">
<title>Files/Documents</title>
<para>
&XSH; is designed as an environment for querying and manipulating XML and
HTML documents. Use <xref linkend="open_command"/> or <xref
linkend="create_command"/> commands to load an XML or HTML
document from a local file, external URL (such as http:// or ftp://),
string or pipe. &XSH; can optionally validate the document during parse
process (see <xref linkend="validation" /> and
<xref linkend="load_ext_dtd"/>). Parsed documents are stored in memory
as <ulink url="http://www.w3.org/DOM/">DOM</ulink> trees, that can be
<link linkend="Navigation">navigated</link> and <link
linkend="Manipulation">manipulated</link> with &XSH; commands and XPath
language, whose names and syntax make working with
the DOM tree a flavor of working in a UNIX filesystem.
</para>
<para>
A parsed document is usually stored in a variable.
&XSH; shares variables
with the XPath engine, so if e.g. <literal>$doc</literal> is a &XSH;
variable holding a document (or, more generally any node-set), then
<literal>$doc//section/title</literal> is an
XPath expression selecting all <literal>title</literal>
subelements of all
<literal>section</literal> elements within the (sub)tree of $doc.
</para>
<para>
Although &XSH; is able to parse remote documents via
<literal>http://</literal> or <literal>ftp://</literal>, it is only
able to save them locally. To upload a document to a remote server
(e.g. using FTP) or to store it into a database, use <xref
linkend="save_command" /> command with a <literal>--pipe</literal>
parameter, in connection with an external program able to store
its standard input (XML) to the desired location.
You can also use similar
parameter with <xref linkend="open_command"/> in order to parse
documents from standard output of some external program.
</para>
<example>
<title>Store a &XSH; document
on a remote machine using the Secure Shell</title>
<code>xsh> <userinput> save --pipe "ssh my.remote.org 'cat > test.xml'" $doc</userinput></code>
</example>
</section>
<section id="Navigation">
<title>Tree navigation</title>
<para>
With &XSH;, it is possible to browse a <link
linkend="Documents">document tree</link>
(XML data represented as a DOM-tree) as if it was a local
filesystem, except that <link
linkend="xpath">XPath</link>
expressions are used instead of ordinary directory paths.
</para>
<para>
To mimic the filesystem navigation as closely as
possible, &XSH; contains several commands named by analogy of
UNIX filesystem commands, such as <xref linkend="chxpath_command"/>, <xref linkend="list_command"/> and
<xref linkend="pwd_command"/>.
</para>
<para>The current position in the document tree
is called the <emphasis>current node</emphasis>. Current node's XPath
may be queried with <xref
linkend="pwd_command"/> command. In the interactive shell, current
node is also displayed in the command line prompt.
(Since there may be
multiple document trees open at the same time, &XSH; tries to locate a
variable holding the current document and use it to fully qualify
current node's XPath in the &XSH; prompt.) Remember, that beside <xref
linkend="chxpath_command"/> command, current node (and document) is
also silently changed by <xref
linkend="open_command"/> command, <xref
linkend="create_command"/> command and temporarily also by the
node-list variant of the <xref linkend="foreach"/> loop without
a loop variable.
</para>
<para>XPath expressions are always evaluated in context
of the current node. Different documents can be accessed
through variables: <literal>$doc/foo[1]/bar</literal>.</para>
<example>
<title>&XSH; shell</title>
<code>$scratch:/> <userinput>$docA := open "testA.xml"</userinput>
$docA/> <userinput>$docB := open "testB.xml"</userinput>
$docB/> <userinput>pwd</userinput>
/
$docB/> <userinput>cd $docA/article/chapter[title='Conclusion']</userinput>
$docA/article/chapter[5]> <userinput>pwd</userinput>
/article/chapter[5]
$docA/article/chapter[5]> <userinput>cd previous-sibling::chapter</userinput>
$docA/article/chapter[4]> <userinput>cd ..</userinput>
$docA/article> <userinput>cd $docB</userinput>
$docB:/> <userinput>ls</userinput>
<?xml version="1.0" encoding="utf-8"?>
<article>...</article>
</code>
</example>
</section>
<section id="Manipulation">
<title>Tree modification</title>
<para>
&XSH; not only provides ways to browse and inspect the DOM tree but also
many commands to modify its content by various operations,
such as copying,
moving, and deleting its nodes as well as creating completely new nodes
or XML fragments and attaching them to it. It is quite easy to learn
these commands since their names or aliases mimic their well-known
filesystem analogies. On the other hand, many of these commands have
two versions one of which is prefixed with a letter "x". This
"x" stands for "cross", thus e.g. <xref linkend="xcopy_command" /> should be read as "cross copy".
Let's explain the difference on the example of <xref
linkend="xcopy_command"/>.</para>
<para>
In a copy operation, you have to specify what nodes are to be
copied and where to, in other words, you have to specify the
<emphasis>source</emphasis> and the
<emphasis>target</emphasis>. &XSH; is very much XPath-based so,
XPath is used here to specify both of them. However, there
might be more than one node that satisfies an XPath expression. So,
the rule of thumb is that the "cross" variant of a
command places <emphasis>one and every</emphasis> of the source nodes
to the location of <emphasis>one and every</emphasis> destination
node, while the plain variant works one-by-one, placing the
first source node to the first destination, the second source
node to the second destination, and so on (as long as there
are both source nodes and destinations left).
</para>
<example>
<code>$scratch/> <userinput>$a := create "<X><A/><Y/><A/></X>";</userinput>
$a/> <userinput>$b := create "<X><B/><C/><B/><C/><B/></X>";</userinput>
$b/> <userinput>xcopy $a//A replace $b//B;</userinput>
$b/> <userinput>copy $b//C before $a//A;</userinput>
$b/> <userinput>ls $a;</userinput>
<?xml version="1.0" encoding="utf-8"?>
<X><C/><A/><Y/><C/><A/></X>
$b/> <userinput>ls $b;</userinput>
<?xml version="1.0" encoding="utf-8"?>
<X><A/><A/><C/><A/><A/><C/><A/><A/></X>
</code>
</example>
<para>
As already indicated by the example, another issue of tree modification
is the way in which the destination node determines the target
location. Should the source node be placed before, after, or somewhere
among the children of the resulting node? Or maybe, should it replace
it completely? This information has to be given in the
<xref linkend="loc"/> argument that usually precedes the destination
XPath.
</para>
<para>
Now, what happens if source and destination nodes are of
incompatible types? &XSH; tries to avoid this by implicitly
converting between node types when necessary. For example, if
a text, comment, and attribute node is copied into, before or
after an attribute node, the original value of the
attribute is replaced, prepended or appended respectively with
the textual content of the source node. Note however, that
<emphasis>element nodes are never converted</emphasis> into
text, attribute or any other textual node. There
are many combinations here, so try yourself and see the
results.
</para>
<para>You may even use some more sophisticated way to convert
between node types, as shown in the following example, where
an element is first commented out and than again uncommented.
Note, that the particular approach used for resurrecting the
commented XML material works only for well-balanced chunks of
XML.
</para>
<example>
<title>Using string variables to convert between different
types of nodes</title>
<code><userinput>$doc := create <<EOF;
<?xml version='1.0'?>
<book>
<tab count="1"/><chapter>
<tab count="2"/><title>Intro</title>
<tab count="1"/></chapter>
<tab count="1"/><chapter>
<tab count="2"/><title>Rest</title>
<tab count="1"/></chapter>
</book>
EOF
</userinput>
# comment out the first chapter
<userinput>ls //chapter[1] |> $chapter_xml;</userinput>
<userinput>insert comment $chapter_xml replace //chapter[1];</userinput>
<userinput>ls / 0;</userinput>
# OUTPUT:
<?xml version="1.0"?>
<book>
<!--<tab count="1"/><chapter>
<tab count="2"/><title>Intro</title>
<tab count="1"/></chapter>
-->
<tab count="1"/><chapter>
<tab count="2"/><title>Rest</title>
<tab count="1"/></chapter>
</book>
# un-comment the chapter
<userinput>$comment = string(//comment()[1]);</userinput>
<userinput>insert chunk $comment replace //comment()[1];</userinput>
<userinput>ls / 0;</userinput>
# OUTPUT:
<?xml version="1.0"?>
<book>
<tab count="1"/><chapter>
<tab count="2"/><title>Intro</title>
<tab count="1"/></chapter>
<tab count="1"/><chapter>
<tab count="2"/><title>Rest</title>
<tab count="1"/></chapter>
</book>
</code>
</example>
</section>
<section id="Flow">
<title>Flow control</title>
<para>
As almost every scripting language, &XSH; supports subroutines,
various conditional statements, loops and even exceptions.
</para>
</section>
<section id="Information">
<title>Retrieving more information</title>
<para> Beside the possibility to browse the DOM tree and
list some parts of it (as described in <xref linkend="Navigation"/>),
&XSH; provides commands to obtain other
information related to open documents as well as the &XSH;
interpreter itself. These commands are listed bellow.
</para>
</section>
<section id="Namespaces">
<title>Namespaces in XML and XPath</title> <para>Namespaces provide a
simple method for qualifying element and attribute names in
XML documents. Namespaces are represented by a namespace URI
but, since the URI can be very long, element and attribute
names are associated with a namespace using a namespace prefix
(see the <ulink url="http://www.w3.org/TR/REC-xml-names/">W3C
recommendation</ulink> for details). In an XML document, a
prefix can be associated with a namespace URI using a
declaration which takes form of special attribute of the form
<literal>xmlns:prefix="namespace uri"</literal> on an element.
The scope of the namespace declaration is then the subtree of the
element carrying the special <literal>xmlns:prefix</literal> attribute (and includes
attributes of the element). Moreover, a default namespace can
be declared using just <literal>xmlns="namespace
uri"</literal>. In that case all unprefixed element names
in the scope of such a
declaration belong to the namespace.
An unprefixed element which is not in scope of
a default namespace declaration does not belong to any namespace.
It is recommended not to combine namespaced elements and
non-namespaced elements in a single document.
Note that regardless of default
namespace declarations, unprefixed attributes do not belong to any namespace
(because they are uniquely determined by their name
and the namespace and name of the the element which carries them).
</para>
<para>&XSH; tries to deal namespace declarations transparently
(creating them if necessary when nodes are copied between
different documents or scopes of namespace declarations).
Most commands which create new elements or attributes provide
means to indicate a namespace. In addition, &XSH; provides commands <xref
linkend="declare_namespace_command"/>, <xref
linkend="set_namespace_command"/>, <xref
linkend="change_namespace_uri_command"/>, and <xref
linkend="change_namespace_prefix_command"/> to
directly manipulate XML namespace declarations on the current
node.
</para>
<para>
Since &XSH; is heavily XPath-based, it is important to
remember that XPath 1.0 maps prefixes to namespaces
independently of the declarations in the current document. The
mapping is instead provided via so called XPath context.
Namespaces can be tested in XPath either using the built-in
<literal>namespace-uri()</literal> function, but it is more
convenient to use namespace prefixes associated with namespace
URIs in the XPath context. This association is independent of
the documents to which the XPath expression is applied and can
be established using the command <xref
linkend="registerns_command"/>. Additional, &XSH;
automatically propagates the namespace association in the
scope of the current node to the XPath context, so that
per-document prefixes in the current scope can also be used.
</para>
<para>
IMPORTANT: <ulink url="http://www.w3.org/TR/xpath">XPath 1.0</ulink> has no concept of a default namespace.
Unprefixed names in XPath only match names which have no
namespace. So, if the document uses a default namespace,
it is required to associate a
non-empty prefix with the default namespace
via <xref linkend="registerns_command"/>
and add that prefix to names in XPath expressions intended to match
nodes in the default namespace.
</para>
<example>
<title>Manipulating nodes in XHTML documents</title>
<code>open "index.xhtml";
$xhtmlns = "http://www.w3.org/1999/xhtml";
register-namespace x $xhtmlns;
wrap --namespace $xhtmlns '<font color="blue">' //x:a[@href];
# or
wrap '<x:font color="blue">' //x:a[@href];</code>
</example>
<para>In the preceding example we associate the (typically
default) namespace of XHTML documents with the prefix
<literal>x</literal>. We than use this prefix to match all
links (<literal>a</literal> elements) in the document. Note
that we do not write <literal>@x:href</literal> to match the
<literal>@href</literal> attribute because unprefixed
attributes do not belong to the default namespace. The <xref
linkend="wrap_command"/> command is used to create new containing
elements for the nodes matched by the XPath expression. We may
either specify the namespace of the containing element
explicitly, using <literal>--namespace</literal> option, or
implicitly, by using a prefix associated with the namespace in
the XPath context. In the latter case, &XSH; chooses a
suitable prefix declared for the namespace in the document
scope (in this case the default, i.e. no, prefix), adding a
new namespace declaration if necessary.
</para>
</section>
<section id="Argtypes">
<title>Argument Types</title>
<para>
&XSH; commands accept arguments of various types,
usually expressed as Perl or XPath
<xref linkend="exp"/>s. Unlike in most languages,
individual &XSH; commands may evaluate the same expression differently,
usually
to enforce a result
of a certain type (such as a node-list, a string, a number,
a filename, a node name, etc.).
See <xref linkend="exp"/> and
individual argument types for more information.
</para>
</section>
<section id="Variables">
<title>Variables</title>
<para>
In &XSH;, like in Perl and XPath,
<link linkend="varname">variable names</link> are are prefixed
with a dollar sign ($).
Variables can
contain arbitrary Perl Scalar (string, number, array
reference, hash reference or an object reference). XPath
objects are transparently mapped to Perl objects via
XML::LibXML objects.
Values can be assigned to variables
either by simple <link linkend="assign_command">assignments</link> of the form
<literal>$variable = <xref linkend="exp"/></literal>,
where the right hand side is an expression, or by command
<link linkend="assign_command">assignments</link> of the form
<literal>$variable := <xref linkend="command"/></literal>,
where the right hand side is a &XSH; command, or by
capturing the output of some command with a variable
redirection of the following form:</para>
<code>command |> $variable;</code>
<para>
&XSH; expressions are evaluated either by XPath
engine or by Perl (the latter only happens if the entire
expression is enclosed with braces
<literal>{...}</literal>), and
both Perl and XPath can access all &XSH; variables
transparently (Perl expressions may even assign to them).
</para>
<para>
A simple simple expression consisting of a variable name
(e.g. <literal>$variable</literal>) is always evaluated by the
XPath engine and the result is the content of the variable as
it appears to the XPath data model. Since in XPath object
cannot be void (undefined), XPath engine complains, if the
value of the variable is undefined. On the other hand,
expressions like <literal>{$variable}</literal> are evaluated by
Perl, which results in the value of the variable as seen
by Perl.
</para>
<para>
Variables can also be used as macros for complicated XPath
expressions. Any occurrence of a substring of the form
<literal>${variable}</literal> in an XPath expression is
interpolated to the value of <literal>$variable</literal> (if
<literal>$variable</literal> contains an object rather than a
string or number, then the object is cast to string first) before the
entire expression is evaluated. So, for example, if
<literal>${variable}</literal> contains string
"<literal>chapter[title]</literal>" (without the quotes), then
the XPath expression
<literal>//sect1/${variable}/para</literal> interpolates to
<literal>//sect1/chapter[title]/para</literal> prior
to evaluation.
</para>
<para>
To display the current value of a variable, use either
<xref linkend="print_command"/>
or (in case of a global variables - the distinction is discussed below)
the command <xref linkend="var_command"/>:
</para>
<example>
<code>xsh> <userinput>$b="my_document";</userinput>
xsh> <userinput>$file="${b}s.xml";</userinput>
xsh> <userinput>$f := open $file;</userinput>
xsh> <userinput>ls //$b[count(descendant::para)>10]</userinput>
xsh> <userinput>print $b</userinput>
my_document
xsh> <userinput>variables</userinput>
...
$b='my_document';
...
$file='my_documents.xml';
...
</code>
</example>
<para>
Variables can also serve as containers for documents and can be used to
store lists of nodes that result from evaluating an XPath
expression (a.k.a. XPath node-sets). This is especially useful
when a sequence of commands is to be performed on some fixed
set of nodes and repetitive evaluation of the same XPath
expression would be lengthy. XPath
node-sets are represented by
<literal>XML::LibXML::NodeList</literal> Perl objects (which
is simply a array reference blessed to the above class, which
provides some simple operator overloading). In XPath, by a
node-set by definition can only contain a single copy of each
node and the nodes within a node-set are processed in the same
order as they appear in the XML document. Having XPath
node-sets represented by a list gives us the advantage of having
the possibility to process the list in a different order than
the one implied by the document (which is what happens
if a variable containing a node-list is evaluated by Perl
rather than XPath), see an example below.
</para>
<example>
<code>xsh> <userinput>$creatures = //creature[@status='alive']</userinput>
# process creatures in the document order:
xsh> <userinput>foreach $creature print @name;</userinput>
# process creatures in the reverse document order:
xsh> <userinput>foreach { reverse @$creature } print @name;</userinput>
# append some more nodes to a node-list (using a variant of
# a simple assignment)
xsh> <userinput>$creatures += //creature[@status='dead'];</userinput>
# again, we can process creatures in order implied by the document:
xsh> <userinput>foreach $creature print @name;</userinput>
# but we can also process first living and then dead creatures,
# since this is how they are listed in $creature
xsh> <userinput>foreach {$creature} print @name;</userinput>
# same as the above is
xsh> <userinput>foreach {@$creature} print @name;</userinput>
</code>
</example>
<para>
&XSH; variables are either globally or lexically scoped.
Global variables need not to be declared (they can be directly
assigned to), whereas lexical variables must be declared
using the command <xref linkend="my_command"/>. Global variable
assignment may also be made temporal for the enclosing block,
using <xref linkend="local_command"/>.
</para>
<example>
<code>$var1 = "foo"; # a global variable requires no declaration
local $var1 $var2 $var3; # localizes global variables
$var1 = "bar"; # assignment to a localized variable is temporary
local $var4 = "foo"; # localized assignment
my $var1 $var $var3; # declares lexical variables
my $var1 = "foo"; # lexical variable declaration with assignment
</code>
</example>
<para>
Lexical variables are only defined in the scope of current
block or subroutine. There is no way to refer to a lexical
variable form outside of the block it was declared in, nor
from within a nested subroutine call. Of course, lexical
variables can be referred to from nested blocks or Perl
expressions (where they behave just like Perl's lexical
variables).
</para>
<para>
On the other hand, global or localized &XSH; variables are just
Perl Scalar variables belonging to the
<literal>XML::XSH2::Map</literal> namespace, which is also the
default namespace for any Perl code evaluated from &XSH; (so
there's no need to use this prefix explicitly in Perl expressions,
unless of course there is a lexical variable in the current
scope with the same).
</para>
<para>Localizing a variable using the <literal>local</literal>
keyword makes all assignments to it occurring in the enclosing block
temporary. The variable itself remains global, only its
original value is restored at the end of the block that localized it.
</para>
<para>
In all above cases, it is possible to arbitrarily
intermix &XSH; and Perl assignments:
</para>
<example>
<code>xsh> <userinput>ls //chapter[1]/title</userinput>
<title>Introduction</title>
xsh> <userinput>$a=string(//chapter[1]/title)</userinput>
xsh> <userinput>perl { $b="CHAPTER 1: ".uc($a); }</userinput>
xsh> <userinput>print $b</userinput>
CHAPTER 1: INTRODUCTION
</code>
</example>
<para>
Although all &XSH; variables are in fact Perl Scalars, it is
still possible to store Perl Array or Hash value to a &XSH;
variable via reference. The following example demonstrates
using Perl Hashes to collect and print some simple racial
statistics about the population of Middle-Earth:
</para>
<example>
<code>my $races;
foreach a:/middle-earth/creature {
<tab count="1"/>my $race=string(@race);
<tab count="1"/>perl { $races->{$race}++ };
}
print "Middle-Earth Population (race/number of creatures)"
print { map "$_/$races->{$_}\n" keys(%$races); };
</code>
</example>
</section>
<section id="Redirection">
<title>Command output redirection</title>
<para>WARNING: XSH2 redirection syntax is not
yet finished. It is currently the same as in XSH1
but this may be changed in the future releases.
</para>
<para>
Output redirection can be used to pipe output of some XSH <xref
linkend="command"/> to some external program, or to capture it
to a variable. Redirection of output of more than one XSH
command can be achieved using the <xref linkend="do_command"/> command.
</para>
<section id="Redirection_pipe">
<title>Redirect output to an external program</title>
<para>The syntax for redirecting the output of a XSH command to
an external program, is <literal>xsh-command | shell-command
;</literal>, where <literal>xsh-command</literal> is any &XSH;
command and <literal>shell-command</literal> is any command
(or code) recognized by the default shell interpreter of the
operating system (i.e. on UNIX systems by
<literal>/bin/sh</literal> or <literal>/bin/csh</literal>, on
Windows systems by <literal>cmd</literal>). The shell command
may contain further redirections (as supported by the system
shell interpreter), but should not contain semicolons, except when
the whole shell command is enclosed in brackets.
</para>
<example>
<title>Use well-known UNIX commands to filter XPath-based XML
listing from a document and count the results</title>
<code>xsh> <userinput>ls //something/* | grep foo | wc</userinput></code>
</example>
</section>
<section id="Redirection_variable">
<title>Capture output to a variable</title>
<para>
The syntax for capturing the output of an XSH command to a variable is
<literal>xsh-command |> $variable</literal>,
where <literal>xsh-command</literal> is
any XSH <xref linkend="command"/> and
<literal>$variable</literal> is any valid
name for a <link linkend="Variables">variable</link>.
</para>
<example>
<title>Store the number of all words in a variable named count.</title>
<code>xsh> <userinput>count //words |> $count</userinput></code>
</example>
</section>
</section>
<section id="Configuration">
<title>Global settings</title> <para>The commands listed below
can be used to modify the default behavior of the XML parser or
&XSH; itself. Some of the commands switch between two different
modes according to a given expression (which is expected to
result either in zero or non-zero value). Other commands also
working as a flip-flop have their own explicit counterparts
(e.g. <xref linkend="verbose"/> and <xref linkend="quiet"/> or
<xref linkend="debug"/> and <xref linkend="nodebug"/>). This
inconsistency is due to historical reasons.
</para>
<para>
The <xref linkend="encoding"/> and <xref linkend="query_encoding"/>
settings
allow to specify character
encodings of user's input and &XSH;'s own output. This is particularly
useful when you work with UTF-8 encoded documents on a console
which only supports 8-bit characters.
</para>
<para>
The <xref linkend="options_command"/> command
displays current settings by means of &XSH; commands.
Thus it can not only be used to review current values, but
also to store them for future use, e.g. in ~/.xsh2rc file.
</para>
<example>
<code>xsh> <userinput>settings | cat > ~/.xsh2rc</userinput></code>
</example>
</section>
<section id="Perl_shell">
<title>Interacting with Perl and Shell</title>
<para>
Along with XPath, Perl is one of two &XSH; expression languages,
and borrows &XSH; its great expressive power.
Perl is a language optimized for scanning arbitrary text
files, extracting information from those text files, and
printing reports based on that information. It has built-in
regular expressions and powerful yet easy to learn
data structures (scalars, arrays, hash tables). It's also a
good language for many system management tasks.
&XSH; itself is written in Perl (except for the XML engine,
which uses libxml2 library written in C by Daniel Veillard).
</para>
<section id="binding_perl">
<title>Calling Perl</title>
<para>
Perl <link linkend="perl_code">expressions or blocks of
code</link> can either be used as arguments to any &XSH; command.
One of them is
<xref linkend="perl_command"/> command
which simply evaluates the given Perl block.
Other commands, such as <xref linkend="map_command"/>,
even require Perl expression argument and allow
quickly change DOM node content.
Perl expressions may also provide lists of strings to iterate over
with a <xref linkend="foreach"/> loop, or serve as
conditions for <xref linkend="if"/>, <xref linkend="unless"/>, and
<xref linkend="while"/> statements.
</para>
<para>
To prevent conflict between &XSH; internals and the evaluated
Perl code, &XSH; runs such code in the context of a special
namespace <literal>XML::XSH2::Map</literal>. As described in
the section <xref linkend="Variables"/>, &XSH; string
variables may be accessed and possibly assigned from Perl
code in the most obvious way, since they actually
<emphasis>are</emphasis> Perl variables defined in the
<literal>XML::XSH2::Map</literal> namespace.</para>
<para>
The interaction between &XSH; and Perl actually works the
other way round as well, so that you may call back &XSH; from the
evaluated Perl code. For this, Perl function
<literal>xsh</literal> is defined in the
<literal>XML::XSH2::Map</literal> namespace. All parameters
passed to this function are interpreted as &XSH; commands.</para>
<para>Moreover, the following Perl helper functions are defined:
</para>
<para><literal>xsh(string,....)</literal> - evaluates
given string(s) as &XSH; commands.
</para>
<para><literal>call(name)</literal> - call a given
&XSH; subroutine.
</para>
<para><literal>count(string)</literal> - evaluates
given string as an XPath expression and returns
either literal value of the result (in case of
boolean, string and float result type) or
number of nodes in a returned node-set.
</para>
<para><literal>literal(string|object)</literal> -
if passed a string, evaluates it as a &XSH; expression
and returns the literal value of the result;
if passed an object, returns literal value of
the object.
For example,
<literal>literal('$doc/expression')</literal> returns the same
value as <literal>count('string($doc/expression)')</literal>.
</para>
<para>
<literal>serialize(string|object)</literal> -
if passed a string, it first evaluates the string
as a &XSH; expression to obtain a node-list object.
Then it serializes the object into XML.
The resulting string is equal to the output of the &XSH; command <xref
linkend="list_command"/> applied on the same expression or object
expression only without indentation and folding.
</para>
<para>
<literal>type(string|object)</literal> -
if passed a string, it first evaluates
the string as &XSH; expression to obtain a node-list object.
It returns a list of strings representing
the types of nodes in the node-list
(ordered in the canonical document order).
The returned type strings are:
<literal>element</literal>,
<literal>attribute</literal>,
<literal>text</literal>,
<literal>cdata</literal>,
<literal>pi</literal>,
<literal>entity_reference</literal>,
<literal>document</literal>,
<literal>chunk</literal>,
<literal>comment</literal>,
<literal>namespace</literal>,
<literal>unknown</literal>.
</para>
<para>
<literal>nodelist(string|object,...)</literal> -
converts its arguments to objects if necessary
and returns a node-list consisting of the objects.
</para>
<para>
<literal>xpath(string, node?)</literal> -
evaluates a given string as an XPath expression
in the context of a given node and returns
the result.
</para>
<para>
<literal>echo(string,...)</literal> - prints
given strings on &XSH; output.
Note, that in the interactive mode,
&XSH; redirects all output to a specific terminal file handle
stored in the variable <literal>$OUT</literal>.
So, if you for example mean to pipe the result
to a shell command, you should avoid using STDOUT filehandle
directly. You may either use the usual <literal>print</literal>
without a filehandle,
use the <literal>echo</literal> function,
or use <literal>$OUT</literal> as a filehandle.
</para>
<para>
In the following examples we use Perl to populate the
Middle-Earth with Hobbits whose names are read from a text
file called <literal>hobbits.txt</literal>, unless there are
some Hobbits in Middle-Earth already.
</para>
<example>
<title>Use Perl to read text files</title>
<code>unless (//creature[@race='hobbit']) {
<tab count="1"/>perl {
<tab count="2"/>open my $fh, "hobbits.txt" };
<tab count="2"/>@hobbits=<$file>;
<tab count="2"/>close $fh;
<tab count="1"/>}
<tab count="1"/>foreach { @hobbits } {
<tab count="2"/>copy xsh:new-element("creature","name",.,"race","hobbit")
<tab count="3"/>into m:/middle-earth/creatures;
<tab count="1"/>}
}
</code>
</example>
<example>
<title>The same code as a single Perl block</title>
<code>perl {
<tab count="1"/>unless (count(//creature[@race='hobbit'])) {
<tab count="2"/>open my $file, "hobbits.txt";
<tab count="2"/>foreach (<$file>) {
<tab count="3"/>xsh(qq{insert element "<creature name='$_' race='hobbit'>"
<tab count="4"/>into m:/middle-earth/creatures});
<tab count="2"/>}
<tab count="2"/>close $file;
<tab count="1"/>}
};</code>
</example>
</section>
<section id="binding_perl_xpathextensions">
<title>Writing your own XPath extension functions in Perl</title>
<para>
&XSH; allows users to extend the set of XPath functions by
providing extension functions written in Perl. This can
be achieved using the <xref linkend="registerfunc_command"/>
command. The perl code implementing an extension function
works as a usual perl routine accepting its arguments in
<literal>@_</literal> and returning the result. The
following conventions are used:
</para>
<para>
The arguments passed to the perl implementation by the XPath
engine are simple scalars for string, boolean and float
argument types and
<literal>XML::LibXML::NodeList</literal> objects for node-set
argument types. The implementation is
responsible for checking the argument number and types. The
implementation may use general Perl functions as well as
<literal>XML::LibXML</literal>
methods to process the arguments and return the result.
Documentation for the <literal>XML::LibXML</literal> Perl module
can be found for example at <ulink url="http://search.cpan.org/~pajas/XML-LibXML/">http://search.cpan.org/~pajas/XML-LibXML/</ulink>.
</para>
<para>
Extension functions SHOULD NOT MODIFY the document DOM tree.
Doing so could not only confuse the XPath engine but possibly
even result in an critical error (such as segmentation fault).
Calling &XSH; commands from extension function implementations
is also dangerous and isn't generally recommended.
</para>
<para>
The extension function implementation must return
a single value, which can be of
one of the following types: simple scalar (a number or
string), <literal>XML::LibXML::Boolean</literal> object
reference (result is a boolean value),
<literal>XML::LibXML::Literal</literal> object reference
(result is a string), <literal>XML::LibXML::Number</literal>
object reference (result is a float),
<literal>XML::LibXML::Node</literal> (or derived) object
reference (result is a node-set consisting of a single node),
or <literal>XML::LibXML::NodeList</literal> (result is a
node-set). For convenience, simple (non-blessed) array
references consisting of
<literal>XML::LibXML::Node</literal> objects can also be
used for a node-set result instead of a
<literal>XML::LibXML::NodeList</literal>.
</para>
</section>
<section id="binding_shell">
<title>Calling the System Shell</title>
<para>
In the interactive mode, &XSH; interprets all lines starting
with the exclamation mark (<literal>!</literal>) as shell
commands and invokes the system shell to interpret the line
(this is to mimic FTP and similar command-line interpreters).
</para>
<example>
<code>xsh> <userinput>!ls -l</userinput>
-rw-rw-r-- 1 pajas pajas 6355 Mar 14 17:08 Artistic
drwxrwxr-x 2 pajas users 128 Sep 1 10:09 CVS
-rw-r--r-- 1 pajas pajas 14859 Aug 26 15:19 ChangeLog
-rw-r--r-- 1 pajas pajas 2220 Mar 14 17:03 INSTALL
-rw-r--r-- 1 pajas pajas 18009 Jul 15 17:35 LICENSE
-rw-rw-r-- 1 pajas pajas 417 May 9 15:16 MANIFEST
-rw-rw-r-- 1 pajas pajas 126 May 9 15:16 MANIFEST.SKIP
-rw-r--r-- 1 pajas pajas 20424 Sep 1 11:04 Makefile
-rw-r--r-- 1 pajas pajas 914 Aug 26 14:32 Makefile.PL
-rw-r--r-- 1 pajas pajas 1910 Mar 14 17:17 README
-rw-r--r-- 1 pajas pajas 438 Aug 27 13:51 TODO
drwxrwxr-x 5 pajas users 120 Jun 15 10:35 blib
drwxrwxr-x 3 pajas users 1160 Sep 1 10:09 examples
drwxrwxr-x 4 pajas users 96 Jun 15 10:35 lib
-rw-rw-r-- 1 pajas pajas 0 Sep 1 16:23 pm_to_blib
drwxrwxr-x 4 pajas users 584 Sep 1 21:18 src
drwxrwxr-x 3 pajas users 136 Sep 1 10:09 t
-rw-rw-r-- 1 pajas pajas 50 Jun 16 00:06 test
drwxrwxr-x 3 pajas users 496 Sep 1 20:18 tools
-rwxr-xr-x 1 pajas pajas 5104 Aug 30 17:08 xsh</code>
</example>
<para>
To invoke a system shell command or program
from the non-interactive mode or from a complex
&XSH; construction, use the <xref linkend="exec_command"/>
command.
</para>
<para>
Since UNIX shell commands are very powerful tool for
processing textual data, &XSH; supports direct redirection of
&XSH; commands output to system shell command. This is very
similarly to the redirection known from UNIX shells, except
that here, of course, the first command in the pipe-line
colone is an &XSH; <xref linkend="command"/>. Since semicolon (<literal>;</literal>)
is used in &XSH; to separate commands, it has to be prefixed
with a backslash if it should be used for other purposes.
</para>
<example>
<title>Use grep and less to display context of `funny'</title>
<code>xsh> ls //chapter[5]/para | grep funny | less</code>
</example>
<example>
<title>The same on Windows 2000/XP systems</title>
<code>xsh> ls //chapter[5]/para | find "funny" | more</code>
</example>
</section>
</section>
<section id="Prompt">
<title>Prompt in the interactive shell</title>
<para>
Like many other shells, &XSH; provides means for customizing
the format of its interactive shell prompt. The prompt is
displayed according to the content of the variable
<literal>$PROMPT</literal> on which the following
substitutions and interpolations are performed
(in this order):
</para>
<para>1. Prompt-string replacements</para>
<code>
%% - percent sign
%p - XPath location of the current node
%P - like %p but without an initial document variable
%l - XPath location of the current node with ID-shortcuts
%L - like %l but without an initial document variable
%n - name of the current node
%N - local name of the current node
%c - canonical XPath name of the current node
%y - type of the current node (element,attribute,...)
%i - ID of the current node
%d - current document variable
%h - the hostname up to the first '.'
%H - the hostname
%s - XSH shell name (basename of $0)
%t - the current time in 24-hour HH:MM:SS format
%T - the current time in 12-hour HH:MM:SS format
%@ - the current time in 12-hour am/pm format
%A - the current time in 24-hour HH:MM format
%u - the username of the current user
%v - the version of XSH2 (e.g., 2.1.0)
%V - the revision number of XML::XSH2::Functions (e.g. 2.40)
%w - current working directory (on the local filesystem)
%W - basename of %w
</code>
<para>2. Variable, XPath and Perl interpolations</para>
<para>
Substrings of the forms <literal>${variable}</literal>,
<literal>${{...perl...}}</literal> and
<literal>${(...xpath...)}</literal> are interpolated as in &XSH;
<link linkend="exp">expressions</link>.
</para>
<para>3. Special character substitution</para>
<code>
\n - newline character
\r - line-feed character
\t - tab character
\a - bell character
\b - backspace character
\f - form feed character
\e - escape character (\033)
\\ - backslash character
\nnn - the character corresponding to the octal number nnn
(useful for non-printable terminal control characters)
</code>
<para>The default value of <literal>$PROMPT</literal> is <literal>"%p>"</literal>.</para>
<para>Note that you must escape <literal>${...}</literal>
interpolators like <literal>\${...}</literal> if you
want them to be evaluated at each prompt
rather than at the time of the assignment to <literal>$PROMPT</literal>.
For example:
</para>
<example>
<title>Let `uname` be computed once, `date` at every prompt</title>
<code>$PROMPT="[${{ chomp($u=`uname`);$u }} \${{ chomp($d=`date`);$d }}] %p>"</code>
</example>
</section>
<section id="xsh2delta">
<title>Changes since XSH 1.x</title>
<para>
This section briefly describes
differences between XSH2 and previous XSH 1.x releases.
The list should not be considered complete.
Some syntax variations or amendments in
the semantics of various commands may not be documented
in this section, neither are various improvements in the
XSH interpreter.
</para>
<section id="new_in_xsh2">
<title>Changes in XSH2</title>
<enumerate>
<listitem>
<para>
In XSH2, subroutines can be called without a
<xref linkend="call_command"/>. They can be
<link linkend="def">redefined</link> and
<link linkend="undef">undefined</link>.
The command <xref linkend="call_command"/>
can still be used, but it's use only makes sense
in indirect calls, where subroutine's name is computed
from an expression.
</para>
<code>def foo $param1 $param2 {
<tab/># param1 and $param2 are lexical (a.k.a. my)
<tab/>ls $param1;
<tab/>echo $param2
}
foo (//chapter)[1] (//chapter)[1]/title
def inc $param1 { return ($param1 + 1) }
$two := inc 1;
</code>
</listitem>
<listitem>
<para>
XSH2 uses variables of the form <xref linkend="varname"/>
for all kinds of objects, including node-sets
(which, if evaluated as Perl expressions, preserve node order).
Node-list variables of XSH 1.x have been deprecated.
</para>
<code>$var = //foo/bar; # node set
$var = "hallo world"; # string
$var = xsh:new-element("foo"); # node object
$var = { ['a','b','c'] }; # Perl array reference
$var = {{ 'a'=>'A', 'b'=>'B' }}; # Perl hash reference
</code>
</listitem>
<listitem>
<para>
XSH2 allows variables to be used in XPath just as they are used in XSLT:
</para>
<code>$var = //foo/bar;
ls //baz[ . = $var[@test=1]/any ]
</code>
<para>
Variable interpolation is still available in XSH2 via ${var},
but it's importance is diminished compared to XSH 1.x,
because the XPath engine now evaluates
variables directly. Interpolation can still be used for
things like "XPath-macros":
</para>
<code>$filter = "[ . = $var[@test=1]/any ]";
ls //baz${filter};
</code>
</listitem>
<listitem>
<para>
XSH2 equally supports XPath and
Perl <link linkend="exp">expressions</link>
(written in braces { ... }).
Unfortunately, Perl expressions can't be embedded in XPath
<link linkend="exp">expressions</link>,
but one can still use variables as an agent:
</para>
<code>perl { use MIME::Base64 };
my $encoded = { encode_base64('open sesame') }
ls //secret-cave[string(password) = $encoded]
</code>
<para>We can, however, use Perl-only expressions complemented with auto-conversion
to do things like:</para>
<code>copy { encode_base64('Pe do mellon a minno!') } replace //secret-cave/password/text();
</code>
</listitem>
<listitem>
<para>
Commands return values
(see <link linkend="assign_command">:= assignment</link>,
or <link linkend="exp">&{ } expressions</link>).
</para>
<code>$moved_paras := xmove //para replace .;
$chapter := wrap chapter $moved_paras;
ls $chapter;
# or just
ls &{ wrap chapter &{ xmove //para replace . } };
</code>
</listitem>
<listitem>
<para>
XSH2 deprecates "string" expressions of XSH 1.x. However,
for convenience, some XSH2 commands interpret name-like
XPath expressions on certain argument positions as strings
(mostly commands that expect file-name or node-name
arguments):
</para>
<code>insert element my_document into .;
insert text "foo" into my_document;
$doc := open my_document; # opens file named "my_document"
$doc := open "my_document"; # same
$doc := open (my_document); # opens file named "foo"
$doc := open string(my_document); # same
</code>
</listitem>
<listitem>
<para>
In XSH2, XML documents
have no ID.
They are referred to using variables (which fits in well with the unified variable concept):
</para>
<code>$doc1 := open "foo1.xml";
$doc2 := open "foo2.xml";
ls ($doc1//para|$doc2//para);
cd $doc1;
ls id('intro'); # finds ID intro in the current document ($doc1)
ls xsh:id2($doc2, 'intro'); # finds ID intro in $doc2
</code>
</listitem>
<listitem>
<para>
XSH2 commands have options and flags instead of many optional (positional) arguments.
Options/flags usually have both long forms (like --flag) and equivalent
short forms (like :f) (colon is borrowed from Scheme, because dash is reserved for XPath minus).
</para>
<code>$doc := open --format html "version1.html";
save --file "version2.xml" $doc;
ls --fold /;
ls :f /;
ls --depth 1 /;
ls :d 1 /;
# all the same:
$sorted = sort --key @name --locale --descending //user;
$sorted = sort :l:d:k@name //user;
$sorted = sort --key @name --compare { use locale; $b cmp $a } //user;
validate --relaxng --file "test.rng" $mydoc;
validate --public "-//OASIS//DTD DocBook XML V4.1.2//EN" $mydoc;
validate --yesno $mydoc;
</code>
</listitem>
<listitem>
<para>Finally, <xref linkend="eval_command"/> is no longer
an alias for <xref linkend="perl_command"/> in &XSH;,
but instead evaluates strings containing &XSH; commands
(so <literal>eval $string</literal> now practically works like old ugly
<literal>perl { xsh($string) }</literal>). See the documentation for
<xref linkend="eval_command"/> for a handy usage example
(no more PHP, XSTL and XPathScript :-)).
</para>
</listitem>
</enumerate>
</section>
<section id="xsh2delta_examples">
<title>Examples</title>
<example>
<title>Open command has changed.</title>
<code>XSH1:
foo = file.xml;
or
foo = "file.xml";
</code>
<code>XSH2:
$foo := open file.xml; # file.xml is a bareword in file-name context
or
$foo := open "file.xml"; # "file.xml" is a XPath string
or
$foo := open {"file.xml"}; # "file.xml" is a Perl string
or
$foo = xsh:open("file.xml"); # righthand side is an XPath extension function
</code>
</example>
<example>
<title>XSH2 commands have options</title>
<code>XSH1:
open HTML FILE foo2 = "file.html";
</code>
<code>XSH2:
$foo2 := open --format html "file.html";
</code>
</example>
<example>
<title>documents</title>
<code>XSH1:
foo = file.xml;
ls foo:(//bar|//baz);
</code>
<code>XSH2:
$foo := open file.xml;
ls ($foo//bar|$foo//baz);
</code>
</example>
<example>
<title>variable interpretation</title>
<code>XSH1:
$family = "Arial";
ls //font[@family="$family"]; # interpolation
or
ls //font[@family="${family}"]; # interpolation
</code>
<code>XSH2:
$family = "Arial";
ls //font[@family=$family]; # evaluation by XPath engine
or
ls //font[@family="${family}"]; # interpolation
</code>
</example>
<example>
<title>adding new nodes</title>
<code>XSH1:
insert attribute "foo=bar" into /scratch;
</code>
<code>XSH2:
insert attribute "foo=bar" into /scratch;
or
copy xsh:new-attribute("foo","bar") into /scratch;
</code>
</example>
<example>
<title>foreach with perl expression</title>
<code>XSH1:
foreach { glob('*.xml') } {
<tab/>open doc = $__;
<tab/>...
}
</code>
<code>XSH2:
foreach { glob('*.xml') } {
<tab/>my $doc := open .;
<tab/>...
}
</code>
</example>
<example>
<title>foreach (perl expression) with variable</title>
<code>XSH2:
foreach my $filename in { glob('*.xml') } {
<tab/>my $doc := open $filename;
<tab/>...
}
</code>
</example>
<example>
<title>sorting nodes</title>
<code>XSH1:
%list = //player;
sort @best_score { $a <=> $b } %list;
copy %list into .;
</code>
<code>XSH2:
$list := sort --numeric --key @best_score //player;
copy { $list } into .;
or
copy &{ sort --numeric --key @best_score //player } into .;
or (using short options)
copy &{ sort :n :k @best_score //player } into .;
</code>
</example>
</section>
</section>
</doc>
<preamb>
<![CDATA[
package XML::XSH2::Grammar;
use strict;
use Parse::RecDescent;
use vars qw/$grammar/;
$Parse::RecDescent::skip = '(\s|\n|#[^\n]*)*';
$grammar=<<'_EO_GRAMMAR_';
]]>
</preamb>
<postamb>
<![CDATA[
_EO_GRAMMAR_
sub compile {
my @opts = ( { -standalone => 1 },
$grammar,
"XML::XSH2::Parser",
);
shift @opts
if $Parse::RecDescent::VERSION < 1.967_005; # Standalone not supported.
Parse::RecDescent->Precompile(@opts);
}
sub new {
return new Parse::RecDescent ($grammar);
}
1;
]]>
</postamb>
<rules>
<!-- ================== commands and options ====================== -->
<rule id="command" type="argtype" inline="no">
<production>
<regexp>(?=\s*[}{;]|\s*\Z)</regexp>
<directive type="commit"/>
<directive type="reject"/>
</production>
<ruleref ref="assign_command" arguments=""/>
<ruleref ref="my_command" arguments=""/>
<ruleref ref="local_command" arguments=""/>
<ruleref ref="do_command" arguments=""/>
<ruleref ref="if_command" arguments=""/>
<ruleref ref="unless_command" arguments=""/>
<ruleref ref="while_command" arguments=""/>
<ruleref ref="foreach_command" arguments=""/>
<ruleref ref="stream_process_command" arguments=""/>
<ruleref ref="undef" arguments=""/>
<ruleref ref="ignore_use_command" arguments=""/>
<ruleref ref="test_mode" arguments=""/>
<ruleref ref="run_mode" arguments=""/>
<!-- ADD NEW COMMANDS HERE -->
<production>
<regexp>(?!(?:iterate|try|def|define)\b)</regexp>
<regexp>\.|[a-zA-Z_][-a-zA-Z0-9_]*</regexp>
<ruleref ref="exp_or_opt" rep="s?" arguments=""/>
<action>
bless
[<lineinfo/>,$item[2],@{$item[3]}],
'XML::XSH2::Command'
</action>
</production>
<documentation sections="Argtypes">
<title>command</title>
<shortdesc>List of &XSH; commands and their general syntax</shortdesc>
<description>
<para>
&XSH; command consists of a command name
and possibly command parameters separated
by whitespace. Individual <link linkend="command">&XSH; commands</link> are
separated with a semicolon.
A command may optionally be followed
by an output redirection directive
(see <xref linkend="binding_shell"/> for output
redirection to a command
and <xref linkend="Variables"/> for output
redirection to variable).
Most commands have aliases, so for example
<xref linkend="prune_command"/> command
may also be invoked as <literal>del</literal> or
<literal>rm</literal>.
</para>
<para>&XSH; recognizes the following commands
(not including aliases):
<typeref types="command"/></para>
</description>
<see-also>
<ruleref ref="block" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="statement" inline="no">
<production>
<regexp>(?=\s*[}{;])</regexp>
<directive type="commit"/>
<directive type="reject"/>
</production>
<ruleref ref="if" arguments=""/>
<ruleref ref="unless" arguments=""/>
<ruleref ref="while" arguments=""/>
<ruleref ref="foreach" arguments=""/>
<ruleref ref="try_catch" arguments=""/>
<ruleref ref="iterate" arguments=""/>
<ruleref ref="def" arguments=""/>
</rule>
<rule id="complex_command" inline="no">
<production>
<regexp>(?=\s*[{}]|\s*\Z)</regexp>
<directive type="commit"/>
<directive type="reject"/>
</production>
<production>
<regexp>\s*;</regexp>
<directive type="commit"/>
</production>
<production>
<regexp>(?=(?:foreach|for|if|unless|iterate|while|try|def|define)\b)</regexp>
<ruleref ref="statement" arguments=""/>
<directive type="commit"/>
<ruleref ref="trail" rep="?" arguments=""/>
<action>
if (scalar(@{$item[4]})) {
if ($item[4][0][0] eq 'pipe') {
$return=[<lineinfo/>,'pipe_command',[$item[2]],$item[4][0][1]]
} else {
$return=[<lineinfo/>,'string_pipe_command',[$item[2]],$item[4][0][1]]
}
} else {
$return=$item[2]
}
</action>
</production>
<production>
<ruleref ref="command" arguments=""/>
<directive type="commit"/>
<ruleref ref="trail" rep="?" arguments=""/>
<regexp>\s*;|(?=\s*}|\s*\Z)</regexp>
<action>
if (scalar(@{$item[3]})) {
if ($item[3][0][0] eq 'pipe') {
$return=[<lineinfo/>,'pipe_command',[$item[1]],$item[3][0][1]]
} else {
$return=[<lineinfo/>,'string_pipe_command',[$item[1]],$item[3][0][1]]
}
} else {
$return=$item[1]
}
</action>
</production>
<production>
<directive type="error">Parse error near: "}.substr($text,0,40).qq{ ..."</directive>
</production>
</rule>
<rule id="block" type="argtype" name="block" inline="no">
<production>
<string>{</string>
<directive type="commit"/>
<ruleref ref="complex_command" rep="s" arguments=""/>
<string>}</string>
<action>[grep ref,@{$item[3]}]</action>
</production>
<documentation sections="Argtypes Flow">
<title>block argument type</title>
<shortdesc>a block of &XSH; commands</shortdesc>
<description>
<para>
a block of semicolon-separated
&XSH; commands enclosed within braces.
</para>
<example>
<title>Count paragraphs in each chapter</title>
<code>$i=0;
foreach //chapter {
<tab count="1"/>$c=count(./para);
<tab count="1"/>$i=$i+1;
<tab count="1"/>print "$c paragraphs in chapter no.$i";
}
</code>
</example>
</description>
</documentation>
</rule>
<!-- ================== help on types ====================== -->
<rule id="type" type="list" inline="no">
<documentation>
<title>List of command argument types</title>
<description>
<para><typeref types="argtype"/></para>
</description>
</documentation>
</rule>
<!-- ================== exp/rule ====================== -->
<rule id="exp_or_opt" inline="no">
<production>
<regexp>(?=\s*[};]|\s*\Z)</regexp>
<directive type="commit"/>
<directive type="reject"/>
</production>
<production>
<ruleref ref="option" arguments=""/>
</production>
<production>
<ruleref ref="exp" arguments=""/>
</production>
</rule>
<rule id="option" inline="no">
<production>
<regexp>:[[:alnum:]]|--[-_[:alnum:]]+</regexp>
</production>
</rule>
<!-- ================== expressions ====================== -->
<rule id="inline_doc_string" inline="no">
<production>
<regexp>'[a-zA-Z_][a-zA-Z0-9_]*'|"[a-zA-Z_][a-zA-Z0-9_]*"|\([a-zA-Z_][a-zA-Z0-9_]*\)|\{[a-zA-Z_][a-zA-Z0-9_]*\}|[a-zA-Z_][a-zA-Z0-9_]*</regexp>
<action>[($item[1]=~/^(['"({])?(.*?)(['")}])?$/)]</action>
</production>
</rule>
<rule id="inline_doc" inline="no">
<production>
<regexp><<</regexp>
<ruleref ref="inline_doc_string" arguments=""/>
<directive type="skip">""</directive>
<regexp>.*\n</regexp>
<regexp>(.|\n)*?\n$item[2][1]\s*(\n|$)</regexp>
<action>
$text=$item[4].$text;
local $_=$item[5]; s/\n$item[2][1]\s*$//;
my $paren = $item[2][0];
$paren = '"' if $paren eq "";
if ($paren eq "'") {
$paren = '"';
s{(\\)(.|\n)|(\$)}{ (defined($3) and $3 eq '$') ? "\\\$"
: ((defined($2) and $2 eq "\\")
? "\\\\" : ((defined($2) and $2 eq "'") ? "'" : (
(defined($2) and $2 eq '$') ? "\\\\\\$2" :
"\\\\$2"))) }eg;
} "<<".$paren.$_;
</action>
</production>
</rule>
<!-- ================== encoding string ====================== -->
<rule id="enc_string" type="argtype" name="encoding" inline="no">
<production>
<ruleref ref="exp" arguments=""/>
</production>
<documentation sections="Argtypes Configuration">
<title>enc_string argument type</title>
<shortdesc>character encoding (codepage) identifier</shortdesc>
<description>
<para>
An <xref linkend="exp"/> which evaluates to a valid encoding
name, e.g. to utf-8, utf-16, iso-8859-1, iso-8859-2,
windows-1250 etc. As with <xref linkend="filename"/>,
as long as the expression doesn't contain special characters
like braces, brackets, quotes, <literal>$</literal>, nor
<literal>@</literal>, it is taken as a literal and
evaluates to itself.
</para>
</description>
</documentation>
</rule>
<!-- ================== identifyer ====================== -->
<rule id="ID" inline="no">
<production>
<regexp>[a-zA-Z_][a-zA-Z0-9_]*</regexp>
</production>
</rule>
<rule id="varname" type="argtype" name="$variable" inline="no">
<documentation sections="Argtypes Variables Documents">
<title>variable name</title>
<description>
<para>
Variable names start with a dollar-sign (<literal>$</literal>)
followed by an identifier. The identifier must
match the following regular
expression <literal>[a-zA-Z_][a-zA-Z0-9_]*</literal>,
i.e., it must be at least one character long, must
beginning with a letter or
underscore, and may only containing letters, underscores, and
digits.
</para>
</description>
<see-also>
<ruleref ref="Variables"/>
<ruleref ref="assign_command"/>
<ruleref ref="my_command"/>
<ruleref ref="local_command"/>
</see-also>
</documentation>
</rule>
<rule id="subname" type="argtype" name="subroutine" inline="no">
<documentation sections="Argtypes Variables Documents">
<title>sub-routine name</title>
<shortdesc>name of a sub-routine</shortdesc>
<description>
<para>
A sub-routine name is an identifier
matching the following regular
expression <literal>[a-zA-Z_][a-zA-Z0-9_]*</literal>,
i.e., it must be at least one character long, must
beginning with a letter or
underscore, and may only containing letters, underscores, and
digits.
</para>
</description>
</documentation>
</rule>
<rule id="document" type="argtype" name="document" inline="no">
<documentation sections="Argtypes Documents Variables">
<title>document</title>
<shortdesc>specifying documents</shortdesc>
<description>
<para>
A document is specified by arbitrary
<xref linkend="exp"/> which evaluates
to a non-empty node-list.
From this node-list, the first node
is taken and its owner document is used.
</para>
</description>
<see-also>
<ruleref ref="Variables"/>
<ruleref ref="assign_command"/>
<ruleref ref="my_command"/>
<ruleref ref="local_command"/>
</see-also>
</documentation>
</rule>
<rule id="filename" type="argtype" inline="no">
<production>
<ruleref ref="exp" arguments=""/>
</production>
<documentation sections="Argtypes Documents">
<title>Filename argument type</title>
<shortdesc>specifying filenames</shortdesc>
<description>
<para>An <xref linkend="exp"/> which evaluates to a valid
filename or URL. As long as the expression contains no
whitespace, no brackets of any type, quotes,
double-quotes, <literal>$</literal> character nor
<literal>@</literal> character, it is treated as a literal token
which evaluates to itself.
</para>
</description>
</documentation>
</rule>
<rule id="nodename" type="argtype" inline="no">
<production>
<ruleref ref="exp" arguments=""/>
</production>
<documentation sections="Argtypes Documents">
<title>Node-name argument type</title>
<shortdesc>specifying names of DOM nodes</shortdesc>
<description>
<para>An <xref linkend="exp"/> which evaluates to a valid
name of an element, attribute or processing-instruction
node. As long as the expression contains no
whitespace, no brackets of any type, quotes,
double-quotes, <literal>$</literal> character,
nor <literal>@</literal> character, it is treated as a literal token
which evaluates to itself.
</para>
</description>
</documentation>
</rule>
<!-- ================== XPATH ====================== -->
<!--
XPath accepted by &XSH; are either string constants "...", '...'
or
more compliex expressions of the form xpsimple xpcont?
-->
<rule id="xpath" type="argtype" inline="no">
<production>
<regexp>(?=['"])</regexp>
<directive type="commit"/>
<ruleref ref="xpstring" arguments=""/>
<action>$item[3]</action>
</production>
<production>
<ruleref ref="xpsimple" arguments=""/>
<directive type="skip">""</directive>
<ruleref ref="xpcont" rep="?" arguments=""/>
<action>$item[1].join("",@{$item[3]})</action>
</production>
<production>
<directive type="error">expected XPath, but got "}.substr($text,0,40).qq{ ..."</directive>
</production>
<documentation sections="Argtypes Navigation Manipulation Variables">
<title>XPath argument type</title>
<shortdesc>XPath expression</shortdesc>
<description>
<para>
&XSH; can evaluate XPath expressions as defined in W3C
recommendation at <ulink
url="http://www.w3.org/TR/xpath">http://www.w3.org/TR/xpath</ulink>
with only a little limitation on use of syntactically
ignorable whitespace.
(Nice interactive XPath tutorials and references
can be found at <ulink url="http://www.zvon.org">http://www.zvon.org</ulink>.)
</para>
<para>
In order to allow &XSH; to use white-space as a command
argument delimiter (which is far more convenient to type
than, say, commas), the use of white-space in XPath is
slightly restricted. Thus, in &XSH;, white-space can only occur in
those parts of an XPath expression, that are surrounded by
either brackets, square brackets, single or double quotes.
So, for example, otherwise valid XPath expression like
</para>
<code>/ foo / bar [ @baz = "bar" ]</code>
<para>
should in &XSH; be written as either of
</para>
<code>/foo/bar[ @baz = "bar" ]</code>
<para>
avoiding any white-space outside the square brackets,
or completely enclosed in brackets as in
</para>
<code>( / foo / bar [ @baz = "bar" ] ).</code>
<para>
&XSH; provides a number of powerful XPath extension
functions, listed below and described in separate
sections. XPath extension
functions by default belong to &XSH; namespace
<literal>http://xsh.sourceforge.net/xsh/</literal> with
a namespace prefix set to <literal>xsh</literal>. A
program may however call the <xref
linkend="xpath_extensions_command"/> command to map &XSH;
XPath extension functions into the default namespace, so
that they may be used directly without any prefix.
</para>
<para>
XPath extension functions defined in &XSH;:
<typeref types="function"/>
</para>
<example>
<title>Open a document and count all sections containing a
subsection
</title>
<code>xsh $scratch/> <userinput>$v := open mydocument1.xml;</userinput>
xsh $v/> <userinput>$k := open mydocument2.xml;</userinput>
xsh $k/> <userinput>count //section[subsection];</userinput> # searches k
xsh $k/> <userinput>count $v//section[subsection];</userinput> # searches v
</code>
</example>
</description>
</documentation>
</rule>
<!--
xpsimple : start of an XPath expression
-->
<rule id="xpsimple" inline="no">
<production>
<regexp mod="x">
(?:
\$\{ (?: \$?[a-zA-Z_][a-zA-Z0-9_]* | \{.*?\} | \(.+?\) ) \} |
\$(?!\{) |
[^-:\$\[\]{}|"'\ \s();] |
-[^-\[\]{}|"'\ \s();]
)
(?:
\$\{ (?: \$?[a-zA-Z_][a-zA-Z0-9_]* | \{.*?\} | \(.+?\) ) \} |
\$(?!\{) |
[^\[\]\${}|"'\ \s();]
)*</regexp>
</production>
<production>
<ruleref ref="xpbrackets" arguments=""/>
</production>
</rule>
<!--
xpcont : continuation XPath expression: filters or brackets
-->
<rule id="xpcont" inline="no">
<production>
<group>
<production>
<ruleref ref="xpfilters" arguments=""/>
</production>
<production>
<ruleref ref="xpbrackets" arguments=""/>
</production>
</group>
<directive type="skip">""</directive>
<ruleref ref="xpath" rep="?" arguments=""/>
<action>$item[1].join("",@{$item[3]})</action>
</production>
<production>
<ruleref ref="xpath" arguments=""/>
<action>$item[1]</action>
</production>
</rule>
<!--
xpfilters : one or more filters enclosed in [...]
-->
<rule id="xpfilters" inline="no">
<production>
<regexp>(?=\[)</regexp>
<ruleref ref="xpfilter" rep="s" arguments=""/>
<action>join("",@{$item[2]})</action>
</production>
</rule>
<rule id="xpfilter" inline="no">
<production>
<string>[</string>
<ruleref ref="xpinter" arguments=""/>
<string>]</string>
<action>"[$item[2]]"</action>
</production>
</rule>
<!--
xpbracket : balanced (...)
-->
<rule id="xpbracket" inline="no">
<production>
<string>(</string>
<directive type="skip">""</directive>
<ruleref ref="xpinter" arguments=""/>
<string>)</string>
<action>"($item[3])"</action>
</production>
</rule>
<rule id="xpbrackets" inline="no">
<production>
<regexp>(?=\()</regexp>
<ruleref ref="xpbracket" arguments=""/>
<directive type="skip">""</directive>
<ruleref ref="xpfilters" rep="?" arguments=""/>
<action>join "",$item[2],@{$item[4]}</action>
</production>
</rule>
<!--
xpinter : XPath expression occuring within (...) or [...]
-->
<rule id="xpinter" inline="no">
<production>
<ruleref ref="xps" arguments=""/>
<directive type="skip">""</directive>
<ruleref ref="xpintercont" rep="?" arguments=""/>
<action>join("",$item[1],@{$item[3]})</action>
</production>
</rule>
<!--
xpintercont : continuation of an XPath expression within (...) or [...]
-->
<rule id="xpintercont" inline="no">
<production>
<group>
<production>
<ruleref ref="xpfilters" arguments=""/>
</production>
<production>
<ruleref ref="xpbrackets" arguments=""/>
</production>
</group>
<directive type="skip">""</directive>
<ruleref ref="xpinter" rep="?" arguments=""/>
<action>join("",$item[1],@{$item[3]})</action>
</production>
</rule>
<!--
xps : XPath fragment not containing brackets and closed upon strings
-->
<rule id="xps" inline="no">
<production>
<regexp mod="x">
(?: [^\$\[\]()'"};]+ |
\$(?!\{) |
\$\{ (?:\$?[a-zA-Z_][a-zA-Z0-9_]* |
\{.*?\} |
\(.+?\)
)
\} |
'(?:\$\{ (?: \$?[a-zA-Z_][a-zA-Z0-9_]* | \{.*?\} | \(.+?\)) \} |
\$(?!\{) | [^\$'] | \\\$
)*' |
"(?:\$\{ (?: \$?[a-zA-Z_][a-zA-Z0-9_]* | \{.*?\} | \(.+?\)) \} |
\$(?!\{) | [^\$"] | \\\$
)*"
)*</regexp>
</production>
</rule>
<!--
xpstring : XPath string constant
-->
<rule id="xpstring" inline="no">
<production>
<regexp mod="x">
'(?:\$\{(?:\$?[a-zA-Z_][a-zA-Z0-9_]*|\{.*?\}|\(.+?\))\}|\$(?!\{)|[^\$']|\\\$)*' |
"(?:\$\{(?:\$?[a-zA-Z_][a-zA-Z0-9_]*|\{.*?\}|\(.+?\))\}|\$(?!\{)|[^\$"]|\\\$)*"
</regexp>
</production>
</rule>
<!-- ================== perl expression=expression ====================== -->
<rule id="perl_expression" inline="no">
<production>
<action>$main::myline = $thisline;</action>
<directive type="reject"/>
</production>
<production>
<ruleref ref="exp" arguments=""/>
<action>{local $^W=0; "\n# line $main::myline \"$XML::XSH2::Functions::SCRIPT\"\n".$item[1]}</action>
</production>
</rule>
<rule id="perl_block" inline="no">
<production>
<action>$main::myline = $thisline;</action>
<directive type="reject"/>
</production>
<production>
<action>$main::myline = $thisline;</action>
<directive type="reject"/>
</production>
<production>
<directive type="perl_codeblock"/>
<action>{
$return=$item[1];
{
local $^W = 0; # don't warn about undefined contants
my $pos="# line $main::myline \"$XML::XSH2::Functions::SCRIPT\"\n";
$return=~s/^\{/\{\n$pos/;
}
}</action>
</production>
</rule>
<!-- ================== general expression ======================
-->
<rule id="loose_exp" inline="no">
<production>
<regexp>^(?={)</regexp>
<ruleref ref="perl_block" arguments=""/>
<action>$item[2]</action>
</production>
<production>
<string>&</string>
<ruleref ref="block" arguments=""/>
<action>$item[2]</action>
</production>
<production>
<regexp>^(?=<<)</regexp>
<ruleref ref="inline_doc" arguments=""/>
<action>$item[2]</action>
</production>
<production>
<ruleref ref="xpinter" arguments=""/>
</production>
</rule>
<rule id="exp" type="argtype" name="expression" inline="no">
<production>
<regexp>^(?={)</regexp>
<ruleref ref="perl_block" arguments=""/>
<action>$item[2]</action>
</production>
<production>
<string>&</string>
<ruleref ref="block" arguments=""/>
<action>$item[2]</action>
</production>
<production>
<regexp>^(?=<<)</regexp>
<ruleref ref="inline_doc" arguments=""/>
<action>$item[2]</action>
</production>
<production>
<ruleref ref="xpath" arguments=""/>
</production>
<documentation sections="Argtypes Variables Manipulation Perl_shell">
<title>expression</title>
<shortdesc>expression argument type</shortdesc>
<description>
<para>An &XSH; expression can be one of the following constructs:</para>
<enumerate>
<listitem>
<para>
XPath 1.0 expression with the following restriction:
whitespace is only allowed within parts the expression
enclosed in quotes (literal strings) or brackets (XPath
has two types of brackets - plain and square). Thus, while
<literal>/ foo / bar</literal> is a valid XPath expression
matching element named bar under root element foo, in &XSH; this
expression must be written as <literal>/foo/bar</literal> or
<literal>(/ foo / bar)</literal> or
<literal>(/foo/bar)</literal> etc.
The reason for this restriction is simple:
&XSH;, like most shell
languages, uses whitespace as argument delimiter so it must
be able to determine expression boundaries
(otherwise, <literal>/ bar / foo</literal> could be
anything between one and four expressions).
</para>
</listitem>
<listitem>
<para>
In certain contexts, usually when a filename or a node
name is
expected as an argument, bareword (otherwise XPath)
expressions are
evaluated in a non-standard way: as long as the
expression contains no whitespace, no brackets of any
kind, quotes, double-quotes, <literal>$</literal>
character, nor <literal>@</literal> character,
it is treated as a literal
token which evaluates to itself.
This usually happens if a file name or element
name is expected, but some other commands, like
<xref linkend="print_command"/>,
evaluate its arguments in this way. In order to force an
XPath evaluation in such situations, the entire expression
should be enclosed with brackets <literal>(...)</literal>.
For example, with
<xref linkend="open_command"/> command, <literal>open
file</literal> or <literal>open "file"</literal> both
open a file whose name is <literal>file</literal>
(literally) whereas <literal>open (file)</literal> or
<literal>open @file</literal> compute the file name
by evaluating <literal>(file)</literal> or
<literal>@file</literal> respectively, as XPath
expressions.
</para>
</listitem>
<listitem>
<para>
Perl blocks. These are enclosed in braces like:
<literal>{ perl-code }</literal>.
Perl expressions can be used to evaluate more complicated
things, like complex string expressions, regexp matches,
perl commands, etc. In short, arbitrary perl.
Of course, things like <literal>{`ls`}</literal> work
too, and that's why we don't need to define shell-like backticks
in &XSH; itself.
</para>
</listitem>
<listitem>
<para>
Result of one &XSH; command can be directly passed as an argument
to another. This is done using &{ xsh-code } expressions.
Most &XSH; commands always return <literal>undef</literal> or 1,
but some do return a value, usually a node-list. Examples of
such commands are
<xref linkend="open_command" />, <xref
linkend="copy_command"/>, <xref
linkend="move_command"/>, <xref
linkend="wrap_command"/>, <xref
linkend="edit_command"/>, or <xref
linkend="xslt_command"/>.
</para>
</listitem>
<listitem>
<para>
Large blocks of literal data can be passed to commands
via "here document" expressions
<literal><<EOF</literal>,
<literal><<'EOF'</literal>,
<<"EOF"<literal></literal>, where
<literal>EOF</literal> is an arbitrary
<literal>ID</literal> string.
<literal><<EOF</literal> and
<literal><<"EOF"</literal> are equivalent, and
are subject to interpolation of
<literal>${...}</literal> constructs, where as
<literal><<'EOF'</literal> does not. The result
of evaluation of these three is the literal content
(with <literal>${...}</literal> possibly interpolated)
of the script starting at the following line and
ending at a line containing just
<literal>EOF</literal>. <literal><<{EOF}</literal>
and <literal><<(EOF)</literal> are implemented
too, but I'm not sure they are of any use since
putting the expression in ( ) or { } has the same
effect.
</para>
</listitem>
</enumerate>
<para>
XPath expressions (and their filename variant) are subject
to interpolation of substrings of the form
<literal>${...}</literal> (called interpolators), where
<literal>...</literal> can be of several different forms,
described below. The interpolation can be suppressed
by preceding the <literal>$</literal> sign with a backslash.
</para>
<para>
Substrings of the form <literal>${id}</literal> or
<literal>${$id}</literal> are interpolated with the
value of the variable named <literal>$id</literal>.
</para>
<para>
Interpolators of the form
<literal>${{</literal> and <literal>}}</literal>
evaluate their contents
as a Perl expression (in very much the same way as the
<xref linkend="perl_command"/> command) and interpolate
to the resulting value.
</para>
<para>
Interpolators of the form
<literal>${(</literal> and <literal>)}</literal>
evaluate their contents as an XPath expression and interpolates to
a string value of the result.
</para>
<para>
Substrings of the form <literal>\${</literal>
interpolate to <literal>${</literal>
(as a means for escaping <literal>${...}</literal>
in an expression).
</para>
<para>
Expressions are evaluated by &XSH; commands themselves, so
the exact value an expression evaluates to, is also
command-dependent. There are commands that can handle
all data types, but some commands expect their arguments to
evaluate only to specific kinds of values.
As already mentioned above, commands
expecting a filename or a node name usually evaluate
simple expressions not containing any special characters
as literal strings, whereas commands expecting strings
evaluate all expressions so that they get a string value
(e.g. by converting a node-set to its text content).
Similarly, commands expecting a node-set usually convert
strings to a small XML fragments, while commands
expecting a single document node usually convert
node-sets to a document node by taking the owner
document of the first element in the node-set.
</para>
<example>
<code>$a = "bar"; # $a contains: bar</code>
<code>$b = $a; # $b contains: bar</code>
<code>$b = "$a"; # $b contains: $a</code>
<code>$b = "${a}"; # $b contains: bar</code>
<code>$b = {$a}; # $b contains: bar</code>
<code>$b = //creature; # $b contains a node-set</code>
<code>ls $b; # prints the node-set as XML in document order</code>
<code>count $b; # prints number of nodes in the node-set</code>
<code>echo count($b); # the same</code>
<code>$c = string($b[1]/@name) # $c contains string value of //creature[1]/@name (e.g. Bilbo)</code>
<code>echo //creature # prints: //creature</code>
<code>echo (//creature) # evaluates (//creature) as XPath and prints the
# text content of the resulting node-set</code>
<code></code>
<code>echo { join(",",split(//,$a)) } # prints: b,a,r</code>
<code>echo ${{ join(",",split(//,$a)) }} # the same</code>
<code>echo "${{ join(",",split(//,$a)) }}" # the same</code>
<code>echo "${(//creature[1]/@name)}" # prints e.g.: Bilbo</code>
<code>echo ${(//creature[1]/@name)} # the same</code>
<code>echo //creature[1]/@name # the same</code>
<code>echo string(//creature[1]/@name) # the same</code>
<code>echo (//creature[1]/@name) # the same</code>
</example>
<example>
<title>In-line documents</title>
<code>$a="bar"</code>
<code>echo foo <<END baz;
xx ${a} yy
END
# prints foo xx bar yy baz</code>
<code>echo foo <<"END" baz;
xx ${a} yy
END
# same as above</code>
<code>echo foo <<'END' baz;
xx ${a} yy
END
# prints foo xx $a yy baz</code>
</example>
<example>
<title>Expressions returning result of a &XSH; command</title>
<code>copy &{ sort --key @best_score --numeric //player } into .;</code>
</example>
</description>
</documentation>
</rule>
<!-- ================== variables ====================== -->
<rule id="variable" inline="no">
<production>
<regexp>\$[a-zA-Z_][a-zA-Z0-9_]*</regexp>
</production>
</rule>
<!-- ================== EOF ====================== -->
<rule id="eof" inline="no">
<production>
<regexp>\Z</regexp>
<action>1;</action>
</production>
</rule>
<!-- ================== STARTRULE and such ====================== -->
<rule id="startrule" inline="no">
<production>
<ruleref ref="shell" arguments=""/>
<directive type="commit"/>
<ruleref ref="eof" arguments=""/>
<action>$item[1]</action>
</production>
<production>
<ruleref ref="complex_command" rep="s" arguments=""/>
<directive type="commit"/>
<ruleref ref="eof" arguments=""/>
<action>$item[1]</action>
</production>
</rule>
<rule id="trail" inline="no">
<production>
<regexp>(?=\s*[};]|\s*\Z)</regexp>
<directive type="commit"/>
<directive type="reject"/>
</production>
<production>
<string>|></string>
<directive type="commit"/>
<ruleref ref="variable" arguments=""/>
<action>['var',$item[3]]</action>
</production>
<production>
<string>|</string>
<directive type="commit"/>
<ruleref ref="shline" arguments=""/>
<action>['pipe',$item[3]]</action>
</production>
</rule>
<rule id="shline_nosc" inline="no">
<production>
<regexp>([^;()\\"'\|]|\|[^>]|\\.|\"([^\"\\]|\\.)*\"|\'([^\'\\]|\\\'|\\\\|\\[^\'\\])*\')*</regexp>
</production>
</rule>
<rule id="shline_inter" inline="no">
<production>
<regexp>([^()\\"']|\\.|\"([^\"\\]|\\.)*\"|\'([^\'\\]|\\\'|\\\\|\\[^\'\\])*\')*</regexp>
</production>
</rule>
<rule id="shline_bracket" inline="no">
<production>
<string>(</string>
<ruleref ref="shline_inter" arguments=""/>
<ruleref ref="shline_bracket" rep="?" arguments=""/>
<ruleref ref="shline_inter" arguments=""/>
<string>)</string>
<action>join("",'(',$item[2],@{$item[3]},$item[4],')')</action>
</production>
</rule>
<rule id="shline" inline="no">
<production>
<ruleref ref="shline_nosc" arguments=""/>
<ruleref ref="shline_bracket" rep="?" arguments=""/>
<ruleref ref="shline_nosc" arguments=""/>
<action>join("",$item[1],@{$item[2]},$item[3])</action>
</production>
</rule>
<rule id="shell" inline="no">
<production>
<regexp>!\s*</regexp>
<directive type="commit"/>
<regexp>.*</regexp>
<action>[[<lineinfo/>,'sh_noev',$item[3]]]</action>
</production>
<production>
<directive type="error-if-committed">Parse error near: "! }.substr($text,0,40).qq{ ..."</directive>
<directive type="reject"/>
</production>
</rule>
<!-- ================== STATEMENTS ====================== -->
<rule id="elsif_block" name="elsif" inline="no">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="exp" arguments=""/>
<ruleref ref="block" arguments=""/>
<ruleref ref="elsif_block" arguments=""/>
<action>[[$item[3],$item[4]],@{$item[5]}]</action>
</production>
<production>
<regexp>(?!elsif)</regexp>
<action>[]</action>
</production>
<production>
<directive type="uncommit"/>
<directive type="error">Parse error near keyword elsif: "}.substr($text,0,40).qq{ ..."</directive>
</production>
</rule>
<rule id="else_block" name="else" inline="no">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="block" arguments=""/>
<action>[[undef,$item[3]]]</action>
</production>
<production>
<regexp>(?!else)</regexp>
<action>[]</action>
</production>
<production>
<directive type="uncommit"/>
<directive type="error">Parse error near keyword else: "}.substr($text,0,40).qq{ ..."</directive>
</production>
</rule>
<!-- try/catch -->
<rule id="local_var" inline="no">
<production>
<group rep="?">
<production>
<regexp>(local|my)\s</regexp>
</production>
</group>
<ruleref ref="variable" arguments=""/>
<action>[$item[2],@{$item[1]}]</action>
</production>
</rule>
<rule id="try_catch" type="command" name="try" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="block" arguments=""/>
<string>catch</string>
<ruleref ref="local_var" rep="?" arguments=""/>
<ruleref ref="block" arguments=""/>
<action>[<lineinfo/>,'try_catch',$item[3],$item[6],@{$item[5]}]</action>
</production>
<documentation sections="Flow">
<usage>try <xref linkend="block"/> catch [[local|my] <xref linkend="varname"/>] <xref linkend="block"/></usage>
<shortdesc>try/catch statement</shortdesc>
<description>
<para>
Execute the <xref linkend="block"/> following the
<literal>try</literal> keyword. If an error or exception
occurs during the evaluation, execute the
<literal>catch</literal> <xref linkend="block"/>. If the
<literal>catch</literal> keyword is followed by a
variable (possibly localized for the following block using
<xref linkend="my_command"/> or <xref linkend="local_command"/>)
and the <literal>try</literal> block fails
with an exception, the error message of
the exception is stored to the variable before the
<literal>catch</literal> block is executed.
</para>
<para>
The <xref linkend="throw_command"/> command as well as an equivalent
Perl construction <literal>perl { die "error message" }</literal> allow user to throw custom exceptions.
</para>
<para>
Unless exception is raised or error occurs, this command
returns the return value of the <literal>try</literal> block;
otherwise it returns the return value of
the <literal>catch</literal> block.
</para>
<example>
<title>Handle parse errors</title>
<code>try {
<tab count="1"/>$doc:=open --format xml $input;
} catch {
<tab count="1"/>try {
<tab count="2"/>echo "XML parser failed, trying HTML";
<tab count="2"/>$doc := open --format html $input;
<tab count="1"/>} catch my $error {
<tab count="2"/>echo "Stopping due to errors: $error";
<tab count="2"/>exit 1;
<tab count="1"/>}
}
</code>
</example>
</description>
<see-also>
<ruleref ref="throw_command" arguments=""/>
</see-also>
</documentation>
</rule>
<!-- if -->
<rule id="if" type="command" name="if" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="exp" arguments=""/>
<ruleref ref="block" arguments=""/>
<ruleref ref="elsif_block" arguments=""/>
<ruleref ref="else_block" arguments=""/>
<action>[<lineinfo/>,'if_statement',[$item[3],$item[4]],@{$item[5]},@{$item[6]}]</action>
</production>
<documentation sections="Flow">
<usage>if <xref linkend="exp"/> <xref linkend="command"/>
</usage>
<usage>
if <xref linkend="exp"/>
<xref linkend="block"/> [ elsif <xref linkend="block"/> ]* [ else <xref linkend="block"/> ]
</usage>
<shortdesc>if statement</shortdesc>
<description>
<para>
Executes <xref linkend="command"/> or <xref linkend="block"/> if a given <xref linkend="exp"/>
expression evaluates to a non-emtpty node-list, true
boolean-value, non-zero number or non-empty literal. If
the first expression fails, then
<literal>elsif</literal> conditions are tested (if any) and the
<xref linkend="block"/> corresponding to the first one of
them which is true is executed. If none of the conditions is satisfied, an
optional <literal>else</literal> <xref linkend="block"/> is executed.
</para>
<example>
<title>Display node type</title>
<code>def node_type %n {
<tab count="1"/>foreach (%n) {
<tab count="2"/>if ( . = self::* ) { # XPath trick to check if . is an element
<tab count="3"/>echo 'element';
<tab count="2"/>} elsif ( . = ../@* ) { # XPath trick to check if . is an attribute
<tab count="3"/>echo 'attribute';
<tab count="2"/>} elsif ( . = ../processing-instruction() ) {
<tab count="3"/>echo 'pi';
<tab count="2"/>} elsif ( . = ../text() ) {
<tab count="3"/>echo 'text';
<tab count="2"/>} elsif ( . = ../comment() ) {
<tab count="3"/>echo 'comment'
<tab count="2"/>} else { # well, this should not happen, but anyway, ...
<tab count="3"/>echo 'unknown-type';
<tab count="2"/>}
<tab count="1"/>}
}
</code>
</example>
<example>
<title>Check a environment variable</title>
<code>if { defined($ENV{HOME}) } lcd { $ENV{HOME} }</code>
</example>
</description>
</documentation>
</rule>
<rule id="if_command" name="if" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="exp" arguments=""/>
<ruleref ref="command" arguments=""/>
<action>[<lineinfo/>,'if_statement',[$item[3],[$item[4]]]]</action>
</production>
</rule>
<!-- unless -->
<rule id="unless" type="command" name="unless" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="exp" arguments=""/>
<ruleref ref="block" arguments=""/>
<ruleref ref="else_block" rep="?" arguments=""/>
<action>[<lineinfo/>,'unless_statement',$item[3],$item[4],@{$item[5]}]</action>
</production>
<documentation sections="Flow">
<usage>unless <xref linkend="exp"/>
<xref linkend="command"/>
</usage>
<usage>
unless <xref linkend="exp"/>
<xref linkend="block"/> [ else <xref linkend="block"/> ]
</usage>
<shortdesc>negated if statement</shortdesc>
<description>
<para>Like if but negating the result of the expression.
Also, unlike if, <literal>unless</literal> has no
<literal>elsif</literal> block.
</para>
</description>
<see-also>
<ruleref ref="if" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="unless_command" name="unless" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="exp" arguments=""/>
<ruleref ref="command" arguments=""/>
<action>[<lineinfo/>,'unless_statement',$item[3],[$item[4]]]</action>
</production>
</rule>
<!-- while -->
<rule id="while_command" name="while" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="exp" arguments=""/>
<ruleref ref="command" arguments=""/>
<action>[<lineinfo/>,'while_statement',$item[3],[$item[4]]]</action>
</production>
</rule>
<rule id="while" type="command" name="while" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="exp" arguments=""/>
<ruleref ref="block" arguments=""/>
<action>[<lineinfo/>,'while_statement',$item[3],$item[4]]</action>
</production>
<documentation sections="Flow">
<usage>while <xref linkend="exp"/> <xref linkend="block"/></usage>
<shortdesc>simple while loop</shortdesc>
<description>
<para> Execute the <xref linkend="command"/> or <xref linkend="block"/> as long as
the given <xref linkend="exp"/> evaluates to a non-emtpty
node-list, true boolean-value, non-zero number or
non-empty literal.
</para>
<example>
<title>The commands in this example do the same thing</title>
<code>xsh> <userinput>while /table/row remove /table/row[1];</userinput>
xsh> <userinput>remove /table/row;</userinput>
</code>
</example>
</description>
</documentation>
</rule>
<!-- do -->
<rule id="do_command" type="command" name="do" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="block" arguments=""/>
<action>[<lineinfo/>,'run_commands',$item[3],0]</action>
</production>
<documentation sections="Flow">
<usage>do <xref linkend="block"/></usage>
<shortdesc>execute a given block of commands</shortdesc>
<description>
<para>
Execute <xref linkend="block"/>.
This command is probably only useful when one wants to
redirect output of more than one command.
</para>
</description>
<see-also>
<ruleref ref="block"/>
</see-also>
</documentation>
</rule>
<rule id="eval_command" type="command" name="eval" inline="yes">
<command minargs="1" maxargs="1" func="run_exp"/>
<documentation sections="Flow">
<usage>eval <xref linkend="exp"/></usage>
<shortdesc>evaluate given expression as XSH commands</shortdesc>
<description>
<para>NOTE: This command has very different behavior from XSH1,
where it used to be an alias for <xref linkend="perl_command"/>.
</para>
<para>This command first evaluates a given <xref linkend="exp"/> to obtain a string,
then evaluates this string as &XSH; code in the current context, returning
the return value of the last evaluated command.
This command raises
an exception if either <xref linkend="exp"/> evaluates to
invalid &XSH; code or if evaluating the code raises an exception.
</para>
<example>
<title>Evaluate "in-line" XSH snippets within a XML document</title>
<code>foreach //inline-xsh eval .;</code>
</example>
</description>
</documentation>
</rule>
<!-- foreach -->
<rule id="local_var_in" inline="no">
<production>
<ruleref ref="local_var" arguments=""/>
<string>in</string>
<action>$item[1]</action>
</production>
</rule>
<rule id="foreach_command" name="foreach" inline="yes">
<aliases>
<alias name="for"/>
</aliases>
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="local_var_in" rep="?" arguments=""/>
<ruleref ref="exp" arguments=""/>
<ruleref ref="command" arguments=""/>
<action>[<lineinfo/>,'foreach_statement',$item[4],[$item[5]],@{$item[3]}]</action>
</production>
</rule>
<rule id="foreach" type="command" name="foreach" inline="yes">
<aliases>
<alias name="for"/>
</aliases>
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="local_var_in" rep="?" arguments=""/>
<ruleref ref="exp" arguments=""/>
<ruleref ref="block" arguments=""/>
<action>[<lineinfo/>,'foreach_statement',@item[4,5],@{$item[3]}]</action>
</production>
<documentation sections="Flow">
<usage>foreach <xref linkend="exp"/>
<xref linkend="command"/>|<xref linkend="block"/>
</usage>
<usage>foreach [my|local] <xref linkend="varname"/> in <xref linkend="exp"/>
<xref linkend="command"/>|<xref linkend="block"/>
</usage>
<shortdesc>loop iterating over a node-list or a perl array</shortdesc>
<description>
<para>
Evaluate given <xref linkend="exp" /> to a node-list and for each
resulting node execute given <xref linkend="command"/> or
<xref linkend="block"/>. If used without a loop <xref
linkend="varname"/>, the loop temporarily sets current node to
the node being processed. Otherwise, the processed node is assigned
to the loop variable.
</para>
<para>
The <xref linkend="exp" /> may be <xref linkend="xpath"/> as well as
a <xref linkend="perl_code"/>.
In the latter case, if used without a loop variable,
the loop automatically converts Perl objects to
nodes. No conversion is performed when
a loop variable is used.
</para>
<example>
<title>Move all employee sub-elements in a company element
into the first staff subelement of the same company</title>
<code>xsh> <userinput>foreach //company xmove employee into staff[1];</userinput></code>
</example>
<example>
<title>List content of all XML files in current directory</title>
<code>xsh> <userinput>foreach my $filename in { glob('*.xml') } {
<tab/>$f := open $filename;
<tab/>do_something $f;
}</userinput>
</code>
</example>
</description>
</documentation>
</rule>
<!-- def -->
<rule id="undef" type="command" name="undef" inline="no">
<aliases>
<alias name="undefine"/>
</aliases>
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<regexp>\$?[a-zA-Z_][a-zA-Z0-9_]*</regexp>
<action>
[<lineinfo/>,'undefine',$item[3]];
</action>
</production>
<documentation sections="Flow">
<usage>undef [<xref linkend="subname"/> | <xref linkend="varname"/>]</usage>
<shortdesc>undefine sub-routine or variable</shortdesc>
<description>
<para>
This command can be used to undefine previously defined
&XSH; subroutines and variables.
</para>
</description>
<see-also>
<ruleref ref="close_command"/>
<ruleref ref="def"/>
</see-also>
</documentation>
</rule>
<rule id="def" type="command" name="def" inline="yes">
<aliases>
<alias name="define"/>
</aliases>
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="ID" arguments=""/>
<action>XML::XSH2::Functions::is_command($item[3])?undef:1</action>
<ruleref ref="variable" rep="s?" arguments=""/>
<ruleref ref="block" arguments=""/>
<action>
[<lineinfo/>,'def',$item[3],$item[6],$item[5]]
</action>
</production>
<documentation sections="Flow">
<usage>def <xref linkend="subname"/> [<xref linkend="varname"/> ...] <xref linkend="block"/>
</usage>
<shortdesc>sub-routine declaration</shortdesc>
<description>
<para>
Define a new &XSH; sub-routine named <xref linkend="subname"/>.
The subroutine may require zero or more parameters.
These are declared as a
whitespace-separated list of <emphasis>parametric
variables</emphasis>. The body of the
subroutine is specified as a <xref linkend="block"/>.
</para>
<para>A sub-routine can be invoked directly by its name
followed by its arguments
just as any &XSH; command, or indirectly
using the <xref linkend="call_command" />
command followed by an expression evaluating
to the routine name and sub-routine arguments.
Sub-routine arguments can be arbitrary
expressions. These expressions are evaluated
<emphasis>prior</emphasis> the sub-routine's code
execution and are assigned to the sub-routine's
parametric variables in the respective order.
The number of parameter variables in a sub-routine
definition and the number of arguments in a call to it
must match.
Calling a sub-routine with less or more arguments
than declared is a run-time error.
</para>
<para>
Parametric variables are lexical
variables within the sub-routine body as if they
were declared with <xref linkend="my_command" />.
</para>
<para>
Note that a subroutine has to be defined before it is
first called (in terms of execution -- depending on the structure
of the program, the actual definition of the sub-routine
must not necessarily precede all references to it).
</para>
<example>
<code>def l3 $nodes {
<tab count="1"/>ls --depth 3 $nodes; # list given nodes upto depth 3
}
l3 //chapter; # direct call
$subref = 'l3';
call $subref //chapter; # in-direct call
</code>
</example>
<example>
<title>Commenting and un-commenting pieces of document</title>
<code>def comment
<tab count="1"/><tab count="1"/>$n # nodes to move to comments
<tab count="1"/><tab count="1"/>$mark # maybe some handy mark to recognize such comments
{
<tab count="1"/>foreach $n {
<tab count="1"/><tab count="1"/>if ( . = ../@* ) {
<tab count="1"/><tab count="1"/><tab count="1"/>echo "Warning: attribute nodes are not supported!";
<tab count="1"/><tab count="1"/>} else {
<tab count="1"/><tab count="1"/><tab count="1"/>echo "Commenting out:";
<tab count="1"/><tab count="1"/><tab count="1"/>ls --depth 0 .;
<tab count="1"/><tab count="1"/><tab count="1"/>add comment concat($mark,xsh:serialize(.)) replace .;
<tab count="1"/><tab count="1"/>}
<tab count="1"/>}
}
def uncomment $n $mark {
<tab count="1"/>foreach $n {
<tab count="1"/><tab count="1"/>if (. = ../comment()) { # is this node a comment node
<tab count="1"/><tab count="1"/><tab count="1"/>local $string = substring-after(.,"$mark");
<tab count="1"/><tab count="1"/><tab count="1"/>add chunk $string replace .;
<tab count="1"/><tab count="1"/>} else {
<tab count="1"/><tab count="1"/><tab count="1"/>echo "Warning: Ignoring non-comment node:";
<tab count="1"/><tab count="1"/><tab count="1"/>ls --depth 0 .;
<tab count="1"/><tab count="1"/>}
<tab count="1"/>}
}
# comment out all chapters with no paragraphs
comment //chapter[not(para)] "COMMENT-NOPARA";
# uncomment all comments stamped with COMMENT-NOPARA
$mark="COMMENT-NOPARA";
uncomment //comment()[starts-with(.,"$mark")] $mark;
</code>
</example>
</description>
<see-also>
<ruleref ref="call_command" arguments=""/>
<ruleref ref="return_command" arguments=""/>
<ruleref ref="my_command" arguments=""/>
<ruleref ref="local_command" arguments=""/>
</see-also>
</documentation>
</rule>
<!-- ================== COMMANDS ====================== -->
<rule id="assign_command" type="command" name="assign" inline="yes">
<production>
<regexp>assign\b|(?:local\b|my\b)?(?=\s*\$[a-zA-Z_][a-zA-Z0-9_]*\s*\s*(?:[\-\+\*\/%x.]|\|\||\&\&)?:?=)</regexp>
<directive type="commit"></directive>
<ruleref ref="variable" arguments=""/>
<group>
<production>
<regexp>(?:[\-\+\*\/%x.]|\|\||\&\&)?=</regexp>
<directive type="commit"/>
<ruleref ref="loose_exp" arguments=""/>
<action>['xpath_assign',$item[3],$item[1]]</action>
</production>
<production>
<regexp>\s*(?:[\-\+\*\/%x.]|\|\||\&\&)?:=</regexp>
<ruleref ref="command"/>
<action>['command_assign',$item[2],$item[1]]</action>
</production>
</group>
<action>[<lineinfo/>,@{$item[4]},$item[1],$item[3]]</action>
</production>
<documentation sections="Variables">
<usage>[assign] <xref linkend="varname"/> = <xref
linkend="exp"/></usage>
<usage>[assign] <xref linkend="varname"/> := <xref linkend="command"/></usage>
<usage>[assign]
<xref linkend="varname"/> [-= | += | *= | /= | %= | x= | .= | ||= | &&= ] <xref linkend="exp"/></usage>
<usage>[assign]
<xref linkend="varname"/> [-:= | +:= | *:= | /:= | %:= | x:= | .:= | ||:= | &&:= ] <xref linkend="command"/></usage>
<shortdesc>variable assignment</shortdesc>
<description>
<para>Evaluate the expression (= assignment)
or command (:= assignment) on the right
side of the assignment and store the result in
a given variable. Optionally a Perl operator
(- subtraction, + addition, * multiplication,
/ division, % modulo, x repeat string n-times,
. concatenation, || logical OR, && logical AND)
can precede the assignment, in which
case the variable is assigned the result
of applying given operator on its previous
value and the value of the right side of the assignment.
</para>
<example>
<title>Assign XPath (node-set, string), or Perl results</title>
<code>xsh> <userinput>$a=chapter/title;</userinput>
xsh> <userinput>$b="hallo world";</userinput>
xsh> <userinput>$c={ `uname` };</userinput>
xsh> <userinput>ls $a;</userinput>
</code>
</example>
<example>
<title>Arithmetic expressions (XPath)</title>
<code>xsh> <userinput>$a=5*100 </userinput> # assign 500 to $a
xsh> <userinput>$a += 20 </userinput> # add 20 to $a
xsh> <userinput>$a = (($a+5) div 10) </userinput>
</code>
</example>
<example>
<title>Arithmetic expressions (Perl)</title>
<code>xsh> <userinput>$a={ 5*100 } </userinput>
xsh> <userinput>$a = { join ';', split //,"hallo" } </userinput> # assigns "h;a;l;l;o" to $a
</code>
</example>
<example>
<title>Command result assignment</title>
<code>xsh> <userinput>$doc := open "file.xml" </userinput> # open a document
xsh> <userinput>$copies := xcopy //foo into //bar </userinput> # copy elements and store the copies
xsh> <userinput>$wrappers := wrap "wrapper" $copies </userinput> # wrap each node from $copies to a new element "wrapper" and store the wrapping elements
</code>
</example>
</description>
<see-also>
<ruleref ref="var_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="my_command" type="command" name="my" inline="yes">
<production>
<selfref sep="yes"/>
<ruleref ref="variable" rep="s" arguments=""/>
<action>[<lineinfo/>,'store_lex_variables',0,@{$item[2]}]</action>
</production>
<documentation>
<usage>my <xref linkend="varname"/> [$var2 ...];</usage>
<usage>my <xref linkend="varname"/> = <xref
linkend="exp"/>;</usage>
<shortdesc>Create a new lexically scoped variable</shortdesc>
<description>
<para>Same as in Perl: a "my" declares the listed variables to be local
(lexically) to the enclosing block, or sub-routine.
</para>
</description>
<see-also>
<ruleref ref="local_command"/>
</see-also>
</documentation>
</rule>
<rule id="local_command" type="command" name="local" inline="yes">
<production>
<selfref sep="yes"/>
<ruleref ref="variable" rep="s" arguments=""/>
<action>[<lineinfo/>,'make_local',@{$item[2]}]</action>
</production>
<documentation sections="Variables">
<usage>local <xref linkend="varname"/> = <xref linkend="xpath"/></usage>
<usage>local <xref linkend="varname"/> [ <xref linkend="varname"/> ... ] </usage>
<shortdesc>temporarily assign new value to a variable</shortdesc>
<description>
<para>
This command acts in a very similar way as
<xref linkend="assign_command"/> does, except
that the variable assignment is done temporarily
and lasts only for the rest of its enclosing
<xref linkend="block"/> or subroutine. At the end of the
enclosing block or subroutine, the original value
is restored. This also reverts any later usual assignments to the
variable done occurring before the end of the block.
This command may also be used without the assignment part.
</para>
<para>Note, that the variable itself remains
global in the sense that it is still visible to any
subroutine called subsequently from the same block.
Unlike <xref linkend="my_command"/>
declaration, it does not <emphasis>create</emphasis> a
new lexically scoped variable.
</para>
<para>
Hint for Perl programmers: <literal>local</literal>
in &XSH; works exactly as <literal>local</literal>
in Perl.
</para>
</description>
<see-also>
<ruleref ref="assign_command" arguments=""/>
<ruleref ref="my_command" arguments=""/>
<ruleref ref="def" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="options_command" type="command" name="settings" inline="yes">
<command maxargs="0" func="list_flags">
<param name="variables" short="v"/>
</command>
<documentation sections="Information Configuration">
<usage>settings</usage>
<shortdesc>list current settings using &XSH; syntax</shortdesc>
<description>
<para>List current values of all &XSH; settings (such as
validation flag or query-encoding).</para>
<para><literal>--variables</literal> or <literal>:v</literal>
flag enforces syntax which makes use of variable assignments.
Otherwise, settings are listed in the form of XSH commands.
</para>
<example>
<title>Store current settings in your .xsh2rc</title>
<code>xsh> <userinput>settings | cat > ~/.xsh2rc</userinput></code>
</example>
</description>
</documentation>
</rule>
<rule id="list_defs_command" type="command" name="defs" inline="yes">
<command maxargs="0" func="list_defs"/>
<documentation sections="Information">
<usage>defs</usage>
<shortdesc>list all user-defined subroutines</shortdesc>
<description>
<para>List names and parametric variables for all user-defined &XSH; subroutines.</para>
</description>
<see-also>
<ruleref ref="def" arguments=""/>
<ruleref ref="var_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="ifinclude_command" type="command" name="ifinclude" inline="yes">
<command minargs="1" maxargs="1" func="include" extraargs="1">
<param name="encoding" short="e" type="string" argument="enc_string"/>
</command>
<documentation sections="Flow">
<usage>ifinclude [--encoding|:e <xref linkend="enc_string"/>] <xref linkend="filename"/></usage>
<shortdesc>conditionally include another &XSH; source in current position</shortdesc>
<description>
<para>
Unless the file <xref linkend="filename"/> has already
been included using either <xref linkend="include_command"/> of
<xref linkend="ifinclude_command"/>, load the file and
execute it as a &XSH; script.
</para>
<para>Use <literal>--encoding</literal> or <literal>:e</literal>
parameter to specify character encoding used in
the included file.
</para>
</description>
<see-also>
<ruleref ref="include_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="include_command" type="command" name="include" inline="yes">
<aliases>
<alias name="." regexp="\."/>
</aliases>
<command minargs="1" maxargs="1" func="include">
<param name="encoding" short="e" type="string"
argument="enc_string"/>
</command>
<documentation sections="Flow">
<usage>include [--encoding|:e <xref linkend="enc_string"/>] <xref linkend="filename"/></usage>
<shortdesc>include another &XSH; source in current position</shortdesc>
<description>
<para>
Load a file named <xref linkend="filename"/> and execute it as a &XSH;
script.
</para>
<para>Use <literal>--encoding</literal> or <literal>:e</literal>
parameter to specify character encoding used in
the included file.
</para>
</description>
<see-also>
<ruleref ref="ifinclude_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="apropos_command" type="command" name="apropos" inline="yes">
<command minargs="1" maxargs="1" func="apropos">
<param name="regexp" short="r"/>
<param name="fulltext" short="f"/>
</command>
<documentation sections="Information">
<usage>apropos [--fulltext] [--regexp] <xref linkend="exp"/></usage>
<shortdesc>search the documentation</shortdesc>
<description>
<para>
Print all help topics containing given expression
in their short description. The
<literal>--fulltext</literal> flag forces
the search to be performed over the full text
of help.
<literal>--regexp</literal> indicates,
that the given <xref linkend="exp"/>
is a regular expression instead of a literal string.
</para>
</description>
</documentation>
</rule>
<rule id="help_command" type="command" name="help" inline="yes">
<command minargs="0" maxargs="1" func="help"/>
<documentation sections="Information">
<usage>help <xref linkend="command"/>|argument-type|xsh:xpath-function</usage>
<shortdesc>on-line documentation</shortdesc>
<description>
<para>Print help on a given command, argument type or
XPath extension function
(use <literal>xsh:</literal> as a prefix to XPath extensions
function names, e.g <literal>help xsh:id2</literal>).
</para>
</description>
</documentation>
</rule>
<rule id="exec_command" type="command" name="exec" inline="yes">
<aliases>
<alias name="system"/>
</aliases>
<command minargs="1" func="sh"/>
<documentation sections="Perl_shell">
<usage>exec <xref linkend="exp"/> [<xref linkend="exp"/> ...]</usage>
<shortdesc>execute a shell command</shortdesc>
<description>
<para>This command executes given <xref linkend="exp"/>(s)
as a system command and returns the exit code.
</para>
<example>
<title>Count words in "hallo wold" string, then print name
of your machine's operating system.</title>
<code>exec echo hallo world; # prints hallo world
exec "echo hallo word" | wc; # counts words in hallo world
exec uname; # prints operating system name
</code>
</example>
</description>
</documentation>
</rule>
<rule id="xslt_command" type="command" name="xslt" inline="yes">
<aliases>
<alias name="transform"/>
<alias name="xsl"/>
<alias name="xsltproc"/>
<alias name="process"/>
</aliases>
<command minargs="1" func="xslt">
<param name="doc" short="d"/>
<param name="string" short="s"/>
<param name="compile" short="c"/>
<param name="precompiled" short="p"/>
</command>
<documentation sections="Manipulation">
<usage>$result := xslt [--doc|:d | --precompiled|:p] [--string] <xref linkend="exp"/> [<xref
linkend="document"/> name=<xref linkend="xpath"/> [name=<xref linkend="xpath"/> ...]]</usage>
<usage>$pre_compiled := xslt [--compile|:c] <xref linkend="exp"/></usage>
<shortdesc>compile a XSLT stylesheet and/or transform a document with XSLT</shortdesc>
<description>
<para>
This function compiles a given XSLT stylesheet
and/or transforms a given document with XSLT.
</para>
<para>A XSLT stylesheet is specified in the
first argument either as a file name (default), or as a
document (<literal>--doc</literal> or
<literal>:d</literal>), or as a precompiled XSLT
stylesheet object (<literal>--precompiled</literal> or
<literal>:p</literal> - see <literal>--compile</literal>
above).</para>
<para>
If <literal>--compile</literal> or <literal>:c</literal>
is used, compile a given XSLT stylesheet and return a
compiled XSLT stylesheet object. This object can be later
passed as a XSLT stylesheet to <literal>xslt
--precompiled</literal>.
</para>
<para>
Without <literal>--compile</literal> or
<literal>:c</literal>, transform a given <xref
linkend="document"/> (or - if used with
only the stylesheet argument - the current document)
using a given XSLT stylesheet and
return the result.</para>
<para>
All arguments following the second (document) argument are
considered to be stylesheet parameters and (after
expanding <literal>${...}</literal> interpolators) are
directly passed to the XSLT engine without being evaluated
by &XSH;. All stylesheet parameters should be of the form
<literal>name=<xref linkend="xpath"/></literal> (possibly
in brackets).
</para>
<example>
<title>Process current document with XSLT</title>
<code>$result := xslt stylesheet.xsl . font='14pt' color='red'</code>
</example>
<example>
<title>Same for several documents, reusing the XSLT stylesheet</title>
<code>$xslt := xslt --compile stylesheet.xsl;
foreach my $file in {qw(f1.xml f2.xml f3.xml)} {
<tab/>save --file {"out_$file"} &{xslt --precompiled $xslt &{ open $file } font='14pt' color='red'};
}
</code>
</example>
</description>
</documentation>
</rule>
<rule id="param" inline="no">
<production>
<regexp>[^=\s]+</regexp>
<string>=</string>
<ruleref ref="exp"/>
<action>[$item[1],$item[3]]</action>
</production>
</rule>
<rule id="files_command" type="command" name="documents" inline="yes">
<aliases>
<alias name="files"/>
<alias name="docs"/>
</aliases>
<command maxargs="0" func="files"/>
<documentation sections="Information Documents">
<usage>documents</usage>
<shortdesc>display a list of open documents</shortdesc>
<description>
<para>Try to identify open documents and list their URIs
and variables that contain them.
</para>
</description>
<see-also>
<ruleref ref="open_command" arguments=""/>
<ruleref ref="close_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="set_filename_command" type="command" name="set_filename" inline="yes">
<command minargs="1" maxargs="2" func="set_filename"/>
<documentation sections="Documents">
<usage>set_filename <xref linkend="exp"/> [<xref linkend="document"/>]</usage>
<shortdesc>change filename or URL associated with a document</shortdesc>
<description>
<para>Changes filename or URL associated with a
given document (or the current document, if only
one argument is specified). Document filename is initialized
by the <xref linkend="open_command" /> command
and used e.g. by <xref linkend="save_command"/>.
It can be queried in XPath expressions using the
<xref linkend="filename_function"/> function.
</para>
</description>
<see-also>
<ruleref ref="open_command" arguments=""/>
<ruleref ref="save_command" arguments=""/>
<ruleref ref="filename_function" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="var_command" type="command" name="variables" inline="yes">
<aliases>
<alias name="vars"/>
<alias name="var"/>
</aliases>
<command maxargs="0" func="variables"/>
<documentation sections="Information">
<usage>variables</usage>
<shortdesc>list global variables</shortdesc>
<description>
<para>List all global variables and their current values.</para>
</description>
<see-also>
<ruleref ref="files_command" arguments=""/>
<ruleref ref="list_defs_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="copy_command" type="command" name="copy" inline="yes">
<aliases>
<alias name="cp"/>
</aliases>
<command minargs="3" maxargs="3" func="copy" extraargs="0">
<param name="respective" short="r"/>
</command>
<documentation sections="Manipulation">
<usage>copy [--respective|:r] <xref linkend="exp"/> <xref linkend="loc"/> <xref
linkend="exp"/></usage>
<usage>$results := copy [--respective|:r] <xref linkend="exp"/> <xref linkend="loc"/> <xref linkend="exp"/></usage>
<shortdesc>copy nodes (in the one-to-one mode)</shortdesc>
<description>
<para>
Copies nodes in the first node-list <xref linkend="exp"/>
(source nodes) to the destinations determined by the
the <xref linkend="loc"/> directive
applied to nodes in the second node-list <xref linkend="exp"/>
(target nodes). If the source node-list contains
more than one node, than N'th node in the source node-list
is copied to the location relative to the N'th node in
the target node-list.
</para>
<para>
If <literal>--respective|:r</literal> option
is used, then the target node-list <xref linkend="exp"/>
is evaluated in the context of the source node
being copied.
</para>
<para>Possible values for <xref linkend="loc"/> are:
<literal>after</literal>, <literal>before</literal>,
<literal>into</literal>, <literal>replace</literal>,
<literal>append</literal> and <literal>prepend</literal>. The first
three location directives cause making a copy of the source nodes
after, before, and within (as the last child-node) the target
nodes, respectively.
If <literal>replace</literal> location directive is used,
source node are copied before the respective
target nodes and target nodes are removed.
The <literal>append</literal> and <literal>prepend</literal>
location directives allow,
depending on the destination node type,
either inserting copies of the
source nodes as the first or last child nodes of
a destination element or appending/prepending
destination node data in case of non-element destination nodes.
See <xref linkend="loc"/> argument type
for more detail.
</para>
<para>The command returns a node-list consisting of
the copies of all source nodes created by the command.
</para>
<para>Despite the fact the command is named "copy",
nodes resulting from copying
the source nodes may pass through certain type conversion before
they are inserted at the appointed destinations. This, however,
only happens in cases where the types of the source and target
nodes are not compatible with the location
directive. See <xref linkend="loc" /> argument
type for more detail.
</para>
<para>Note that &XSH; refuses to create multiple top-level
elements using <literal>copy</literal>,
<xref linkend="move_command"/> and similar commands.</para>
<example>
<title>Replace living-thing elements in the document b with copies
of the corresponding creature elements from the document $a.</title>
<code>xsh> <userinput>copy $a//creature replace $b//living-thing</userinput></code>
</example>
<example>
<title>Copy every element into itself</title>
<code>xsh> <userinput>copy --respective $a//* into .</userinput></code>
<code>xsh> <userinput>copy $a//* into $a//*</userinput> #same as
above</code>
</example>
</description>
<see-also>
<ruleref ref="xcopy_command" arguments=""/>
<ruleref ref="move_command" arguments=""/>
<ruleref ref="xmove_command" arguments=""/>
<ruleref ref="insert_command" arguments=""/>
<ruleref ref="xinsert_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="xcopy_command" type="command" name="xcopy" inline="yes">
<aliases>
<alias name="xcp"/>
</aliases>
<command minargs="3" maxargs="3" func="copy" extraargs="1">
<param name="respective" short="r"/>
<param name="preserve-order" short="p"/>
</command>
<documentation sections="Manipulation">
<usage>xcopy [--respective|:r] [--preserve-order|:p] <xref linkend="exp"/> <xref linkend="loc"/> <xref linkend="exp"/></usage>
<shortdesc>copy nodes (in the all-to-every mode)</shortdesc>
<description>
<para>
xcopy is similar to <xref linkend="copy_command"/>, but copies
<emphasis>all</emphasis> nodes in the first node-list
<xref linkend="exp"/> to <emphasis>all</emphasis>
destinations determined by the
<xref linkend="loc"/> directive relative
to the second node-list <xref linkend="exp"/>.
See <xref linkend="copy_command"/> for detailed description of
<literal>xcopy</literal> arguments.
</para>
<para>
If <literal>--respective|:r</literal> option
is used, then the target node-list <xref linkend="exp"/>
is evaluated in the context of the source node
being copied.
</para>
<para>
The <literal>--preserve-order|:p</literal> option can be
used to ensure that the copied nodes are in the same
relative order as the corresponding source nodes.
Otherwise, if <xref linkend="loc"/> is
<literal>after</literal> or <literal>prepend</literal>,
the relative order of the copied nodes will be reversed,
because source nodes are placed to the target location one
by one.
</para>
<example>
<title>Copy all middle-earth creatures within the document $a
into every world of the document $b.</title>
<code>xsh> <userinput>xcopy $a/middle-earth/creature into $b//world</userinput></code>
</example>
</description>
<see-also>
<ruleref ref="copy_command" arguments=""/>
<ruleref ref="move_command" arguments=""/>
<ruleref ref="xmove_command" arguments=""/>
<ruleref ref="insert_command" arguments=""/>
<ruleref ref="xinsert_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="cd_command" type="command" name="lcd" inline="yes">
<aliases>
<alias name="chdir"/>
</aliases>
<command maxargs="1" func="cd"/><documentation sections="Perl_shell">
<usage>lcd <xref linkend="exp"/></usage>
<shortdesc>change system working directory</shortdesc>
<description>
<para>
Changes the filesystem working directory
to <xref linkend="exp"/>, if possible.
If <xref linkend="exp"/> is omitted, changes to the directory
specified in HOME environment variable, if set; if not,
changes to the directory specified by LOGDIR environment
variable.
</para>
</description>
</documentation>
</rule>
<rule id="insert_command" type="command" name="insert" inline="yes">
<aliases>
<alias name="add"/>
</aliases>
<command minargs="4" maxargs="4" func="insert" extraargs="0">
<param name="namespace" short="n" type="exp" argument="exp"/>
</command>
<documentation sections="Manipulation">
<usage>insert [--namespace|:n <xref linkend="exp"/>] <xref linkend="nodetype"/> <xref linkend="exp"/> <xref linkend="loc"/> <xref linkend="xpath"/>
</usage>
<shortdesc>create a node in on a given target location</shortdesc>
<description>
<para>
Works just like <xref linkend="xinsert_command"/>,
except that the new node is attached
only the first node matched.
</para>
</description>
<see-also>
<ruleref ref="xinsert_command" arguments=""/>
<ruleref ref="move_command" arguments=""/>
<ruleref ref="xmove_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="wrap_command" type="command" name="wrap" inline="yes">
<command minargs="2" maxargs="2" func="wrap">
<param name="namespace" short="n" type="exp" argument="exp"/>
<param name="while" short="W" type="xpath" argument="exp"/>
<param name="until" short="U" type="xpath" argument="exp"/>
<param name="skip-whitespace" short="w"/>
<param name="skip-comments" short="c"/>
<param name="skip-pi" short="p"/>
<param name="inner" short="i"/>
</command>
<documentation sections="Manipulation">
<usage>wrap [--namespace <xref linkend="exp"/>]
[ [--inner] | [--while|:W <xref linkend="exp"/>] [--until|:U <xref linkend="exp"/>]
[--skip-whitespace|:w] [--skip-comments|:c] [--skip-pi|:p] ]
<xref linkend="exp"/> <xref linkend="xpath"/>
</usage>
<shortdesc>wrap given nodes into elements</shortdesc>
<description>
<para>
For each node matching the <xref linkend="xpath"/> argument,
this command creates a new element node according to a
given <xref linkend="exp"/> (in the same
way as <xref linkend="xinsert_command"/> does)
which replaces the matching node, and
moves the matching node into this newly created element.
If namespace <xref linkend="exp"/> is given,
the namespace is applied on the created element.
The command returns a node-list consisting
of the elements created.
</para>
<para>
With <literal>--inner</literal> (or <literal>:i</literal>)
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 <literal>--while</literal>
and <literal>--until</literal>, which we describe next.
</para>
<para>
<literal>--while</literal> (<literal>:W</literal>)
and/or <literal>--until</literal> (<literal>:U</literal>)
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 <literal>--until</literal>, or
before a first following node not matching the expression
of <literal>--while</literal>, 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 <xref
linkend="wrap_command"/> even if included in the node-list
produced by the <xref
linkend="xpath"/> argument. This allows to easily wrap
certain adjacent elements without worrying about some
elements being wrapped multiple times
(for example, <literal>wrap :W x y //x</literal> wraps
each sequence of adjacent elements <literal><x></literal> in a <literal><y></literal>).
</para>
<para><literal>--skip-whitespace</literal> (<literal>:w</literal>),
<literal>--skip-comments</literal> (<literal>:c</literal>), and
<literal>--skip-pi</literal> (<literal>:p</literal>) can be used
in combination with <literal>--while</literal> (<literal>:W</literal>)
and/or <literal>--until</literal> (<literal>:U</literal>)
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.
</para>
<example>
<code>$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">
<tab count="1"/><foo xmlns:a="http://foo/bar">
<tab count="1"/><tab count="1"/><elem ccc="ddd">
<tab count="1"/><tab count="1"/><tab count="1"/><scratch>
<tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><elem ccc="ddd">
<tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><text aaa="bbb">some text</text>
<tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/></elem>
<tab count="1"/><tab count="1"/><tab count="1"/></scratch>
<tab count="1"/><tab count="1"/></elem>
<tab count="1"/><tab count="1"/><elem ccc="ddd">
<tab count="1"/><tab count="1"/><tab count="1"/><a:A xmlns:a="http://foo/bar" bar="baz"/>
<tab count="1"/><tab count="1"/></elem>
<tab count="1"/></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">
<tab count="1"/><foo xmlns:a="http://foo/bar">
<tab count="1"/><tab count="1"/><bar>
<tab count="1"/><tab count="1"/><tab count="1"/><elem ccc="ddd">
<tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><scratch>
<tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><elem ccc="ddd">
<tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><text aaa="bbb">some text</text>
<tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/></elem>
<tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/></scratch>
<tab count="1"/><tab count="1"/><tab count="1"/></elem>
<tab count="1"/><tab count="1"/><tab count="1"/><elem ccc="ddd">
<tab count="1"/><tab count="1"/><tab count="1"/><tab count="1"/><a:A xmlns:a="http://foo/bar" bar="baz"/>
<tab count="1"/><tab count="1"/><tab count="1"/></elem>
<tab count="1"/><tab count="1"/></bar>
<tab count="1"/></foo>
</elem>
</code>
</example>
<example>
<title>Wrapping a range of adjacent nodes</title>
<code># 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>
<tab/><li>1</li>
<tab/><li>2</li>
<tab/><li>3</li>
<tab/><br/>
<tab/><li>4</li>
<tab/><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>
<tab/><ol>
<tab count="2"/><li>1</li>
<tab count="2"/><li>2</li>
<tab count="2"/><li>3</li>
<tab/></ol>
<tab/><br/>
<tab/><ol>
<tab count="2"/><li>4</li>
<tab count="2"/><li>5</li>
<tab/></ol>
</scratch>
</code>
</example>
</description>
<see-also>
<ruleref ref="xinsert_command" arguments=""/>
<ruleref ref="insert_command" arguments=""/>
<ruleref ref="move_command" arguments=""/>
<ruleref ref="xmove_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="wrap_span_command" type="command" name="wrap-span" inline="yes">
<aliases>
<alias name="wrap_span"/>
</aliases>
<command minargs="3" maxargs="3" func="wrap_span">
<param name="namespace" short="n" type="exp" argument="exp"/>
</command>
<documentation sections="Manipulation">
<usage>wrap-span [--namespace <xref linkend="exp"/>] <xref linkend="exp"/> <xref linkend="exp"/> <xref linkend="exp"/></usage>
<shortdesc>wrap spans of nodes into elements</shortdesc>
<description>
<para>
This command is very similar to <xref linkend="wrap_command"/>
command, except that it works on spans of nodes.
It wraps spans (i.e. sequence of adjacent nodes between (and including)
a start node and an end node) with a new element
whose name is specified as the first argument.
Nodes within each span must have the same parent node.
The spans to be wrapped are defined
by a pair of node-lists in the second and third argument.
The first node-list specifies the
start node of one or more spans, while
the second node-list should contain the corresponding
end nodes.
The two node-lists must evaluate to the exactly same number of
nodes, otherwise a runtime error is reported.
The N'th span is then defined as a span
starting on the N'th node in the start node-list
and ending at the N'th node in the end node-list.
</para>
<para>
All nodes within the spans are removed from
the document and placed into the newly generated elements.
The wrapping elements are put back into the document tree
at the positions previously occupied by the node-spans.</para>
<para>
The command returns a node-list containing the newly created
wrapping elements.
</para>
<example>
<code>xsh $scratch/> $foo := create { "<root>\n<a/><b/>\n<a/><b/>\n<a/><b/>\n</root>" };
xsh $foo/> wrap-span 'span' //a //b;
xsh $foo/> ls /;
<?xml version="1.0" encoding="utf-8"?>
<root>
<span><a/><b/></span>
<span><a/><b/></span>
<span><a/><b/></span>
</root>
</code>
</example>
</description>
<see-also>
<ruleref ref="xinsert_command" arguments=""/>
<ruleref ref="insert_command" arguments=""/>
<ruleref ref="move_command" arguments=""/>
<ruleref ref="xmove_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="xinsert_command" type="command" name="xinsert" inline="yes">
<aliases>
<alias name="xadd"/>
</aliases>
<command minargs="4" maxargs="4" func="insert" extraargs="1">
<param name="namespace" short="n" type="exp" argument="exp"/>
</command>
<documentation sections="Manipulation">
<usage>xinsert [--namespace <xref linkend="exp"/>] <xref linkend="nodetype"/> <xref linkend="exp"/> <xref linkend="loc"/> <xref linkend="xpath"/></usage>
<shortdesc>create nodes on all target locations</shortdesc>
<description>
<para>
Create new nodes of the
<xref linkend="nodetype"/> given in the 1st argument
of name specified in the 2nd argument and insert them
to <xref linkend="loc"/>s relative to nodes
in the node-list specified in the 4th argument.
</para>
<para>
For element nodes, the the 2nd argument <xref
linkend="exp"/>
should evaluate to something like
"<element-name att-name='attvalue' ...>". The
<literal><</literal> and <literal>></literal>
characters are optional. If no attributes are used, the
expression may simply consist the element name. Note,
that in the first case, the quotes are required since
the expression contains spaces.
</para>
<para>
Attribute nodes use the following syntax:
"att-name='attvalue' [...]".
</para>
<para>
For the other types of nodes (text, cdata, comments) the
expression should contain the node's literal content. Again,
it is necessary to quote all whitespace and special
characters as in any expression argument.
</para>
<para>
The <xref linkend="loc"/> argument should be one of:
<literal>after</literal>, <literal>before</literal>,
<literal>into</literal>,
<literal>replace</literal>, <literal>append</literal>
or <literal>prepend</literal>. See documentation
of the <xref linkend="loc"/> argument type for more detail.
</para>
<para>
Optionally, for element and attribute nodes,
a namespace may be specified with <literal>--namespace</literal>
or <literal>:n</literal>. If used,
the expression should evaluate to the desired namespace
URI and the name of the element or attribute being inserted
<emphasis>must have a prefix</emphasis>.
</para>
<para>
The command returns a node-list consisting of nodes it created.
</para>
<para>
Note, that instead of <literal>xinsert</literal>, you can alternatively use
one of <xref linkend="new_attribute_function"/>,
<xref linkend="new_cdata_function"/>,
<xref linkend="new_chunk_function"/>,
<xref linkend="new_comment_function"/>,
<xref linkend="new_element_function"/>,
<xref linkend="new_element_ns_function"/>,
<xref linkend="new_pi_function"/>, and
<xref linkend="new_text_function"/>
together with the command <xref linkend="xcopy_command"/>.
</para>
<example>
<title>Give each chapter a provisional title element.</title>
<code>xsh> <userinput>my $new_titles := xinsert element "<title font-size=large underline=yes>" \
<tab count="1"/>into /book/chapter</userinput>
xsh> <userinput>xinsert text "Change me!" into $new_titles;</userinput></code>
</example>
<example>
<title>Same as above, using xcopy and xsh:new-... instead of xinsert</title>
<code>xsh> <userinput>my $new_titles := xcopy xsh:new-element("title","font-size","large","underline","yes") \
<tab count="1"/>into /book/chapter</userinput>
xsh> <userinput>xcopy xsh:new-text("Change me!") into $new_titles;</userinput></code>
</example>
</description>
<see-also>
<ruleref ref="insert_command" arguments=""/>
<ruleref ref="move_command" arguments=""/>
<ruleref ref="xmove_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="nodetype" name="node-type" type="argtype" inline="no">
<production>
<regexp>element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference</regexp>
</production>
<documentation sections="Argtypes Manipulation">
<title>Node-type argument type</title>
<shortdesc>node type specification (such as element, attribute, etc.)</shortdesc>
<description>
<para>
One of: element, attribute, text, cdata, comment, chunk
and (EXPERIMENTALLY!) entity_reference. A
chunk is a character string which forms a well-balanced
piece of XML.
</para>
<example>
<code>add element hobbit into //middle-earth/creatures;
add attribute 'name="Bilbo"' into //middle-earth/creatures/hobbit[last()];
add chunk '<hobbit name="Frodo">A small guy from <place>Shire</place>.</hobbit>'
<tab count="1"/>into //middle-earth/creatures;
</code>
</example>
</description>
</documentation>
</rule>
<rule id="loc" type="argtype" name="location" inline="no">
<production><regexp>after\s</regexp>
<action>"after"</action>
</production>
<production><regexp>before\s</regexp>
<action>"before"</action>
</production>
<production><regexp>(in)?to\s</regexp>
<action>"into"</action>
</production>
<production><regexp>(append(ing)?|as\s+(a\s+)child(\s+of)?)\s</regexp>
<action>"append"</action>
</production>
<production><regexp>(prepend(ing)?|(as\s+)(the\s+)first(\s+child(\s+of)?)?)\s</regexp>
<action>"prepend"</action>
</production>
<production><regexp>(replace|instead( of)?)\s</regexp>
<action>"replace"</action>
</production>
<documentation sections="Argtypes Manipulation">
<title>Location argument type</title>
<shortdesc>relative destination specification (such as after, before, etc.)</shortdesc>
<description>
<para>One of:
<literal>after</literal>,
<literal>before</literal>,
<literal>into</literal>,
<literal>append</literal>,
<literal>prepend</literal>,
<literal>replace</literal>.
</para>
<para>
This argument is required by all commands that insert
nodes to a document in some way to a destination described
by an XPath expression. The meaning of the values listed
above is supposed be obvious in most cases, however the
exact semantics for location argument values depends on
types of both the source node and the target node.
</para>
<para>
<literal>after/before</literal> place the node right
after/before the destination node, except for when the
destination node is a document node or one of the source
nodes is an attribute: If the destination node is a
document node, the source node is attached to the
end/beginning of the document (remember: there is no
"after/before a document"). If both the source and
destination nodes are attributes, then the source node is
simply attached to the element containing the destination
node (remember: there is no order on attribute nodes). If
the destination node is an attribute but the source node
is of a different type, then the textual content of the
source node is appended to the value of the destination
attribute (i.e. in this case after/before act just as
append/prepend).
</para>
<para>
<literal>append/prepend</literal> appends/prepends the
source node to the destination node. If the destination
node can contain other nodes (i.e. it is an element or a
document node) then the entire source node is attached to
it. In case of other destination node types, the textual
content of the source node is appended/prepended to the
content of the destination node.
</para>
<para>
<literal>into</literal> can also be used to place
the source node to the end of an element (in the same way
as <literal>append</literal>), to attach an attribute
to an element, or, if the destination node is a text node,
cdata section, processing-instruction, attribute or comment,
to replace its textual content with the textual content of
the source node.
</para>
<para>
<literal>replace</literal> replaces the entire destination
node with the source node except for the case when the
destination node is an attribute and the source node is
not. In such a case only the value of the destination
attribute is replaced with the textual content of the
source node. Note also that document node can never be
replaced.
</para>
</description>
</documentation>
</rule>
<rule id="move_command" type="command" name="move" inline="yes">
<aliases>
<alias name="mv"/>
</aliases>
<command minargs="3" maxargs="3" func="move" extraargs="0">
<param name="respective" short="r"/>
</command>
<documentation sections="Manipulation">
<usage>move <xref linkend="xpath"/> <xref linkend="loc"/> <xref linkend="xpath"/></usage>
<shortdesc>move nodes (in the one-to-one mode)</shortdesc>
<description>
<para><literal>move</literal> command acts exactly like
<xref linkend="copy_command"/>, except that it
<emphasis>removes</emphasis> the source nodes after a
successful copy. Remember that the moved nodes are
actually <emphasis>different nodes</emphasis> from the
original ones (which may not be obvious when moving
nodes within a single document into locations that do
not require type conversion). So, after the move, the
original nodes don't belong to any document
and are automatically destroyed unless some
variable still contains to them.
</para>
<para>
This command returns a node-list consisting of nodes
it created on the target locations.
</para>
<para>
See <xref linkend="copy_command"/> for more details on how
the copies of the moved nodes are created.
</para>
</description>
<see-also>
<ruleref ref="xmove_command" arguments=""/>
<ruleref ref="copy_command" arguments=""/>
<ruleref ref="xcopy_command" arguments=""/>
<ruleref ref="insert_command" arguments=""/>
<ruleref ref="xinsert_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="xmove_command" type="command" name="xmove" inline="yes">
<aliases>
<alias name="xmv"/>
</aliases>
<command minargs="3" maxargs="3" func="move" extraargs="1">
<param name="respective" short="r"/>
<param name="preserve-order" short="p"/>
</command>
<documentation sections="Manipulation">
<usage>xmove [--respective|:r] [--preserve-order|:p] <xref linkend="xpath"/> <xref linkend="loc"/> <xref linkend="xpath"/></usage>
<shortdesc>move nodes (in the all-to-every mode)</shortdesc>
<description>
<para>Like <xref linkend="xcopy_command" />, except that
<literal>xmove</literal> <emphasis>removes</emphasis> the source
nodes after a successful copy. Remember that the moved nodes are
actually <emphasis>different nodes</emphasis> from the original
ones (which may not be obvious when moving nodes within a single
document into locations that do not require type conversion). So,
after the move, the original nodes don't belong to any document and
are automatically destroyed unless still contained in some variable.
</para>
<para>
This command returns a node-list consisting of all nodes
it created on the target locations.
</para>
<para>
If <literal>--respective|:r</literal> option
is used, then the target node-list <xref linkend="exp"/>
is evaluated in the context of the source node
being copied.
</para>
<para>
The <literal>--preserve-order|:p</literal> option can be
used to ensure that the copied nodes are in the same
relative order as the corresponding source nodes.
Otherwise, if <xref linkend="loc"/> is
<literal>after</literal> or <literal>prepend</literal>,
the relative order of the copied nodes will be reversed,
because source nodes are placed to the target location one
by one.
</para>
<para>
See <xref linkend="xcopy_command"/> for more details on
how the copies of the moved nodes are created.
</para>
<para>
The following example demonstrates how <literal>xmove</literal>
can be used to get rid of HTML <literal><font></literal>
elements while preserving their content. As an exercise,
try to figure out why simple
<literal>foreach //font { xmove node() replace . }</literal>
would not work here.
</para>
<example>
<title>Get rid of all <font> tags</title>
<code>while //font {
<tab count="1"/>foreach //font {
<tab count="1"/><tab count="1"/>xmove node() replace .;
<tab count="1"/>}
}
</code>
</example>
</description>
<see-also>
<ruleref ref="move_command" arguments=""/>
<ruleref ref="copy_command" arguments=""/>
<ruleref ref="xcopy_command" arguments=""/>
<ruleref ref="insert_command" arguments=""/>
<ruleref ref="xinsert_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="clone_command" type="command" name="clone" inline="yes">
<aliases>
<alias name="dup"/>
</aliases>
<command minargs="0" maxargs="1" func="clone" />
<documentation sections="Manipulation Documents">
<usage>$doc := clone <xref linkend="document" /></usage>
<shortdesc>clone a given document</shortdesc>
<description>
<para>
Create and return a copy of a given <xref linkend="document"/>.
Unless <xref linkend="cdonopen" />
configuration flag is turned off,
the root node of the new document
becomes the current node.
</para>
<para>Calling this command only makes sense if
either
<xref linkend="cdonopen" /> is set, or
if the result is assigned to a variable or
passed to another &XSH; command using the <literal>&{...}</literal>
syntax, since otherwise the newly
created copy of the document is automatically garbage-collected and
destroyed.
</para>
</description>
<see-also>
<ruleref ref="open_command" arguments="" />
<ruleref ref="close_command" arguments=""/>
<ruleref ref="print_enc_command" arguments=""/>
<ruleref ref="files_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="normalize_command" type="command" name="normalize" inline="yes">
<command minargs="1" maxargs="1" func="normalize_nodes"/><documentation sections="Manipulation">
<usage>normalize <xref linkend="exp"/></usage>
<shortdesc>normalizes adjacent textnodes</shortdesc>
<description>
<para><literal>normalize</literal>
evaluates given <xref linkend="exp"/> to a node-list
and puts all text nodes in the full depth of the sub-tree
underneath each node in the node-list
into a "normal" form where only structure (e.g., elements,
comments, processing instructions, CDATA sections, and
entity references) separates text nodes, i.e., there are
neither adjacent text nodes nor empty text nodes.
</para>
<para>
Note, that most &XSH; commands automatically join adjacent text nodes.
</para>
</description>
</documentation>
</rule>
<rule id="strip_ws_command" type="command" name="strip-whitespace" inline="yes">
<aliases>
<alias name="strip_whitespace"/>
</aliases>
<command minargs="1" maxargs="1" func="strip_ws"/><documentation sections="Manipulation">
<usage>strip-whitespace <xref linkend="exp"/></usage>
<shortdesc>strip leading and trailing whitespace</shortdesc>
<description>
<para><literal>strip-whitespace</literal> removes all leading and
trailing whitespace from given nodes. If applied to an
element node, it removes all leading and trailing child
whitespace-only text nodes and CDATA sections.
</para>
</description>
</documentation>
</rule>
<rule id="list_command" type="command" name="ls" inline="yes">
<aliases>
<alias name="list"/>
</aliases>
<command maxargs="1" func="list">
<param name="fold" short="f"/>
<param name="fold-attrs" short="A"/>
<param name="indent" short="i"/>
<param name="no-indent" short="I"/>
<param name="depth" short="d" type="exp" argument="exp"/>
</command>
<documentation sections="Navigation Information">
<usage>ls [--fold|:f] [--fold-attrs|:A] [--indent|:i | --no-indent|:I]
[--depth|:d <xref linkend="exp"/>] [<xref linkend="exp"/>]</usage>
<shortdesc>list a given part of a document as XML</shortdesc>
<description>
<para>
Print XML representation of a given
<xref linkend="exp"/>, in particular,
if used with an <xref linkend="xpath"/>,
list parts of the document matching given expression.
</para>
<para>
If used without an argument,
current node is listed to the depth 1 (see below).
</para>
<para>
<literal>--depth</literal> or <literal>:d</literal>
argument may be used to specify depth of the XML listing.
If negative, the listing depth is unlimited.
All content below the specified depth is replaced with
an ellipsis (<literal>...</literal>).
</para>
<para>
<literal>--fold</literal> or <literal>:f</literal>
option makes the listing fold elements marked using the
<xref linkend="fold_command"/> command are folded, i.e. listed
only to the depth specified in the folding mark.
</para>
<para>
<literal>--fold-attrs</literal> or <literal>:A</literal>
option avoids listing of attributes of the folded
elements (i.e. elements on the lowest level of listing).
Folded attributes are replaced with
ellipsis (<literal>...</literal>).
</para>
<para>
<literal>--indent</literal> (<literal>:i</literal>)
and
<literal>--no-indent</literal> (<literal>:I</literal>)
may be used to enforce/suppress
indentation, overriding current setting
(see command <xref linkend="indent"/>).
</para>
<para>
Unless in <xref linkend="quiet"/> mode,
this command also prints the number of
(top-level) nodes listed.
</para>
</description>
<see-also>
<ruleref ref="count_command" arguments=""/>
<ruleref ref="fold_command" arguments=""/>
<ruleref ref="unfold_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="c14n_command" type="command" name="canonical" inline="yes">
<command maxargs="1" func="c14n">
<param name="comments" short="c"/>
<param name="filter" short="f" type="xpath" argument="xpath"/>
</command>
<documentation sections="Navigation Information">
<usage>canonical [--comments|:c] [--filter|:f <xref linkend="xpath"/>] [<xref linkend="exp"/>]</usage>
<shortdesc>serialize nodes as to canonical XML</shortdesc>
<description>
<para>
This commands prints a canonical XML representing nodes specified
by its argument (or current node, if no argument is given).</para>
<para><literal>--comments</literal> or
<literal>:c</literal> removes comments
from the resulting XML.</para>
<para>
<literal>--filter</literal> or <literal>:f</literal>
can be used to filter
the resulting XML so that it only contains
nodes explicitly included in the given node-set.</para>
<para>
For
details see <ulink url="http://www.w3.org/TR/xml-c14n">"Canonical
XML"</ulink> or <ulink
url="http://www.w3.org/TR/xml-exc-c14n">"Exclusive XML Canonicalization"</ulink> W3C recommendations.
</para>
</description>
<see-also>
<ruleref ref="list_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="count_command" type="command" name="count" inline="yes">
<command minargs="1" maxargs="1" func="print_count">
<param name="quiet" short="q"/>
</command>
<documentation sections="Information">
<usage>count [--quiet|:q] <xref linkend="xpath"/></usage>
<shortdesc>calculate a <xref linkend="exp"/> and enumerate node-lists</shortdesc>
<description>
<para>
Calculates a given <xref linkend="exp"/> expression. If
the result is a node-list, print number of nodes in the
node-list. If the <xref linkend="exp"/> results in a
boolean, numeric or literal value, print the value.
</para>
<para>
If <literal>--quiet</literal> or <literal>:q</literal>
option is used, output is suppressed and the value
is returned.
</para>
</description>
<see-also>
<ruleref ref="expression_command"/>
</see-also>
</documentation>
</rule>
<rule id="change_namespace_uri_command" type="command" name="change-ns-uri" inline="yes">
<command minargs="1" maxargs="2" func="change_namespace_uri"/>
<documentation sections="Namespaces Manipulation">
<usage>change-ns-uri <xref linkend="exp"/> [<xref linkend="exp"/>]</usage>
<shortdesc>change namespace URI (EXPERIMENTAL)</shortdesc>
<description>
<para>
This command takes one or two arguments. The first
argument is a new namespace URI and the second, optional,
argument is a namespace prefix. It changes the URI value
of a namespace declaration of the context node to the new
value. If no prefix is given, the change applies to a
declaration on the context node whose prefix equals to the
prefix of the context node, otherwise the change applies
to a declaration with the given prefix.
</para>
</description>
<see-also>
<ruleref ref="change_namespace_prefix_command"/>
<ruleref ref="set_namespace_command"/>
<ruleref ref="declare_namespace_command"/>
<ruleref ref="namespaces_command"/>
</see-also>
</documentation>
</rule>
<rule id="change_namespace_prefix_command" type="command" name="change-ns-prefix" inline="yes">
<command minargs="1" maxargs="2" func="change_namespace_prefix"/>
<documentation sections="Namespaces Manipulation">
<usage>change-ns-prefix <xref linkend="exp"/> [<xref linkend="exp"/>]</usage>
<shortdesc>change namespace prefix (EXPERIMENTAL)</shortdesc>
<description>
<para>
This command takes one or two arguments. The first
argument is a new prefix and the second, optional,
argument is an old namespace prefix. It changes the prefix
of a namespace declaration of the context node to the new
value. If no old prefix is given, the change applies to a
declaration on the context node whose prefix equals to the
prefix of the context node, otherwise the command changes
the declaration with the given old prefix.
</para>
<para>
The command throws an exception if the new prefix is
already taken by some other declaration in the scope.
</para>
</description>
<see-also>
<ruleref ref="change_namespace_uri_command"/>
<ruleref ref="set_namespace_command"/>
<ruleref ref="declare_namespace_command"/>
<ruleref ref="namespaces_command"/>
</see-also>
</documentation>
</rule>
<rule id="set_namespace_command" type="command" name="set-ns" inline="yes">
<command minargs="1" maxargs="2" func="set_namespace">
<param name="prefix" short="p" type="string" argument="exp"/>
</command>
<documentation sections="Namespaces Manipulation">
<usage>set-ns [:p|--prefix <xref linkend="exp"/>] <xref linkend="exp"/></usage>
<shortdesc>set namespace of the current node (EXPERIMENTAL)</shortdesc>
<description>
<para>
This command takes one argument, the namespace URI,
possibly accompanied by a prefix provided in
the option <literal>--prefix</literal> <literal>:p</literal>;
both these expressions are evaluated as names.
The command changes the namespace of the current element to a given
namespace URI. The current node must be in the scope
of a namespace declaration associating the namespace URI
with a prefix; if prefix option is given, then
one of such declarations must associate the particular given prefix
with the namespace URI. If this condition
is not met or the current node is neither element nor
attribute, an error is issued.
The command also changes the prefix of the current element accordingly.
</para>
</description>
<see-also>
<ruleref ref="declare_namespace_command"/>
<ruleref ref="change_namespace_uri_command"/>
<ruleref ref="change_namespace_prefix_command"/>
<ruleref ref="namespaces_command"/>
</see-also>
</documentation>
</rule>
<rule id="declare_namespace_command" type="command" name="declare-ns" inline="yes">
<command minargs="2" maxargs="2" func="declare_namespace"/>
<documentation sections="Namespaces Manipulation">
<usage>declare-ns <xref linkend="exp"/> <xref linkend="exp"/></usage>
<shortdesc>create a special attribute declaring an XML namespace (EXPERIMENTAL)</shortdesc>
<description>
<para>
This command takes one or two arguments: prefix and URI,
both evaluated as names.
It creates a namespace declaration
of the form <literal>xmlns:prefix="URI"</literal>
on the current node.
The command produces an error if
the prefix is already declared in the scope of the current node
with a different namespace URI.
</para>
</description>
<see-also>
<ruleref ref="set_namespace_command"/>
<ruleref ref="change_namespace_uri_command"/>
<ruleref ref="change_namespace_prefix_command"/>
<ruleref ref="namespaces_command"/>
</see-also>
</documentation>
</rule>
<rule id="set_command" type="command" name="set" inline="yes">
<command minargs="1" maxargs="2" func="xpath_set"/>
<documentation sections="Manipulation">
<usage>set <xref linkend="xpath"/> [<xref linkend="xpath"/>]</usage>
<shortdesc>create or modify document content (EXPERIMENTAL)</shortdesc>
<description>
<para>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 <xref
linkend="xpath"/> results in a node-list and the target
node is an element, nodes).
</para>
<example>
<title>Try the following on an empty scratch document</title>
<code>$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 say="hello world">
<tab/><foo/>
<tab/><tab/><bar>
<tab/><tab/><tab/><baz/>
<tab/><tab/><tab/><baz/>
<tab/><tab/><tab/><baz>HALLO</baz>
<tab/><tab/></bar>
<tab/><foo/>
<scratch/>
</code>
</example>
<para>
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 and new nodes
can only be magically created along the child, sibling, or
attribute axes.
The node-test part of the expression
can neither be a wildcard (<literal>*</literal>,
<literal>@*</literal>, <literal>prefix:*</literal>, ...),
nor the <literal>node()</literal> function. If a namespace
prefix is used, then either the namespace must already be
declared in the document or registered with XSH.
</para>
<para>
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
<literal>[4]</literal>, or
<literal>[position()>3]</literal>, etc), then the
parser tries to automatically create empty siblings nodes
until it finally creates one with for which the predicate
is true.
</para>
<para>
Note, that this command only processes one location step
at a time and always picks the first matching node. So,
expressions like <literal>/root/a/b</literal> are treated
as <literal>/root/a[1]/b[1]</literal>. This means that an
expression <literal>/root/a/b</literal> will magically
create element <literal><b></literal> in a first
matching <literal><a></literal> even if some
following <literal><a></literal> already contains a
<literal><b></literal>.
</para>
<para>
To prevent this, either explicitly state that <literal>b</literal> must
exist with e.g. <literal>/root/a[b]/b</literal> or make the corresponding
element <literal><a></literal> the context
node and use a relative location path:
</para>
<example>
<code>for /root/a/b set b 'foo'</code>
</example>
</description>
</documentation>
</rule>
<rule id="expression_command" type="command" name="get" inline="yes">
<aliases>
<alias name="exp"/>
<alias name="expr"/>
</aliases>
<command minargs="1" maxargs="1" func="expr"/>
<documentation sections="Information">
<usage>get <xref linkend="exp"/></usage>
<shortdesc>calculate a given expression and return the result.</shortdesc>
<description>
<para>
Calculate a given <xref linkend="exp"/> and return the value.
</para>
</description>
<see-also>
<ruleref ref="count_command"/>
</see-also>
</documentation>
</rule>
<rule id="perl_code" type="argtype" name="perl-code" inline="no">
<documentation sections="Argtypes Perl_shell">
<title>Perl-code argument type</title>
<shortdesc>in-line code in Perl programming language</shortdesc>
<description>
<para>
A block of Perl code enclosed in braces.
All &XSH; variables are transparently accessible from
the Perl code as well.
</para>
<para>
For more information about embedded Perl code in &XSH;, predefined
functions etc., see <xref linkend="Perl_shell"/>.
</para>
<example>
<code>xsh> <userinput>$i={ "foo" };</userinput>
xsh> <userinput>perl { echo "$i-bar\n"; }</userinput> # prints foo-bar
xsh> <userinput>echo { "$i-bar" }</userinput> # very much the same as above
</code>
</example>
</description>
</documentation>
</rule>
<rule id="perl_command" type="command" name="perl" inline="yes">
<command minargs="1" maxargs="1" func="perl_eval_command"/>
<documentation sections="Perl_shell">
<usage>perl <xref linkend="perl_code"/></usage>
<shortdesc>evaluate in-line Perl code</shortdesc>
<description>
<para>Evaluate a given perl expression and return
the result.</para>
</description>
<see-also>
<ruleref ref="count_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="prune_command" type="command" name="remove" inline="yes">
<aliases>
<alias name="rm"/>
<alias name="prune"/>
<alias name="delete"/>
<alias name="del"/>
</aliases>
<command minargs="1" maxargs="1" func="prune"/><documentation sections="Manipulation">
<usage>remove <xref linkend="exp"/></usage>
<shortdesc>remove given nodes</shortdesc>
<description>
<para>Unlink all nodes in a given node-list
from their respective documents. Nodes, which
are neither attached to a document or stored in a variable
are automatically garbage-collected.
</para>
<para>Returns a number of nodes removed.</para>
<example>
<title>Get rid of all evil creatures.</title>
<code>xsh> <userinput>del //creature[@manner='evil']</userinput></code>
</example>
</description>
</documentation>
</rule>
<rule id="print_command" type="command" name="print" inline="yes">
<aliases>
<alias name="echo"/>
</aliases>
<command func="echo">
<param name="nonl" short="n"/>
<param name="nospace" short="s"/>
<param name="stderr" short="e"/>
</command>
<documentation sections="Information">
<usage>print [--nonl|:n] [--nospace|:s] [--stderr|:e] <xref linkend="exp"/> [<xref linkend="exp"/> ...]</usage>
<shortdesc>print stuff on standard or standard error output</shortdesc>
<description>
<para>Evaluate given expression(s) and print the results
(separated by a single space character).
Expressions not containing any special characters, such as
brackets, quotes, $, or @ are considered as bare words
and evaluate to themselves.
</para>
<para>
<literal>--nonl</literal> or <literal>:n</literal>
can be used to avoid printing a trailing new-line.
</para>
<para>
<literal>--nospace</literal> or <literal>:s</literal>
suppresses printing additional spaces between individual arguments.
</para>
<para>
<literal>--stderr</literal> or <literal>:e</literal>
causes the command to print on standard error output.
</para>
<example>
<code>print foo bar; # prints "foo bar"</code>
<code>print "foo bar"; # prints "foo bar"</code>
</example>
</description>
</documentation>
</rule>
<rule id="sort_command" type="command" name="sort" inline="yes">
<command minargs="1" maxargs="1" func="perlsort">
<param name="compare" short="c" type="perl" argument="perl_code"/>
<param name="key" short="k" type="exp" argument="exp"/>
<param name="numeric" short="n"/>
<param name="locale" short="l"/>
<param name="descending" short="d"/>
</command>
<documentation sections="Manipulation">
<usage>$result := sort [ --key|:k <xref linkend="exp"/> ]
--compare|:c <xref linkend="perl_code"/> <xref linkend="exp"/></usage>
<usage>$result := sort [ --key|:k <xref linkend="exp"/> ]
[ --numeric|:n ] [ --descending|:d ] [ --locale|:l] <xref linkend="exp"/>
</usage>
<shortdesc>sort a given node-list by given criteria</shortdesc>
<description>
<para>This command sorts a given node-list,
returning a node-list ordered according to a given
key and ordering function.
</para>
<para>
<literal>--key|:k</literal> followed by an expression
specifies the key to be computed for each member of the
node-list and the result used as the sorting key. If omitted,
keys are created by converting the nodes
to string as if XPath expression <literal>string(.)</literal>
was used.
</para>
<para>
<literal>--numeric|:n</literal> specifies, that
keys should be compared by their numerical values
(the default is string comparison).
</para>
<para>
<literal>--descending|:d</literal> specifies,
that the result should be ordered in descending order
(default is ascending).
</para>
<para>
<literal>--locale|:l</literal> forces using
current locale settings for string comparison
(default is no locale).
</para>
<para>
<literal>--compare</literal> argument followed
by a <xref linkend="perl_code" /> allows to define a custom
comparison method in a similar way to Perl <literal>sort</literal>
command. The keys to be compared are passed
to the code in variables <literal>$a</literal> and
<literal>$b</literal>. The code is supposed to return 1 if
the key in <literal>$a</literal> is greater than
<literal>$b</literal>, 0 if the keys are equal
and <literal>-1</literal> if <literal>$a</literal>
is less than <literal>$b</literal>, depending
on how the corresponding elements are to be ordered.
It is a run-time error to use
<literal>--compare</literal> together with either
<literal>--numeric</literal> or
<literal>--descending</literal>.
</para>
<example>
<title>Case-insensitive sort of a given node-list</title>
<code>$ordered := sort --key xsh:lc(.) $unordered;</code>
</example>
<example>
<title>Reorder creature elements by name attribute
in ascending order using Czech locale settings
</title>
<code>perl {
# setup locale collating function
# Note, that the collating function must be UTF8 aware.
use POSIX qw(locale_h);
setlocale(LC_COLLATE,'cs_CZ.UTF-8');
};
xmove &{ sort :k@name :l * } into /middle-earth[1]/creatures;
</code>
</example>
<example>
<title>Sort a node-list by a pre-computed score (Perl-based sort)</title>
<code>$results := sort --numeric --descending --key { $scores{literal('@name')} } $players;
</code>
</example>
</description>
</documentation>
</rule>
<rule id="map_command" type="command" name="map" inline="yes">
<command minargs="2" maxargs="2" func="perlmap">
<param name="in-place" short="i"/>
<param name="reverse" short="r"/>
</command>
<documentation sections="Perl_shell Manipulation">
<usage>map <xref linkend="exp"/> <xref linkend="exp"/></usage>
<shortdesc>transform node value/data using Perl or XPath expression</shortdesc>
<description>
<para>
NOTE: THE SEMANTICS OF COMMAND HAS CHANGED IN 2.1.0
</para>
<para>
This command provides an easy way to transform node's data
(content) using arbitrary expression.
It takes two arguments: a mapping expression
and a node-list.
</para>
<para>
First the second argument is evaluated to a node-list.
For each of the nodes,
the mapping expression is evaluated
and the result is used to replace the original content
of the node.
The node is made the context node for the time
of evaluation of the mapping expression.
Moreover, if the expression is a Perl code,
it gets the original text content in
the variable <literal>$_</literal>.
</para>
<para>
Note that if the processed node is an element
than the mapping expression may even produce nodes
which are then copied into the element discarding
any previous content of the element.
</para>
<para>
If the mapping expression returns an undefined value
for a node, then its content is kept untouched.
</para>
<para>
<literal>--in-place</literal> (<literal>:i</literal>) flag:
if the expression is a Perl code, then
it is sometimes convenient to change the value
in place. In that case use this flag to indicate that the result
should to be taken from the <literal>$_</literal> variable
rather than from the value of the expression itself.
Without this flag, <literal>$_</literal> is read-only.
</para>
<para>
<literal>--reverse</literal> (<literal>:r</literal>) flag
instruct the map to process the nodelist
in reversed order.
</para>
<example>
<title>Capitalizes all hobbit names</title>
<code>map { ucfirst($_) } //hobbit/@name;</code>
</example>
<example>
<title>Changes Goblins to Orcs in all hobbit tales (\b matches word boundary).</title>
<code>map :i { s/\bgoblin\b/orc/gi } //hobbit/tale/text();</code>
</example>
<example>
<title>Recompute column sums in the last row of row-oriented table</title>
<code>map sum(/table/row[position()<last()]/
cell[count(xsh:current()/preceding-sibling::cell)+1])
/table/row[last()]/cell;</code>
</example>
<example>
<title>The following commands do all about the same:</title>
<code>wrap --inner Z //*;
map --reverse xsh:parse(concat("<Z>",xsh:serialize(node()),"</Z>")) //*;
map xsh:parse(concat("<Z>",xsh:serialize(node()),"</Z>")) { reverse xpath('//*') };
</code>
</example>
<para>Note that in the last example we use
<literal>:r</literal> (or Perl <literal>reverse</literal>
function) to reverse the node list order so that child
nodes get processed before their parents. Otherwise, the child
nodes would be replaced by parent's new content before the
processing could reach them.
</para>
</description>
<see-also>
<ruleref ref="rename_command"/>
</see-also>
</documentation>
</rule>
<rule id="rename_command" type="command" name="rename" inline="yes">
<command minargs="2" maxargs="2" func="perlrename">
<param name="namespace" short="n" type="exp" argument="exp"/>
<param name="in-place" short="i"/>
<param name="reverse" short="r"/>
</command>
<documentation sections="Perl_shell Manipulation">
<usage>rename <xref linkend="nodename"/> <xref linkend="exp"/></usage>
<shortdesc>quickly rename nodes with in-line Perl code</shortdesc>
<description>
<para>
NOTE: THE SEMANTICS OF COMMAND HAS CHANGED IN 2.1.0
</para>
<para>
This command is very similar to the <xref linkend="map_command"/>
command, except that it operates on nodes' names rather
than their content. It changes
name of every element, attribute or
processing-instruction contained
in the node-list specified in the second argument <xref
linkend="exp"/>, according to the value of the
<xref linkend="nodename"/> expression,
which is evaluated in the context of each node in turn.
</para>
<para>If the <xref linkend="nodename"/> is a Perl
expression, then the name of the node is also stored into Perl's
<literal>$_</literal> variable prior to evaluation.
</para>
<para>The flag <literal>--in-place</literal> (<literal>:i</literal>)
can be used to indicate that
the new name should be collected from the <literal>$_</literal>
variable rather than from the result of the expression itself.
</para>
<para>
The <literal>--namespace</literal> (<literal>:n</literal>) argument
may be used to provide namespace for the renamed nodes.
</para>
<para>
<literal>--reverse</literal> (<literal>:r</literal>) flag
instruct the map to process the nodelist
in reversed order.
</para>
<para>Note: if the expression <xref linkend="nodename"/>
returns an undefined value for a particular node, the
node's original name and namespace are preserved.
</para>
<example>
<title>Renames all Hobbits to Halflings</title>
<code>xsh> <userinput>rename halfling //hobbit</userinput></code>
</example>
<example>
<title>Make all elements and attributes uppercase (yack!)</title>
<code>xsh> <userinput>rename { uc } (//*|//@*)</userinput></code>
</example>
<example>
<title>Substitute dashes with underscores in all node names</title>
<code>xsh> <userinput>rename :i { s/-/_/g } (//*|//@*)</userinput></code>
</example>
<example>
<title>Make all elements start with the name of their parents</title>
<code>xsh> <userinput>rename concat(local-name(parent::*),'.',local-name(.)) //*[parent::*]</userinput></code>
</example>
</description>
<see-also>
<ruleref ref="map_command" arguments="" />
</see-also>
</documentation>
</rule>
<rule id="hash_command" type="command" name="hash" inline="yes">
<command minargs="2" maxargs="2" func="hash"/>
<documentation sections="Perl_shell Manipulation">
<usage>$hash := hash <xref linkend="exp"/> <xref linkend="exp"/></usage>
<shortdesc>index selected nodes by some key value</shortdesc>
<description>
<para>
This command takes two arguments: an expression computing
a key from a given node (1st argument) and a node-set (2nd
argument). For each node in the node-set, the key value is
computed and the node is stored under the given key in
the resulting hash. For a given key, the value stored
in the hash table is a node-list consisting of all nodes
for which the 1st expression evaluated to an object
string-wise equal to the key. It is therefore possible to
index more than one node under the same key.
</para>
<para>
The XPath function
<literal>xsh:lookup(varname,key)</literal> can
be used to retrieve values from hashes in XPath expressions.
</para>
<example>
<title>Index books by author</title>
<code>my $books_by_author := hash concat(author/firstname," ",author/surname) //book;</code>
</example>
<example>
<title>Lookup books by Jack London.</title>
<code>ls { $books_by_author->{'Jack London'} };
ls xsh:lookup('books_by_author','Jack London');</code>
</example>
</description>
<see-also>
<ruleref ref="lookup_function"/>
</see-also>
</documentation>
</rule>
<rule id="close_command" type="command" name="close" inline="yes">
<command maxargs="1" func="close_doc" /><documentation sections="Documents">
<usage>close [<xref linkend="document"/>]</usage>
<shortdesc>close document (without saving)</shortdesc>
<description>
<para>
Close a given <xref linkend="document"/>
(or, if called with no argument,
the current document)
by trying to remove all references
from &XSH; variables to nodes
belonging to the document. If no references
to the document are left,
the garbage-collector destroys
the DOM tree and frees the memory it occupied
for later reuse (depending on architecture, this
may or may not give the allocated memory back
to the system).
</para>
</description>
</documentation>
</rule>
<rule id="index_command" type="command" name="index" inline="yes">
<command maxargs="1" func="index_doc"/><documentation sections="Documents">
<usage>index [<xref linkend="document"/>]</usage>
<shortdesc>index a static document for faster XPath lookup</shortdesc>
<description>
<para>
This command makes <literal>libxml2</literal> library to remember
document-order position of every element node in the <xref
linkend="document" />. Such indexation makes XPath queries
considerably faster on large documents (with thousands of nodes).
The command should only be used on documents which don't change;
modifying an indexed document might possibly lead to non-conformant
behavior of later XPath queries on the document.
</para>
</description>
</documentation>
</rule>
<rule id="open_command" type="command" name="open" inline="yes">
<command minargs="1" maxargs="1" func="open_doc">
<param name="format" short="F" type="string" argument="exp"/>
<param name="file" short="f"/>
<param name="pipe" short="p"/>
<param name="string" short="s"/>
<param name="switch-to" short="w"/>
<param name="no-switch-to" short="W"/>
<param name="validate" short="v"/>
<param name="no-validate" short="V"/>
<param name="recover" short="r"/>
<param name="no-recover" short="R"/>
<param name="expand-entities" short="e"/>
<param name="no-expand-entities" short="E"/>
<param name="xinclude" short="x"/>
<param name="no-xinclude" short="X"/>
<param name="keep-blanks " short="b"/>
<param name="no-keep-blanks " short="B"/>
<param name="pedantic " short="n"/>
<param name="no-pedantic " short="N"/>
<param name="load-ext-dtd " short="d"/>
<param name="no-load-ext-dtd " short="D"/>
<param name="complete-attributes" short="a"/>
<param name="no-complete-attributes" short="A"/>
</command>
<documentation sections="Documents">
<usage>$doc := open [--format|:F html|xml|docbook]
[--file|:f | --pipe|:p | --string|:s]
[--switch-to|:w | --no-switch-to|:W]
[--validate|:v | --no-validate|:V]
[--recover|:r | --no-recover|:R]
[--expand-entities|:e | --no-expand-entities|:E]
[--xinclude|:x | --no-xinclude|:X]
[--keep-blanks|:b | --no-keep-blanks|:B]
[--pedantic|:n | --no-pedantic|:N]
[--load-ext-dtd|:d | --no-load-ext-dtd|:D]
[--complete-attributes|:a | --no-complete-attributes|:A]
<xref linkend="exp"/></usage>
<shortdesc>load an XML, HTML, or Docbook SGML document from a
file, pipe or URI</shortdesc>
<description>
<para>
Parse a XML, HTML or SGML DOCBOOK document from a file or URL,
command output or string and return a node-set consisting
of the root of the resulting DOM tree.
</para>
<para><literal>--format</literal> (<literal>:F</literal>)
option may be used
to specify file format. Possible values are
<literal>xml</literal> (default),
<literal>html</literal>, and
<literal>docbook</literal>. Note, however,
that the support for parsing <literal>DocBook</literal> SGML
files has been deprecated in recent <literal>libxml2</literal>
versions.
</para>
<para><literal>--file</literal> (<literal>:f</literal>)
instructs the parser to consider a given <xref linkend="exp"/>
as a file name or URL.
</para>
<para>
<literal>--pipe</literal> (<literal>:p</literal>)
instructs the parser to consider a given <xref linkend="exp"/>
as a system command and parse its output.
</para>
<para>
<literal>--string</literal> (<literal>:s</literal>)
instructs the parser to consider a given <xref linkend="exp"/>
as a string of XML or HTML to parse.
</para>
<para>
<literal>--switch-to</literal> (<literal>:w</literal>)
and <literal>--no-switch-to</literal> (<literal>:W</literal>)
control whether the new document's root should
become current node. These option override
current global setting of
<xref linkend="cdonopen"/>.
</para>
<para>
<literal>--validate</literal> (<literal>:v</literal>)
and <literal>--no-validate</literal> (<literal>:V</literal>)
turn on/off DTD-validation of the parsed document.
These option override
current global setting of
<xref linkend="validation"/>.
</para>
<para>
<literal>--recover</literal> (<literal>:r</literal>)
and <literal>--no-recover</literal> (<literal>:R</literal>)
turn on/off parser's ability to recover from
non-fatal errors.
These option override
current global setting of
<xref linkend="recovering"/>.
</para>
<para>
<literal>--expand-entities</literal> (<literal>:e</literal>)
and <literal>--no-expand-entities</literal> (<literal>:E</literal>)
turn on/off entity expansion, overriding current global
setting of <xref linkend="parser_expands_entities"/>.
</para>
<para>
<literal>--xinclude</literal> (<literal>:x</literal>) and
<literal>--no-xinclude</literal> (<literal>:X</literal>) turn
on/off XInclude processing, overriding current global settings of
<xref linkend="parser_expands_xinclude"/>.
</para>
<para>
<literal>--keep-blanks</literal> (<literal>:b</literal>)
and <literal>--no-keep-blanks</literal> (<literal>:B</literal>)
control whether the parser should preserve so called ignorable
whitespace. These option override
current global setting of <xref linkend="keep_blanks"/>.
</para>
<para>
<literal>--pedantic</literal> (<literal>:n</literal>)
and <literal>--no-pedantic</literal> (<literal>:N</literal>)
turn on/off pedantic parser flag.
</para>
<para>
<literal>--load-ext-dtd</literal> (<literal>:d</literal>)
and <literal>--no-load-ext-dtd</literal> (<literal>:D</literal>)
control whether the external DTD subset should be loaded
with the document.
These option override
current global setting of <xref linkend="load_ext_dtd"/>.
</para>
<para>
<literal>--complete-attributes</literal> (<literal>:a</literal>)
and <literal>--no-complete-attributes</literal>
(<literal>:A</literal>)
turn on/off parse-time default attribute completion
based on default values specified in the DTD.
These option override
current global setting of <xref linkend="complete_attributes"/>.
</para>
<example>
<code>$scratch/> <userinput>$x := open mydoc.xml # open an XML document</userinput>
# open a HTML document from the Internet
<userinput>$h:=open --format html "http://www.google.com/?q=xsh"</userinput>
# quote file name if it contains whitespace
<userinput>$y := open "document with a long name with spaces.xml"</userinput>
# use --format html or --format docbook to load these types
$z := open --format html <userinput>index.htm</userinput>
# use --pipe flag to read output of a command
$z := open --format html --pipe <userinput>'wget -O - xsh.sourceforge.net/index.html'</userinput>
# use document variable to restrict XPath search to a
# given document
<userinput>ls $z//chapter/title</userinput>
</code>
</example>
</description>
</documentation>
</rule>
<rule id="create_command" type="command" name="create" inline="yes">
<aliases>
<alias name="new"/>
</aliases>
<command minargs="1" maxargs="1" func="new_doc">
<param name="format" short="F" type="string" argument="exp"/>
</command>
<documentation sections="Documents">
<usage>$doc := create <xref linkend="nodename"/>|<xref linkend="exp"/></usage>
<shortdesc>make a new document from a given XML fragment</shortdesc>
<description>
<para>
Returns a new document object. The
argument must evaluate either to
a valid element name (possibly followed
by some attribute declarations) to be used
for the document element, or to
a well-formed XML string.
</para>
<para>
Unless <xref linkend="cdonopen"/> option is turned off,
this command also changes current node
to the new document.
</para>
<example>
<code>$scratch/> <userinput>$t1 := create root</userinput>
$t1> <userinput>ls $t1</userinput>
<?xml version="1.0" encoding="utf-8"?>
<root/>
$t1> <userinput>$t2 := create "root id='r1'"</userinput>
$t2> <userinput>ls $t2</userinput>
<?xml version="1.0" encoding="utf-8"?>
<root id="r1"/>
$t2> <userinput>create "<root id='r0'>Just a <b>test</b></root>"</userinput>
/> <userinput>ls /</userinput>
<?xml version="1.0" encoding="utf-8"?>
<root id='r0'>Just a <b>test</b></root>
</code>
</example>
</description>
<see-also>
<ruleref ref="open_command" arguments=""/>
<ruleref ref="clone_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="save_command" type="command" name="save" inline="yes">
<command minargs="0" maxargs="1" func="save_doc">
<param name="format" short="F" type="string" argument="exp"/>
<param name="xinclude" short="x"/>
<param name="file" short="f" type="string" argument="filename"/>
<param name="pipe" short="p" type="string" argument="exp"/>
<param name="subtree" short="S"/>
<param name="print" short="r"/>
<param name="string" short="s"/>
<param name="indent" short="i"/>
<param name="no-indent" short="I"/>
<param name="skip-dtd" short="d"/>
<param name="no-skip-dtd" short="D"/>
<param name="skip-xmldecl" short="x"/>
<param name="no-skip-xmldecl" short="X"/>
<param name="skip-empty-tags" short="t"/>
<param name="no-skip-empty-tags" short="T"/>
<param name="backup" short="b"/>
<param name="backups" short="B"/>
<param name="encoding" short="e" type="string" argument="enc_string"/>
</command>
<documentation sections="Documents">
<usage>save [--format|:F html|xml] [--xinclude|:x]
[--file|:f <xref linkend="filename"/> |
--pipe|:p <xref linkend="filename"/> |
--string|:s |
--print|:r ]
[--subtree|:S]
[--indent|:i | --no-indent|:I]
[--skip-dtd|:d | --no-skip-dtd|:D]
[--skip-empty-tags|:t | --no-skip-empty-tags|:T]
[--skip-xmldecl|:x]
[--encoding|:e <xref linkend="enc_string"/>]
<xref linkend="document"/>
</usage>
<shortdesc>save a document as XML or HTML</shortdesc>
<description>
<para>
This takes a given <xref linkend="document" />,
serializes it to XML or HTML and
either saves the result
to its original file or another file (default),
pipes it to an external command,
prints it on standard output, or
simply returns it. Without arguments
it simply saves current document
to its original file.
</para>
<para>
<literal>--file|:f</literal> option
may be used to specify an output file-name.
By default, the original document's file-name
is used.
</para>
<para>
<literal>--pipe|:p</literal> option
specifies, that the output should be
piped to an external command
specified as the option's argument.
</para>
<para>
<literal>--print|:r</literal> option
specifies, that the output should
be printed on standard output.</para>
<para>
<literal>--string|:s</literal>
option specifies, that the output
should be returned by the command
as a string. In this case, the result is
always in UTF8, regardless on which
encoding is specified in the document
or using <literal>--encoding</literal> option.
</para>
<para>The above four options are mutually exclusive.</para>
<para>
<literal>--format</literal> option may be used
to specify the output format. It's argument
should be either <literal>xml</literal>,
<literal>html</literal> or an expression
evaluating to one of these. If not specified,
XML output is assumed.
Note, that a document should be saved as HTML only if it
actually is a HTML document, otherwise the result would be
an invalid XML instance. Note also, that the optional
encoding parameter only forces character conversion; it is
up to the user to declare the document encoding in the
appropriate HTML <META> tag, if needed.
</para>
<para>
<literal>--xinclude</literal>
automatically implies XML format and
can be used to force &XSH; to save all already expanded
XInclude sections back to their original files while
replacing them with <xi:include> tags in the main
XML file. Moreover, all material included within
<include> elements from the
<ulink url="http://www.w3.org/2001/XInclude">http://www.w3.org/2001/XInclude</ulink>
namespace is saved to separate files too according to the
<literal>href</literal> attribute, leaving only empty
<include> element in the root file. This feature may
be used to split the document to a new set of XInclude fragments.
</para>
<para>
If the <literal>--subtree</literal> (<literal>:S</literal>)
flag is used, only the subtree of the
specified node is saved instead of the complete document
(this flag cannot be used
with <literal>--html</literal> format).
</para>
<para>
<literal>--indent</literal> (<literal>:i</literal>)
and
<literal>--no-indent</literal> (<literal>:I</literal>)
may be used to enforce/suppress
indentation, overriding current global setting
of <xref linkend="indent"/>.
</para>
<para>
<literal>--skip-dtd</literal> (<literal>:d</literal>)
and
<literal>--no-skip-dtd</literal> (<literal>:D</literal>)
may be used to enforce/suppress
skipping DTD declaration and internal subset
on output, overriding current global setting
of <xref linkend="skip_dtd"/>.
</para>
<para>
<literal>--empty-tags</literal> (<literal>:t</literal>)
and
<literal>--no-empty-tags</literal> (<literal>:T</literal>)
may be used to override current global setting
of <xref linkend="empty_tags"/>.
<literal>--no-empty-tags</literal> instructs &XSH;
to serialize elements with no child nodes
as start-tag/end-tag pair
<literal><element></element></literal>
instead of using a short empty-tag form
<literal><element/></literal>.
</para>
<para>
<literal>--skip-xmldecl</literal> (<literal>:x</literal>)
instructs &XSH; to omit the XML declaration
from the saved document. Note however, that XML declaration
is obligatory for XML documents. It usually looks like
<literal><?xml version="1.0" ...?></literal>.
</para>
<para>
<literal>--backup</literal> (<literal>:b</literal>)
and
<literal>--no-backup</literal> (<literal>:B</literal>)
can be used to enforce/suppress
creation of a backup file if target file
already exists. Using these options
overrides current global setting of <xref linkend="backups"/>.
</para>
<para>
<literal>--encoding</literal>
followed by a <xref linkend="enc_string" />
instructs &XSH; to save the document in the specified
encoding. In case of XML output, the <?xml?>
declaration is automatically changed accordingly.
</para>
<example>
<title>Use save to preview current HTML document in Lynx</title>
<code>save --format html --pipe 'lynx -stdin'</code>
</example>
</description>
<see-also>
<ruleref ref="open_command" arguments=""/>
<ruleref ref="close_command" arguments=""/>
<ruleref ref="print_enc_command" arguments=""/>
<ruleref ref="files_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="set_dtd_command" type="command" name="set-dtd" inline="yes">
<aliases>
<alias name="set_dtd"/>
</aliases>
<command maxargs="1" func="set_dtd">
<param name="internal"/>
<param name="name" short="n" type="string" argument="exp"/>
<param name="system" short="s" type="string" argument="exp"/>
<param name="public" short="p" type="public" argument="exp"/>
</command>
<documentation sections="Manipulation">
<usage>set-dtd [--internal] [--name|:n <xref linkend="exp"/>]
[--public|:p <xref linkend="exp"/>]
[--system|:s <xref linkend="exp"/>]
[<xref linkend="document"/>]</usage>
<shortdesc>set document's DTD declaration</shortdesc>
<description>
<para>
Set external (default) or internal DTD for a given document. If
no <xref linkend="document"/> is given, the current
document is used. At least one of <literal>--public</literal>
and <literal>--system</literal> options should be used
to specify the PUBLIC and SYSTEM identifiers of the DTD.
If <literal>--name</literal> parameter is not provided,
name of the document root element is used as DTD name.
</para>
</description>
<see-also>
<ruleref ref="list_dtd_command" arguments=""/>
<ruleref ref="validate_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="list_dtd_command" type="command" name="dtd" inline="yes">
<command maxargs="1" func="list_dtd"/><documentation sections="Information">
<usage>dtd [<xref linkend="document"/>]</usage>
<shortdesc>show document's DTD</shortdesc>
<description>
<para>
Print external or internal DTD for a given document.
If used without arguments prints DTD of the current document.
</para>
</description>
<see-also>
<ruleref ref="set_dtd_command" arguments=""/>
<ruleref ref="validate_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="set_enc_command" type="command" name="set-enc" inline="yes">
<command minargs="1" maxargs="2" func="set_doc_enc"/>
<documentation sections="Manipulation">
<usage>set-enc <xref linkend="enc_string"/> [<xref linkend="document"/>]</usage>
<shortdesc>set document's charset (encoding)</shortdesc>
<description>
<para>
Changes character encoding of a given document.
If no <xref linkend="document"/>
is given, the command applies to the
current document. This has two effects:
changing the XMLDecl encoding declaration
in the document prolog to display the new
encoding and making all future <xref linkend="save_command"/> operations
on the document default to the given charset.
</para>
<example>
<code>xsh> <userinput>ls</userinput>
<?xml version="1.0" encoding="iso-8859-1"?>
<foo>...</foo>
xsh> <userinput>set-enc "utf-8"</userinput>
xsh> <userinput>ls</userinput>
<?xml version="1.0" encoding="utf-8"?>
<foo>...</foo>
xsh> <userinput>save</userinput> # saves the file in UTF-8 encoding
</code>
</example>
</description>
<see-also>
<ruleref ref="print_enc_command" arguments=""/>
<ruleref ref="doc_info_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="set_standalone_command" type="command" name="set-standalone" inline="yes">
<command minargs="1" maxargs="2" func="set_doc_standalone"/>
<documentation sections="Manipulation">
<usage>set-standalone <xref linkend="exp"/> [<xref linkend="document"/>]</usage>
<shortdesc>set document's standalone flag</shortdesc>
<description>
<para>
Changes the value of <literal>standalone</literal> declaration
in the XMLDecl prolog of a document. The <xref linkend="exp"/> should evaluate to either 1 or 0
or <literal>'yes'</literal> or <literal>'no'</literal>.
The result of applying the command on other values is not specified.
If no <xref linkend="document"/> is given,
the command applies to the current document.
</para>
</description>
<see-also>
<ruleref ref="doc_info_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="print_enc_command" type="command" name="enc" inline="yes">
<command maxargs="1" func="print_enc"/><documentation sections="Information">
<usage>enc [<xref linkend="document"/>]</usage>
<shortdesc>show document's original character encoding</shortdesc>
<description>
<para>
Print the original document encoding string.
If no <xref linkend="document"/> is given, the current document is
used.
</para>
</description>
<see-also>
<ruleref ref="set_enc_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="validate_command" type="command" name="validate" inline="yes">
<command maxargs="1" func="validate_doc">
<param name="yesno" short="q"/>
<param name="dtd" short="D"/>
<param name="relaxng" short="R"/>
<param name="schema" short="S"/>
<param name="file" short="f" type="string" argument="filename"/>
<param name="string" short="s" type="exp" argument="exp"/>
<param name="public" short="p" type="exp" argument="exp"/>
<param name="doc" short="d" type="exp" argument="document"/>
</command>
<documentation sections="Information">
<usage>validate [--yesno|:q] [<xref linkend="document"/>]</usage>
<usage>validate [--yesno|:q] [--dtd|:D | --relaxng|:R | --schema|:S] --file|:f <xref linkend="filename"/>] [<xref
linkend="document"/>]</usage>
<usage>validate [--yesno|:q] [--dtd|:D | --relaxng|:R | --schema|:S] --string|:s <xref linkend="exp"/>] [<xref
linkend="document"/>]</usage>
<usage>validate [--yesno|:q] [--dtd|:D | --relaxng|:R | --schema|:S] --doc|:d <xref linkend="document"/>] [<xref linkend="document"/>]</usage>
<usage>validate [--yesno|:q] [--dtd|:d] --public|:p <xref linkend="exp"/> [--file|:f <xref linkend="exp"/>] [<xref linkend="document"/>]</usage>
<shortdesc>validate a document against a DTD, RelaxNG, or XSD schemas</shortdesc>
<description>
<para>
This command validates the current document or
a document specified in the argument against a DTD,
RelaxNG or XSD schema.
If <literal>--yesno</literal> or <literal>:q</literal> is specified, only prints
<literal>yes</literal> and returns 1 if the document validates or
<literal>no</literal> and returns 0 if it does
not. Without <literal>--yesno</literal>, it throws an
exception with a complete validation error message if
the document doesn't validate.
</para>
<para><literal>--dtd</literal> or <literal>:D</literal> forces DTD validation
(default).</para>
<para><literal>--relaxng</literal> or <literal>:R</literal> forces RelaxNG
validation. Only XML RelaxNG grammars are supported.</para>
<para><literal>--schema</literal> or <literal>:S</literal> forces W3C XML Schema
validation (XSD). Support for schema validation may still
be incomplete (see <ulink
url="http://xmlsoft.org">libxml2 home page</ulink>
for more details).</para>
<para>
A DTD subset can be specified by its PUBLIC identifier (with
<literal>--public</literal>), by its SYSTEM identifier
(with <literal>--file</literal>), or as a string (with
<literal>--string</literal>). If none of these options is
used, validation is performed against the internal or
external DTD subset of the document being validated.
</para>
<para>
RelaxNG grammars and XML Schemas can either be
specified either as a filename or url (with
<literal>--file</literal>),
as a string containing (with <literal>--string</literal>),
or as a document currently open in &XSH; (with
<literal>--doc</literal>).
</para>
<example>
<code>$mydoc := open "test.xml"</code>
<code># in all examples below, mydoc can be omitted</code>
<code>validate --yesno $mydoc; # validate against the document's DOCTYPE</code>
<code>validate --public "-//OASIS//DTD DocBook XML V4.1.2//EN" $mydoc</code>
<code>validate --file "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" $mydoc</code>
</example>
<example>
<code>validate --relaxng --file "test.rng" $mydoc</code>
<code>validate --relaxng --string $relaxschema $mydoc</code>
<code>$rng := open "test.rng"</code>
<code>validate --relaxng --doc $rng $mydoc</code>
</example>
<example>
<code>validate --schema --file "test.xsd" $mydoc</code>
<code>validate --schema --string $xsdschema $mydoc</code>
<code>$xsd := open "test.xsd"</code>
<code>validate --schema --doc $xsd $mydoc</code>
</example>
</description>
<see-also>
<ruleref ref="list_dtd_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="exit_command" type="command" name="exit" inline="yes">
<aliases>
<alias name="quit"/>
</aliases>
<command maxargs="1" func="quit"/><documentation sections="Flow">
<usage>exit [<xref linkend="exp"/>]</usage>
<shortdesc>exit &XSH; shell</shortdesc>
<description>
<para>
Exit xsh, optionally with an exit-code
resulting from evaluation of a given <xref linkend="exp"/>.
</para>
<para>
WARNING: No files are saved on exit.
</para>
</description>
</documentation>
</rule>
<rule id="process_xinclude_command" type="command" name="process-xinclude" inline="yes">
<aliases>
<alias name="process_xinclude"/>
<alias name="process-xincludes"/>
<alias name="process_xincludes"/>
<alias name="xinclude"/>
<alias name="xincludes"/>
<alias name="load_xincludes"/>
<alias name="load-xincludes"/>
<alias name="load_xinclude"/>
<alias name="load-xinclude"/>
</aliases>
<command maxargs="1" func="process_xinclude"/><documentation sections="Manipulation Documents">
<usage>process-xinclude [<xref linkend="document"/>]</usage>
<shortdesc>load and insert XInclude sections</shortdesc>
<description>
<para>
Replace any xinclude tags in a given <xref linkend="document"/>
with the corresponding content. See
<ulink
url="http://www.w3.org/TR/xinclude/">http://www.w3.org/TR/xinclude/</ulink>
to find out more about XInclude technology.
</para>
</description>
<see-also>
<ruleref ref="parser_expands_xinclude" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="chxpath_command" type="command" name="cd" inline="yes">
<aliases>
<alias name="chxpath"/>
</aliases>
<command maxargs="1" func="set_local_xpath"/>
<documentation sections="Navigation">
<usage>cd [<xref linkend="exp"/>]</usage>
<shortdesc>change current context node</shortdesc>
<description>
<para>
Evaluate given <xref linkend="exp"/>
to a node-list and
change current context node to
the first node in it.
</para>
</description>
</documentation>
</rule>
<rule id="pwd_command" type="command" name="pwd" inline="yes">
<command maxargs="0" func="print_pwd">
<param name="id" short="i"/>
</command>
<documentation sections="Navigation Information">
<usage>pwd [--id|:i]</usage>
<shortdesc>show current context node location (as a canonical XPath)</shortdesc>
<description>
<para>Print XPath leading to the current context node
(equivalent to <literal>locate .</literal>).
</para>
<para>
If flag <literal>--id</literal> (<literal>:i</literal>) is
used then ID-based shortcut is allowed in the resulting
location path. That means that if the current node or some of its
ancestors has an ID attribute (either
<literal>xml:id</literal> or one specified in a DTD) then
the corresponding segment of the canonical location path
is replaced by the <literal>id()</literal> function
which jumps directly to an element based on its ID.
</para>
</description>
<see-also>
<ruleref ref="locate_command" arguments=""/>
<ruleref ref="path_function" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="locate_command" type="command" name="locate" inline="yes">
<command maxargs="1" func="locate">
<param name="id" short="i"/>
</command>
<documentation sections="Navigation Information">
<usage>locate [--id|:i] <xref linkend="xpath"/></usage>
<shortdesc>show a given node location (as a canonical XPath)</shortdesc>
<description>
<para>Print canonical XPaths leading to nodes matched by
a given <xref linkend="xpath"/>.</para>
<para>
If flag <literal>--id</literal> (<literal>:i</literal>) is
used then ID-based shortcuts are allowed in the resulting
location paths. That means that if the node or some of its
ancestors has an ID attribute (either
<literal>xml:id</literal> or one specified in a DTD) then
the corresponding segment of the canonical location path
is replaced by the <literal>id()</literal> function
which jumps directly to an element based on its ID.
</para>
</description>
<see-also>
<ruleref ref="pwd_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="xupdate_command" type="command" name="xupdate" inline="yes">
<command minargs="1" maxargs="2" func="xupdate"/><documentation sections="Manipulation">
<usage>xupdate <xref linkend="document"/> [<xref linkend="document"/>]</usage>
<shortdesc>apply XUpdate commands on a document</shortdesc>
<description>
<para>Modify the current document or the document specified
by the second <xref linkend="document"/> argument according to
XUpdate commands of the first <xref linkend="document"/>
argument.
XUpdate, or more specifically the XML Update Language, aims to
be a language for updating XML documents.
</para>
<para>
XUpdate language is described in XUpdate Working Draft at
<ulink url="http://xmldb-org.sourceforge.net/xupdate/xupdate-wd.html">http://xmldb-org.sourceforge.net/xupdate/xupdate-wd.html</ulink>.
</para>
<para>XUpdate output can be generated for example by
Python xmldiff utility from
<ulink url="http://www.logilab.org/projects/xmldiff/">http://www.logilab.org/projects/xmldiff/</ulink>.
</para>
</description>
</documentation>
</rule>
<rule id="verbose" type="command" name="verbose" inline="yes">
<command maxargs="0" func="set_quiet" extraargs="0"/><documentation sections="Configuration">
<usage>verbose</usage>
<shortdesc>make &XSH; print many messages</shortdesc>
<description>
<para>Turn on verbose messages (default).</para>
<para>This is equivalent to setting
<literal>$QUIET</literal> variable to 0.</para>
</description>
<see-also>
<ruleref ref="quiet" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="test_mode" type="command" name="test-mode" inline="yes">
<aliases>
<alias name="test_mode"/>
</aliases>
<production>
<selfref sep="yes"/>
<action>[<lineinfo/>,"test-mode"]</action>
</production>
<documentation sections="Flow Configuration">
<usage>test-mode</usage>
<shortdesc>do not execute any command, only check the syntax</shortdesc>
<description>
<para>
Switch into a mode in which no commands are actually
executed and only command syntax is checked.
</para>
<para>This is equivalent to setting
<literal>$TEST_MODE</literal> variable to 1.</para>
</description>
<see-also>
<ruleref ref="run_mode" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="run_mode" type="command" name="run-mode" inline="yes">
<aliases>
<alias name="run_mode"/>
</aliases>
<production>
<selfref sep="yes"/>
<action>[<lineinfo/>,"run-mode"]</action>
</production>
<documentation sections="Flow Configuration">
<usage>run-mode</usage>
<shortdesc>switch into normal execution mode (quit <xref linkend="test_mode"/>)</shortdesc>
<description>
<para>
Switch from the <xref linkend="test_mode"/> back
to the normal execution mode.
</para>
<para>This is equivalent to setting
<literal>$TEST_MODE</literal> variable to 0.</para>
</description>
<see-also>
<ruleref ref="test_mode" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="debug" type="command" name="debug" inline="yes">
<command maxargs="0" func="set_debug" extraargs="1"/><documentation sections="Configuration">
<usage>debug</usage>
<shortdesc>display many annoying debugging messages</shortdesc>
<description>
<para>Turn on debugging messages.</para>
<para>This is equivalent to setting
<literal>$DEBUG</literal> variable to 1.</para>
</description>
<see-also>
<ruleref ref="nodebug" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="nodebug" type="command" name="nodebug" inline="yes">
<command maxargs="0" func="set_debug" extraargs="0"/><documentation sections="Configuration">
<usage>nodebug</usage>
<shortdesc>turn off debugging messages</shortdesc>
<description>
<para>Turn off debugging messages.</para>
<para>This is equivalent to setting
<literal>$DEBUG</literal> variable to 0.</para>
</description>
<see-also>
<ruleref ref="debug" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="version" type="command" name="version" inline="yes">
<command maxargs="0" func="print_version" extraargs="0"/><documentation sections="Information">
<usage>version</usage>
<shortdesc>show version information</shortdesc>
<description>
<para>
Prints program version plus version numbers of the most
important libraries used.
</para>
</description>
</documentation>
</rule>
<rule id="validation" type="command" name="validation" inline="yes">
<command minargs="1" maxargs="1" func="set_validation"/><documentation sections="Configuration">
<usage>validation <xref linkend="exp"/></usage>
<shortdesc>turn on/off validation in XML parser</shortdesc>
<description>
<para>
Turn on validation during the parse process if the
<xref linkend="exp"/> is non-zero or off otherwise.
Defaults to off.
</para>
<para>This command is equivalent to setting the
<literal>$VALIDATION</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="recovering" type="command" name="recovering" inline="yes">
<command minargs="1" maxargs="1" func="set_recovering"/><documentation sections="Configuration">
<usage>recovering <xref linkend="exp"/></usage>
<shortdesc>turn on/off parser's ability to fix broken XML</shortdesc>
<description>
<para>
If the <xref linkend="exp"/> evaluates to non-zero value,
turn on the recovering parser mode on; turn it off otherwise.
Defaults to off.</para>
<para>Note, that the in the recovering mode,
validation is not performed by the parser even if
the validation flag is on.
</para>
<para>The recover mode helps to efficiently recover
documents that are almost well-formed. This for example
includes documents without a close tag for the document
element (or any other element inside the document).</para>
<para>This command is equivalent to setting the
<literal>$RECOVERING</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="parser_expands_entities" type="command" name="parser-expands-entities" inline="yes">
<aliases>
<alias name="parser_expands_entities"/>
</aliases>
<command minargs="1" maxargs="1" func="set_expand_entities"/><documentation sections="Configuration">
<usage>parser-expands-entities <xref linkend="exp"/></usage>
<shortdesc>turn on/off parser's tendency to expand entities</shortdesc>
<description>
<para>
If the
<xref linkend="exp"/> is non-zero
enable the entity expansion during the parse process; disable it otherwise.
If entity expansion is disabled, any external entity references in parsed
documents are preserved as references. By default, entity expansion
is enabled.
</para>
<para>This command is equivalent to setting the
<literal>$PARSER_EXPANDS_ENTITIES</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="keep_blanks" type="command" name="keep-blanks" inline="yes">
<aliases>
<alias name="keep_blanks"/>
</aliases>
<command minargs="1" maxargs="1" func="set_keep_blanks"/><documentation sections="Configuration">
<usage>keep-blanks <xref linkend="exp"/></usage>
<shortdesc>turn on/off ignorable whitespace preservation</shortdesc>
<description>
<para>
Allows you to turn on/off preserving the parser's default
behavior of preserving all whitespace in the document.
Setting this option to 0, instructs the XML parser
to ignore whitespace occurring between adjacent element
nodes, so that no extra text nodes are created for it.
</para>
<para>This command is equivalent to setting the
<literal>$KEEP_BLANKS</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="pedantic_parser" type="command" name="pedantic-parser" inline="yes">
<aliases>
<alias name="pedantic_parser"/>
</aliases>
<command minargs="1" maxargs="1" func="set_pedantic_parser"/><documentation sections="Configuration">
<usage>pedantic-parser <xref linkend="exp"/></usage>
<shortdesc>make the parser more pedantic</shortdesc>
<description>
<para>
If you wish, you can make the XML parser little more pedantic by passing
a non-zero <xref linkend="exp" /> to this command.
</para>
<para>This command is equivalent to setting the
<literal>$PEDANTIC_PARSER</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="complete_attributes" type="command" name="parser-completes-attributes" inline="yes">
<aliases>
<alias name="complete_attributes"/>
<alias name="complete-attributes"/>
<alias name="parser_completes_attributes"/>
</aliases>
<command minargs="1" maxargs="1" func="set_complete_attributes"/><documentation sections="Configuration">
<usage>parser-completes-attributes <xref linkend="exp"/></usage>
<shortdesc>turn on/off parser's ability to fill default attribute values</shortdesc>
<description>
<para>
If the expression is non-zero, the command makes XML parser
add missing attributes with default values as specified in
a DTD. By default, this option is enabled.
</para>
<para>This command is equivalent to setting the
<literal>$PARSER_COMPLETES_ATTRIBUTES</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="indent" type="command" name="indent" inline="yes">
<command minargs="1" maxargs="1" func="set_indent"/><documentation sections="Configuration">
<usage>indent <xref linkend="exp"/></usage>
<shortdesc>turn on/off pretty-printing</shortdesc>
<description>
<para>If the value of <xref linkend="exp"/> is 1,
saved and listed XML will be formatted
using some (hopefully) ignorable whitespace.
If the value is 2 (or
higher), &XSH; will act as in case of 1, plus it will add a
leading and a trailing linebreak to each text node.
</para>
<para>Note, that since the underlying C library
(libxml2) uses a hard-coded indentation of 2 space
characters per indentation level, the amount of
whitespace used for indentation can not be
altered at runtime.
</para>
<para>This command is equivalent to setting the
<literal>$INDENT</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="empty_tags" type="command" name="empty-tags" inline="yes">
<aliases>
<alias name="empty_tags"/>
</aliases>
<command minargs="1" maxargs="1" func="set_empty_tags"/><documentation sections="Configuration">
<usage>empty-tags <xref linkend="exp"/></usage>
<shortdesc>turn on/off serialization of empty tags</shortdesc>
<description>
<para>If the value of <xref linkend="exp"/> is 1
(non-zero), empty tags are serialized as a
start-tag/end-tag pair
(<literal><foo></foo></literal>). This option
affects both <xref linkend="list_command"/> and <xref linkend="save_command"/> and possibly other
commands. Otherwise, they are compacted into a short-tag
form (<literal><foo/></literal>). Default value is
<literal>0</literal>.
</para>
<para>This command is equivalent to setting the
<literal>$EMPTY_TAGS</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="skip_dtd" type="command" name="skip-dtd" inline="yes">
<aliases>
<alias name="skip_dtd"/>
</aliases>
<command minargs="1" maxargs="1" func="set_skip_dtd"/><documentation sections="Configuration">
<usage>skip-dtd <xref linkend="exp"/></usage>
<shortdesc>turn on/off serialization of DTD DOCTYPE declaration</shortdesc>
<description>
<para>If the value of <xref linkend="exp"/> is 1 (non-zero),
DTD DOCTYPE declaration is omitted from any further serializations
of XML documents (including <xref linkend="list_command"/>
and <xref linkend="save_command"/>). Default value is
<literal>0</literal>.
</para>
<para>This command is equivalent to setting the
<literal>$SKIP_DTD</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="parser_expands_xinclude" type="command" name="parser-expands-xinclude" inline="yes">
<aliases>
<alias name="parser_expands_xinclude"/>
</aliases>
<command minargs="1" maxargs="1" func="set_expand_xinclude"/><documentation sections="Configuration">
<usage>parser-expands-xinclude <xref linkend="exp"/></usage>
<shortdesc>turn on/off transparent XInclude insertion by parser</shortdesc>
<description>
<para>
If the <xref linkend="exp"/> is non-zero, the parser is
allowed to expand XInclude tags immediately while parsing the
document.
</para>
<para>This command is equivalent to setting the
<literal>$PARSER_EXPANDS_XINCLUDE</literal> variable.</para>
</description>
<see-also>
<ruleref ref="process_xinclude_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="load_ext_dtd" type="command" name="load-ext-dtd" inline="yes">
<aliases>
<alias name="load_ext_dtd"/>
</aliases>
<command minargs="1" maxargs="1" func="set_load_ext_dtd"/><documentation sections="Configuration">
<usage>load-ext-dtd <xref linkend="exp"/></usage>
<shortdesc>turn on/off external DTD fetching</shortdesc>
<description>
<para>
Non-zero <xref linkend="exp"/> instructs
the XML parser to load external DTD
subsets declared in XML documents.
This option is enabled by default.
</para>
<para>This command is equivalent to setting the
<literal>$LOAD_EXT_DTD</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="encoding" type="command" name="encoding" inline="yes">
<command minargs="1" maxargs="1" func="set_encoding"/><documentation sections="Configuration">
<usage>encoding <xref linkend="enc_string"/></usage>
<shortdesc>choose output charset</shortdesc>
<description>
<para>Set the default character encoding used
for standard (e.g. terminal) output. This doesn't influence
the encoding used for saving XML documents.
</para>
<para>This command is equivalent to setting the
<literal>$ENCODING</literal> variable.</para>
</description>
<see-also>
<ruleref ref="query_encoding"/>
</see-also>
</documentation>
</rule>
<rule id="query_encoding" type="command" name="query-encoding" inline="yes">
<aliases>
<alias name="query_encoding"/>
</aliases>
<command minargs="1" maxargs="1" func="set_qencoding"/><documentation sections="Configuration">
<usage>query-encoding <xref linkend="enc_string"/></usage>
<shortdesc>declare the charset of &XSH; source files and terminal input</shortdesc>
<description>
<para>Set the default query character encoding, i.e.
encoding used when taking input from &XSH; prompt or standard input.</para>
<para>This command is equivalent to setting the
<literal>$QUERY_ENCODING</literal> variable.</para>
</description>
<see-also>
<ruleref ref="encoding"/>
</see-also>
</documentation>
</rule>
<rule id="quiet" type="command" name="quiet" inline="yes">
<command maxargs="0" func="set_quiet" extraargs="1"/><documentation sections="Configuration">
<usage>quiet</usage>
<shortdesc>turn off many &XSH; messages</shortdesc>
<description>
<para>Turn off verbose messages.</para>
<para>This command is equivalent to setting the
<literal>$QUIET</literal> variable.</para>
</description>
<see-also>
<ruleref ref="verbose" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="cdonopen" type="command" name="switch-to-new-documents" inline="yes">
<aliases>
<alias name="switch_to_new_documents"/>
</aliases>
<command minargs="1" maxargs="1" func="set_cdonopen"/><documentation sections="Configuration Documents">
<usage>switch-to-new-documents <xref linkend="exp"/></usage>
<shortdesc>set on/off changing current document to newly
open/created files</shortdesc>
<description>
<para>If non-zero, &XSH; changes
current node to the document node of a newly open/created
files every time a new document is opened or created with
<xref linkend="open_command"/> or <xref linkend="create_command"/>.
Default value for this option is 1.
</para>
<para>This command is equivalent to setting the
<literal>$SWITCH_TO_NEW_DOCUMENTS</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="backups" type="command" name="backups" inline="yes">
<command maxargs="0" func="set_backups" extraargs="1"/><documentation sections="Configuration Documents">
<usage>backups</usage>
<shortdesc>turn on backup file creation</shortdesc>
<description>
<para>Enable creating backup files on save (default).</para>
<para>This command is equivalent to setting the
<literal>$BACKUPS</literal> variable to 1.</para>
</description>
<see-also>
<ruleref ref="nobackups" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="nobackups" type="command" name="nobackups" inline="yes">
<command maxargs="0" func="set_backups" extraargs="0"/><documentation sections="Configuration Documents">
<usage>nobackups</usage>
<shortdesc>turn off backup file creation</shortdesc>
<description>
<para>Disable creating backup files on save.</para>
<para>This command is equivalent to setting the
<literal>$BACKUPS</literal> variable to 0.</para>
</description>
<see-also>
<ruleref ref="nobackups" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="fold_command" type="command" name="fold" inline="yes">
<command minargs="0" maxargs="1" func="mark_fold">
<param name="depth" short="d" type="exp" argument="exp"/>
</command><documentation sections="Navigation">
<usage>fold [--depth|:d <xref linkend="exp"/>] [<xref linkend="exp"/>]</usage>
<shortdesc>mark elements to be folded by list
command</shortdesc>
<description>
<para>
This feature is still EXPERIMENTAL and
may change in the future!
Fold command may be used to
mark elements with a
<literal>xsh:fold</literal> attribute from the
<literal>http://xsh.sourceforge.net/xsh/</literal> namespace.
When
listing the DOM tree using
<literal><xref linkend="list_command"/> --fold <xref linkend="xpath"/></literal>,
elements marked in this
way are folded to a given depth (default is 0 = fold immediately).
</para>
<para>
The option <literal>--depth</literal> (<literal>:d</literal>)
may be used to specify the depth at which
subtrees of given elements are to be folded.
</para>
<para>
If called without arguments,
the command applies to the current element,
otherwise the <xref linkend="exp"/> is evaluated to the node-list
and folding is applied to all elements within this node-list.
</para>
<example>
<code>xsh> <userinput>fold --depth 1 //chapter</userinput>
xsh> <userinput>ls --fold //chapter[1]</userinput>
<chapter id="intro" xsh:fold="1">
<tab count="1"/><title>...</title>
<tab count="1"/><para>...</para>
<tab count="1"/><para>...</para>
</chapter>
</code>
</example>
</description>
<see-also>
<ruleref ref="unfold_command" arguments=""/>
<ruleref ref="list_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="unfold_command" type="command" name="unfold" inline="yes">
<command minargs="1" maxargs="1" func="mark_unfold"/><documentation sections="Navigation">
<usage>unfold <xref linkend="exp"/></usage>
<shortdesc>unfold elements folded with fold command</shortdesc>
<description>
<para>
This feature is still EXPERIMENTAL!
</para>
<para>Unfold command removes
<literal>xsh:fold</literal> attributes from all given elements.
Such attributes are usually created by previous
usage of <xref linkend="fold_command"/>. Be aware, that
<literal>xmlns:xsh</literal> namespace declaration may
still be present in the document even when all elements
are unfolded.
</para>
</description>
<see-also>
<ruleref ref="fold_command" arguments=""/>
<ruleref ref="list_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="redo_command" type="command" name="redo" inline="yes">
<command maxargs="1" func="loop_redo"/><documentation sections="Flow">
<usage>redo [<xref linkend="exp"/>]</usage>
<shortdesc>restart the innermost enclosing loop block</shortdesc>
<description>
<para>
<literal>redo</literal> restarts a loop block without evaluating
the conditional again. The optional <xref linkend="exp"/> argument
may evaluate to a positive integer number that indicates which
level of the nested loops should be restarted. If omitted, it
defaults to 1, i.e. the innermost loop.
</para>
<para>
Using this command outside a loop causes an immediate
run-time error.
</para>
<example>
<title>Restart a higher level loop from an inner one</title>
<code>while ($i<100) {
<tab count="1"/># ...
<tab count="1"/>foreach //para {
<tab count="1"/><tab count="1"/># some code
<tab count="1"/><tab count="1"/>if $param {
<tab count="1"/><tab count="1"/><tab count="1"/>redo; # redo foreach loop
<tab count="1"/><tab count="1"/>} else {
<tab count="1"/><tab count="1"/><tab count="1"/>redo 2; # redo while loop
<tab count="1"/><tab count="1"/>}
<tab count="1"/>}
}
</code>
</example>
</description>
<see-also>
<ruleref ref="foreach" arguments=""/>
<ruleref ref="while" arguments=""/>
<ruleref ref="iterate" arguments=""/>
<ruleref ref="next_command" arguments=""/>
<ruleref ref="last_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="next_command" type="command" name="next" inline="yes">
<command maxargs="1" func="loop_next"/><documentation sections="Flow">
<usage>next [<xref linkend="exp"/>]</usage>
<shortdesc>start the next iteration of an enclosing
loop</shortdesc>
<description>
<para>
<literal>next</literal> is like the continue statement in C; it starts the
next iteration of an enclosing loop.
The command may be used with an optional argument evaluating
to a positive integer number indicating which
level of the nested loops should be restarted.
If the argument is omitted, it defaults to 1, i.e. the innermost loop.
</para>
<para>
Using this command outside a loop causes an
immediate run-time error.
</para>
</description>
<see-also>
<ruleref ref="foreach" arguments=""/>
<ruleref ref="while" arguments=""/>
<ruleref ref="iterate" arguments=""/>
<ruleref ref="redo_command" arguments=""/>
<ruleref ref="last_command" arguments=""/>
<ruleref ref="prev_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="prev_command" type="command" name="prev" inline="yes">
<command maxargs="1" func="loop_prev"/><documentation sections="Flow">
<usage>prev [<xref linkend="exp"/>]</usage>
<shortdesc>restart an iteration on a previous node</shortdesc>
<description>
<para>
This command is only allowed inside an
<literal>iterate</literal> loop. It returns the iteration
one step back, to the previous node on the iterated axis.
The optional <xref linkend="exp"/> argument may be
used to indicate to which level of nested loops the
command applies to (default is 1).
</para>
</description>
<see-also>
<ruleref ref="iterate" arguments=""/>
<ruleref ref="redo_command" arguments=""/>
<ruleref ref="last_command" arguments=""/>
<ruleref ref="next_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="last_command" type="command" name="last" inline="yes">
<command maxargs="1" func="loop_last"/><documentation sections="Flow">
<usage>last [<xref linkend="exp"/>]</usage>
<shortdesc>immediately exit an enclosing loop</shortdesc>
<description>
<para>
The <literal>last</literal> command is like the break
statement in C (as used in loops); it immediately exits an
enclosing loop. The optional <xref linkend="exp"/>
argument may evaluate to a positive integer number that
indicates which level of the nested loops to quit. If this
argument is omitted, it defaults to 1, i.e. the innermost
loop.
</para>
<para>
Using this command outside a loop causes an
immediate run-time error.
</para>
</description>
<see-also>
<ruleref ref="foreach" arguments=""/>
<ruleref ref="while" arguments=""/>
<ruleref ref="iterate" arguments=""/>
<ruleref ref="next_command" arguments=""/>
<ruleref ref="last_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="return_command" type="command" name="return" inline="yes">
<command maxargs="1" func="call_return"/><documentation sections="Flow">
<usage>return [<xref linkend="exp"/>]</usage>
<shortdesc>return from a subroutine</shortdesc>
<description>
<para>
This command immediately stops the execution of a
procedure it occurs in and returns the execution to the
place of the script from which the subroutine was called.
Optional argument may be used as a return value for the
subroutine call.
</para>
<para>
Using this command outside a subroutine causes an
immediate run-time error.
</para>
</description>
<see-also>
<ruleref ref="def" arguments=""/>
<ruleref ref="call_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="throw_command" type="command" name="throw" inline="yes">
<command minargs="1" maxargs="1" func="throw_exception"/><documentation sections="Flow">
<usage>throw <xref linkend="exp"/></usage>
<shortdesc>throw an exception</shortdesc>
<description>
<para>
This command throws and exception containing error message
given by the obligatory <xref linkend="exp"/>
argument. If the exception is not handled
by some surrounding <xref linkend="try_catch"/> block,
the execution is stopped immediately and the error
message is printed.
</para>
</description>
<see-also>
<ruleref ref="try_catch" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="catalog_command" type="command" name="catalog" inline="yes">
<command minargs="1" maxargs="1" func="load_catalog"/><documentation sections="Documents">
<usage>catalog <xref linkend="filename"/></usage>
<shortdesc>use a catalog file during all parsing processes</shortdesc>
<description>
<para>
Make use of a given XML file as a catalog during all parsing
processes. Using a catalog may significantly speed up
parsing processes if many external resources are loaded
into the parsed documents (such as DTDs or XIncludes).
</para>
</description>
</documentation>
</rule>
<rule id="xpaxis" inline="no">
<production>
<regexp>[-a-z]+::</regexp>
</production>
</rule>
<rule id="xpnodetest" inline="no">
<production>
<regexp>node\(\)|text\(\)|comment\(\)|processing-instruction\(\s*(?:"[^"]*"\s*|'[^'*]'\s*)?\)|[^\(\[\/\"\'\&\;\s]+</regexp>
</production>
</rule>
<rule id="xplocationstep" inline="no">
<production>
<ruleref ref="xpaxis" rep="?" arguments=""/>
<ruleref ref="xpnodetest" arguments=""/>
<action>[ (@{$item[1]} ? $item[1][0] : 'child::'),$item[3] ]</action>
</production>
</rule>
<rule id="xpstep" inline="no">
<production>
<ruleref ref="xplocationstep" arguments=""/>
<directive type="skip">""</directive>
<ruleref ref="xpfilter" rep="?" arguments=""/>
<action>[ @{$item[1]}, @{$item[3]}]</action>
</production>
</rule>
<rule id="iterate" type="command" name="iterate" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<ruleref ref="xpstep" arguments=""/>
<ruleref ref="block" arguments=""/>
<action>[<lineinfo/>,'iterate',$item[4],@{$item[3]}]</action>
</production>
<documentation sections="Flow">
<usage>iterate <xref linkend="xpath"/> <xref linkend="block"/></usage>
<shortdesc>iterate a block over current subtree</shortdesc>
<description>
<para>
Iterate works very much like a <xref
linkend="foreach" /> loop with the
same <xref linkend="xpath"/> expression, except that it
evaluates the <xref linkend="block"/> as soon as a new node
matching a given <xref linkend="xpath"/> is found. As a
limitation, an <xref linkend="xpath"/> expression
used with <literal>iterate</literal> may consist of one XPath
step only, i.e. it may not contain an XPath step separator
<literal>/</literal>.
</para>
<para>
A possible benefit of using <literal>iterate</literal> instead of
<xref linkend="foreach" /> is some efficiency when
iterating over huge node-sets. Since
<literal>iterate</literal> doesn't compute
the resulting node-set in advance, it
doesn't have to 1) allocate extra memory for it
and 2) (more importantly) doesn't have to sort
the node-list in the document order (which
tends to be slow on large node-sets, unless
<xref linkend="index_command"/> is used). On the other
hand, <literal>iterate</literal> suffers from a considerable
speed penalty since it isn't implemented in C (unlike
libxml2's XPath engine).
</para>
<para>
Author's experience shows that, unless <xref linkend="index_command"/>
is used, <literal>iterate</literal> beats
<xref linkend="foreach"/> in speed on large
node-lists (>=1500 nodes, but your milage may vary) while
<xref linkend="foreach"/> wins on smaller node-lists.
</para>
<para>The following two examples give equivalent results.
However, the one using <literal>iterate</literal>
may be faster if the number of nodes being counted
is huge and document order isn't indexed.</para>
<example>
<title>Count inhabitants of the kingdom of Rohan in productive age</title>
<code>cd rohan/inhabitants;</code>
<code>iterate child::*[@age>=18 and @age<60] { perl $productive++ };</code>
<code>echo "$productive inhabitants in productive age";</code>
</example>
<example>
<title>Using XPath</title>
<code>$productive=count(rohan/inhabitants/*[@age>=18 and @age<60]);</code>
<code>echo "$productive inhabitants in productive age";</code>
</example>
<para>
Hint: use e.g. <literal>| time cut</literal> pipe-line
redirection to benchmark a &XSH; command on a UNIX system.
</para>
</description>
<see-also>
<ruleref ref="foreach" arguments=""/>
<ruleref ref="index_command" arguments=""/>
<ruleref ref="next_command" arguments=""/>
<ruleref ref="prev_command" arguments=""/>
<ruleref ref="last_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="registerns_command" type="command" name="register-namespace" inline="yes">
<aliases>
<alias name="regns"/>
</aliases>
<command minargs="2" maxargs="2" func="register_ns"/>
<documentation sections="Namespaces Configuration">
<usage>register-namespace <xref linkend="exp"/> <xref linkend="exp"/></usage>
<shortdesc>register namespace prefix to use XPath expressions</shortdesc>
<description>
<para>
Registers the first argument
as a prefix for the namespace given in the second argument.
The prefix can later be used in XPath expressions.
</para>
</description>
</documentation>
</rule>
<rule id="unregisterns_command" type="command" name="unregister-namespace" inline="yes">
<aliases>
<alias name="unregns"/>
</aliases>
<command minargs="1" maxargs="1" func="unregister_ns"/>
<documentation sections="Namespaces Configuration">
<usage>unregister-namespace <xref linkend="exp"/></usage>
<shortdesc>unregister namespace prefix</shortdesc>
<description>
<para>
Unregisters given namespace prefix previously registered
using <xref linkend="registerns_command"/>. The prefix
can no longer be used in XPath expressions unless declared
within the current scope of the queried document.
</para>
</description>
</documentation>
</rule>
<rule id="registerns_xhtml_command" type="command" name="register-xhtml-namespace" inline="yes">
<aliases>
<alias name="regns-xhtml"/>
</aliases>
<command minargs="1" maxargs="1" func="register_xhtml_ns"/>
<documentation sections="Namespaces Configuration">
<usage>register-xhtml-namespace <xref linkend="exp"/></usage>
<shortdesc>register a prefix for the XHTML namespace</shortdesc>
<description>
<para>
Registers a prefix for the XHTML namespace
<literal>http://www.w3.org/1999/xhtml</literal>.
The prefix can later be used in XPath expressions.
</para>
</description>
</documentation>
</rule>
<rule id="registerns_xsh_command" type="command" name="register-xsh-namespace" inline="yes">
<aliases>
<alias name="regns-xsh"/>
</aliases>
<command minargs="1" maxargs="1" func="register_xsh_ns"/>
<documentation sections="Namespaces Configuration">
<usage>register-xsh-namespace <xref linkend="exp"/></usage>
<shortdesc>register a prefix for the &XSH; namespace</shortdesc>
<description>
<para>
Registers a new prefix for the &XSH; namespace <literal>http://xsh.sourceforge.net/xsh/</literal>. The prefix
can later be used in XPath expressions. Note, that &XSH;
namespace is by default registered with the prefix
<literal>xsh</literal>. This command is thus, in
general, useful only when some document uses
<literal>xsh</literal> prefix for a different namespace
or if you want a shorter prefix.
</para>
</description>
</documentation>
</rule>
<rule id="registerfunc_command" type="command" name="register-function" inline="yes">
<aliases>
<alias name="function"/>
<alias name="regfunc"/>
</aliases>
<command minargs="2" maxargs="2" func="register_func"/><documentation sections="Navigation Configuration">
<usage>register-function <xref linkend="exp"/> <xref linkend="perl_code"/></usage>
<shortdesc>define XPath extension function (EXPERIMENTAL)</shortdesc>
<description>
<para>
EXPERIMENTAL!
</para>
<para>Registers a given perl code as a new XPath
extension function under a name provided in the first
argument. XML::LibXML DOM
API as well as all Perl functions
pre-defined in the XML::XSH2::Map namespace
may be used in the perl code for object processing. If
the name contains a colon, then the first part before the
colon must be a registered namespace prefix
(see <xref linkend="registerns_command"/>) and the function is
registered within the corresponding namespace.
</para>
</description>
</documentation>
</rule>
<rule id="unregisterfunc_command" type="command" name="unregister-function" inline="yes">
<aliases>
<alias name="unregfunc"/>
</aliases>
<command minargs="1" maxargs="1" func="unregister_func"/><documentation sections="Navigation Configuration">
<usage>unregister-function <xref linkend="exp"/></usage>
<shortdesc>undefine extension function (EXPERIMENTAL)</shortdesc>
<description>
<para>
EXPERIMENTAL! Unregister XPath extension function of a
given name previously registered using <xref linkend="registerfunc_command"/>.
</para>
</description>
</documentation>
</rule>
<rule id="stream_select" inline="no">
<production>
<regexp>select\s</regexp>
<ruleref ref="xpath" arguments=""/>
<ruleref ref="block" arguments=""/>
<action>[$item[2],$item[3]]</action>
</production>
</rule>
<rule id="stream_process_command" type="command" name="stream" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<paramlist>
<param name="input-file" short="f" type="string" argument="filename"/>
<param name="input-pipe" short="p" type="string" argument="filename"/>
<param name="input-string" short="s" type="exp" argument="exp"/>
<param name="output-file" short="F" type="string"
argument="filename"/>
<param name="output-encoding" short="E" type="string" argument="enc_string"/>
<param name="output-pipe" short="P" type="string" argument="filename"/>
<param name="output-string" short="S" type="varname" argument="exp"/>
<param name="no-output" short="N"/>
</paramlist>
<ruleref ref="stream_select" rep="s" arguments=""/>
<action>[<lineinfo/>,'stream_process',$item[3],$item[4]]</action>
</production>
<documentation sections="Flow Documents">
<usage>stream
[ --input-file|:f <xref linkend="filename"/> |
--input-pipe|:p <xref linkend="filename"/> |
--input-string|:s <xref linkend="exp"/>]
[ --output-file|:F <xref linkend="filename"/> |
--output-pipe|:P <xref linkend="filename"/> |
--output-string|:S <xref linkend="varname"/> |
--no-output|:N ]
select <xref linkend="xpath"/> <xref linkend="block"/>
[ select <xref linkend="xpath"/> <xref linkend="block"/> ... ]
</usage>
<shortdesc>process selected elements from an XML stream (EXPERIMENTAL)</shortdesc>
<description>
<para>
EXPERIMENTAL! This command provides a memory efficient
(though slower) way to process selected parts of an XML
document with &XSH;. A streaming XML parser (SAX parser) is
used to parse the input. The parser has two states which
will be referred to as A and B below. The initial state of
the parser is A.</para> <para>In the state A, only a
limited vertical portion of the DOM tree is built. All XML
data coming from the input stream other than start-tags
are immediately copied to the output stream. If a new
start-tag of an element arrives, a new node is created in
the tree. All siblings of the newly created node are
removed. Thus, in the state A, there is exactly one node
on every level of the tree. After a node is added to the
tree, all the <xref linkend="xpath"/> expressions
following the <literal>select</literal> keyword
are
checked. If none matches, the parser remains in state A
and copies the start-tag to the output stream. Otherwise,
the first expression that matches is remembered and the
parser changes its state to B.
</para>
<para>
In state B the parser builds a complete DOM subtree of the
element that was last added to the tree before the parser
changed its state from A to B. No data are sent to the
output at this stage. When the subtree is complete
(i.e. the corresponding end-tag for its topmost element is
encountered), the <xref linkend="block"/> of instructions
following the <xref linkend="xpath"/> expression that
matched is invoked with the root element of the subtree as
the current context node. The commands in <xref linkend="block"/> are allowed to transform the whole
element subtree or even to replace it with a different DOM
subtree or subtrees. They must, however, leave intact
all ancestor nodes of the subtree.
Failing to do so can result in an error or
unpredictable results.
</para>
<para>
After the subtree processing <xref linkend="block"/>
returns, all subtrees that now appear in the DOM tree in
the place of the original subtree are serialized to the
output stream. After that, they are deleted and the parser
returns to state A.
</para>
<para>
Note that this type of processing highly limits the amount
of information the selecting XPath expressions can use. The first
notable fact is, that elements can not be selected by their
content. The only information present in the tree at the
time of the XPath evaluation is the element's name and
attributes plus the same information for all its
ancestors (there is no information at all about its possible
child nodes nor of the node's position
within the list of its siblings).
</para>
<para>The input parameters below are mutually exclusive.
If non is given, standard input is processed.</para>
<para><literal>--input-file</literal> or <literal>:f</literal>
instructs the processor to stream from a given file.</para>
<para><literal>--input-pipe</literal> or <literal>:p</literal>
instructs the processor to stream the output of a given a command.</para>
<para><literal>--input-string</literal> or <literal>:s</literal>
instructs the processor to use the result of a given
expression as the input to be processed.
</para>
<para>The output parameters below are mutually exclusive.
If none is given, standard output is used.
</para>
<para><literal>--output-file</literal> or <literal>:F</literal>
instructs the processor to save the output
to a given file.</para>
<para><literal>--output-pipe</literal> or <literal>:P</literal>
instructs the processor to pipe the output
to a given command.
</para>
<para><literal>--output-string</literal> or <literal>:S</literal>
followed by a variable name instructs the processor to
store the result in the given variable.
</para>
<para><literal>--no-output</literal> or <literal>:N</literal>
instructs the processor to throw the result away.
</para>
</description>
</documentation>
</rule>
<rule id="namespaces_command" type="command" name="namespaces" inline="yes">
<command maxargs="1" func="list_namespaces">
<param name="registered" short="r"/>
</command>
<documentation sections="Namespaces Information">
<usage>namespaces [--registered|:r] [<xref linkend="exp"/>]</usage>
<shortdesc>List namespaces available in a context of
a given nodes</shortdesc>
<description>
<para>
For each node in a given node-list lists
all namespaces that are valid the scope of the node.
Namespaces are listed in the form of
<literal>xmlns:prefix="uri"</literal> declarations,
preceded by a canonical xpath of the corresponding node
on a separate line.
</para>
<para>
If <literal>--registered</literal> or <literal>:r</literal>
flag is used, list also namespaces registered with the
<xref linkend="registerns_command"/> command
in XSH syntax.
</para>
<para>
If called without the <literal>--registered</literal> flag and
no <xref linkend="xpath"/> is given, lists namespaces
in the scope of the current node.
</para>
</description>
</documentation>
</rule>
<rule id="xpath_completion_command" type="command" name="xpath-completion" inline="yes">
<aliases>
<alias name="xpath_completion"/>
</aliases>
<command minargs="1" maxargs="1" func="set_xpath_completion"/><documentation sections="Configuration">
<usage>xpath-completion <xref linkend="exp"/></usage>
<shortdesc>turn on/off TAB completion for xpath expressions in
the interactive mode</shortdesc>
<description>
<para>
If the
<xref linkend="exp"/> is non-zero,
enable the TAB completion for <xref linkend="xpath"/>
expansions in the interactive shell mode, disable it
otherwise. Defaults to on.
</para>
<para>This command is equivalent to setting the
<literal>$XPATH_COMPLETION</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="xpath_axis_completion_command" type="command" name="xpath-axis-completion" inline="yes">
<aliases>
<alias name="xpath_axis_completion"/>
</aliases>
<command minargs="1" maxargs="1" func="set_xpath_axis_completion"/><documentation sections="Configuration">
<usage>xpath-axis-completion <xref linkend="exp"/></usage>
<shortdesc>sets TAB completion for axes in xpath expressions in
the interactive mode</shortdesc>
<description>
<para>
The following values are allowed:
<literal>always</literal>, <literal>never</literal>,
<literal>when-empty</literal>. Note, that all other values
(including 1) work as <literal>never</literal>!
</para>
<para>
If the <xref linkend="exp"/> evaluates
to <literal>always</literal>, TAB completion for
XPath expressions always includes axis names.
</para>
<para>
If the <xref linkend="exp"/> evaluates to
<literal>when-empty</literal>, the TAB completion list for
XPath expressions includes axis names only if no element name
matches the completion.
</para>
<para>
If the <xref linkend="exp"/> evaluates to
<literal>never</literal>, the TAB completion list for
XPath expressions never includes axis names.
</para>
<para>
The default value for this option is
<literal>always</literal>.
</para>
<para>This command is equivalent to setting the
<literal>$XPATH_AXIS_COMPLETION</literal> variable.</para>
</description>
</documentation>
</rule>
<rule id="doc_info_command" type="command" name="doc-info" inline="yes">
<aliases>
<alias name="doc_info"/>
</aliases>
<command maxargs="1" func="doc_info"/><documentation sections="Information">
<usage>doc-info [<xref linkend="document"/>]</usage>
<shortdesc>displays various information about a document</shortdesc>
<description>
<para>
In the present implementation, this command displays
information provided in the <literal><?xml
...?></literal> declaration of a document:
<literal>version, encoding, standalone</literal>,
plus information about
level of <literal>gzip</literal> compression of the
original XML file and
the original XML file URI.
</para>
</description>
<see-also>
<ruleref ref="set_enc_command" arguments=""/>
<ruleref ref="set_standalone_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="xpath_extensions_command" type="command" name="xpath-extensions" inline="yes">
<aliases>
<alias name="xpath_extensions"/>
</aliases>
<command maxargs="1" func="xpath_extensions"/><documentation sections="Configuration">
<usage>xpath-extensions [<xref linkend="exp"/>]</usage>
<shortdesc>map predefined &XSH; XPath extension functions to
no or other namespace
</shortdesc>
<description>
<para>
<literal>xpath-extensions</literal>
remaps all extra
XPath extension functions provided by &XSH;
(which by default belong to the namespace
<literal>http://xsh.sourceforge.net/xsh/</literal>)
to a new namespace given by <xref linkend="exp"/>.
If the argument is omitted, the functions
are re-registered without any namespace,
so that they may be called without a
namespace prefix, just by their function
names. This quite convenient.
</para>
<example>
<code>xpath-extensions;
ls grep(//word,"^.*tion$");</code>
</example>
</description>
<see-also>
<ruleref ref="set_enc_command" arguments=""/>
<ruleref ref="set_standalone_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="lineno_command" type="command" name="lineno" inline="yes">
<command maxargs="1" func="print_lineno"/><documentation sections="Information">
<usage>lineno [<xref linkend="exp"/>]</usage>
<shortdesc>print line-numbers corresponding to matching nodes</shortdesc>
<description>
<para>
<literal>lineno</literal>
command prints line numbers of
all nodes in a given node-list. Note however, that
<literal>libxml2</literal>
only stores line number information for element nodes.
</para>
</description>
<see-also>
<ruleref ref="locate_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="ignore_use_command" name="use" inline="yes">
<production>
<selfref sep="yes"/>
<directive type="commit"/>
<regexp>XML::XSH2::(?:Inline|Compile)</regexp>
<action>1</action>
</production>
</rule>
<rule id="edit_string_command" type="command" name="edit-string" inline="yes">
<command minargs="1" maxargs="1" func="edit" extraargs="1">
<param name="editor" short="E" type="string" argument="exp"/>
<param name="encoding" short="e" type="string" argument="enc_string"/>
<param name="allow-empty" short="0"/>
</command>
<documentation sections="Manipulation">
<usage>edit-string [--editor|:E <xref linkend="filename"/>]
[--encoding|:e <xref linkend="enc_string"/>]
[--allow-empty|:0] <xref linkend="exp"/></usage>
<shortdesc>Edit a string or variable in a text editor.</shortdesc>
<description>
<para>
Evaluating given <xref linkend="exp"/> to a string,
save it in a temporary file,
open the file an external editor as a plain text,
and when the editor exits,
read and return the result. The <literal>--editor</literal>
(<literal>:E</literal>) parameter can be used
to provide an editor command, whereas
<literal>--encoding</literal> (<literal>:e</literal>)
can be used to specify character encoding used for
communication with the editor. If the result
is empty, the interactive &XSH; shell asks user for
confirmation before returning the result in order
to prevent data loss due to some unexpected error.
To suppress this feature, use <literal>--allow-empty</literal>
or <literal>:0</literal> flag.
</para>
</description>
</documentation>
</rule>
<rule id="edit_command" type="command" name="edit" inline="yes">
<command maxargs="1" func="edit">
<param name="editor" short="E" type="string" argument="exp"/>
<param name="all" short="A"/>
<param name="noindent" short="n"/>
<param name="recover" short="r"/>
<param name="keep-blanks" short="k"/>
<param name="allow-empty" short="0"/>
<param name="no-comment" short="q"/>
<param name="encoding" short="e" type="string" argument="enc_string"/>
</command>
<documentation sections="Manipulation">
<usage>edit [--editor|:E <xref linkend="filename"/>]
[--all|:A] [--noindent|:n] [--recover|:r] [--keep-blanks|:k]
[--allow-empty|:0] [--no-coment|:q] [--encoding|:e <xref
linkend="enc_string"/>] <xref linkend="exp"/>
</usage>
<shortdesc>Edit parts of a XML document in a text editor.</shortdesc>
<description>
<para>This command may be used to interactively edit parts of a XML
document directly in your favorite editor.
</para>
<para>
A given <xref linkend="exp" /> is evaluated to a node-list and the
first the first resulting node is opened
in an external editor as a XML fragment.
When the editor exits, the (possibly modified) fragment
is parsed and returned to the original document. Unless
<literal>--no-comment</literal> (<literal>:q</literal>) flag is
used, the XML fragment is preceded with a XML comment specifying
canonical XPath of the node being edited.
</para>
<para>
The command returns a node-list consisting of nodes
that resulted from parsing the individual edits.
</para>
<para>
<literal>--editor</literal> or <literal>:E</literal>
option may be used to specify external editor command.
If not specified, environment variables
<literal>EDITOR</literal> and <literal>VISUAL</literal>
are tried first, then <literal>vi</literal> editor
is used as a fallback.
</para>
<para>
If <literal>--all</literal> or <literal>:A</literal>
flag is present, all nodes from the node-list
are opened in the editor, one at a time.
</para>
<para>
If <literal>--recover</literal> or <literal>:r</literal>
is specified, the parser tries to recover from possible
syntax errors when parsing the resulting XML.
</para>
<para>
<literal>--keep-blanks</literal> or <literal>:b</literal>
option may be used to force the parser to
include ignorable white space.
</para>
<para>If the result saved
by the editor is empty, the interactive
&XSH; shell asks user to confirm this was correct.
This confirmation can be suppressed using
<literal>--allow-empty</literal> or
<literal>:0</literal> (zero) options.
</para>
<para>
The <literal>--encoding</literal> or <literal>:e</literal>
parameter can be used to specify character encoding to
use when communicating with the external editor.
</para>
<example>
<title>Edit all chapter elements (one by one) with emacs</title>
<code>edit --editor 'emacs -nw' --encoding iso-8859-1 --all //chapter</code>
</example>
</description>
</documentation>
</rule>
<!-- ================== FUNCTIONS ====================== -->
<rule id="doc_function" type="function" name="xsh:doc" inline="no">
<documentation>
<usage>node-set xsh:doc(node-set)</usage>
<description>
<para>
Returns a node-set consisting of the owner document nodes
of all nodes in the given node-set.
</para>
</description>
</documentation>
</rule>
<rule id="document_uri_function" type="function" name="xsh:document-uri" inline="no">
<documentation>
<usage>string xsh:document-uri(node-set?)</usage>
<description>
<para>Returns URI of the document containing
the first node in the given node-set.
If called without arguments, or if the node-set is
empty, returns filename of the document containing the current node.
</para>
</description>
</documentation>
</rule>
<rule id="filename_function" type="function" name="xsh:filename" inline="no">
<documentation>
<usage>string xsh:filename(node-set?)</usage>
<description>
<para>Same as xsh:document-uri();</para>
</description>
</documentation>
</rule>
<rule id="base_uri_function" type="function" name="xsh:base-uri" inline="no">
<documentation>
<usage>string xsh:base-uri(node-set?)</usage>
<description>
<para>Returns base URI of the first node in the node-set (or
the current node). The function should work on both XML and
HTML documents even if base mechanisms for these are
completely different. It returns the base as defined in RFC
2396 sections "5.1.1. Base URI within Document Content" and
"5.1.2. Base URI from the Encapsulating Entity". However it
does not return the document base (5.1.3), use
document-uri() for this.
</para>
</description>
</documentation>
</rule>
<rule id="resolve_uri_function" type="function" name="xsh:resolve-uri" inline="no">
<documentation>
<usage>string xsh:resolve-uri(string, string?)</usage>
<description>
<para>
This function takes one or two arguments: a relative URI and an optional base URI.
If the first argument is a relative URI reference,
this function resolves it against either the
given base URI, if given (which is assumed to be an absolute URI)
or, if base URI not given, against the URI of the current working directory.
If the first argument is an absolute URI reference, it is returned unchanged.
</para>
<para>
If the first argument is the zero-length string, returns
the base URI if given and the URI of the current working directory otherwise.
</para>
<para>
Note: Resolving a URI does not dereference it (download
the referenced content); it is merely a syntactic
operation on two character strings.
</para>
</description>
</documentation>
</rule>
<rule id="lineno_function" type="function" name="xsh:lineno" inline="no">
<documentation>
<usage>node-set xsh:lineno(node-set)</usage>
<description>
<para>Returns line number of the occurrence of
the first node in the given node-set in its original XML
document (if available).
</para>
</description>
</documentation>
</rule>
<rule id="var_function" type="function" name="xsh:var" inline="no">
<documentation>
<usage>node-set xsh:var(string NAME)</usage>
<description>
<para>
Returns a node-set consisting of nodes stored in a &XSH; node-list
variable named <literal>NAME</literal>.
</para>
</description>
</documentation>
</rule>
<rule id="matches_function" type="function" name="xsh:matches" inline="no">
<documentation>
<usage>boolean xsh:matches(string STR,string PATTERN)</usage>
<description>
<para>
Returns <literal>true</literal> if <literal>STR</literal>
matches the regular expression <literal>PATTERN</literal>.
Otherwise returns <literal>false</literal>.
</para>
</description>
</documentation>
</rule>
<rule id="match_function" type="function" name="xsh:match" inline="no">
<documentation>
<usage>node-set xsh:match(string STR,string PATTERN,string OPTIONS)</usage>
<description>
<para>
Searches a given string for a pattern match
specified by a regular expression <literal>PATTERN</literal>
and returns a node-set consisting of
<literal><xsh:string></literal>
elements containing portions of the string matched
by the pattern subexpressions enclosed in parentheses.
The OPTIONS string may contain the following flags:
<literal>c</literal> - do not reset search position on a failed match when /g is in effect;
<literal>g</literal> - match globally, i.e. find all occurrences;
<literal>i</literal> - do case insensitive search;
<literal>m</literal> - treat string as multiple lines
(change "^" and "$" from matching the start or end of the string to matching the start or end
of any line anywhere within the string)
<literal>o</literal> - compile pattern only once;
<literal>s</literal> - treat string as single line (change "." to match any character whatsoever, even a newline, which normally it would not match);
<literal>x</literal> - extend your pattern's legibility by permitting whitespace and comments.
</para>
</description>
</documentation>
</rule>
<rule id="grep_function" type="function" name="xsh:grep" inline="no">
<documentation>
<usage>node-set xsh:grep(node-set NODES, string PATTERN)</usage>
<description>
<para>
Returns a node set consisting of those nodes of
<literal>NODES</literal> whose content
(as returned by the built-in XPath
function <literal>string()</literal>)
matches the regular expression <literal>PATTERN</literal>.
</para>
</description>
</documentation>
</rule>
<rule id="substr_function" type="function" name="xsh:substr" inline="no">
<documentation>
<usage>string xsh:substr(string STR,float OFFSET,[float LENGTH])</usage>
<description>
<para>
Extracts a substring out of <literal>STR</literal>
and returns it. First character is at offset 0.</para>
<para>
If <literal>OFFSET</literal> is negative, starts
that far from the end of the string. </para>
<para>
If <literal>LENGTH</literal> is
omitted, returns everything to the end of the
string. If <literal>LENGTH</literal> is negative,
leaves that many characters off the end of the string.</para>
<para>
If <literal>OFFSET</literal> and
<literal>LENGTH</literal> specify a substring that is
partly outside the string, only the part within
the string is returned. If the substring is
beyond either end of the string, substr() returns
empty string and produces a warning.
</para>
</description>
</documentation>
</rule>
<rule id="reverse_function" type="function" name="xsh:reverse" inline="no">
<documentation>
<usage>string xsh:reverse(string STR)</usage>
<description>
<para>
Returns a string value same as <literal>STR</literal>
but with all characters in the opposite order.
</para>
</description>
</documentation>
</rule>
<rule id="lc_function" type="function" name="xsh:lc" inline="no">
<documentation>
<usage>string xsh:lc(string STR)</usage>
<description>
<para>
Returns a lowercased version of <literal>STR</literal>.
</para>
</description>
</documentation>
</rule>
<rule id="uc_function" type="function" name="xsh:uc" inline="no">
<documentation>
<usage>string xsh:uc(string STR)</usage>
<description>
<para>
Returns a uppercased version of <literal>STR</literal>.
</para>
</description>
</documentation>
</rule>
<rule id="lcfirst_function" type="function" name="xsh:lcfirst" inline="no">
<documentation>
<usage>string xsh:lcfirst(string STR)</usage>
<description>
<para>
Returns the value of <literal>STR</literal>
with the first character lowercased.
</para>
</description>
</documentation>
</rule>
<rule id="ucfirst_function" type="function" name="xsh:ucfirst" inline="no">
<documentation>
<usage>string xsh:ucfirst(string STR)</usage>
<description>
<para>
Returns the value of <literal>STR</literal>
with the first character uppercased.
</para>
</description>
</documentation>
</rule>
<rule id="same_function" type="function" name="xsh:same" inline="no">
<documentation>
<usage>bool xsh:same(node-set N1, node-set N2)</usage>
<description>
<para>
Returns <literal>true</literal> if the given node sets
both contain the same node
(in XPath, this can also be expressed as
<literal>count(N1|N2)+count(N1)+count(N2)=3</literal>).
</para>
</description>
</documentation>
</rule>
<rule id="max_function" type="function" name="xsh:max" inline="no">
<documentation>
<usage>float xsh:max(object EXPRESSION, ...)</usage>
<description>
<para>
Returns the maximum of numeric values
computed from given <literal>EXPRESSION</literal>(s).
If <literal>EXPRESSION</literal> evaluates to a node-set,
string values of individual nodes are used.
</para>
</description>
</documentation>
</rule>
<rule id="min_function" type="function" name="xsh:min" inline="no">
<documentation>
<usage>float xsh:min(object EXPRESSION, ...)</usage>
<description>
<para>
Returns the minimum of numeric values
computed from given <literal>EXPRESSION</literal>(s).
If <literal>EXPRESSION</literal> evaluates to a node-set,
string values of individual nodes are used.
</para>
</description>
</documentation>
</rule>
<rule id="strmax_function" type="function" name="xsh:strmax" inline="no">
<documentation>
<usage>string xsh:strmax(object EXPRESSION, ...)</usage>
<description>
<para>
Returns a string value computed as the maximum
(in lexicographical order)
of all string values computed from given
<literal>EXPRESSION</literal>(s).
If <literal>EXPRESSION</literal> evaluates to a node-set,
string values of individual nodes are used.
</para>
</description>
</documentation>
</rule>
<rule id="strmin_function" type="function" name="xsh:strmin" inline="no">
<documentation>
<usage>string xsh:strmin(object EXPRESSION, ...)</usage>
<description>
<para>
Returns a string value computed as the minimum
(in lexicographical order)
of all string values computed from given
<literal>EXPRESSION</literal>(s).
If <literal>EXPRESSION</literal> evaluates to a node-set,
string values of individual nodes are used.
</para>
</description>
</documentation>
</rule>
<rule id="sum_function" type="function" name="xsh:sum" inline="no">
<documentation>
<usage>float xsh:sum(object EXPRESSION, ...)</usage>
<description>
<para>
Returns the sum of numerical value
computed from given
<literal>EXPRESSION</literal>(s).
If <literal>EXPRESSION</literal> evaluates to a node-set,
string values of individual nodes are used.
</para>
</description>
</documentation>
</rule>
<rule id="join_function" type="function" name="xsh:join" inline="no">
<documentation>
<usage>string xsh:join(string DELIM, object EXPRESSION,...)</usage>
<description>
<para>
Joins the separate string values computed from
<literal>EXPRESSION</literal>(s) into a single
string with fields separated by the
value of <literal>DELIM</literal>,
and returns that new string.
If <literal>EXPRESSION</literal> evaluates to a node-set,
joins string values of individual nodes.
</para>
</description>
</documentation>
</rule>
<rule id="subst_function" type="function" name="xsh:subst" inline="no">
<documentation>
<usage>string xsh:subst(string STR,string REGEXP,string
REPLACEMENT, [string OPTIONS])</usage>
<description>
<para>
Acts in the very same way as perl substitution operation
<literal>STRING =~ s/REGEXP/REPLACEMENT/OPTIONS</literal>,
returning the resulting string.
Searches a string for a pattern, and if found,
replaces that pattern with the replacement text.
If the <literal>REPLACEMENT</literal> string
contains a <literal>$</literal> that looks like a variable,
the variable will be interpolated
into the </para>
<para><literal>REPLACEMENT</literal> at run-time.
Options are:
</para>
<para>
<literal>e</literal> - evaluate <literal>REPLACEMENT</literal>
as a Perl expression,</para>
<para>
<literal>g</literal> - replace globally, i.e., all occurrences,</para>
<para>
<literal>i</literal> - do case-insensitive pattern matching,</para>
<para>
<literal>m</literal> - treat string as multiple lines,
that is, change <literal>^</literal>
and <literal>$</literal> from matching the start or end
of the string to matching the start or end of any line anywhere
within the string,</para>
<para>
<literal>s</literal> - treat string as single line,
that is, change <literal>.</literal>
to match any character whatsoever, even a newline, which
normally it would not match,</para>
<para>
<literal>x</literal> - use extended regular expressions.
</para>
</description>
</documentation>
</rule>
<rule id="sprintf_function" type="function" name="xsh:sprintf" inline="no">
<documentation>
<usage>string xsh:sprintf(string FORMAT,object EXPRESSION,...)</usage>
<description>
<para>
Returns a string formatted by the usual <literal>printf</literal>
conventions of the C library function <literal>sprintf</literal>
and <literal>sprintf</literal> Perl function.</para>
<para>
See C documentation for an explanation of the
general principles and Perl documentation
for a list of supported formatting conversions.
</para>
</description>
</documentation>
</rule>
<rule id="serialize_function" type="function" name="xsh:serialize" inline="no">
<documentation>
<usage>string xsh:serialize(node-set N,...)</usage>
<description>
<para>
Serializes nodes of given node-set(s)
into XML strings and returns concatenation of
those strings.
</para>
</description>
</documentation>
</rule>
<rule id="parse_function" type="function" name="xsh:parse" inline="no">
<documentation>
<usage>node-set xsh:parse(string XML-STRING)</usage>
<description>
<para>
This function runs XML parser on <literal>XML-STRING</literal>
and returns a node-set consisting
of the top-level nodes of the resulting document node.
</para>
</description>
</documentation>
</rule>
<rule id="current_function" type="function" name="xsh:current" inline="no">
<documentation>
<usage>node-set xsh:current()</usage>
<description>
<para>
This function (very similar to XSLT <literal>current()</literal>
extension function) returns a node-set having the
current node as its only
member.
</para>
</description>
</documentation>
</rule>
<rule id="path_function" type="function" name="xsh:path" inline="no">
<documentation>
<usage>string xsh:path(node-set NODE)</usage>
<description>
<para>
This function returns a string containing
canonical XPath leading
to <literal>NODE</literal>.
</para>
</description>
<see-also>
<ruleref ref="pwd_command" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="if_function" type="function" name="xsh:if" inline="no">
<documentation>
<usage>object xsh:if(object CONDITION, object YES, object NO)</usage>
<description>
<para>
This function returns the <literal>YES</literal> object
if <literal>CONDITION</literal> is an non-empty
node-set or a string, boolean or integer
evaluating to non-zero boolean. Otherwise the
<literal>NO</literal> object is returned.
</para>
</description>
</documentation>
</rule>
<rule id="new_attribute_function" type="function" name="xsh:new-attribute" inline="no">
<documentation>
<usage>node-set xsh:new-attribute(string NAME1,string
VALUE1,[string NAME2, string VALUE2, ...])</usage>
<description>
<para>
Return a node-set consisting
of newly created attribute nodes
with given names and respective values.
</para>
</description>
</documentation>
</rule>
<rule id="new_element_function" type="function" name="xsh:new-element" inline="no">
<documentation>
<usage>node-set xsh:new-element(string NAME,[string ATTR1-NAME1,
string ATTR-VALUE1, ...])</usage>
<description>
<para>
Create a new element node with given
<literal>NAME</literal> and optionally attributes with
given names and values and return a node-set containing
the new node as its only member.
</para>
</description>
</documentation>
</rule>
<rule id="new_element_ns_function" type="function" name="xsh:new-element-ns" inline="no">
<documentation>
<usage>node-set xsh:new-element-ns(string NAME,string NS,[string ATTR1-NAME1,
string ATTR-VALUE1, ...])</usage>
<description>
<para>
Create a new element node with given <literal>NAME</literal> and
namespace-uri <literal>NS</literal> and optionally attributes with given
names and values and return a node-set
containing the new node as its only member.
</para>
</description>
</documentation>
</rule>
<rule id="new_text_function" type="function" name="xsh:new-text" inline="no">
<documentation>
<usage>node-set xsh:new-text(string DATA)</usage>
<description>
<para>
Create a new text node containing given
<literal>DATA</literal> and return a node-set containing
the new node as its only member.
</para>
</description>
</documentation>
</rule>
<rule id="new_comment_function" type="function" name="xsh:new-comment" inline="no">
<documentation>
<usage>node-set xsh:new-comment(string DATA)</usage>
<description>
<para>
Create a new comment node containing given
<literal>DATA</literal> and return a node-set containing
the new node as its only member.
</para>
</description>
</documentation>
</rule>
<rule id="new_pi_function" type="function" name="xsh:new-pi" inline="no">
<documentation>
<usage>node-set xsh:new-pi(string NAME, [string DATA])</usage>
<description>
<para>
Create a new processing instruction node node with given
<literal>NAME</literal> and (optionally) given
<literal>DATA</literal> and return a node-set containing
the new node as its only member.
</para>
</description>
</documentation>
</rule>
<rule id="new_cdata_function" type="function" name="xsh:new-cdata" inline="no">
<documentation>
<usage>node-set xsh:new-cdata(string DATA)</usage>
<description>
<para>
Create a new cdata section node node filled with
given <literal>DATA</literal> and return a node-set
containing the new node as its only member.
</para>
</description>
</documentation>
</rule>
<rule id="new_chunk_function" type="function" name="xsh:new-chunk" inline="no">
<documentation>
<usage>node-set xsh:new-chunk(string XML)</usage>
<description>
<para>
This is just an alias for <xref linkend="parse_function"/>. It parses given piece of XML
and returns a node-set consisting of the top-level element
within the parsed tree.
</para>
</description>
</documentation>
</rule>
<rule id="map_function" type="function" name="xsh:map" inline="no">
<documentation>
<usage>node-set xsh:map(node-set NODE, string XPATH)</usage>
<description>
<para>
This function is very similar to EXSLT
<literal>dynamic:map</literal> function. The description
below is almost literally taken from the <ulink url="http://www.exslt.org/dyn/functions/map/index.html">EXSLT
specification</ulink>.
</para>
<para>
The <literal>xsh:map</literal> function evaluates the
expression passed as the second argument for each of
the nodes passed as the first argument, and returns a
node-set of those values.
</para>
<para>
The expressions are evaluated relative to the nodes
passed as the first argument. In other words, the value
for each node is calculated by evaluating the XPath
expression with all context information being the same as
that for the call to the <literal>xsh:map</literal>
function itself, except for the following:
</para>
<para>
1) the context node is the node whose value is being
calculated, 2) the context position is the position of the
node within the node set passed as the first argument to
the <literal>xsh:map</literal> function, arranged in
document order, and 3) the context size is the number of
nodes passed as the first argument to the dyn:map function.
</para>
<para>
If the expression string passed as the second argument is
an invalid XPath expression (including an empty string),
this function returns an empty node set.
</para>
<para>
If <literal>XPATH</literal> evaluates as a node set, the
<literal>xsh:map</literal> function returns the union of
the node sets returned by evaluating the expression for
each of the nodes in the first argument. Note that this
may mean that the node set resulting from the call to the
<literal>xsh:map</literal> function contains a different
number of nodes from the number in the node set passed as
the first argument to the function.
</para>
<para>
If <literal>XPATH</literal> evaluates as a number, the
<literal>xsh:map</literal> function returns a node set
containing one <literal>xsh:number</literal> element
(namespace
<literal>http://xsh.sourceforge.net/xsh/</literal>) for
each node in the node set passed as the first argument to
the dyn:map function, in document order. The string value
of each <literal>xsh:number</literal> element is the same
as the result of converting the number resulting from
evaluating the expression to a string as with the number
function, with the exception that Infinity results in an
<literal>xsh:number</literal> holding the highest number
the implementation can store, and -Infinity results in an
<literal>xsh:number</literal> holding the lowest number
the implementation can store.
</para>
<para>
If <literal>XPATH</literal> evaluates as a boolean, the
<literal>xsh:map</literal> function returns a node set
containing one <literal>xsh:boolean</literal> element
(namespace
<literal>http://xsh.sourceforge.net/xsh/</literal>) for
each node in the node set passed as the first argument to
the <literal>xsh:map</literal> function, in document
order. The string value of each
<literal>xsh:boolean</literal> element is
<literal>true</literal> if the expression evaluates as
true for the node, and is empty if the expression evaluates as
false.
</para>
<para>
Otherwise, the <literal>xsh:map</literal> function returns
a node set containing one <literal>xsh:string</literal>
element (namespace
<literal>http://xsh.sourceforge.net/xsh/</literal>) for
each node in the node set passed as the first argument to
the <literal>xsh:map</literal> function, in document
order. The string value of each
<literal>xsh:string</literal> element is the same as the
result of converting the result of evaluating the
expression for the relevant node to a string as with the
string function.
</para>
</description>
<see-also>
<ruleref ref="evaluate_function" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="evaluate_function" type="function" name="xsh:evaluate" inline="no">
<documentation>
<usage>node-set xsh:evaluate(string XPATH)</usage>
<description>
<para>
This function is very similar to EXSLT
<literal>dynamic:evaluate</literal> function. The description
below is almost literally taken from the <ulink url="http://www.exslt.org/dyn/functions/map/index.html">EXSLT
specification</ulink>.
</para>
<para>
The <literal>xsh:evaluate</literal> function evaluates a string as an XPath expression
and returns the resulting value, which might be a boolean, number,
string, node set, result tree fragment or external object. The sole
argument is the string to be evaluated.
</para>
<para>
The string is always evaluated exactly as if it had been literally
included in place of the call to the <literal>xsh:evaluate</literal> function.
</para>
<para>
In other words, the context information used when evaluating the
XPath expression passed as the argument to the <literal>xsh:evaluate</literal>
function is exactly the same as the context information used when
evaluating the <literal>xsh:evaluate</literal> function. This context information
includes:
</para>
<enumerate>
<listitem>
<para>
the context node, such that paths are evaluated relative to the
context node at the point where the <literal>xsh:evaluate</literal> function is
called
</para>
</listitem>
<listitem>
<para>
the context position, such that the expression can contain
calls to the position function
</para>
</listitem>
<listitem>
<para>
the context size, such that the expression can contain calls to
the last function
</para>
</listitem>
<listitem>
<para>
variable bindings, such that the expression can contain
variable references
</para>
</listitem>
<listitem>
<para>
function library, such that the expression can contain calls to
extension functions
</para>
</listitem>
<listitem>
<para>
namespace declarations, such that paths can contain prefixes
the current node, such that the expression can contain calls to
the current function
</para>
</listitem>
</enumerate>
<para>
If the expression string passed as the second argument is an
invalid XPath expression (including an empty string), this function
returns an empty node set.
</para>
<para>
You should only use this function if the expression must be
constructed dynamically - otherwise it is much more efficient to
use the expression literally. For expressions that simply give an
element or attribute's name (to select a child element or
attribute), it is more efficient to use an expression
in the style:
</para>
<code>*[name() = $expression]</code>
</description>
<see-also>
<ruleref ref="map_function" arguments=""/>
</see-also>
</documentation>
</rule>
<rule id="split_function" type="function" name="xsh:split" inline="no">
<documentation>
<usage>node-set xsh:split(string PATTERN, string STRING)</usage>
<description>
<para>
This function provides direct access to the very powerful
Perl function <literal>split</literal>. It splits
<literal>STRING</literal> to a list of
fields. <literal>PATTERN</literal> is a regular expression
specifying strings delimiting individual fields of
<literal>STRING</literal>. If <literal>PATTERN</literal>
is empty, <literal>STRING</literal> is split to individual
characters. If the regular expression in
<literal>PATTERN</literal> is enclosed in brackets, then
strings matching <literal>PATTERN</literal> are also
included in the resulting list.
</para>
<para>
The function returns a node-set consisting of
newly created <literal><xsh:string></literal>
elements containing individual strings of the resulting
list as their only text child nodes.
</para>
</description>
</documentation>
</rule>
<rule id="times_function" type="function" name="xsh:times" inline="no">
<documentation>
<usage>node-set xsh:times(string STRING, float COUNT)</usage>
<description>
<para>
This function returns a string
resulting from concatenation of <literal>COUNT</literal>
copies of <literal>STRING</literal>.
<literal>COUNT</literal> must be a non-negative integer value.
</para>
</description>
</documentation>
</rule>
<rule id="id2_function" type="function" name="xsh:id2" inline="no">
<documentation>
<usage>node-set xsh:id2(node-set DOC, string IDs)</usage>
<description>
<para>
This function is like XPath built-in <literal>id(IDs)</literal>
function, except that it operates on the document
specified in the first argument. It returns a node-set
consisting of nodes that belong to the document DOC
and whose ID belongs to the list of space separated
IDs specified in the second argument.
</para>
</description>
</documentation>
</rule>
<rule id="lookup_function" type="function" name="xsh:lookup" inline="no">
<documentation>
<usage>node-set xsh:lookup(string VARNAME, string KEY)</usage>
<description>
<para>
This function is similar to XSLT <literal>key()</literal>
function. It returns a node-set
stored in a hash VARNAME under the key KEY.
The VARNAME must be a name of a lexical or global
XSH variable containing a Perl hash reference.
</para>
</description>
<see-also>
<ruleref ref="hash_command"/>
</see-also>
</documentation>
</rule>
<rule id="document_function" type="function" name="xsh:document" inline="no">
<documentation>
<usage>node-set xsh:document(string URL)</usage>
<description>
<para>
Looks up among the currently open document the one whose
filename is same as the given URL and returns the
corresponding document node. If no document's filename
matches exactly the given URL, then several heuristic
matches are tried: if the URI is a relative filename, it
is tilde-expanded and resolved (using the current working
directory as a base) and the lookup is restarted with the
absolute filename; finally, a lookup identifying filenames
with URLs of the file:// protocol is attempted. If the
lookup fails completely, an empty node set is returned.
</para>
</description>
<see-also>
<ruleref ref="hash_command"/>
</see-also>
</documentation>
</rule>
<rule id="documents_function" type="function" name="xsh:documents" inline="no">
<documentation>
<usage>node-set xsh:documents()</usage>
<description>
<para>
Returns a node-set consisting of the document
nodes of all currently open documents.
</para>
</description>
<see-also>
<ruleref ref="hash_command"/>
</see-also>
</documentation>
</rule>
<rule id="span_function" type="function" name="xsh:span" inline="no">
<documentation>
<usage>node-set xsh:span(node-set START,node-set END)</usage>
<description>
<para>
Returns a node-set which forms a span of sibling nodes
starting at START node and ending at END node (only the first node
of each of the nodesets is used). It is an error if the START
node and END node are not siblings.
</para>
</description>
</documentation>
</rule>
<rule id="context_function" type="function" name="xsh:context" inline="no">
<documentation>
<usage>node-set xsh:context(node-set NODE, float BEFORE, float AFTER)</usage>
<description>
<para>
Returns a node-set of sibling nodes surrounding NODE. The
span consists of (up to) BEFORE-many nodes immediately
preceding NODE, the NODE itself, and (up to) AFTER-many
nodes immediately following NODE. If the AFTER is not
given, AFTER is set equal to BEFORE.
</para>
</description>
</documentation>
</rule>
<!-- CALL COMMAND SHOULD BE LAST ! -->
<rule id="call_command" type="command" name="call" inline="no">
<command minargs="1" func="call_command"/>
<documentation sections="Flow">
<usage>call <xref linkend="exp"/> [<xref linkend="exp"/> ...]</usage>
<shortdesc>indirect call to a user-defined routine (macro)</shortdesc>
<description>
<para>
Call a subroutine whose name is computed by evaluating
the first argument <xref linkend="exp"/>. All other
expressions are evaluated too and the results are passed
to the subroutine as arguments.
</para>
<para>
This command should only be used if the name of the subroutine
isn't known at the compile time. Otherwise it is recommended
to use a direct subroutine call of the form:
</para>
<code>subroutine-name [argument1 argument2 ...]</code>
<example>
<code>def a $arg { echo "A says" $arg }
def b $arg { echo "B says" $arg }
a "hallo!"; # call subroutine a
b "hallo!"; # call subroutine b
call { chr(ord("a")+rand(2)) } "surprise!"; # call a or b randomly
</code>
</example>
</description>
<see-also>
<ruleref ref="def" arguments=""/>
<ruleref ref="return_command" arguments=""/>
</see-also>
</documentation>
</rule>
</rules>
</recdescent-xml>
<!-- Keep this comment at the end of the file
Local variables:
mode: xml
sgml-omittag:nil
sgml-shorttag:nil
sgml-namecase-general:nil
sgml-general-insert-case:lower
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-exposed-tags:nil
sgml-local-catalogs:("/usr/lib/sgml-tools/dtd/catalog /home/pajas/lib/sgml/iso-entities-8879.1986/iso-entities.cat /home/pajas/share/sgml/dtd/docbook/3.1/docbook.cat /home/pajas/share/sgml/stylesheets/docbook/catalog /home/pajas/share/sgml/entities/iso-entities-8879.1986/iso-entities.cat /home/pajas/share/sgml/dtd/jade/dsssl.cat /home/pajas/share/sgml/stylesheets/sgmltools/sgmltools.cat /home/pajas/share/sgml/dtd/sgmltools/catalog")
sgml-local-ecat-files:nil
End:
-->