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

keys.c
Go to the documentation of this file.
00001 /*
00002  * keys.c: Implemetation of the keys support
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  */
00011 
00012 #define IN_LIBXSLT
00013 #include "libxslt.h"
00014 
00015 #include <string.h>
00016 
00017 #include <libxml/xmlmemory.h>
00018 #include <libxml/tree.h>
00019 #include <libxml/valid.h>
00020 #include <libxml/hash.h>
00021 #include <libxml/xmlerror.h>
00022 #include <libxml/parserInternals.h>
00023 #include <libxml/xpathInternals.h>
00024 #include "xslt.h"
00025 #include "xsltInternals.h"
00026 #include "xsltutils.h"
00027 #include "imports.h"
00028 #include "templates.h"
00029 #include "keys.h"
00030 
00031 #ifdef WITH_XSLT_DEBUG
00032 #define WITH_XSLT_DEBUG_KEYS
00033 #endif
00034 
00035 static int
00036 xsltInitDocKeyTable(xsltTransformContextPtr ctxt, const xmlChar *name,
00037                     const xmlChar *nameURI);
00038 
00039 /************************************************************************
00040  *                                  *
00041  *          Type functions                  *
00042  *                                  *
00043  ************************************************************************/
00044 
00054 static xsltKeyDefPtr
00055 xsltNewKeyDef(const xmlChar *name, const xmlChar *nameURI) {
00056     xsltKeyDefPtr cur;
00057 
00058     cur = (xsltKeyDefPtr) xmlMalloc(sizeof(xsltKeyDef));
00059     if (cur == NULL) {
00060     xsltTransformError(NULL, NULL, NULL,
00061         "xsltNewKeyDef : malloc failed\n");
00062     return(NULL);
00063     }
00064     memset(cur, 0, sizeof(xsltKeyDef));
00065     if (name != NULL)
00066     cur->name = xmlStrdup(name);
00067     if (nameURI != NULL)
00068     cur->nameURI = xmlStrdup(nameURI);
00069     cur->nsList = NULL;
00070     return(cur);
00071 }
00072 
00079 static void
00080 xsltFreeKeyDef(xsltKeyDefPtr keyd) {
00081     if (keyd == NULL)
00082     return;
00083     if (keyd->comp != NULL)
00084     xmlXPathFreeCompExpr(keyd->comp);
00085     if (keyd->usecomp != NULL)
00086     xmlXPathFreeCompExpr(keyd->usecomp);
00087     if (keyd->name != NULL)
00088     xmlFree(keyd->name);
00089     if (keyd->nameURI != NULL)
00090     xmlFree(keyd->nameURI);
00091     if (keyd->match != NULL)
00092     xmlFree(keyd->match);
00093     if (keyd->use != NULL)
00094     xmlFree(keyd->use);
00095     if (keyd->nsList != NULL)
00096         xmlFree(keyd->nsList);
00097     memset(keyd, -1, sizeof(xsltKeyDef));
00098     xmlFree(keyd);
00099 }
00100 
00107 static void
00108 xsltFreeKeyDefList(xsltKeyDefPtr keyd) {
00109     xsltKeyDefPtr cur;
00110 
00111     while (keyd != NULL) {
00112     cur = keyd;
00113     keyd = keyd->next;
00114     xsltFreeKeyDef(cur);
00115     }
00116 }
00117 
00127 static xsltKeyTablePtr
00128 xsltNewKeyTable(const xmlChar *name, const xmlChar *nameURI) {
00129     xsltKeyTablePtr cur;
00130 
00131     cur = (xsltKeyTablePtr) xmlMalloc(sizeof(xsltKeyTable));
00132     if (cur == NULL) {
00133     xsltTransformError(NULL, NULL, NULL,
00134         "xsltNewKeyTable : malloc failed\n");
00135     return(NULL);
00136     }
00137     memset(cur, 0, sizeof(xsltKeyTable));
00138     if (name != NULL)
00139     cur->name = xmlStrdup(name);
00140     if (nameURI != NULL)
00141     cur->nameURI = xmlStrdup(nameURI);
00142     cur->keys = xmlHashCreate(0);
00143     return(cur);
00144 }
00145 
00152 static void
00153 xsltFreeKeyTable(xsltKeyTablePtr keyt) {
00154     if (keyt == NULL)
00155     return;
00156     if (keyt->name != NULL)
00157     xmlFree(keyt->name);
00158     if (keyt->nameURI != NULL)
00159     xmlFree(keyt->nameURI);
00160     if (keyt->keys != NULL)
00161     xmlHashFree(keyt->keys, 
00162             (xmlHashDeallocator) xmlXPathFreeNodeSet);
00163     memset(keyt, -1, sizeof(xsltKeyTable));
00164     xmlFree(keyt);
00165 }
00166 
00173 static void
00174 xsltFreeKeyTableList(xsltKeyTablePtr keyt) {
00175     xsltKeyTablePtr cur;
00176 
00177     while (keyt != NULL) {
00178     cur = keyt;
00179     keyt = keyt->next;
00180     xsltFreeKeyTable(cur);
00181     }
00182 }
00183 
00184 /************************************************************************
00185  *                                  *
00186  *      The interpreter for the precompiled patterns        *
00187  *                                  *
00188  ************************************************************************/
00189 
00190 
00197 void
00198 xsltFreeKeys(xsltStylesheetPtr style) {
00199     if (style->keys)
00200     xsltFreeKeyDefList((xsltKeyDefPtr) style->keys);
00201 }
00202 
00212 static int
00213 skipString(const xmlChar *cur, int end) {
00214     xmlChar limit;
00215 
00216     if ((cur == NULL) || (end < 0)) return(-1);
00217     if ((cur[end] == '\'') || (cur[end] == '"')) limit = cur[end];
00218     else return(end);
00219     end++;
00220     while (cur[end] != 0) {
00221         if (cur[end] == limit)
00222         return(end + 1);
00223     end++;
00224     }
00225     return(-1);
00226 }
00227 
00237 static int
00238 skipPredicate(const xmlChar *cur, int end) {
00239     if ((cur == NULL) || (end < 0)) return(-1);
00240     if (cur[end] != '[') return(end);
00241     end++;
00242     while (cur[end] != 0) {
00243         if ((cur[end] == '\'') || (cur[end] == '"')) {
00244         end = skipString(cur, end);
00245         if (end <= 0)
00246             return(-1);
00247         continue;
00248     } else if (cur[end] == '[') {
00249         end = skipPredicate(cur, end);
00250         if (end <= 0)
00251             return(-1);
00252         continue;
00253     } else if (cur[end] == ']')
00254         return(end + 1);
00255     end++;
00256     }
00257     return(-1);
00258 }
00259 
00273 int
00274 xsltAddKey(xsltStylesheetPtr style, const xmlChar *name,
00275        const xmlChar *nameURI, const xmlChar *match,
00276        const xmlChar *use, xmlNodePtr inst) {
00277     xsltKeyDefPtr key;
00278     xmlChar *pattern = NULL;
00279     int current, end, start, i = 0;
00280 
00281     if ((style == NULL) || (name == NULL) || (match == NULL) || (use == NULL))
00282     return(-1);
00283 
00284 #ifdef WITH_XSLT_DEBUG_KEYS
00285     xsltGenericDebug(xsltGenericDebugContext,
00286     "Add key %s, match %s, use %s\n", name, match, use);
00287 #endif
00288 
00289     key = xsltNewKeyDef(name, nameURI);
00290     key->match = xmlStrdup(match);
00291     key->use = xmlStrdup(use);
00292     key->inst = inst;
00293     key->nsList = xmlGetNsList(inst->doc, inst);
00294     if (key->nsList != NULL) {
00295         while (key->nsList[i] != NULL)
00296         i++;
00297     }
00298     key->nsNr = i;
00299 
00300     /*
00301      * Split the | and register it as as many keys
00302      */
00303     current = end = 0;
00304     while (match[current] != 0) {
00305     start = current;
00306     while (IS_BLANK_CH(match[current]))
00307         current++;
00308     end = current;
00309     while ((match[end] != 0) && (match[end] != '|')) {
00310         if (match[end] == '[') {
00311             end = skipPredicate(match, end);
00312         if (end <= 0) {
00313             xsltTransformError(NULL, style, inst,
00314                                "key pattern is malformed: %s",
00315                        key->match);
00316             if (style != NULL) style->errors++;
00317             goto error;
00318         }
00319         } else
00320         end++;
00321     }
00322     if (current == end) {
00323         xsltTransformError(NULL, style, inst,
00324                    "key pattern is empty\n");
00325         if (style != NULL) style->errors++;
00326         goto error;
00327     }
00328     if (match[start] != '/') {
00329         pattern = xmlStrcat(pattern, (xmlChar *)"//");
00330         if (pattern == NULL) {
00331         if (style != NULL) style->errors++;
00332         goto error;
00333         }
00334     }
00335     pattern = xmlStrncat(pattern, &match[start], end - start);
00336     if (pattern == NULL) {
00337         if (style != NULL) style->errors++;
00338         goto error;
00339     }
00340 
00341     if (match[end] == '|') {
00342         pattern = xmlStrcat(pattern, (xmlChar *)"|");
00343         end++;
00344     }
00345     current = end;
00346     }
00347 #ifdef WITH_XSLT_DEBUG_KEYS
00348     xsltGenericDebug(xsltGenericDebugContext,
00349     "   resulting pattern %s\n", pattern);
00350 #endif
00351     /*
00352     * XSLT-1: "It is an error for the value of either the use
00353     *  attribute or the match attribute to contain a
00354     *  VariableReference."
00355     * TODO: We should report a variable-reference at compile-time.
00356     *   Maybe a search for "$", if it occurs outside of quotation
00357     *   marks, could be sufficient.
00358     */
00359     key->comp = xsltXPathCompile(style, pattern);
00360     if (key->comp == NULL) {
00361     xsltTransformError(NULL, style, inst,
00362         "xsl:key : XPath pattern compilation failed '%s'\n",
00363                  pattern);
00364     if (style != NULL) style->errors++;
00365     }
00366     key->usecomp = xsltXPathCompile(style, use);
00367     if (key->usecomp == NULL) {
00368     xsltTransformError(NULL, style, inst,
00369         "xsl:key : XPath pattern compilation failed '%s'\n",
00370                  use);
00371     if (style != NULL) style->errors++;
00372     }
00373 
00374     /*
00375      * Sometimes the stylesheet writer use the order to ease the
00376      * resolution of keys when they are dependant, keep the provided
00377      * order so add the new one at the end.
00378      */
00379     if (style->keys == NULL) {
00380     style->keys = key;
00381     } else {
00382         xsltKeyDefPtr prev = style->keys;
00383 
00384     while (prev->next != NULL)
00385         prev = prev->next;
00386 
00387     prev->next = key;
00388     }
00389     key->next = NULL;
00390 
00391 error:
00392     if (pattern != NULL)
00393     xmlFree(pattern);
00394     return(0);
00395 }
00396 
00410 xmlNodeSetPtr
00411 xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name,
00412        const xmlChar *nameURI, const xmlChar *value) {
00413     xmlNodeSetPtr ret;
00414     xsltKeyTablePtr table;
00415     int init_table = 0;
00416 
00417     if ((ctxt == NULL) || (name == NULL) || (value == NULL) ||
00418     (ctxt->document == NULL))
00419     return(NULL);
00420 
00421 #ifdef WITH_XSLT_DEBUG_KEYS
00422     xsltGenericDebug(xsltGenericDebugContext,
00423     "Get key %s, value %s\n", name, value);
00424 #endif
00425 
00426     /*
00427      * keys are computed only on-demand on first key access for a document
00428      */
00429     if ((ctxt->document->nbKeysComputed < ctxt->nbKeys) &&
00430         (ctxt->keyInitLevel == 0)) {
00431         /*
00432      * If non-recursive behaviour, just try to initialize all keys
00433      */
00434     if (xsltInitAllDocKeys(ctxt))
00435         return(NULL);
00436     }
00437 
00438 retry:
00439     table = (xsltKeyTablePtr) ctxt->document->keys;
00440     while (table != NULL) {
00441     if (((nameURI != NULL) == (table->nameURI != NULL)) &&
00442         xmlStrEqual(table->name, name) &&
00443         xmlStrEqual(table->nameURI, nameURI))
00444     {
00445         ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value);
00446         return(ret);
00447     }
00448     table = table->next;
00449     }
00450 
00451     if ((ctxt->keyInitLevel != 0) && (init_table == 0)) {
00452         /*
00453      * Apparently one key is recursive and this one is needed,
00454      * initialize just it, that time and retry
00455      */
00456         xsltInitDocKeyTable(ctxt, name, nameURI);
00457     init_table = 1;
00458     goto retry;
00459     }
00460 
00461     return(NULL);
00462 }
00463 
00464 
00472 static int
00473 xsltInitDocKeyTable(xsltTransformContextPtr ctxt, const xmlChar *name,
00474                     const xmlChar *nameURI)
00475 {
00476     xsltStylesheetPtr style;
00477     xsltKeyDefPtr keyd = NULL;
00478     int found = 0;
00479 
00480 #ifdef KEY_INIT_DEBUG
00481 fprintf(stderr, "xsltInitDocKeyTable %s\n", name);
00482 #endif
00483 
00484     style = ctxt->style;
00485     while (style != NULL) {
00486     keyd = (xsltKeyDefPtr) style->keys;
00487     while (keyd != NULL) {
00488         if (((keyd->nameURI != NULL) ==
00489          (nameURI != NULL)) &&
00490         xmlStrEqual(keyd->name, name) &&
00491         xmlStrEqual(keyd->nameURI, nameURI))
00492         {
00493         xsltInitCtxtKey(ctxt, ctxt->document, keyd);
00494         if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
00495             return(0);
00496         found = 1;
00497         }
00498         keyd = keyd->next;
00499     }
00500     style = xsltNextImport(style);
00501     }
00502     if (found == 0) {
00503 #ifdef WITH_XSLT_DEBUG_KEYS
00504     XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
00505          "xsltInitDocKeyTable: did not found %s\n", name));
00506 #endif
00507     xsltTransformError(ctxt, NULL, keyd? keyd->inst : NULL,
00508         "Failed to find key definition for %s\n", name);
00509     ctxt->state = XSLT_STATE_STOPPED;
00510         return(-1);
00511     }
00512 #ifdef KEY_INIT_DEBUG
00513 fprintf(stderr, "xsltInitDocKeyTable %s done\n", name);
00514 #endif
00515     return(0);
00516 }
00517 
00528 int
00529 xsltInitAllDocKeys(xsltTransformContextPtr ctxt)
00530 {
00531     xsltStylesheetPtr style;
00532     xsltKeyDefPtr keyd;
00533     xsltKeyTablePtr table;
00534 
00535     if (ctxt == NULL)
00536     return(-1);
00537 
00538 #ifdef KEY_INIT_DEBUG
00539 fprintf(stderr, "xsltInitAllDocKeys %d %d\n",
00540         ctxt->document->nbKeysComputed, ctxt->nbKeys);
00541 #endif
00542 
00543     if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
00544     return(0);
00545 
00546 
00547     /*
00548     * TODO: This could be further optimized
00549     */
00550     style = ctxt->style;
00551     while (style) {
00552     keyd = (xsltKeyDefPtr) style->keys;
00553     while (keyd != NULL) {
00554 #ifdef KEY_INIT_DEBUG
00555 fprintf(stderr, "Init key %s\n", keyd->name);
00556 #endif
00557         /*
00558         * Check if keys with this QName have been already
00559         * computed.
00560         */
00561         table = (xsltKeyTablePtr) ctxt->document->keys;
00562         while (table) {
00563         if (((keyd->nameURI != NULL) == (table->nameURI != NULL)) &&
00564             xmlStrEqual(keyd->name, table->name) &&
00565             xmlStrEqual(keyd->nameURI, table->nameURI))
00566         {
00567             break;
00568         }
00569         table = table->next;
00570         }
00571         if (table == NULL) {
00572         /*
00573         * Keys with this QName have not been yet computed.
00574         */
00575         xsltInitDocKeyTable(ctxt, keyd->name, keyd->nameURI);
00576         }
00577         keyd = keyd->next;
00578     }
00579     style = xsltNextImport(style);
00580     }
00581 #ifdef KEY_INIT_DEBUG
00582 fprintf(stderr, "xsltInitAllDocKeys: done\n");
00583 #endif
00584     return(0);
00585 }
00586 
00597 int
00598 xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc,
00599             xsltKeyDefPtr keyDef)
00600 {
00601     int i, len, k;
00602     xmlNodeSetPtr matchList = NULL, keylist;
00603     xmlXPathObjectPtr matchRes = NULL, useRes = NULL;
00604     xmlChar *str = NULL;
00605     xsltKeyTablePtr table;
00606     xmlNodePtr oldInst, cur;
00607     xmlNodePtr oldContextNode;
00608     xsltDocumentPtr oldDocInfo;
00609     int oldXPPos, oldXPSize;
00610     xmlDocPtr oldXPDoc;
00611     int oldXPNsNr;
00612     xmlNsPtr *oldXPNamespaces;
00613     xmlXPathContextPtr xpctxt;
00614 
00615 #ifdef KEY_INIT_DEBUG
00616 fprintf(stderr, "xsltInitCtxtKey %s : %d\n", keyDef->name, ctxt->keyInitLevel);
00617 #endif
00618 
00619     if ((keyDef->comp == NULL) || (keyDef->usecomp == NULL))
00620     return(-1);
00621 
00622     /*
00623      * Detect recursive keys
00624      */
00625     if (ctxt->keyInitLevel > ctxt->nbKeys) {
00626 #ifdef WITH_XSLT_DEBUG_KEYS
00627     XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,
00628                xsltGenericDebug(xsltGenericDebugContext,
00629                "xsltInitCtxtKey: key definition of %s is recursive\n",
00630                keyDef->name));
00631 #endif
00632     xsltTransformError(ctxt, NULL, keyDef->inst,
00633         "Key definition for %s is recursive\n", keyDef->name);
00634     ctxt->state = XSLT_STATE_STOPPED;
00635         return(-1);
00636     }
00637     ctxt->keyInitLevel++;
00638 
00639     xpctxt = ctxt->xpathCtxt;
00640     idoc->nbKeysComputed++;
00641     /*
00642     * Save context state.
00643     */
00644     oldInst = ctxt->inst;
00645     oldDocInfo = ctxt->document;
00646     oldContextNode = ctxt->node;
00647 
00648     oldXPDoc = xpctxt->doc;
00649     oldXPPos = xpctxt->proximityPosition;
00650     oldXPSize = xpctxt->contextSize;
00651     oldXPNsNr = xpctxt->nsNr;
00652     oldXPNamespaces = xpctxt->namespaces;
00653 
00654     /*
00655     * Set up contexts.
00656     */
00657     ctxt->document = idoc;
00658     ctxt->node = (xmlNodePtr) idoc->doc;
00659     ctxt->inst = keyDef->inst;
00660 
00661     xpctxt->doc = idoc->doc;
00662     xpctxt->node = (xmlNodePtr) idoc->doc;
00663     /* TODO : clarify the use of namespaces in keys evaluation */
00664     xpctxt->namespaces = keyDef->nsList;
00665     xpctxt->nsNr = keyDef->nsNr;
00666 
00667     /*
00668     * Evaluate the 'match' expression of the xsl:key.
00669     * TODO: The 'match' is a *pattern*.
00670     */
00671     matchRes = xmlXPathCompiledEval(keyDef->comp, xpctxt);
00672     if (matchRes == NULL) {
00673 
00674 #ifdef WITH_XSLT_DEBUG_KEYS
00675     XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
00676          "xsltInitCtxtKey: %s evaluation failed\n", keyDef->match));
00677 #endif
00678     xsltTransformError(ctxt, NULL, keyDef->inst,
00679         "Failed to evaluate the 'match' expression.\n");
00680     ctxt->state = XSLT_STATE_STOPPED;
00681     goto error;
00682     } else {
00683     if (matchRes->type == XPATH_NODESET) {
00684         matchList = matchRes->nodesetval;
00685 
00686 #ifdef WITH_XSLT_DEBUG_KEYS
00687         if (matchList != NULL)
00688         XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
00689              "xsltInitCtxtKey: %s evaluates to %d nodes\n",
00690                  keyDef->match, matchList->nodeNr));
00691 #endif
00692     } else {
00693         /*
00694         * Is not a node set, but must be.
00695         */
00696 #ifdef WITH_XSLT_DEBUG_KEYS
00697         XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
00698          "xsltInitCtxtKey: %s is not a node set\n", keyDef->match));
00699 #endif
00700         xsltTransformError(ctxt, NULL, keyDef->inst,
00701         "The 'match' expression did not evaluate to a node set.\n");
00702         ctxt->state = XSLT_STATE_STOPPED;
00703         goto error;
00704     }
00705     }
00706     if ((matchList == NULL) || (matchList->nodeNr <= 0))
00707     goto exit;
00708 
00713     table = (xsltKeyTablePtr) idoc->keys;
00714     while (table != NULL) {
00715         if (xmlStrEqual(table->name, keyDef->name) &&
00716         (((keyDef->nameURI == NULL) && (table->nameURI == NULL)) ||
00717          ((keyDef->nameURI != NULL) && (table->nameURI != NULL) &&
00718           (xmlStrEqual(table->nameURI, keyDef->nameURI)))))
00719         break;
00720     table = table->next;
00721     }
00726     if (table == NULL) {
00727         table = xsltNewKeyTable(keyDef->name, keyDef->nameURI);
00728         if (table == NULL)
00729         goto error;
00730         table->next = idoc->keys;
00731         idoc->keys = table;
00732     }
00733 
00734     /*
00735     * SPEC XSLT 1.0 (XSLT 2.0 does not clarify the context size!)
00736     * "...the use attribute of the xsl:key element is evaluated with x as
00737     "  the current node and with a node list containing just x as the
00738     *  current node list"
00739     */
00740     xpctxt->contextSize = 1;
00741     xpctxt->proximityPosition = 1;
00742 
00743     for (i = 0; i < matchList->nodeNr; i++) {
00744     cur = matchList->nodeTab[i];
00745     if (! IS_XSLT_REAL_NODE(cur))
00746         continue;
00747     xpctxt->node = cur;
00748     /*
00749     * Process the 'use' of the xsl:key.
00750     * SPEC XSLT 1.0:
00751     * "The use attribute is an expression specifying the values of
00752     *  the key; the expression is evaluated once for each node that
00753     *  matches the pattern."
00754     */
00755     if (useRes != NULL)
00756         xmlXPathFreeObject(useRes);
00757     useRes = xmlXPathCompiledEval(keyDef->usecomp, xpctxt);
00758     if (useRes == NULL) {
00759         xsltTransformError(ctxt, NULL, keyDef->inst,
00760         "Failed to evaluate the 'use' expression.\n");
00761         ctxt->state = XSLT_STATE_STOPPED;
00762         break;
00763     }
00764     if (useRes->type == XPATH_NODESET) {
00765         if ((useRes->nodesetval != NULL) &&
00766         (useRes->nodesetval->nodeNr != 0))
00767         {
00768         len = useRes->nodesetval->nodeNr;
00769         str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[0]);
00770         } else {
00771         continue;
00772         }
00773     } else {
00774         len = 1;
00775         if (useRes->type == XPATH_STRING) {
00776         /*
00777         * Consume the string value.
00778         */
00779         str = useRes->stringval;
00780         useRes->stringval = NULL;
00781         } else {
00782         str = xmlXPathCastToString(useRes);
00783         }
00784     }
00785     /*
00786     * Process all strings.
00787     */
00788     k = 0;
00789     while (1) {
00790         if (str == NULL)
00791         goto next_string;
00792 
00793 #ifdef WITH_XSLT_DEBUG_KEYS
00794         XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
00795         "xsl:key : node associated to ('%s', '%s')\n", keyDef->name, str));
00796 #endif
00797 
00798         keylist = xmlHashLookup(table->keys, str);
00799         if (keylist == NULL) {
00800         keylist = xmlXPathNodeSetCreate(cur);
00801         if (keylist == NULL)
00802             goto error;
00803         xmlHashAddEntry(table->keys, str, keylist);
00804         } else {
00805         /*
00806         * TODO: How do we know if this function failed?
00807         */
00808         xmlXPathNodeSetAdd(keylist, cur);
00809         }
00810         switch (cur->type) {
00811         case XML_ELEMENT_NODE:
00812         case XML_TEXT_NODE:
00813         case XML_CDATA_SECTION_NODE:
00814         case XML_PI_NODE:
00815         case XML_COMMENT_NODE:
00816             cur->psvi = keyDef;
00817             break;
00818         case XML_ATTRIBUTE_NODE:
00819             ((xmlAttrPtr) cur)->psvi = keyDef;
00820             break;
00821         case XML_DOCUMENT_NODE:
00822         case XML_HTML_DOCUMENT_NODE:
00823             ((xmlDocPtr) cur)->psvi = keyDef;
00824             break;
00825         default:
00826             break;
00827         }
00828         xmlFree(str);
00829         str = NULL;
00830 
00831 next_string:
00832         k++;
00833         if (k >= len)
00834         break;
00835         str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[k]);
00836     }
00837     }
00838 
00839 exit:
00840 error:
00841     ctxt->keyInitLevel--;
00842     /*
00843     * Restore context state.
00844     */
00845     xpctxt->doc = oldXPDoc;
00846     xpctxt->nsNr = oldXPNsNr;
00847     xpctxt->namespaces = oldXPNamespaces;
00848     xpctxt->proximityPosition = oldXPPos;
00849     xpctxt->contextSize = oldXPSize;
00850 
00851     ctxt->node = oldContextNode;
00852     ctxt->document = oldDocInfo;
00853     ctxt->inst = oldInst;
00854 
00855     if (str)
00856     xmlFree(str);
00857     if (useRes != NULL)
00858     xmlXPathFreeObject(useRes);
00859     if (matchRes != NULL)
00860     xmlXPathFreeObject(matchRes);
00861     return(0);
00862 }
00863 
00873 void
00874 xsltInitCtxtKeys(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc) {
00875     xsltStylesheetPtr style;
00876     xsltKeyDefPtr keyDef;
00877 
00878     if ((ctxt == NULL) || (idoc == NULL))
00879     return;
00880 
00881 #ifdef KEY_INIT_DEBUG
00882 fprintf(stderr, "xsltInitCtxtKeys on document\n");
00883 #endif
00884 
00885 #ifdef WITH_XSLT_DEBUG_KEYS
00886     if ((idoc->doc != NULL) && (idoc->doc->URL != NULL))
00887     XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n",
00888              idoc->doc->URL));
00889 #endif
00890     style = ctxt->style;
00891     while (style != NULL) {
00892     keyDef = (xsltKeyDefPtr) style->keys;
00893     while (keyDef != NULL) {
00894         xsltInitCtxtKey(ctxt, idoc, keyDef);
00895 
00896         keyDef = keyDef->next;
00897     }
00898 
00899     style = xsltNextImport(style);
00900     }
00901 
00902 #ifdef KEY_INIT_DEBUG
00903 fprintf(stderr, "xsltInitCtxtKeys on document: done\n");
00904 #endif
00905 
00906 }
00907 
00914 void
00915 xsltFreeDocumentKeys(xsltDocumentPtr idoc) {
00916     if (idoc != NULL)
00917         xsltFreeKeyTableList(idoc->keys);
00918 }
00919 

Generated on Sun May 27 2012 04:19:37 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.