Over the holidays I decided to whet my appetite to do more with client-side XSLT by developing a small Web App. I've started things off with an XPath Analyser, a simple app, but one that can be developed to be a more sophisticated XPath Tool in a number of separate stages.
Even with a small app it helps to write a tool that accomplishes something vaguely useful, so XPath Analyser lets you enter any XPath Expression (1.0 or 2.0) and colorises it when you press . If I want to include an XPath Expression in my blog (using Bloggers Rich Editor), instead of including something like:
if (count($splitToken) ne 2)
then dxt:main[attribute::place + 1.34e-27 = 28] (: Edit XPath and Refresh :)
else if ($splitToken[1] eq 'instance' and $splitToken[2] eq 'of') (:to review expressions (: castable as :) :)
then (count($pxt:pcz) ge 2200 or pxt:dema/pxt:semi[@test])
else if ($splitToken[1] = ('cast','castable','treat','(:literal:)') and $splitToken[2] eq 'as')
then true() else some $pxa in tree/branches satisfies $pxa > 22
I can make it prettier, by pressing Run and then copying and pasting from the tool, I then get this:
if (count($splitToken) ne 2)
then dxt:main[attribute::place + 1.34e-27 = 28] (: Edit XPath and Refresh :)
else if ($splitToken[1] eq 'instance' and $splitToken[2] eq 'of') (:to review expressions (: castable as :) :)
then (count($pxt:pcz) ge 2200 or pxt:dema/pxt:semi[@test])
else if ($splitToken[1] = ('cast','castable','treat','(:literal:)') and $splitToken[2] eq 'as')
then true() else some $pxa in tree/branches satisfies $pxa > 22
Much better, and just 500 or so lines of XSLT! One of the benefits of writing a lexer/parser with XSLT is that the declarative nature of the language helps enforce a certain-level of design discipline, especially helpful with XPath as there are some quite complex syntax rules.
Now, this isn't a true XPath Parser, such as Dimitre Novatchev's, but it does provides enough structure for colorising and will help with the next stage which is to dynamically generate selected parts as sub-expressions, by prepending the context path:
$a[position() lt $c][position() gt sum(25 + @books
when @books is selected, output is
$a[position() lt $c]/@books
0 comments:
Post a Comment