To allow more complex tasks to be achieved, XSH provides ways for interaction with the Perl programming language and the system shell.
Perl is a language optimized for scanning arbitrary text files, extracting information from those text files, and printing reports based on that information. It's also a good language for many system management tasks. The language is intended to be practical (easy to use, efficient, and complete). XSH itself is written in Perl, so it is extremely easy to support this language as an extension to XSH.
Perl expressions or blocks of code can either be simply evaluated with the perl command, used to do quick changes to nodes of the DOM tree (see map command), used to provide list of strings to iterate over in a foreach loop, or to specify more complex conditions for if, unless, and while statements.
To prevent conflict between XSH internals and the evaluated perl code, XSH runs such code in the context of a special namespace XML::XSH::Map. As described in the section Variables, XSH string variables may be accessed and possibly assigned from Perl code in the most obvious way, since they actually are Perl variables defined in the XML::XSH::Map namespace.
The interaction between XSH and Perl actually works also the other way round, so that you may call back XSH from the evaluated Perl code. For this, Perl function xsh is defined in the XML::XSH::Map namespace. All parameters passed to this function are interpreted as XSH commands. To simplify evaluation of XPath expressions, another three functions: The first one, named count, returns the same value as would be printed by count command in XSH on the same XPath expression. The second function, named literal, returns the result of XPath evaluation as if the whole expression was wrapped with the XPath string() function. In other words, literal('doc:expression') returns the same value as count('doc:string(expression)'). The third function, named xml_list, returns the result of the XPath search as a XML string which is equivallent to the output of a ls on the same XPath expression (without indentation and without folding or any other limitation on the depth of the listing).
In the following examples we use Perl to populate the Middle-Earth with Hobbits whose names are read from a text file called hobbits.txt, unless there are some Hobbits in Middle-Earth already.
XSH allows the user to extend the set of XPath functions by providing an extension function written in Perl. This can be achieved using the register-function command. The perl code implementing an extension function works as a usual perl routine accepting its arguments in @_ and returning the result. The following conventions are used:
The arguments passed to the perl implementation by the XPath engine are either simple scalars or XML::LibXML::NodeList objects, depending on the types of the XPath arguments. The implementation is responsible for checking the argument number and types. The implementation may use arbitrary XML::LibXML methods to process the arguments and return the result. (XML::LibXML perl module documentation can be found for example at http://search.cpan.org/author/PHISH/XML-LibXML-1.54/LibXML.pm).
The implementation SHOULD NOT, however, MODIFY the document. Doing so could not only confuse the XPath engine but result in an critical error (such as segmentation fault).
Calling XSH commands from extension function implementations is not currently allowed.
The perl code must return a single value, which can be of one of the following types: a simple scalar (a number or string), XML::LibXML::Boolean object reference (result is a boolean value), XML::LibXML::Literal object reference (result is a string), XML::LibXML::Number object reference (resulat is a float), XML::LibXML::Node (or derived) object reference (result is a nodeset consisting of a single node), or XML::LibXML::NodeList (result is a nodeset). For convenience, simple (non-blessed) array references consisting of XML::LibXML::Node objects can also be used for a nodeset result instead of a XML::LibXML::NodeList.
In the interactive mode, XSH interprets all lines starting with a exclamation mark (!) as shell commands and invokes the system shell to interpret them (this is to mimic FTP command-line interpreters).
xsh> !ls -l -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
To invoke a system shell command or program from the non-interactive mode or from a complex XSH construction, use the exec command.
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 command. Since semicolon (;) is used in XSH to separate commands, it has to be prefixed with a backslash if it should be used for other purposes.