1 /* 2 * Copyright (C) 2007 - 2011 Vivien Malerba <malerba@gnome-db.org> 3 * Copyright (C) 2010 David King <davidk@openismus.com> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the 17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <stdarg.h> 24 #include <time.h> 25 #include <string.h> 26 #include <errno.h> 27 28 #include <libxml/xpathInternals.h> 29 30 #include <libgda-xslt.h> 31 #include "sql_backend.h" 32 33 34 static void gda_xslt_getnodeset_function (xmlXPathParserContextPtr ctxt, 35 int nargs); 36 static void gda_xslt_checkif_function (xmlXPathParserContextPtr ctxt, 37 int nargs); 38 static void gda_xslt_getvalue_function (xmlXPathParserContextPtr ctxt, 39 int nargs); 40 static void gda_xslt_getxmlvalue_function (xmlXPathParserContextPtr ctxt, 41 int nargs); 42 static void gda_xslt_section_element (xsltTransformContextPtr tctxt, 43 xmlNodePtr node, xmlNodePtr inst, 44 xsltStylePreCompPtr comp); 45 46 void * 47 _gda_xslt_extension_init (xsltTransformContextPtr ctxt, const xmlChar * URI) 48 { 49 int res; 50 GdaXsltIntCont *data; 51 #ifdef GDA_DEBUG_NO 52 g_print ("_gda_xslt_extension_init"); 53 #endif 54 if (!URI || strcmp ((gchar*) URI, GDA_XSLT_EXTENSION_URI)) { 55 #ifdef GDA_DEBUG_NO 56 g_print ("called for another URI, exit"); 57 #endif 58 return NULL; 59 } 60 61 data = calloc (1, sizeof (GdaXsltIntCont)); 62 if (data == NULL) { 63 #ifdef GDA_DEBUG_NO 64 g_print ("no memory"); 65 #endif 66 return NULL; 67 } 68 #ifdef GDA_DEBUG_NO _gda_xslt_holder_set_value(GdaHolder * param,xsltTransformContextPtr ctxt)69 g_print ("initialize result_sets hash"); 70 #endif 71 data->result_sets = 72 g_hash_table_new_full (g_str_hash, g_str_equal, 73 g_free, 74 NULL); 75 76 res = xsltRegisterExtFunction (ctxt, 77 (const xmlChar *) 78 GDA_XSLT_FUNC_GETVALUE, URI, 79 gda_xslt_getvalue_function); 80 res = xsltRegisterExtFunction (ctxt, 81 (const xmlChar *) 82 GDA_XSLT_FUNC_GETXMLVALUE, URI, 83 gda_xslt_getxmlvalue_function); 84 res |= xsltRegisterExtFunction (ctxt, 85 (const xmlChar *) 86 GDA_XSLT_FUNC_CHECKIF, URI, 87 gda_xslt_checkif_function); 88 res |= xsltRegisterExtFunction (ctxt, 89 (const xmlChar *) 90 GDA_XSLT_FUNC_GETNODESET, URI, 91 gda_xslt_getnodeset_function); 92 if (res != 0) { 93 g_error ("failed to xsltRegisterExtFunction = [%d]", res); 94 } 95 96 res = xsltRegisterExtElement (ctxt, 97 (const xmlChar *) GDA_XSLT_ELEM_SECTION, 98 URI, 99 (xsltTransformFunction) 100 gda_xslt_section_element); 101 if (res != 0) { 102 g_error ("failed to xsltRegisterExtElement = [%d]", res); _gda_xslt_bk_section(GdaXsltExCont * exec,GdaXsltIntCont * pdata,xsltTransformContextPtr ctxt,xmlNodePtr node,xmlNodePtr inst,G_GNUC_UNUSED xsltStylePreCompPtr comp)103 } 104 return data; 105 } 106 107 void 108 _gda_xslt_extension_shutdown (G_GNUC_UNUSED xsltTransformContextPtr ctxt, 109 G_GNUC_UNUSED const xmlChar * URI, void *data) 110 { 111 GdaXsltIntCont *p_data = (GdaXsltIntCont *) data; 112 if (p_data) { 113 free (p_data); 114 } 115 } 116 117 static void 118 gda_xslt_getnodeset_function (xmlXPathParserContextPtr ctxt, int nargs) 119 { 120 GdaXsltIntCont *data; 121 xsltTransformContextPtr tctxt; 122 xmlXPathObjectPtr setname, nodeset; 123 GdaXsltExCont *execc; 124 if (nargs != 1) { 125 xsltGenericError (xsltGenericErrorContext, 126 "gda_xslt_getnodeset_function: invalid number of arguments\n"); 127 return; 128 } 129 tctxt = xsltXPathGetTransformContext (ctxt); 130 if (tctxt == NULL) { 131 xsltGenericError (xsltGenericErrorContext, 132 "sqlxslt: failed to get the transformation context\n"); 133 return; 134 } 135 execc = (GdaXsltExCont *) tctxt->_private; 136 data = (GdaXsltIntCont *) xsltGetExtData (tctxt, 137 BAD_CAST GDA_XSLT_EXTENSION_URI); 138 if (data == NULL) { 139 xsltGenericError (xsltGenericErrorContext, 140 "sqlxslt: failed to get module data\n"); 141 return; 142 } 143 setname = valuePop (ctxt); 144 if (setname == NULL) { 145 xsltGenericError (xsltGenericErrorContext, 146 "sqlxslt: internal error\n"); 147 return; 148 } 149 150 if (setname->type != XPATH_STRING) { 151 valuePush (ctxt, setname); 152 xmlXPathStringFunction (ctxt, 1); 153 setname = valuePop (ctxt); 154 if (setname == NULL) { 155 xsltGenericError (xsltGenericErrorContext, 156 "sqlxslt: internal error\n"); 157 return; 158 } 159 } 160 nodeset = 161 _gda_xslt_bk_fun_getnodeset (setname->stringval, execc, data); 162 if (nodeset == NULL) { 163 xsltGenericError (xsltGenericErrorContext, 164 "exsltDynMapFunctoin: ret == NULL\n"); 165 return; 166 } 167 valuePush (ctxt, nodeset); 168 } 169 170 static void 171 gda_xslt_checkif_function (xmlXPathParserContextPtr ctxt, int nargs) 172 { 173 GdaXsltIntCont *data; 174 xsltTransformContextPtr tctxt; 175 xmlXPathObjectPtr setname, sql, value; 176 GdaXsltExCont *execc; 177 if (nargs != 2) { 178 xsltGenericError (xsltGenericErrorContext, 179 "gda_xslt_checkif_function: invalid number of arguments\n"); 180 return; 181 } 182 tctxt = xsltXPathGetTransformContext (ctxt); 183 if (tctxt == NULL) { _gda_xslt_bk_fun_getnodeset(xmlChar * set,GdaXsltExCont * exec,GdaXsltIntCont * pdata)184 xsltGenericError (xsltGenericErrorContext, 185 "gda_xslt_checkif_function: failed to get the transformation context\n"); 186 return; 187 } 188 execc = (GdaXsltExCont *) tctxt->_private; 189 data = (GdaXsltIntCont *) xsltGetExtData (tctxt, 190 BAD_CAST GDA_XSLT_EXTENSION_URI); 191 if (data == NULL || execc == NULL) { 192 xsltGenericError (xsltGenericErrorContext, 193 "gda_xslt_checkif_function: failed to get module internal data\n"); 194 return; 195 } 196 sql = valuePop (ctxt); 197 setname = valuePop (ctxt); 198 if (sql == NULL || setname == NULL) { 199 xsltGenericError (xsltGenericErrorContext, 200 "gda_xslt_checkif_function: internal error\n"); 201 return; _gda_xslt_bk_fun_getvalue(xmlChar * set,xmlChar * name,GdaXsltExCont * exec,GdaXsltIntCont * pdata,int getXml)202 } 203 204 if (sql->type != XPATH_STRING) { 205 valuePush (ctxt, sql); 206 xmlXPathStringFunction (ctxt, 1); 207 sql = valuePop (ctxt); 208 if (sql == NULL) { 209 xsltGenericError (xsltGenericErrorContext, 210 "sqlxslt: internal error. sql parameter is not a string\n"); 211 return; 212 } 213 } 214 if (setname->type != XPATH_STRING) { 215 valuePush (ctxt, setname); 216 xmlXPathStringFunction (ctxt, 1); 217 setname = valuePop (ctxt); 218 if (setname == NULL) { 219 xsltGenericError (xsltGenericErrorContext, 220 "sqlxslt: internal error. Setname parameter is not a string\n"); 221 return; 222 } 223 } 224 value = _gda_xslt_bk_fun_checkif (setname->stringval, sql->stringval, 225 execc, data); 226 if (value == NULL) { 227 xsltGenericError (xsltGenericErrorContext, 228 "sqlxslt: internal error. Empty value\n"); 229 return; 230 } 231 valuePush (ctxt, value); 232 } 233 234 static void 235 gda_xslt_getvalue_function (xmlXPathParserContextPtr ctxt, int nargs) 236 { 237 GdaXsltIntCont *data; 238 xsltTransformContextPtr tctxt; 239 xmlXPathObjectPtr set, name, value; 240 GdaXsltExCont *execc; 241 242 if (nargs != 2) { 243 xsltGenericError (xsltGenericErrorContext, 244 "gda_xslt_getvalue_function: invalid number of arguments\n"); 245 return; 246 } 247 tctxt = xsltXPathGetTransformContext (ctxt); 248 if (tctxt == NULL) { 249 xsltGenericError (xsltGenericErrorContext, 250 "gda_xslt_getvalue_function: failed to get the transformation context\n"); 251 return; 252 } _gda_xslt_bk_fun_checkif(G_GNUC_UNUSED xmlChar * setname,G_GNUC_UNUSED xmlChar * sql_condition,G_GNUC_UNUSED GdaXsltExCont * exec,G_GNUC_UNUSED GdaXsltIntCont * pdata)253 254 execc = (GdaXsltExCont *) tctxt->_private; 255 data = (GdaXsltIntCont *) xsltGetExtData (tctxt, 256 BAD_CAST GDA_XSLT_EXTENSION_URI); 257 if (data == NULL || execc == NULL) { 258 xsltGenericError (xsltGenericErrorContext, 259 "gda_xslt_getvalue_function: failed to get module internal data\n"); 260 return; 261 } 262 name = valuePop (ctxt); set_resultset_value(GdaXsltIntCont * pdata,const char * resultset_name,GObject * result,G_GNUC_UNUSED GError ** error)263 set = valuePop (ctxt); 264 if (name == NULL || set == NULL) { 265 xsltGenericError (xsltGenericErrorContext, 266 "gda_xslt_getvalue_function: internal error\n"); 267 return; 268 } 269 270 if (name->type != XPATH_STRING) { 271 valuePush (ctxt, name); 272 xmlXPathStringFunction (ctxt, 1); 273 name = valuePop (ctxt); get_resultset_col_value(GdaXsltIntCont * pdata,const char * resultset_name,const char * colname,char ** outvalue,GError ** error)274 if (name == NULL) { 275 xsltGenericError (xsltGenericErrorContext, 276 "gda_xslt_getvalue_function: internal error. Name parameter is not a string\n"); 277 return; 278 } 279 } 280 if (set->type != XPATH_STRING) { 281 valuePush (ctxt, set); 282 xmlXPathStringFunction (ctxt, 1); 283 set = valuePop (ctxt); 284 if (set == NULL) { 285 xsltGenericError (xsltGenericErrorContext, 286 "gda_xslt_getvalue_function: internal error. Set parameter is not a string\n"); 287 return; 288 } 289 } 290 291 value = _gda_xslt_bk_fun_getvalue (set->stringval, name->stringval, 292 execc, data,0); 293 if (value == NULL) { 294 xsltGenericError (xsltGenericErrorContext, 295 "gda_xslt_getvalue_function: internal error. Empty value\n"); 296 return; 297 } 298 valuePush (ctxt, value); 299 } 300 301 static void 302 gda_xslt_getxmlvalue_function (xmlXPathParserContextPtr ctxt, int nargs) 303 { 304 GdaXsltIntCont *data; 305 xsltTransformContextPtr tctxt; 306 xmlXPathObjectPtr set, name, value; 307 GdaXsltExCont *execc; 308 309 if (nargs != 2) { 310 xsltGenericError (xsltGenericErrorContext, 311 "gda_xslt_getxmlvalue_function: invalid number of arguments\n"); 312 return; 313 } 314 tctxt = xsltXPathGetTransformContext (ctxt); 315 if (tctxt == NULL) { 316 xsltGenericError (xsltGenericErrorContext, 317 "gda_xslt_getxmlvalue_function: failed to get the transformation context\n"); 318 return; 319 } 320 321 execc = (GdaXsltExCont *) tctxt->_private; 322 data = (GdaXsltIntCont *) xsltGetExtData (tctxt, 323 BAD_CAST GDA_XSLT_EXTENSION_URI); 324 if (data == NULL || execc == NULL) { 325 xsltGenericError (xsltGenericErrorContext, 326 "gda_xslt_getxmlvalue_function: failed to get module internal data\n"); 327 return; 328 } 329 name = valuePop (ctxt); 330 set = valuePop (ctxt); 331 if (name == NULL || set == NULL) { 332 xsltGenericError (xsltGenericErrorContext, 333 "gda_xslt_getxmlvalue_function: internal error\n"); 334 return; 335 } 336 337 if (name->type != XPATH_STRING) { 338 valuePush (ctxt, name); 339 xmlXPathStringFunction (ctxt, 1); get_resultset_nodeset(GdaXsltIntCont * pdata,const char * resultset_name,xmlXPathObjectPtr * nodeset,GError ** error)340 name = valuePop (ctxt); 341 if (name == NULL) { 342 xsltGenericError (xsltGenericErrorContext, 343 "gda_xslt_getxmlvalue_function: internal error. Name parameter is not a string\n"); 344 return; 345 } 346 } 347 if (set->type != XPATH_STRING) { 348 valuePush (ctxt, set); 349 xmlXPathStringFunction (ctxt, 1); 350 set = valuePop (ctxt); 351 if (set == NULL) { 352 xsltGenericError (xsltGenericErrorContext, 353 "gda_xslt_getxmlvalue_function: internal error. Set parameter is not a string\n"); 354 return; 355 } 356 } 357 358 value = _gda_xslt_bk_fun_getvalue (set->stringval, name->stringval, 359 execc, data,1); 360 if (value == NULL) { 361 xsltGenericError (xsltGenericErrorContext, 362 "gda_xslt_getxmlvalue_function: internal error. Empty value\n"); 363 return; 364 } 365 valuePush (ctxt, value); 366 } 367 368 static void 369 gda_xslt_section_element (xsltTransformContextPtr tctxt, 370 xmlNodePtr node, 371 xmlNodePtr inst, xsltStylePreCompPtr comp) 372 { 373 int res; 374 GdaXsltIntCont *data; 375 GdaXsltExCont *execc; 376 377 // gda_xslt_dump_element(tctxt,node,inst,comp); 378 if (tctxt == NULL || node == NULL || inst == NULL 379 || tctxt->insert == NULL) { 380 xsltGenericError (xsltGenericErrorContext, 381 "gda_xslt_section_element: bad input date\n"); 382 tctxt->state = XSLT_STATE_STOPPED; _utility_data_model_to_nodeset(GdaDataModel * model,xmlXPathObjectPtr * nodeset,GError ** error)383 return; 384 } 385 386 execc = (GdaXsltExCont *) tctxt->_private; 387 data = (GdaXsltIntCont *) xsltGetExtData (tctxt, 388 BAD_CAST GDA_XSLT_EXTENSION_URI); 389 if (data == NULL || execc == NULL) { 390 xsltGenericError (xsltGenericErrorContext, 391 "gda_xslt_section_element: failed to get module internal data\n"); 392 tctxt->state = XSLT_STATE_STOPPED; 393 return; 394 } 395 res = _gda_xslt_bk_section (execc, data, tctxt, node, inst, comp); 396 if (res < 0) { 397 xsltGenericError (xsltGenericErrorContext, 398 "gda_xslt_section_element: execute query backend\n"); 399 tctxt->state = XSLT_STATE_STOPPED; 400 return; 401 } 402 return; 403 } 404