1 /* xmlj_xpath.c -
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 #include "gnu_xml_libxmlj_dom_GnomeDocument.h"
39 #include "gnu_xml_libxmlj_dom_GnomeElement.h"
40 #include "gnu_xml_libxmlj_dom_GnomeXPathExpression.h"
41 #include "gnu_xml_libxmlj_dom_GnomeXPathNodeList.h"
42 #include "gnu_xml_libxmlj_dom_GnomeXPathResult.h"
43 #include "xmlj_node.h"
44 #include "xmlj_util.h"
45 #include <libxml/xpath.h>
46
47 /* Local function prototypes */
48
49 xmlXPathContextPtr
50 xmljCreateXPathContextPtr (xmlNodePtr node);
51
52 jobject
53 xmljGetXPathResult (JNIEnv *env, xmlXPathObjectPtr obj);
54
55 jobject
56 xmljGetXPathNodeList (JNIEnv *env, xmlXPathObjectPtr obj);
57
58 xmlXPathObjectPtr
59 xmljGetXPathObjectID (JNIEnv *env, jobject obj);
60
61 /**
62 * Creates an XPath context for the given node.
63 */
64 xmlXPathContextPtr
xmljCreateXPathContextPtr(xmlNodePtr node)65 xmljCreateXPathContextPtr (xmlNodePtr node)
66 {
67 xmlXPathContextPtr ctx;
68
69 ctx = xmlXPathNewContext (node->doc);
70 ctx->node = node;
71 return ctx;
72 }
73
74 /**
75 * Converts an xmlXPathObjectPtr to a Java XPathResult.
76 */
77 jobject
xmljGetXPathResult(JNIEnv * env,xmlXPathObjectPtr obj)78 xmljGetXPathResult (JNIEnv *env, xmlXPathObjectPtr obj)
79 {
80 jclass cls;
81 jmethodID method;
82 jobject ret;
83 jobject val;
84
85 if (obj == NULL)
86 {
87 return NULL;
88 }
89 cls = (*env)->FindClass (env, "gnu/xml/libxmlj/dom/GnomeXPathResult");
90 if (cls == NULL)
91 {
92 return NULL;
93 }
94 method = (*env)->GetMethodID (env, cls, "<init>", "(Ljava/lang/Object;)V");
95 if (method == NULL)
96 {
97 return NULL;
98 }
99 val = xmljAsField (env, obj);
100 ret = (*env)->NewObject (env, cls, method, val);
101
102 return ret;
103 }
104
105 /**
106 * Converts an xmlXPathObjectPtr to a Java XPathNodeList.
107 */
108 jobject
xmljGetXPathNodeList(JNIEnv * env,xmlXPathObjectPtr obj)109 xmljGetXPathNodeList (JNIEnv *env, xmlXPathObjectPtr obj)
110 {
111 jclass cls;
112 jmethodID method;
113 jobject ret;
114 jobject val;
115
116 if (obj == NULL)
117 {
118 return NULL;
119 }
120 cls = (*env)->FindClass (env, "gnu/xml/libxmlj/dom/GnomeXPathNodeList");
121 if (cls == NULL)
122 {
123 return NULL;
124 }
125 method = (*env)->GetMethodID (env, cls, "<init>", "(Ljava/lang/Object;)V");
126 if (method == NULL)
127 {
128 return NULL;
129 }
130 val = xmljAsField (env, obj);
131 ret = (*env)->NewObject (env, cls, method, val);
132
133 return ret;
134 }
135
136 xmlXPathObjectPtr
xmljGetXPathObjectID(JNIEnv * env,jobject obj)137 xmljGetXPathObjectID (JNIEnv *env, jobject obj)
138 {
139 jclass cls;
140 jfieldID field;
141 jobject val;
142 xmlXPathObjectPtr ret;
143
144 cls = (*env)->GetObjectClass (env, obj);
145 if (cls == NULL)
146 {
147 return NULL;
148 }
149 field = (*env)->GetFieldID (env, cls, "obj", "Ljava/lang/Object;");
150 if (field == NULL)
151 {
152 return NULL;
153 }
154 val = (*env)->GetObjectField (env, obj, field);
155 ret = (xmlXPathObjectPtr) xmljAsPointer (env, val);
156
157 return ret;
158 }
159
160 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeDocument_evaluate(JNIEnv * env,jobject self,jstring expression,jobject contextNode,jobject resolver,jshort type,jobject result)161 Java_gnu_xml_libxmlj_dom_GnomeDocument_evaluate (JNIEnv *env,
162 jobject self
163 __attribute__((__unused__)),
164 jstring expression,
165 jobject contextNode,
166 jobject resolver,
167 jshort type,
168 jobject result)
169 {
170 const xmlChar *str;
171 xmlNodePtr node;
172 xmlXPathContextPtr ctx;
173 xmlXPathObjectPtr eval = NULL;
174
175 str = xmljGetStringChars (env, expression);
176 node = xmljGetNodeID (env, contextNode);
177 if (node == NULL)
178 {
179 return NULL;
180 }
181 ctx = xmljCreateXPathContextPtr (node);
182 if (ctx != NULL)
183 {
184 eval = xmlXPathEval (str, ctx);
185 xmlXPathFreeContext (ctx);
186 }
187 xmlFree ((xmlChar *) str);
188 return xmljGetXPathResult (env, eval);
189 }
190
191 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathExpression_init(JNIEnv * env,jobject self,jstring expression)192 Java_gnu_xml_libxmlj_dom_GnomeXPathExpression_init (JNIEnv *env,
193 jobject self
194 __attribute__((__unused__)),
195 jstring expression)
196 {
197 const xmlChar *str;
198 xmlXPathCompExprPtr ptr;
199
200 str = xmljGetStringChars (env, expression);
201 ptr = xmlXPathCompile (str);
202 xmlFree ((xmlChar *) str);
203 return xmljAsField (env, ptr);
204 }
205
206 JNIEXPORT void JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathExpression_free(JNIEnv * env,jobject self,jobject ptr)207 Java_gnu_xml_libxmlj_dom_GnomeXPathExpression_free (JNIEnv *env,
208 jobject self
209 __attribute__((__unused__)),
210 jobject ptr)
211 {
212 xmlXPathCompExprPtr expr;
213
214 expr = (xmlXPathCompExprPtr) xmljAsPointer (env, ptr);
215 xmlXPathFreeCompExpr (expr);
216 }
217
218 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathExpression_doEvaluate(JNIEnv * env,jobject self,jobject ptr,jobject contextNode,jshort type,jobject result)219 Java_gnu_xml_libxmlj_dom_GnomeXPathExpression_doEvaluate (JNIEnv *env,
220 jobject self
221 __attribute__((__unused__)),
222 jobject ptr,
223 jobject contextNode,
224 jshort type,
225 jobject result)
226 {
227 xmlXPathCompExprPtr expr;
228 xmlNodePtr node;
229 xmlXPathContextPtr ctx;
230 xmlXPathObjectPtr eval = NULL;
231
232 expr = (xmlXPathCompExprPtr) xmljAsPointer (env, ptr);
233 node = xmljGetNodeID (env, contextNode);
234 if (node == NULL)
235 {
236 return NULL;
237 }
238 ctx = xmljCreateXPathContextPtr (node);
239 if (ctx != NULL)
240 {
241 eval = xmlXPathCompiledEval (expr, ctx);
242 xmlXPathFreeContext (ctx);
243 }
244 return xmljGetXPathResult (env, eval);
245 }
246
247 JNIEXPORT void JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathResult_free(JNIEnv * env,jobject self,jobject obj)248 Java_gnu_xml_libxmlj_dom_GnomeXPathResult_free (JNIEnv *env,
249 jobject self
250 __attribute__((__unused__)),
251 jobject obj)
252 {
253 xmlXPathFreeObject ((xmlXPathObjectPtr) xmljAsPointer (env, obj));
254 }
255
256 JNIEXPORT jshort JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getResultType(JNIEnv * env,jobject self)257 Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getResultType (JNIEnv *env,
258 jobject self)
259 {
260 xmlXPathObjectPtr obj;
261
262 obj = xmljGetXPathObjectID (env, self);
263 switch (obj->type)
264 {
265 case XPATH_UNDEFINED:
266 return 0; /* ANY_TYPE */
267 case XPATH_NUMBER:
268 return 1; /* NUMBER_TYPE */
269 case XPATH_STRING:
270 return 2; /* STRING_TYPE */
271 case XPATH_BOOLEAN:
272 return 3; /* BOOLEAN_TYPE */
273 case XPATH_NODESET:
274 return 6; /* UNORDERED_NODE_SNAPSHOT_TYPE */
275 case XPATH_POINT:
276 case XPATH_RANGE:
277 case XPATH_LOCATIONSET:
278 case XPATH_USERS:
279 case XPATH_XSLT_TREE:
280 /* TODO */
281 default:
282 return -1; /* TODO */
283 }
284 }
285
286 JNIEXPORT jdouble JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getNumberValue(JNIEnv * env,jobject self)287 Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getNumberValue (JNIEnv *env,
288 jobject self)
289 {
290 xmlXPathObjectPtr obj;
291
292 obj = xmljGetXPathObjectID (env, self);
293 if (obj == NULL)
294 {
295 return 0.0;
296 }
297 return obj->floatval;
298 }
299
300 JNIEXPORT jstring JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getStringValue(JNIEnv * env,jobject self)301 Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getStringValue (JNIEnv *env,
302 jobject self)
303 {
304 xmlXPathObjectPtr obj;
305
306 obj = xmljGetXPathObjectID (env, self);
307 if (obj == NULL)
308 {
309 return NULL;
310 }
311 return xmljNewString (env, obj->stringval);
312 }
313
314 JNIEXPORT jboolean JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getBooleanValue(JNIEnv * env,jobject self)315 Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getBooleanValue (JNIEnv *env,
316 jobject self)
317 {
318 xmlXPathObjectPtr obj;
319
320 obj = xmljGetXPathObjectID (env, self);
321 return obj->boolval;
322 }
323
324 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getSingleNodeValue(JNIEnv * env,jobject self)325 Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getSingleNodeValue (JNIEnv *env,
326 jobject self)
327 {
328 xmlXPathObjectPtr obj;
329
330 obj = xmljGetXPathObjectID (env, self);
331 if (obj == NULL)
332 {
333 return NULL;
334 }
335 if (obj->nodesetval == NULL)
336 {
337 return NULL;
338 }
339 if (obj->nodesetval->nodeNr > 0)
340 {
341 return xmljGetNodeInstance (env, obj->nodesetval->nodeTab[0]);
342 }
343 else
344 {
345 return NULL;
346 }
347 }
348
349 JNIEXPORT jboolean JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getInvalidIteratorState(JNIEnv * env,jobject self)350 Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getInvalidIteratorState (JNIEnv *env,
351 jobject self)
352 {
353 xmlXPathObjectPtr obj;
354
355 obj = xmljGetXPathObjectID (env, self);
356 return 0; /* TODO */
357 }
358
359 JNIEXPORT jint JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getSnapshotLength(JNIEnv * env,jobject self)360 Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getSnapshotLength (JNIEnv *env,
361 jobject self)
362 {
363 xmlXPathObjectPtr obj;
364
365 obj = xmljGetXPathObjectID (env, self);
366 if (obj == NULL)
367 {
368 return -1;
369 }
370 if (obj->nodesetval == NULL)
371 {
372 return -1;
373 }
374 return obj->nodesetval->nodeNr;
375 }
376
377 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathResult_iterateNext(JNIEnv * env,jobject self)378 Java_gnu_xml_libxmlj_dom_GnomeXPathResult_iterateNext (JNIEnv *env,
379 jobject self)
380 {
381 xmlXPathObjectPtr obj;
382
383 obj = xmljGetXPathObjectID (env, self);
384 return NULL; /* TODO */
385 }
386
387 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathResult_snapshotItem(JNIEnv * env,jobject self,jint index)388 Java_gnu_xml_libxmlj_dom_GnomeXPathResult_snapshotItem (JNIEnv *env,
389 jobject self,
390 jint index)
391 {
392 xmlXPathObjectPtr obj;
393
394 obj = xmljGetXPathObjectID (env, self);
395 if (obj == NULL)
396 {
397 return NULL;
398 }
399 if (obj->nodesetval == NULL)
400 {
401 return NULL;
402 }
403 if (obj->nodesetval->nodeNr > 0)
404 {
405 return xmljGetNodeInstance (env, obj->nodesetval->nodeTab[index]);
406 }
407 else
408 {
409 return NULL;
410 }
411 }
412
413 /* -- GnomeXPathNodeList -- */
414
415 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeDocument_getElementsByTagName(JNIEnv * env,jobject self,jstring name)416 Java_gnu_xml_libxmlj_dom_GnomeDocument_getElementsByTagName (JNIEnv *env,
417 jobject self,
418 jstring name)
419 {
420 return Java_gnu_xml_libxmlj_dom_GnomeElement_getElementsByTagName (env,
421 self,
422 name);
423 }
424
425 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeElement_getElementsByTagName(JNIEnv * env,jobject self,jstring name)426 Java_gnu_xml_libxmlj_dom_GnomeElement_getElementsByTagName (JNIEnv *env,
427 jobject self,
428 jstring name)
429 {
430 const xmlChar *s_name;
431 const xmlChar *format;
432 xmlChar expr[256];
433 xmlNodePtr node;
434 xmlXPathContextPtr ctx;
435 xmlXPathObjectPtr eval = NULL;
436
437 node = xmljGetNodeID (env, self);
438 if (node == NULL)
439 {
440 return NULL;
441 }
442 s_name = xmljGetStringChars (env, name);
443 if (xmlStrEqual (s_name, BAD_CAST "*"))
444 {
445 format = xmlCharStrdup ("descendant-or-self::*[node-type()=1]");
446 if (xmlStrPrintf (expr, 256, format) == -1)
447 {
448 return NULL;
449 }
450 }
451 else
452 {
453 format = xmlCharStrdup ("descendant-or-self::*[name()='%s']");
454 if (xmlStrPrintf (expr, 256, format, s_name) == -1)
455 {
456 return NULL;
457 }
458 }
459 xmlFree ((xmlChar *) s_name);
460 ctx = xmljCreateXPathContextPtr (node);
461 if (ctx != NULL)
462 {
463 eval = xmlXPathEval (expr, ctx);
464 xmlXPathFreeContext (ctx);
465 }
466 return xmljGetXPathNodeList (env, eval);
467 }
468
469 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeDocument_getElementsByTagNameNS(JNIEnv * env,jobject self,jstring uri,jstring localName)470 Java_gnu_xml_libxmlj_dom_GnomeDocument_getElementsByTagNameNS (JNIEnv *env,
471 jobject self,
472 jstring uri,
473 jstring localName)
474 {
475 return Java_gnu_xml_libxmlj_dom_GnomeElement_getElementsByTagNameNS (env,
476 self,
477 uri,
478 localName);
479 }
480
481 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeElement_getElementsByTagNameNS(JNIEnv * env,jobject self,jstring uri,jstring localName)482 Java_gnu_xml_libxmlj_dom_GnomeElement_getElementsByTagNameNS (JNIEnv *env,
483 jobject self,
484 jstring uri,
485 jstring localName)
486 {
487 const xmlChar *s_uri;
488 const xmlChar *s_localName;
489 const xmlChar *format;
490 xmlChar expr[256];
491 xmlNodePtr node;
492 xmlXPathContextPtr ctx;
493 xmlXPathObjectPtr eval = NULL;
494
495 node = xmljGetNodeID (env, self);
496 if (node == NULL)
497 {
498 return NULL;
499 }
500 s_uri = xmljGetStringChars (env, uri);
501 s_localName = xmljGetStringChars (env, localName);
502 if (uri == NULL)
503 {
504 /* namespace URI is empty */
505 if (xmlStrEqual (s_localName, BAD_CAST "*"))
506 {
507 format = xmlCharStrdup ("descendant-or-self::*[namespace-uri()='' and node-type()=1]");
508 if (xmlStrPrintf (expr, 256, format) == -1)
509 {
510 return NULL;
511 }
512 }
513 else
514 {
515 format = xmlCharStrdup ("descendant-or-self::*[namespace-uri()='' and local-name()='%s']");
516 if (xmlStrPrintf (expr, 256, format, s_localName) == -1)
517 {
518 return NULL;
519 }
520 }
521 }
522 else if (xmlStrEqual (s_uri, BAD_CAST "*"))
523 {
524 /* matches all namespaces */
525 if (xmlStrEqual (s_localName, BAD_CAST "*"))
526 {
527 format = xmlCharStrdup ("descendant-or-self::*[node-type()=1]");
528 if (xmlStrPrintf (expr, 256, format) == -1)
529 {
530 return NULL;
531 }
532 }
533 else
534 {
535 format = xmlCharStrdup ("descendant-or-self::*[local-name()='%s']");
536 if (xmlStrPrintf (expr, 256, format, s_localName) == -1)
537 {
538 return NULL;
539 }
540 }
541 }
542 else
543 {
544 if (xmlStrEqual (s_localName, BAD_CAST "*"))
545 {
546 format = xmlCharStrdup ("descendant-or-self::*[namespace-uri()='%s' and node-type()=1]");
547 if (xmlStrPrintf (expr, 256, format, s_uri) == -1)
548 {
549 return NULL;
550 }
551 }
552 else
553 {
554 format = xmlCharStrdup ("descendant-or-self::*[namespace-uri()='%s' and local-name()='%s']");
555 if (xmlStrPrintf (expr, 256, format, s_uri, s_localName) == -1)
556 {
557 return NULL;
558 }
559 }
560 }
561 xmlFree ((xmlChar *) s_uri);
562 xmlFree ((xmlChar *) s_localName);
563 ctx = xmljCreateXPathContextPtr (node);
564 if (ctx != NULL)
565 {
566 eval = xmlXPathEval (expr, ctx);
567 xmlXPathFreeContext (ctx);
568 }
569 return xmljGetXPathNodeList (env, eval);
570 }
571
572 JNIEXPORT void JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathNodeList_free(JNIEnv * env,jobject self,jobject obj)573 Java_gnu_xml_libxmlj_dom_GnomeXPathNodeList_free (JNIEnv *env,
574 jobject self
575 __attribute__((__unused__)),
576 jobject obj)
577 {
578 xmlXPathFreeObject ((xmlXPathObjectPtr) xmljAsPointer (env, obj));
579 }
580
581 JNIEXPORT jint JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathNodeList_getLength(JNIEnv * env,jobject self)582 Java_gnu_xml_libxmlj_dom_GnomeXPathNodeList_getLength (JNIEnv *env,
583 jobject self)
584 {
585 xmlXPathObjectPtr obj;
586
587 obj = xmljGetXPathObjectID (env, self);
588 if (obj == NULL)
589 {
590 return 0;
591 }
592 if (obj->nodesetval == NULL)
593 {
594 return 0;
595 }
596 return obj->nodesetval->nodeNr;
597 }
598
599 JNIEXPORT jobject JNICALL
Java_gnu_xml_libxmlj_dom_GnomeXPathNodeList_item(JNIEnv * env,jobject self,jint index)600 Java_gnu_xml_libxmlj_dom_GnomeXPathNodeList_item (JNIEnv *env,
601 jobject self,
602 jint index)
603 {
604 xmlXPathObjectPtr obj;
605
606 obj = xmljGetXPathObjectID (env, self);
607 if (obj == NULL)
608 {
609 return NULL;
610 }
611 if (obj->nodesetval == NULL)
612 {
613 return NULL;
614 }
615 if (obj->nodesetval->nodeNr > 0)
616 {
617 return xmljGetNodeInstance (env, obj->nodesetval->nodeTab[index]);
618 }
619 else
620 {
621 return NULL;
622 }
623 }
624
625