I just found an article titled
Querying s-expressions in Common Lisp
that Slava Akhmechet posted to defmacro.org
last year. (Yes, I know--old news. I have a lot of catching up to do.)
The article got me excited because I am an XQuery programmer and
I've always wanted to see something like XPath in Lisp and in Perl. (Thanks
Slava!) I've even mentioned this to my peers. But I'm not talking about a
library to manipulate, navigate, or query XML. Rather, like Slava, I'm
thinking about a library to deal with native data structures (s-expressions
in Lisp and nested hashes/arrays in Perl).
In my work, I do 2 kinds of things with XQuery:
- Locate large records in a native XML database containing tens of
millions of records. For this I need a highly optimized system that
indexes everything and that uses XQuery, such as Mark Logic Server.
- Take records (for example, the ones I located in Thing 1 above) and
transform them to render the results to XHTML or to some other XML
format (Web service output, for example).
Most of the code that I write is for Thing 2 above, which could be replaced
easily with a Lisp library. A properly written one would probably work
faster than the XQuery that I use. And, in Lisp, you'd have to implement
only the XPath part, because all of the rest of the XQuery functionality is
already implemented in the Lisp language itself, in a way that is far
better than anything XQuery could ever achieve.
XPath supports some idioms that allow you to concisely identify a record or
a set of records. Some of these can be easily emulated using Slava's code
as a basis together with some additional code. I'm certain that Slava's
code could be extended easily to make such idioms just as concise as
XPath. For example, given the following s-expression, which I'll call
(city "New Orleans")
and the equivalent XML (let's call it $node), the XPath for retrieving the names
of the adults that appear in the data structure is:
$node/people/person[age ge 18]/name/text()
$node//person[age ge 18]/name/text()
The way that I came up with for doing the same thing in Lisp (using Slava's
s-query code) is:
(mapcar (lambda (y) (cadar (s-query y '(name))))
(remove-if-not (lambda (x) (> (cadar (s-query x '(age))) 18))
(s-query *xml* '(people *))))
I'd love to see a way to do this in Lisp using 1/3 of the code that I'm
using above. Or rather, I want to be able to do in Lisp everything that XPath
does, in just as concise a manner. It is the XPath that gives XQuery its
strength in a native XML database environment. I'd love to be able to give
Lisp the same capabilities.
If anyone knows of a library like the one I'm describing here, please let
me know in the comments.