Use case: matching instead of selecting

28 views
Skip to first unread message

Bart Schuller

unread,
Oct 3, 2011, 6:14:59 PM10/3/11
to anti-xm...@googlegroups.com
Hi,

Prompted by someone wondering whether Scala could replace XSLT (I happen to think XSLT is very hard to beat when you deal with XML documents as opposed to whatever else it's (mis)used for), I started a little experiment: a demonstration of the <xsl:apply-templates/> and <xsl:template match="foo"/> combo in Scala. See Example1.scala (the whole project is just 2 files).

The idea is that the user of this tool writes templates, each of which is supposed to match one node and do something useful on a successful match. Return values are gathered into a result tree. The special applyTemplates(group) call recursively applies the machinery to the specified group.

Because we're using a language with native matching capabilities, I decided to try how far a PartialFunction would take me, instead of a full-blown language like xpath.

If we take this snippet

case Elem(None, "title", _, _, cs) =>
      Elem(None, "h1", Attributes(), Map(), applyTemplates(cs))

then I observe the following (concentrating on the matching):

a) Yay! it works
b) It's ugly and long-winded, with too many underscores and commas
c) It can't match on parents ("chapter/title" in xpath), but attributes and children can be queried, although that too takes many characters to write out

Solutions I can think of:

b) custom extractors: e@E("title") => applyTemplates(e \ *)
c) something to do with Zippers?

Aside: I'm currently not using zippers, but I already noticed something strange would happen if I were to use them to navigate the tree: Normally you'd use this tool to create an output tree from scratch, but because I use flatMap on the current selection, I will get a giant confused zipper that I really didn't ask for. I know I can strip the zipper, but it seems wasteful to even create one.
Can I have a zipperless flatMap?

Now continuing with c, using a zipper I at least have access to the zipper's parent. But when I flatMap a zipper, I get a plain Node passed to my function, so I'll need to pass something extra (the zipper being traversed I guess) if I want to give my templates access to the parent. Right now it looks like the match expressions will become pretty convoluted, but I'll have a look at what the custom extractors can do.

I now suspect that the answer to my matching question is either extractors or xpath. I also need to explore http://scala-scales.googlecode.com/svn/sites/scales/scales-xml_2.9.1/0.2/ScalesXmlIntro.html because it looks like they are actually quite a bit further along, use case-wise.


Observations on generating XML will follow in another mail.

Regards,

Bart.

Erik Bruchez

unread,
Oct 4, 2011, 1:23:01 PM10/4/11
to anti-xm...@googlegroups.com
XSLT matchers are way more expressive and compact. The main drawback I
see is that they don't do destructuring.

Doing any really useful pattern matching on XML in Scala with a decent
syntax remains a pipe dream. Maybe the idea should just be abandoned
until Scala pattern matching is somehow vastly improved.

Wouldn't it be nice to write something as this (here copying XSLT
syntax for the matching expression but the point is to illustrate the
compactness):

elem match {
case my:foo//*[not(self::my:bar) and my:baz] => ...
}

-Erik

Reply all
Reply to author
Forward
0 new messages