ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

functions.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.