xmlj_xpath.c 17 KB

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