XSLT's principle of greatest surprise

Ruby and Python both claim to adhere to the principle of least surprise, that is: things should work as the human coding in them expects to. But for today the rants about that are on hold. Still, in the last few days I made up my mind on something related: XSLT adheres to the principle of greatest surprise.

  • XPath's data model is based on 4 data types: string, number, boolean, node-set. XSLT adds to it one more: document tree fragment (DTF). When you define a variable (or, better since XSLT is a functional programming language, when you bind a value to a name) you play with a value and a name. No matter the type of the value, that value is automatically casted to a DTF after the binding. Guess you can avoid it? Wrong. Guess you can cast it back to another data type when needed? Wrong, unless the desired data type is a string. The only other thing you can do with it is output to the final document.

    • Sure, you say, but you have the wonderful EXSLT extensions which standardized exsl:node-set() to cast back a DTF to a node-set (which probably has been previously automatically casted to a DTF by binding it to a variable name). Then, after crossing your fingers in the hope your XSLT processor implements the given extension, guess with me: since a node-set is automatically converted to a DTF with a dummy root node and one children for each node in the node-set (as it is according to XSLT specs), what do you expect exsl:node-set() on that node set to return? The original node-set? Wrong. You will have back a node-set with the dummy node as only member. ... enjoy tons of exsl:node-set($var)//* expressions in your code
  • Being node-sets the only sequence-like data type in the language, what would you do in case you need to first create a list of strings and then pack them with a join-like function intermixing a textual separator? I personally would go for recursively creating a node-set of strings and then join them. Nice try, but wrong. Adjacent strings in a node-set are automatically joined during processing: bye-bye hope of joining them later. The solution? Wrapper elements around each string in the node-set ...

  • So you have other wonderful extensions like the set module of EXSLT which implements set-like operations on node-sets. Having seen the following functions: set:difference(), set:intersection(), ... and knowing that for booleans there are true() and false(), wouldn't you expect to have set:empty-node-set()? I would, but unfortunately the problem is not I was unlucky in guessing the name, there is no such function in the language or in the extensions at all. Everyone in using hacks like /..

  • AFAIK the most popular XSLT processor on Unix-like systems is xsltproc, which also implements several of the EXSLT extensions. Yay! Of the modules you see listed on the EXSLT web page, what's the one, out of heart, you think you can't live without. . . . . Regular Expressions!, precisely the one xsltproc is not implementing. I had to switch to 4xslt: nice and Pythonish, but not exactly as fast as a lighting bolt.

/me stops at 50% of my ~/Desktop/xslt-sucks.txt

If only CDuce had a syntax I'm able to remember ...