2
#include "libexslt/libexslt.h"
4
#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
5
#include <win32config.h>
10
#include <libxml/tree.h>
11
#include <libxml/xpath.h>
12
#include <libxml/xpathInternals.h>
13
#include <libxml/parser.h>
14
#include <libxml/hash.h>
16
#include <libxslt/xsltconfig.h>
17
#include <libxslt/xsltutils.h>
18
#include <libxslt/xsltInternals.h>
19
#include <libxslt/extensions.h>
25
* @ctxt: an XSLT transformation context
26
* @URI: the namespace URI for the extension
28
* Initializes the SAXON module.
30
* Returns the data for this transformation
32
static xmlHashTablePtr
33
exsltSaxonInit (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
34
const xmlChar *URI ATTRIBUTE_UNUSED) {
35
return xmlHashCreate(1);
40
* @ctxt: an XSLT transformation context
41
* @URI: the namespace URI for the extension
42
* @data: the module data to free up
44
* Shutdown the SAXON extension module
47
exsltSaxonShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
48
const xmlChar *URI ATTRIBUTE_UNUSED,
49
xmlHashTablePtr data) {
50
xmlHashFree(data, (xmlHashDeallocator) xmlXPathFreeCompExpr);
55
* exsltSaxonExpressionFunction:
56
* @ctxt: an XPath parser context
57
* @nargs: the number of arguments
59
* The supplied string must contain an XPath expression. The result of
60
* the function is a stored expression, which may be supplied as an
61
* argument to other extension functions such as saxon:eval(),
62
* saxon:sum() and saxon:distinct(). The result of the expression will
63
* usually depend on the current node. The expression may contain
64
* references to variables that are in scope at the point where
65
* saxon:expression() is called: these variables will be replaced in
66
* the stored expression with the values they take at the time
67
* saxon:expression() is called, not the values of the variables at
68
* the time the stored expression is evaluated. Similarly, if the
69
* expression contains namespace prefixes, these are interpreted in
70
* terms of the namespace declarations in scope at the point where the
71
* saxon:expression() function is called, not those in scope where the
72
* stored expression is evaluated.
74
* TODO: current implementation doesn't conform to SAXON behaviour
75
* regarding context and namespaces.
78
exsltSaxonExpressionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
80
xmlXPathCompExprPtr ret;
82
xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
85
xmlXPathSetArityError(ctxt);
89
arg = xmlXPathPopString(ctxt);
90
if (xmlXPathCheckError(ctxt) || (arg == NULL)) {
91
xmlXPathSetTypeError(ctxt);
95
hash = (xmlHashTablePtr) xsltGetExtData(tctxt,
96
ctxt->context->functionURI);
98
ret = xmlHashLookup(hash, arg);
101
ret = xmlXPathCompile(arg);
104
xsltGenericError(xsltGenericErrorContext,
105
"{%s}:%s: argument is not an XPath expression\n",
106
ctxt->context->functionURI, ctxt->context->function);
109
xmlHashAddEntry(hash, arg, (void *) ret);
114
xmlXPathReturnExternal(ctxt, ret);
118
* exsltSaxonEvalFunction:
119
* @ctxt: an XPath parser context
120
* @nargs: number of arguments
122
* Implements de SAXON eval() function:
123
* object saxon:eval (saxon:stored-expression)
124
* Returns the result of evaluating the supplied stored expression.
125
* A stored expression may be obtained as the result of calling
126
* the saxon:expression() function.
127
* The stored expression is evaluated in the current context, that
128
* is, the context node is the current node, and the context position
129
* and context size are the same as the result of calling position()
130
* or last() respectively.
133
exsltSaxonEvalFunction (xmlXPathParserContextPtr ctxt, int nargs) {
134
xmlXPathCompExprPtr expr;
135
xmlXPathObjectPtr ret;
138
xmlXPathSetArityError(ctxt);
142
if (!xmlXPathStackIsExternal(ctxt)) {
143
xmlXPathSetTypeError(ctxt);
147
expr = (xmlXPathCompExprPtr) xmlXPathPopExternal(ctxt);
149
ret = xmlXPathCompiledEval(expr, ctxt->context);
151
valuePush(ctxt, ret);
155
* exsltSaxonEvaluateFunction:
156
* @ctxt: an XPath parser context
157
* @nargs: number of arguments
159
* Implements the SAXON evaluate() function
160
* object saxon:evaluate (string)
161
* The supplied string must contain an XPath expression. The result of
162
* the function is the result of evaluating the XPath expression. This
163
* is useful where an expression needs to be constructed at run-time or
164
* passed to the stylesheet as a parameter, for example where the sort
165
* key is determined dynamically. The context for the expression (e.g.
166
* which variables and namespaces are available) is exactly the same as
167
* if the expression were written explicitly at this point in the
168
* stylesheet. The function saxon:evaluate(string) is shorthand for
169
* saxon:eval(saxon:expression(string)).
172
exsltSaxonEvaluateFunction (xmlXPathParserContextPtr ctxt, int nargs) {
174
xmlXPathSetArityError(ctxt);
178
exsltSaxonExpressionFunction(ctxt, 1);
179
exsltSaxonEvalFunction(ctxt, 1);
183
* exsltSaxonSystemIdFunction:
184
* @ctxt: an XPath parser context
185
* @nargs: number of arguments
187
* Implements the SAXON systemId() function
188
* string saxon:systemId ()
189
* This function returns the system ID of the document being styled.
192
exsltSaxonSystemIdFunction(xmlXPathParserContextPtr ctxt, int nargs)
197
xmlXPathSetArityError(ctxt);
201
if ((ctxt->context) && (ctxt->context->doc) &&
202
(ctxt->context->doc->URL))
203
valuePush(ctxt, xmlXPathNewString(ctxt->context->doc->URL));
205
valuePush(ctxt, xmlXPathNewString(BAD_CAST ""));
209
* exsltSaxonLineNumberFunction:
210
* @ctxt: an XPath parser context
211
* @nargs: number of arguments
213
* Implements the SAXON line-number() function
214
* integer saxon:line-number()
216
* This returns the line number of the context node in the source document
217
* within the entity that contains it. There are no arguments. If line numbers
218
* are not maintained for the current document, the function returns -1. (To
219
* ensure that line numbers are maintained, use the -l option on the command
222
* The extension has been extended to have the following form:
223
* integer saxon:line-number([node-set-1])
224
* If a node-set is given, this extension will return the line number of the
225
* node in the argument node-set that is first in document order.
228
exsltSaxonLineNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
229
xmlNodePtr cur = NULL;
232
cur = ctxt->context->node;
233
} else if (nargs == 1) {
234
xmlXPathObjectPtr obj;
235
xmlNodeSetPtr nodelist;
238
if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) {
239
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
240
"saxon:line-number() : invalid arg expecting a node-set\n");
241
ctxt->error = XPATH_INVALID_TYPE;
245
obj = valuePop(ctxt);
246
nodelist = obj->nodesetval;
247
if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) {
248
xmlXPathFreeObject(obj);
249
valuePush(ctxt, xmlXPathNewFloat(-1));
252
cur = nodelist->nodeTab[0];
253
for (i = 1;i < nodelist->nodeNr;i++) {
254
int ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]);
256
cur = nodelist->nodeTab[i];
258
xmlXPathFreeObject(obj);
260
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
261
"saxon:line-number() : invalid number of args %d\n",
263
ctxt->error = XPATH_INVALID_ARITY;
267
valuePush(ctxt, xmlXPathNewFloat(xmlGetLineNo(cur)));
272
* exsltSaxonRegister:
274
* Registers the SAXON extension module
277
exsltSaxonRegister (void) {
278
xsltRegisterExtModule (SAXON_NAMESPACE,
279
(xsltExtInitFunction) exsltSaxonInit,
280
(xsltExtShutdownFunction) exsltSaxonShutdown);
281
xsltRegisterExtModuleFunction((const xmlChar *) "expression",
283
exsltSaxonExpressionFunction);
284
xsltRegisterExtModuleFunction((const xmlChar *) "eval",
286
exsltSaxonEvalFunction);
287
xsltRegisterExtModuleFunction((const xmlChar *) "evaluate",
289
exsltSaxonEvaluateFunction);
290
xsltRegisterExtModuleFunction ((const xmlChar *) "line-number",
292
exsltSaxonLineNumberFunction);
293
xsltRegisterExtModuleFunction ((const xmlChar *) "systemId",
295
exsltSaxonSystemIdFunction);