Implementation of the "x:value-of" function evolved to a quest. There are many questions, and in order to find answers, I have to dig in the source code of libxml and libxslt.
As soon as I finally passed the compilation step, I got a coredump. I used gdb to look at the core and found that the XPath evaluation function may return not only nodesets, but also basic types such as booleans, strings and similar.
I consulted implementation of the xsl:copy-of function and borrowed the approach from it.
It checks if an XPath result is the real nodeset or the document node and performs appropriate actions. Otherwise, it uses xmlXPathConvertString to make a string from the result of any type.
I corrected x:value-of to set the context node for correct calculation of relative XPaths. It took some time because I had no idea how to do it. I remembered about xmlXPathSetContextNode in Python bindings, so I looked at their source code and found that it's enough to set node field of the xmlXPathContext structure.
I shouldn't have problems with the document order, but I'd like to know more about some issues. Does xmlXPathEvalExpression return nodes in the document order? If not, is there an example how it can return a nodeset with an incorrect order? Why there are two functions to sort nodesets: xmlXPathNodeSetSort and xsltDocumentSortFunction? The former looks better, so I use it. But I'm afraid to miss something important.
The problems left:
- the function "document()" is not found. Probably I should perform some additional initialization of libxslt.
- x:value-of should support namespaces and XSLT variables.