Roll src/third_party/WebKit a3b4a2e:7441784 (svn 202551:202552)
[chromium-blink-merge.git] / third_party / libxslt / libexslt / saxon.c
blobe92ba8d04a92114b647bd25dcea813167a035dda
1 #define IN_LIBEXSLT
2 #include "libexslt/libexslt.h"
4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
5 #include <win32config.h>
6 #else
7 #include "config.h"
8 #endif
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>
21 #include "exslt.h"
23 /**
24 * exsltSaxonInit:
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);
38 /**
39 * exsltSaxonShutdown:
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
46 static void
47 exsltSaxonShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
48 const xmlChar *URI ATTRIBUTE_UNUSED,
49 xmlHashTablePtr data) {
50 xmlHashFree(data, (xmlHashDeallocator) xmlXPathFreeCompExpr);
54 /**
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.
77 static void
78 exsltSaxonExpressionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
79 xmlChar *arg;
80 xmlXPathCompExprPtr ret;
81 xmlHashTablePtr hash;
82 xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
84 if (nargs != 1) {
85 xmlXPathSetArityError(ctxt);
86 return;
89 arg = xmlXPathPopString(ctxt);
90 if (xmlXPathCheckError(ctxt) || (arg == NULL)) {
91 xmlXPathSetTypeError(ctxt);
92 return;
95 hash = (xmlHashTablePtr) xsltGetExtData(tctxt,
96 ctxt->context->functionURI);
98 ret = xmlHashLookup(hash, arg);
100 if (ret == NULL) {
101 ret = xmlXPathCompile(arg);
102 if (ret == NULL) {
103 xmlFree(arg);
104 xsltGenericError(xsltGenericErrorContext,
105 "{%s}:%s: argument is not an XPath expression\n",
106 ctxt->context->functionURI, ctxt->context->function);
107 return;
109 xmlHashAddEntry(hash, arg, (void *) ret);
112 xmlFree(arg);
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.
132 static void
133 exsltSaxonEvalFunction (xmlXPathParserContextPtr ctxt, int nargs) {
134 xmlXPathCompExprPtr expr;
135 xmlXPathObjectPtr ret;
137 if (nargs != 1) {
138 xmlXPathSetArityError(ctxt);
139 return;
142 if (!xmlXPathStackIsExternal(ctxt)) {
143 xmlXPathSetTypeError(ctxt);
144 return;
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)).
171 static void
172 exsltSaxonEvaluateFunction (xmlXPathParserContextPtr ctxt, int nargs) {
173 if (nargs != 1) {
174 xmlXPathSetArityError(ctxt);
175 return;
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.
191 static void
192 exsltSaxonSystemIdFunction(xmlXPathParserContextPtr ctxt, int nargs)
194 if (ctxt == NULL)
195 return;
196 if (nargs != 0) {
197 xmlXPathSetArityError(ctxt);
198 return;
201 if ((ctxt->context) && (ctxt->context->doc) &&
202 (ctxt->context->doc->URL))
203 valuePush(ctxt, xmlXPathNewString(ctxt->context->doc->URL));
204 else
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
220 * line)
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.
227 static void
228 exsltSaxonLineNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
229 xmlNodePtr cur = NULL;
231 if (nargs == 0) {
232 cur = ctxt->context->node;
233 } else if (nargs == 1) {
234 xmlXPathObjectPtr obj;
235 xmlNodeSetPtr nodelist;
236 int i;
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;
242 return;
245 obj = valuePop(ctxt);
246 nodelist = obj->nodesetval;
247 if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) {
248 xmlXPathFreeObject(obj);
249 valuePush(ctxt, xmlXPathNewFloat(-1));
250 return;
252 cur = nodelist->nodeTab[0];
253 for (i = 1;i < nodelist->nodeNr;i++) {
254 int ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]);
255 if (ret == -1)
256 cur = nodelist->nodeTab[i];
258 xmlXPathFreeObject(obj);
259 } else {
260 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
261 "saxon:line-number() : invalid number of args %d\n",
262 nargs);
263 ctxt->error = XPATH_INVALID_ARITY;
264 return;
267 valuePush(ctxt, xmlXPathNewFloat(xmlGetLineNo(cur)));
268 return;
272 * exsltSaxonRegister:
274 * Registers the SAXON extension module
276 void
277 exsltSaxonRegister (void) {
278 xsltRegisterExtModule (SAXON_NAMESPACE,
279 (xsltExtInitFunction) exsltSaxonInit,
280 (xsltExtShutdownFunction) exsltSaxonShutdown);
281 xsltRegisterExtModuleFunction((const xmlChar *) "expression",
282 SAXON_NAMESPACE,
283 exsltSaxonExpressionFunction);
284 xsltRegisterExtModuleFunction((const xmlChar *) "eval",
285 SAXON_NAMESPACE,
286 exsltSaxonEvalFunction);
287 xsltRegisterExtModuleFunction((const xmlChar *) "evaluate",
288 SAXON_NAMESPACE,
289 exsltSaxonEvaluateFunction);
290 xsltRegisterExtModuleFunction ((const xmlChar *) "line-number",
291 SAXON_NAMESPACE,
292 exsltSaxonLineNumberFunction);
293 xsltRegisterExtModuleFunction ((const xmlChar *) "systemId",
294 SAXON_NAMESPACE,
295 exsltSaxonSystemIdFunction);