Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfunctions.c
Go to the documentation of this file.
00001 /* 00002 * functions.c: Implementation of the XSLT extra functions 00003 * 00004 * Reference: 00005 * http://www.w3.org/TR/1999/REC-xslt-19991116 00006 * 00007 * See Copyright for the status of this software. 00008 * 00009 * daniel@veillard.com 00010 * Bjorn Reese <breese@users.sourceforge.net> for number formatting 00011 */ 00012 00013 #define IN_LIBXSLT 00014 #include "libxslt.h" 00015 00016 #include <string.h> 00017 00018 #ifdef HAVE_SYS_TYPES_H 00019 #include <sys/types.h> 00020 #endif 00021 #ifdef HAVE_CTYPE_H 00022 #include <ctype.h> 00023 #endif 00024 00025 #include <libxml/xmlmemory.h> 00026 #include <libxml/parser.h> 00027 #include <libxml/tree.h> 00028 #include <libxml/valid.h> 00029 #include <libxml/hash.h> 00030 #include <libxml/xmlerror.h> 00031 #include <libxml/xpath.h> 00032 #include <libxml/xpathInternals.h> 00033 #include <libxml/parserInternals.h> 00034 #include <libxml/uri.h> 00035 #include <libxml/xpointer.h> 00036 #include "xslt.h" 00037 #include "xsltInternals.h" 00038 #include "xsltutils.h" 00039 #include "functions.h" 00040 #include "extensions.h" 00041 #include "numbersInternals.h" 00042 #include "keys.h" 00043 #include "documents.h" 00044 00045 #ifdef WITH_XSLT_DEBUG 00046 #define WITH_XSLT_DEBUG_FUNCTION 00047 #endif 00048 00049 /* 00050 * Some versions of DocBook XSL use the vendor string to detect 00051 * supporting chunking, this is a workaround to be considered 00052 * in the list of decent XSLT processors <grin/> 00053 */ 00054 #define DOCBOOK_XSL_HACK 00055 00067 xmlXPathFunction 00068 xsltXPathFunctionLookup (xmlXPathContextPtr ctxt, 00069 const xmlChar *name, const xmlChar *ns_uri) { 00070 xmlXPathFunction ret; 00071 00072 if ((ctxt == NULL) || (name == NULL) || (ns_uri == NULL)) 00073 return (NULL); 00074 00075 #ifdef WITH_XSLT_DEBUG_FUNCTION 00076 xsltGenericDebug(xsltGenericDebugContext, 00077 "Lookup function {%s}%s\n", ns_uri, name); 00078 #endif 00079 00080 /* give priority to context-level functions */ 00081 /* 00082 ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri); 00083 */ 00084 XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri); 00085 00086 if (ret == NULL) 00087 ret = xsltExtModuleFunctionLookup(name, ns_uri); 00088 00089 #ifdef WITH_XSLT_DEBUG_FUNCTION 00090 if (ret != NULL) 00091 xsltGenericDebug(xsltGenericDebugContext, 00092 "found function %s\n", name); 00093 #endif 00094 return(ret); 00095 } 00096 00097 00098 /************************************************************************ 00099 * * 00100 * Module interfaces * 00101 * * 00102 ************************************************************************/ 00103 00104 static void 00105 xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI) 00106 { 00107 xsltTransformContextPtr tctxt; 00108 xmlURIPtr uri; 00109 xmlChar *fragment; 00110 xsltDocumentPtr idoc; /* document info */ 00111 xmlDocPtr doc; 00112 xmlXPathContextPtr xptrctxt = NULL; 00113 xmlXPathObjectPtr resObj = NULL; 00114 00115 tctxt = xsltXPathGetTransformContext(ctxt); 00116 if (tctxt == NULL) { 00117 xsltTransformError(NULL, NULL, NULL, 00118 "document() : internal error tctxt == NULL\n"); 00119 valuePush(ctxt, xmlXPathNewNodeSet(NULL)); 00120 return; 00121 } 00122 00123 uri = xmlParseURI((const char *) URI); 00124 if (uri == NULL) { 00125 xsltTransformError(tctxt, NULL, NULL, 00126 "document() : failed to parse URI\n"); 00127 valuePush(ctxt, xmlXPathNewNodeSet(NULL)); 00128 return; 00129 } 00130 00131 /* 00132 * check for and remove fragment identifier 00133 */ 00134 fragment = (xmlChar *)uri->fragment; 00135 if (fragment != NULL) { 00136 xmlChar *newURI; 00137 uri->fragment = NULL; 00138 newURI = xmlSaveUri(uri); 00139 idoc = xsltLoadDocument(tctxt, newURI); 00140 xmlFree(newURI); 00141 } else 00142 idoc = xsltLoadDocument(tctxt, URI); 00143 xmlFreeURI(uri); 00144 00145 if (idoc == NULL) { 00146 if ((URI == NULL) || 00147 (URI[0] == '#') || 00148 ((tctxt->style->doc != NULL) && 00149 (xmlStrEqual(tctxt->style->doc->URL, URI)))) 00150 { 00151 /* 00152 * This selects the stylesheet's doc itself. 00153 */ 00154 doc = tctxt->style->doc; 00155 } else { 00156 valuePush(ctxt, xmlXPathNewNodeSet(NULL)); 00157 00158 if (fragment != NULL) 00159 xmlFree(fragment); 00160 00161 return; 00162 } 00163 } else 00164 doc = idoc->doc; 00165 00166 if (fragment == NULL) { 00167 valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc)); 00168 return; 00169 } 00170 00171 /* use XPointer of HTML location for fragment ID */ 00172 #ifdef LIBXML_XPTR_ENABLED 00173 xptrctxt = xmlXPtrNewContext(doc, NULL, NULL); 00174 if (xptrctxt == NULL) { 00175 xsltTransformError(tctxt, NULL, NULL, 00176 "document() : internal error xptrctxt == NULL\n"); 00177 goto out_fragment; 00178 } 00179 00180 resObj = xmlXPtrEval(fragment, xptrctxt); 00181 xmlXPathFreeContext(xptrctxt); 00182 #endif 00183 xmlFree(fragment); 00184 00185 if (resObj == NULL) 00186 goto out_fragment; 00187 00188 switch (resObj->type) { 00189 case XPATH_NODESET: 00190 break; 00191 case XPATH_UNDEFINED: 00192 case XPATH_BOOLEAN: 00193 case XPATH_NUMBER: 00194 case XPATH_STRING: 00195 case XPATH_POINT: 00196 case XPATH_USERS: 00197 case XPATH_XSLT_TREE: 00198 case XPATH_RANGE: 00199 case XPATH_LOCATIONSET: 00200 xsltTransformError(tctxt, NULL, NULL, 00201 "document() : XPointer does not select a node set: #%s\n", 00202 fragment); 00203 goto out_object; 00204 } 00205 00206 valuePush(ctxt, resObj); 00207 return; 00208 00209 out_object: 00210 xmlXPathFreeObject(resObj); 00211 00212 out_fragment: 00213 valuePush(ctxt, xmlXPathNewNodeSet(NULL)); 00214 } 00215 00224 void 00225 xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs) 00226 { 00227 xmlXPathObjectPtr obj, obj2 = NULL; 00228 xmlChar *base = NULL, *URI; 00229 00230 00231 if ((nargs < 1) || (nargs > 2)) { 00232 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00233 "document() : invalid number of args %d\n", 00234 nargs); 00235 ctxt->error = XPATH_INVALID_ARITY; 00236 return; 00237 } 00238 if (ctxt->value == NULL) { 00239 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00240 "document() : invalid arg value\n"); 00241 ctxt->error = XPATH_INVALID_TYPE; 00242 return; 00243 } 00244 00245 if (nargs == 2) { 00246 if (ctxt->value->type != XPATH_NODESET) { 00247 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00248 "document() : invalid arg expecting a nodeset\n"); 00249 ctxt->error = XPATH_INVALID_TYPE; 00250 return; 00251 } 00252 00253 obj2 = valuePop(ctxt); 00254 } 00255 00256 if (ctxt->value->type == XPATH_NODESET) { 00257 int i; 00258 xmlXPathObjectPtr newobj, ret; 00259 00260 obj = valuePop(ctxt); 00261 ret = xmlXPathNewNodeSet(NULL); 00262 00263 if (obj->nodesetval) { 00264 for (i = 0; i < obj->nodesetval->nodeNr; i++) { 00265 valuePush(ctxt, 00266 xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i])); 00267 xmlXPathStringFunction(ctxt, 1); 00268 if (nargs == 2) { 00269 valuePush(ctxt, xmlXPathObjectCopy(obj2)); 00270 } else { 00271 valuePush(ctxt, 00272 xmlXPathNewNodeSet(obj->nodesetval-> 00273 nodeTab[i])); 00274 } 00275 xsltDocumentFunction(ctxt, 2); 00276 newobj = valuePop(ctxt); 00277 ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval, 00278 newobj->nodesetval); 00279 xmlXPathFreeObject(newobj); 00280 } 00281 } 00282 00283 xmlXPathFreeObject(obj); 00284 if (obj2 != NULL) 00285 xmlXPathFreeObject(obj2); 00286 valuePush(ctxt, ret); 00287 return; 00288 } 00289 /* 00290 * Make sure it's converted to a string 00291 */ 00292 xmlXPathStringFunction(ctxt, 1); 00293 if (ctxt->value->type != XPATH_STRING) { 00294 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00295 "document() : invalid arg expecting a string\n"); 00296 ctxt->error = XPATH_INVALID_TYPE; 00297 if (obj2 != NULL) 00298 xmlXPathFreeObject(obj2); 00299 return; 00300 } 00301 obj = valuePop(ctxt); 00302 if (obj->stringval == NULL) { 00303 valuePush(ctxt, xmlXPathNewNodeSet(NULL)); 00304 } else { 00305 if ((obj2 != NULL) && (obj2->nodesetval != NULL) && 00306 (obj2->nodesetval->nodeNr > 0) && 00307 IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) { 00308 xmlNodePtr target; 00309 00310 target = obj2->nodesetval->nodeTab[0]; 00311 if ((target->type == XML_ATTRIBUTE_NODE) || 00312 (target->type == XML_PI_NODE)) { 00313 target = ((xmlAttrPtr) target)->parent; 00314 } 00315 base = xmlNodeGetBase(target->doc, target); 00316 } else { 00317 xsltTransformContextPtr tctxt; 00318 00319 tctxt = xsltXPathGetTransformContext(ctxt); 00320 if ((tctxt != NULL) && (tctxt->inst != NULL)) { 00321 base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst); 00322 } else if ((tctxt != NULL) && (tctxt->style != NULL) && 00323 (tctxt->style->doc != NULL)) { 00324 base = xmlNodeGetBase(tctxt->style->doc, 00325 (xmlNodePtr) tctxt->style->doc); 00326 } 00327 } 00328 URI = xmlBuildURI(obj->stringval, base); 00329 if (base != NULL) 00330 xmlFree(base); 00331 if (URI == NULL) { 00332 valuePush(ctxt, xmlXPathNewNodeSet(NULL)); 00333 } else { 00334 xsltDocumentFunctionLoadDocument( ctxt, URI ); 00335 xmlFree(URI); 00336 } 00337 } 00338 xmlXPathFreeObject(obj); 00339 if (obj2 != NULL) 00340 xmlXPathFreeObject(obj2); 00341 } 00342 00351 void 00352 xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){ 00353 xmlXPathObjectPtr obj1, obj2; 00354 00355 if (nargs != 2) { 00356 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00357 "key() : expects two arguments\n"); 00358 ctxt->error = XPATH_INVALID_ARITY; 00359 return; 00360 } 00361 00362 /* 00363 * Get the key's value. 00364 */ 00365 obj2 = valuePop(ctxt); 00366 xmlXPathStringFunction(ctxt, 1); 00367 if ((obj2 == NULL) || 00368 (ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { 00369 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00370 "key() : invalid arg expecting a string\n"); 00371 ctxt->error = XPATH_INVALID_TYPE; 00372 xmlXPathFreeObject(obj2); 00373 00374 return; 00375 } 00376 /* 00377 * Get the key's name. 00378 */ 00379 obj1 = valuePop(ctxt); 00380 00381 if ((obj2->type == XPATH_NODESET) || (obj2->type == XPATH_XSLT_TREE)) { 00382 int i; 00383 xmlXPathObjectPtr newobj, ret; 00384 00385 ret = xmlXPathNewNodeSet(NULL); 00386 00387 if (obj2->nodesetval != NULL) { 00388 for (i = 0; i < obj2->nodesetval->nodeNr; i++) { 00389 valuePush(ctxt, xmlXPathObjectCopy(obj1)); 00390 valuePush(ctxt, 00391 xmlXPathNewNodeSet(obj2->nodesetval->nodeTab[i])); 00392 xmlXPathStringFunction(ctxt, 1); 00393 xsltKeyFunction(ctxt, 2); 00394 newobj = valuePop(ctxt); 00395 ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval, 00396 newobj->nodesetval); 00397 xmlXPathFreeObject(newobj); 00398 } 00399 } 00400 valuePush(ctxt, ret); 00401 } else { 00402 xmlNodeSetPtr nodelist = NULL; 00403 xmlChar *key = NULL, *value; 00404 const xmlChar *keyURI; 00405 xsltTransformContextPtr tctxt; 00406 xmlChar *qname, *prefix; 00407 xmlXPathContextPtr xpctxt = ctxt->context; 00408 xmlNodePtr tmpNode = NULL; 00409 xsltDocumentPtr oldDocInfo; 00410 00411 tctxt = xsltXPathGetTransformContext(ctxt); 00412 00413 oldDocInfo = tctxt->document; 00414 00415 if (xpctxt->node == NULL) { 00416 xsltTransformError(tctxt, NULL, tctxt->inst, 00417 "Internal error in xsltKeyFunction(): " 00418 "The context node is not set on the XPath context.\n"); 00419 tctxt->state = XSLT_STATE_STOPPED; 00420 goto error; 00421 } 00422 /* 00423 * Get the associated namespace URI if qualified name 00424 */ 00425 qname = obj1->stringval; 00426 key = xmlSplitQName2(qname, &prefix); 00427 if (key == NULL) { 00428 key = xmlStrdup(obj1->stringval); 00429 keyURI = NULL; 00430 if (prefix != NULL) 00431 xmlFree(prefix); 00432 } else { 00433 if (prefix != NULL) { 00434 keyURI = xmlXPathNsLookup(xpctxt, prefix); 00435 if (keyURI == NULL) { 00436 xsltTransformError(tctxt, NULL, tctxt->inst, 00437 "key() : prefix %s is not bound\n", prefix); 00438 /* 00439 * TODO: Shouldn't we stop here? 00440 */ 00441 } 00442 xmlFree(prefix); 00443 } else { 00444 keyURI = NULL; 00445 } 00446 } 00447 00448 /* 00449 * Force conversion of first arg to string 00450 */ 00451 valuePush(ctxt, obj2); 00452 xmlXPathStringFunction(ctxt, 1); 00453 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { 00454 xsltTransformError(tctxt, NULL, tctxt->inst, 00455 "key() : invalid arg expecting a string\n"); 00456 ctxt->error = XPATH_INVALID_TYPE; 00457 goto error; 00458 } 00459 obj2 = valuePop(ctxt); 00460 value = obj2->stringval; 00461 00462 /* 00463 * We need to ensure that ctxt->document is available for 00464 * xsltGetKey(). 00465 * First find the relevant doc, which is the context node's 00466 * owner doc; using context->doc is not safe, since 00467 * the doc could have been acquired via the document() function, 00468 * or the doc might be a Result Tree Fragment. 00469 * FUTURE INFO: In XSLT 2.0 the key() function takes an additional 00470 * argument indicating the doc to use. 00471 */ 00472 if (xpctxt->node->type == XML_NAMESPACE_DECL) { 00473 /* 00474 * REVISIT: This is a libxml hack! Check xpath.c for details. 00475 * The XPath module sets the owner element of a ns-node on 00476 * the ns->next field. 00477 */ 00478 if ((((xmlNsPtr) xpctxt->node)->next != NULL) && 00479 (((xmlNsPtr) xpctxt->node)->next->type == XML_ELEMENT_NODE)) 00480 { 00481 tmpNode = (xmlNodePtr) ((xmlNsPtr) xpctxt->node)->next; 00482 } 00483 } else 00484 tmpNode = xpctxt->node; 00485 00486 if ((tmpNode == NULL) || (tmpNode->doc == NULL)) { 00487 xsltTransformError(tctxt, NULL, tctxt->inst, 00488 "Internal error in xsltKeyFunction(): " 00489 "Couldn't get the doc of the XPath context node.\n"); 00490 goto error; 00491 } 00492 00493 if ((tctxt->document == NULL) || 00494 (tctxt->document->doc != tmpNode->doc)) 00495 { 00496 if (tmpNode->doc->name && (tmpNode->doc->name[0] == ' ')) { 00497 /* 00498 * This is a Result Tree Fragment. 00499 */ 00500 if (tmpNode->doc->_private == NULL) { 00501 tmpNode->doc->_private = xsltNewDocument(tctxt, tmpNode->doc); 00502 if (tmpNode->doc->_private == NULL) 00503 goto error; 00504 } 00505 tctxt->document = (xsltDocumentPtr) tmpNode->doc->_private; 00506 } else { 00507 /* 00508 * May be the initial source doc or a doc acquired via the 00509 * document() function. 00510 */ 00511 tctxt->document = xsltFindDocument(tctxt, tmpNode->doc); 00512 } 00513 if (tctxt->document == NULL) { 00514 xsltTransformError(tctxt, NULL, tctxt->inst, 00515 "Internal error in xsltKeyFunction(): " 00516 "Could not get the document info of a context doc.\n"); 00517 tctxt->state = XSLT_STATE_STOPPED; 00518 goto error; 00519 } 00520 } 00521 /* 00522 * Get/compute the key value. 00523 */ 00524 nodelist = xsltGetKey(tctxt, key, keyURI, value); 00525 00526 error: 00527 tctxt->document = oldDocInfo; 00528 valuePush(ctxt, xmlXPathWrapNodeSet( 00529 xmlXPathNodeSetMerge(NULL, nodelist))); 00530 if (key != NULL) 00531 xmlFree(key); 00532 } 00533 00534 if (obj1 != NULL) 00535 xmlXPathFreeObject(obj1); 00536 if (obj2 != NULL) 00537 xmlXPathFreeObject(obj2); 00538 } 00539 00548 void 00549 xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs){ 00550 xmlXPathObjectPtr obj; 00551 xmlChar *str; 00552 00553 if ((nargs != 1) || (ctxt->value == NULL)) { 00554 xsltGenericError(xsltGenericErrorContext, 00555 "unparsed-entity-uri() : expects one string arg\n"); 00556 ctxt->error = XPATH_INVALID_ARITY; 00557 return; 00558 } 00559 obj = valuePop(ctxt); 00560 if (obj->type != XPATH_STRING) { 00561 obj = xmlXPathConvertString(obj); 00562 } 00563 00564 str = obj->stringval; 00565 if (str == NULL) { 00566 valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); 00567 } else { 00568 xmlEntityPtr entity; 00569 00570 entity = xmlGetDocEntity(ctxt->context->doc, str); 00571 if (entity == NULL) { 00572 valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); 00573 } else { 00574 if (entity->URI != NULL) 00575 valuePush(ctxt, xmlXPathNewString(entity->URI)); 00576 else 00577 valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); 00578 } 00579 } 00580 xmlXPathFreeObject(obj); 00581 } 00582 00591 void 00592 xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) 00593 { 00594 xmlXPathObjectPtr numberObj = NULL; 00595 xmlXPathObjectPtr formatObj = NULL; 00596 xmlXPathObjectPtr decimalObj = NULL; 00597 xsltStylesheetPtr sheet; 00598 xsltDecimalFormatPtr formatValues; 00599 xmlChar *result; 00600 xsltTransformContextPtr tctxt; 00601 00602 tctxt = xsltXPathGetTransformContext(ctxt); 00603 if (tctxt == NULL) 00604 return; 00605 sheet = tctxt->style; 00606 if (sheet == NULL) 00607 return; 00608 formatValues = sheet->decimalFormat; 00609 00610 switch (nargs) { 00611 case 3: 00612 CAST_TO_STRING; 00613 decimalObj = valuePop(ctxt); 00614 formatValues = xsltDecimalFormatGetByName(sheet, decimalObj->stringval); 00615 if (formatValues == NULL) { 00616 xsltTransformError(tctxt, NULL, NULL, 00617 "format-number() : undeclared decimal format '%s'\n", 00618 decimalObj->stringval); 00619 } 00620 /* Intentional fall-through */ 00621 case 2: 00622 CAST_TO_STRING; 00623 formatObj = valuePop(ctxt); 00624 CAST_TO_NUMBER; 00625 numberObj = valuePop(ctxt); 00626 break; 00627 default: 00628 XP_ERROR(XPATH_INVALID_ARITY); 00629 } 00630 00631 if (formatValues != NULL) { 00632 if (xsltFormatNumberConversion(formatValues, 00633 formatObj->stringval, 00634 numberObj->floatval, 00635 &result) == XPATH_EXPRESSION_OK) { 00636 valuePush(ctxt, xmlXPathNewString(result)); 00637 xmlFree(result); 00638 } 00639 } 00640 00641 xmlXPathFreeObject(numberObj); 00642 xmlXPathFreeObject(formatObj); 00643 xmlXPathFreeObject(decimalObj); 00644 } 00645 00654 void 00655 xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){ 00656 xmlNodePtr cur = NULL; 00657 unsigned long val; 00658 xmlChar str[20]; 00659 00660 if (nargs == 0) { 00661 cur = ctxt->context->node; 00662 } else if (nargs == 1) { 00663 xmlXPathObjectPtr obj; 00664 xmlNodeSetPtr nodelist; 00665 int i, ret; 00666 00667 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) { 00668 ctxt->error = XPATH_INVALID_TYPE; 00669 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00670 "generate-id() : invalid arg expecting a node-set\n"); 00671 return; 00672 } 00673 obj = valuePop(ctxt); 00674 nodelist = obj->nodesetval; 00675 if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) { 00676 xmlXPathFreeObject(obj); 00677 valuePush(ctxt, xmlXPathNewCString("")); 00678 return; 00679 } 00680 cur = nodelist->nodeTab[0]; 00681 for (i = 1;i < nodelist->nodeNr;i++) { 00682 ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]); 00683 if (ret == -1) 00684 cur = nodelist->nodeTab[i]; 00685 } 00686 xmlXPathFreeObject(obj); 00687 } else { 00688 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00689 "generate-id() : invalid number of args %d\n", nargs); 00690 ctxt->error = XPATH_INVALID_ARITY; 00691 return; 00692 } 00693 /* 00694 * Okay this is ugly but should work, use the NodePtr address 00695 * to forge the ID 00696 */ 00697 val = (unsigned long)((char *)cur - (char *)0); 00698 val /= sizeof(xmlNode); 00699 sprintf((char *)str, "id%ld", val); 00700 valuePush(ctxt, xmlXPathNewString(str)); 00701 } 00702 00711 void 00712 xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs){ 00713 xmlXPathObjectPtr obj; 00714 xmlChar *prefix, *name; 00715 const xmlChar *nsURI = NULL; 00716 00717 if (nargs != 1) { 00718 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00719 "system-property() : expects one string arg\n"); 00720 ctxt->error = XPATH_INVALID_ARITY; 00721 return; 00722 } 00723 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { 00724 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00725 "system-property() : invalid arg expecting a string\n"); 00726 ctxt->error = XPATH_INVALID_TYPE; 00727 return; 00728 } 00729 obj = valuePop(ctxt); 00730 if (obj->stringval == NULL) { 00731 valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); 00732 } else { 00733 name = xmlSplitQName2(obj->stringval, &prefix); 00734 if (name == NULL) { 00735 name = xmlStrdup(obj->stringval); 00736 } else { 00737 nsURI = xmlXPathNsLookup(ctxt->context, prefix); 00738 if (nsURI == NULL) { 00739 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00740 "system-property() : prefix %s is not bound\n", prefix); 00741 } 00742 } 00743 00744 if (xmlStrEqual(nsURI, XSLT_NAMESPACE)) { 00745 #ifdef DOCBOOK_XSL_HACK 00746 if (xmlStrEqual(name, (const xmlChar *)"vendor")) { 00747 xsltStylesheetPtr sheet; 00748 xsltTransformContextPtr tctxt; 00749 00750 tctxt = xsltXPathGetTransformContext(ctxt); 00751 if ((tctxt != NULL) && (tctxt->inst != NULL) && 00752 (xmlStrEqual(tctxt->inst->name, BAD_CAST "variable")) && 00753 (tctxt->inst->parent != NULL) && 00754 (xmlStrEqual(tctxt->inst->parent->name, 00755 BAD_CAST "template"))) 00756 sheet = tctxt->style; 00757 else 00758 sheet = NULL; 00759 if ((sheet != NULL) && (sheet->doc != NULL) && 00760 (sheet->doc->URL != NULL) && 00761 (xmlStrstr(sheet->doc->URL, 00762 (const xmlChar *)"chunk") != NULL)) { 00763 valuePush(ctxt, xmlXPathNewString( 00764 (const xmlChar *)"libxslt (SAXON 6.2 compatible)")); 00765 00766 } else { 00767 valuePush(ctxt, xmlXPathNewString( 00768 (const xmlChar *)XSLT_DEFAULT_VENDOR)); 00769 } 00770 } else 00771 #else 00772 if (xmlStrEqual(name, (const xmlChar *)"vendor")) { 00773 valuePush(ctxt, xmlXPathNewString( 00774 (const xmlChar *)XSLT_DEFAULT_VENDOR)); 00775 } else 00776 #endif 00777 if (xmlStrEqual(name, (const xmlChar *)"version")) { 00778 valuePush(ctxt, xmlXPathNewString( 00779 (const xmlChar *)XSLT_DEFAULT_VERSION)); 00780 } else if (xmlStrEqual(name, (const xmlChar *)"vendor-url")) { 00781 valuePush(ctxt, xmlXPathNewString( 00782 (const xmlChar *)XSLT_DEFAULT_URL)); 00783 } else { 00784 valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); 00785 } 00786 } 00787 if (name != NULL) 00788 xmlFree(name); 00789 if (prefix != NULL) 00790 xmlFree(prefix); 00791 } 00792 xmlXPathFreeObject(obj); 00793 } 00794 00803 void 00804 xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){ 00805 xmlXPathObjectPtr obj; 00806 xmlChar *prefix, *name; 00807 const xmlChar *nsURI = NULL; 00808 xsltTransformContextPtr tctxt; 00809 00810 if (nargs != 1) { 00811 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00812 "element-available() : expects one string arg\n"); 00813 ctxt->error = XPATH_INVALID_ARITY; 00814 return; 00815 } 00816 xmlXPathStringFunction(ctxt, 1); 00817 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { 00818 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00819 "element-available() : invalid arg expecting a string\n"); 00820 ctxt->error = XPATH_INVALID_TYPE; 00821 return; 00822 } 00823 obj = valuePop(ctxt); 00824 tctxt = xsltXPathGetTransformContext(ctxt); 00825 if (tctxt == NULL) { 00826 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00827 "element-available() : internal error tctxt == NULL\n"); 00828 xmlXPathFreeObject(obj); 00829 valuePush(ctxt, xmlXPathNewBoolean(0)); 00830 return; 00831 } 00832 00833 00834 name = xmlSplitQName2(obj->stringval, &prefix); 00835 if (name == NULL) { 00836 xmlNsPtr ns; 00837 00838 name = xmlStrdup(obj->stringval); 00839 ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL); 00840 if (ns != NULL) nsURI = xmlStrdup(ns->href); 00841 } else { 00842 nsURI = xmlXPathNsLookup(ctxt->context, prefix); 00843 if (nsURI == NULL) { 00844 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00845 "element-available() : prefix %s is not bound\n", prefix); 00846 } 00847 } 00848 00849 if (xsltExtElementLookup(tctxt, name, nsURI) != NULL) { 00850 valuePush(ctxt, xmlXPathNewBoolean(1)); 00851 } else { 00852 valuePush(ctxt, xmlXPathNewBoolean(0)); 00853 } 00854 00855 xmlXPathFreeObject(obj); 00856 if (name != NULL) 00857 xmlFree(name); 00858 if (prefix != NULL) 00859 xmlFree(prefix); 00860 } 00861 00870 void 00871 xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){ 00872 xmlXPathObjectPtr obj; 00873 xmlChar *prefix, *name; 00874 const xmlChar *nsURI = NULL; 00875 00876 if (nargs != 1) { 00877 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00878 "function-available() : expects one string arg\n"); 00879 ctxt->error = XPATH_INVALID_ARITY; 00880 return; 00881 } 00882 xmlXPathStringFunction(ctxt, 1); 00883 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { 00884 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00885 "function-available() : invalid arg expecting a string\n"); 00886 ctxt->error = XPATH_INVALID_TYPE; 00887 return; 00888 } 00889 obj = valuePop(ctxt); 00890 00891 name = xmlSplitQName2(obj->stringval, &prefix); 00892 if (name == NULL) { 00893 name = xmlStrdup(obj->stringval); 00894 } else { 00895 nsURI = xmlXPathNsLookup(ctxt->context, prefix); 00896 if (nsURI == NULL) { 00897 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00898 "function-available() : prefix %s is not bound\n", prefix); 00899 } 00900 } 00901 00902 if (xmlXPathFunctionLookupNS(ctxt->context, name, nsURI) != NULL) { 00903 valuePush(ctxt, xmlXPathNewBoolean(1)); 00904 } else { 00905 valuePush(ctxt, xmlXPathNewBoolean(0)); 00906 } 00907 00908 xmlXPathFreeObject(obj); 00909 if (name != NULL) 00910 xmlFree(name); 00911 if (prefix != NULL) 00912 xmlFree(prefix); 00913 } 00914 00923 static void 00924 xsltCurrentFunction(xmlXPathParserContextPtr ctxt, int nargs){ 00925 xsltTransformContextPtr tctxt; 00926 00927 if (nargs != 0) { 00928 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00929 "current() : function uses no argument\n"); 00930 ctxt->error = XPATH_INVALID_ARITY; 00931 return; 00932 } 00933 tctxt = xsltXPathGetTransformContext(ctxt); 00934 if (tctxt == NULL) { 00935 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 00936 "current() : internal error tctxt == NULL\n"); 00937 valuePush(ctxt, xmlXPathNewNodeSet(NULL)); 00938 } else { 00939 valuePush(ctxt, xmlXPathNewNodeSet(tctxt->node)); /* current */ 00940 } 00941 } 00942 00943 /************************************************************************ 00944 * * 00945 * Registration of XSLT and libxslt functions * 00946 * * 00947 ************************************************************************/ 00948 00955 void 00956 xsltRegisterAllFunctions(xmlXPathContextPtr ctxt) 00957 { 00958 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "current", 00959 xsltCurrentFunction); 00960 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "document", 00961 xsltDocumentFunction); 00962 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "key", xsltKeyFunction); 00963 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "unparsed-entity-uri", 00964 xsltUnparsedEntityURIFunction); 00965 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "format-number", 00966 xsltFormatNumberFunction); 00967 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "generate-id", 00968 xsltGenerateIdFunction); 00969 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "system-property", 00970 xsltSystemPropertyFunction); 00971 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "element-available", 00972 xsltElementAvailableFunction); 00973 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "function-available", 00974 xsltFunctionAvailableFunction); 00975 } Generated on Sat May 26 2012 04:18:26 for ReactOS by
1.7.6.1
|