XML-XSH2
view release on metacpan or search on metacpan
src/xsh_grammar.xml view on Meta::CPAN
</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'>"
src/xsh_grammar.xml view on Meta::CPAN
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>
src/xsh_grammar.xml view on Meta::CPAN
<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
( run in 0.509 second using v1.01-cache-2.11-cpan-39bf76dae61 )