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.
In XSH2, subroutines can be called without a call. They can be redefined and undefined. The command call can still be used, but it's use only makes sense in indirect calls, where subroutine's name is computed from an expression.
def foo $param1 $param2 { # param1 and $param2 are lexical (a.k.a. my) ls $param1; echo $param2 } foo (//chapter)[1] (//chapter)[1]/title def inc $param1 { return ($param1 + 1) } $two := inc 1;
XSH2 uses variables of the form $variable 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.
$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
XSH2 allows variables to be used in XPath just as they are used in XSLT:
$var = //foo/bar; ls //baz[ . = $var[@test=1]/any ]
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":
$filter = "[ . = $var[@test=1]/any ]"; ls //baz${filter};
XSH2 equally supports XPath and Perl expressions (written in braces { ... }). Unfortunately, Perl expressions can't be embedded in XPath expressions, but one can still use variables as an agent:
perl { use MIME::Base64 }; my $encoded = { encode_base64('open sesame') } ls //secret-cave[string(password) = $encoded]
We can, however, use Perl-only expressions complemented with auto-conversion to do things like:
copy { encode_base64('Pe do mellon a minno!') } replace //secret-cave/password/text();
Commands return values (see := assignment, or &{ } expressions).
$moved_paras := xmove //para replace .; $chapter := wrap chapter $moved_paras; ls $chapter; # or just ls &{ wrap chapter &{ xmove //para replace . } };
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):
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
In XSH2, XML documents have no ID. They are referred to using variables (which fits in well with the unified variable concept):
$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
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).
$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;
Finally, eval is no longer
an alias for perl in XSH2,
but instead evaluates strings containing XSH2 commands
(so eval $string
now practically works like old ugly
perl { xsh($string) }
). See the documentation for
eval for a handy usage example
(no more PHP, XSTL and XPathScript :-)).
Example 12. Open command has changed.
XSH1: foo = file.xml; or foo = "file.xml";
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
Example 13. XSH2 commands have options
XSH1: open HTML FILE foo2 = "file.html";
XSH2: $foo2 := open --format html "file.html";
Example 14. documents
XSH1: foo = file.xml; ls foo:(//bar|//baz);
XSH2: $foo := open file.xml; ls ($foo//bar|$foo//baz);
Example 15. variable interpretation
XSH1: $family = "Arial"; ls //font[@family="$family"]; # interpolation or ls //font[@family="${family}"]; # interpolation
XSH2: $family = "Arial"; ls //font[@family=$family]; # evaluation by XPath engine or ls //font[@family="${family}"]; # interpolation
Example 16. adding new nodes
XSH1: insert attribute "foo=bar" into /scratch;
XSH2: insert attribute "foo=bar" into /scratch; or copy xsh:new-attribute("foo","bar") into /scratch;
Example 17. foreach with perl expression
XSH1: foreach { glob('*.xml') } { open doc = $__; ... }
XSH2: foreach { glob('*.xml') } { my $doc := open .; ... }
Example 18. foreach (perl expression) with variable
XSH2: foreach my $filename in { glob('*.xml') } { my $doc := open $filename; ... }
Example 19. sorting nodes
XSH1: %list = //player; sort @best_score { $a <=> $b } %list; copy %list into .;
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 .;