Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenkeys.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
1.7.6.1
|