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 * exsltSaxonLineNumberFunction:
184 * @ctxt: an XPath parser context
185 * @nargs: number of arguments
187 * Implements the SAXON line-number() function
188 * integer saxon:line-number()
190 * This returns the line number of the context node in the source document
191 * within the entity that contains it. There are no arguments. If line numbers
192 * are not maintained for the current document, the function returns -1. (To
193 * ensure that line numbers are maintained, use the -l option on the command
196 * The extension has been extended to have the following form:
197 * integer saxon:line-number([node-set-1])
198 * If a node-set is given, this extension will return the line number of the
199 * node in the argument node-set that is first in document order.
202 exsltSaxonLineNumberFunction(xmlXPathParserContextPtr ctxt
, int nargs
) {
203 xmlNodePtr cur
= NULL
;
206 cur
= ctxt
->context
->node
;
207 } else if (nargs
== 1) {
208 xmlXPathObjectPtr obj
;
209 xmlNodeSetPtr nodelist
;
212 if ((ctxt
->value
== NULL
) || (ctxt
->value
->type
!= XPATH_NODESET
)) {
213 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
214 "saxon:line-number() : invalid arg expecting a node-set\n");
215 ctxt
->error
= XPATH_INVALID_TYPE
;
219 obj
= valuePop(ctxt
);
220 nodelist
= obj
->nodesetval
;
221 if ((nodelist
== NULL
) || (nodelist
->nodeNr
<= 0)) {
222 xmlXPathFreeObject(obj
);
223 valuePush(ctxt
, xmlXPathNewFloat(-1));
226 cur
= nodelist
->nodeTab
[0];
227 for (i
= 1;i
< nodelist
->nodeNr
;i
++) {
228 int ret
= xmlXPathCmpNodes(cur
, nodelist
->nodeTab
[i
]);
230 cur
= nodelist
->nodeTab
[i
];
232 xmlXPathFreeObject(obj
);
234 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
235 "saxon:line-number() : invalid number of args %d\n",
237 ctxt
->error
= XPATH_INVALID_ARITY
;
241 valuePush(ctxt
, xmlXPathNewFloat(xmlGetLineNo(cur
)));
246 * exsltSaxonRegister:
248 * Registers the SAXON extension module
251 exsltSaxonRegister (void) {
252 xsltRegisterExtModule (SAXON_NAMESPACE
,
253 (xsltExtInitFunction
) exsltSaxonInit
,
254 (xsltExtShutdownFunction
) exsltSaxonShutdown
);
255 xsltRegisterExtModuleFunction((const xmlChar
*) "expression",
257 exsltSaxonExpressionFunction
);
258 xsltRegisterExtModuleFunction((const xmlChar
*) "eval",
260 exsltSaxonEvalFunction
);
261 xsltRegisterExtModuleFunction((const xmlChar
*) "evaluate",
263 exsltSaxonEvaluateFunction
);
264 xsltRegisterExtModuleFunction ((const xmlChar
*) "line-number",
266 exsltSaxonLineNumberFunction
);