ReactOS 0.4.16-dev-319-g6cf4263
keys.c File Reference
#include "precomp.h"
Include dependency graph for keys.c:

Go to the source code of this file.

Functions

: the key name or NULL

xsltGetKey: @ctxt: an XSLT transformation context

@nameURI: the name URI or NULL @value: the key value to look for

Looks up a key of the in current source doc (the document info on @ctxt->document). Computes the key if not already done for the current source doc.

Returns the nodeset resulting from the query or NULL

static int xsltInitDocKeyTable (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI)
 
static xsltKeyDefPtr xsltNewKeyDef (const xmlChar *name, const xmlChar *nameURI)
 
static void xsltFreeKeyDef (xsltKeyDefPtr keyd)
 
static void xsltFreeKeyDefList (xsltKeyDefPtr keyd)
 
static xsltKeyTablePtr xsltNewKeyTable (const xmlChar *name, const xmlChar *nameURI)
 
static void xsltFreeNodeSetEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
 
static void xsltFreeKeyTable (xsltKeyTablePtr keyt)
 
static void xsltFreeKeyTableList (xsltKeyTablePtr keyt)
 
void xsltFreeKeys (xsltStylesheetPtr style)
 
static int skipString (const xmlChar *cur, int end)
 
static int skipPredicate (const xmlChar *cur, int end)
 
int xsltAddKey (xsltStylesheetPtr style, const xmlChar *name, const xmlChar *nameURI, const xmlChar *match, const xmlChar *use, xmlNodePtr inst)
 
xmlNodeSetPtr xsltGetKey (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI, const xmlChar *value)
 
int xsltInitAllDocKeys (xsltTransformContextPtr ctxt)
 
int xsltInitCtxtKey (xsltTransformContextPtr ctxt, xsltDocumentPtr idoc, xsltKeyDefPtr keyDef)
 
void xsltInitCtxtKeys (xsltTransformContextPtr ctxt, xsltDocumentPtr idoc)
 
void xsltFreeDocumentKeys (xsltDocumentPtr idoc)
 

Function Documentation

◆ skipPredicate()

static int skipPredicate ( const xmlChar cur,
int  end 
)
static

skipPredicate: @cur: the current pointer @end: the current offset

skip a predicate

Returns the byte after the predicate or -1 in case of error

Definition at line 225 of file keys.c.

225 {
226 int level = 0;
227
228 if ((cur == NULL) || (end < 0)) return(-1);
229 if (cur[end] != '[') return(end);
230 end++;
231 while (cur[end] != 0) {
232 if ((cur[end] == '\'') || (cur[end] == '"')) {
233 end = skipString(cur, end);
234 if (end <= 0)
235 return(-1);
236 continue;
237 } else if (cur[end] == '[') {
238 level += 1;
239 } else if (cur[end] == ']') {
240 if (level == 0)
241 return(end + 1);
242 level -= 1;
243 }
244 end++;
245 }
246 return(-1);
247}
#define NULL
Definition: types.h:112
FxCollectionEntry * cur
GLint level
Definition: gl.h:1546
GLuint GLuint end
Definition: gl.h:1545
static int skipString(const xmlChar *cur, int end)
Definition: keys.c:200

Referenced by xsltAddKey().

◆ skipString()

static int skipString ( const xmlChar cur,
int  end 
)
static

skipString: @cur: the current pointer @end: the current offset

skip a string delimited by " or '

Returns the byte after the string or -1 in case of error

Definition at line 200 of file keys.c.

200 {
202
203 if ((cur == NULL) || (end < 0)) return(-1);
204 if ((cur[end] == '\'') || (cur[end] == '"')) limit = cur[end];
205 else return(end);
206 end++;
207 while (cur[end] != 0) {
208 if (cur[end] == limit)
209 return(end + 1);
210 end++;
211 }
212 return(-1);
213}
GLint limit
Definition: glext.h:10326
unsigned char xmlChar
Definition: xmlstring.h:28

Referenced by skipPredicate().

◆ xsltAddKey()

int xsltAddKey ( xsltStylesheetPtr  style,
const xmlChar name,
const xmlChar nameURI,
const xmlChar match,
const xmlChar use,
xmlNodePtr  inst 
)

Definition at line 263 of file keys.c.

265 {
268 int current, end, start, i = 0;
269
270 if ((style == NULL) || (name == NULL) || (match == NULL) || (use == NULL))
271 return(-1);
272
273#ifdef WITH_XSLT_DEBUG_KEYS
275 "Add key %s, match %s, use %s\n", name, match, use);
276#endif
277
278 key = xsltNewKeyDef(name, nameURI);
279 key->match = xmlStrdup(match);
280 key->use = xmlStrdup(use);
281 key->inst = inst;
282 key->nsList = xmlGetNsList(inst->doc, inst);
283 if (key->nsList != NULL) {
284 while (key->nsList[i] != NULL)
285 i++;
286 }
287 key->nsNr = i;
288
289 /*
290 * Split the | and register it as as many keys
291 */
292 current = end = 0;
293 while (match[current] != 0) {
294 start = current;
295 while (xmlIsBlank_ch(match[current]))
296 current++;
297 end = current;
298 while ((match[end] != 0) && (match[end] != '|')) {
299 if (match[end] == '[') {
301 if (end <= 0) {
303 "xsl:key : 'match' pattern is malformed: %s",
304 key->match);
305 if (style != NULL) style->errors++;
306 goto error;
307 }
308 } else
309 end++;
310 }
311 if (current == end) {
313 "xsl:key : 'match' pattern is empty\n");
314 if (style != NULL) style->errors++;
315 goto error;
316 }
317 if (match[start] != '/') {
318 pattern = xmlStrcat(pattern, (xmlChar *)"//");
319 if (pattern == NULL) {
320 if (style != NULL) style->errors++;
321 goto error;
322 }
323 }
325 if (pattern == NULL) {
326 if (style != NULL) style->errors++;
327 goto error;
328 }
329
330 if (match[end] == '|') {
331 pattern = xmlStrcat(pattern, (xmlChar *)"|");
332 end++;
333 }
334 current = end;
335 }
336 if (pattern == NULL) {
338 "xsl:key : 'match' pattern is empty\n");
339 if (style != NULL) style->errors++;
340 goto error;
341 }
342#ifdef WITH_XSLT_DEBUG_KEYS
344 " resulting pattern %s\n", pattern);
345#endif
346 /*
347 * XSLT-1: "It is an error for the value of either the use
348 * attribute or the match attribute to contain a
349 * VariableReference."
350 * TODO: We should report a variable-reference at compile-time.
351 * Maybe a search for "$", if it occurs outside of quotation
352 * marks, could be sufficient.
353 */
354#ifdef XML_XPATH_NOVAR
355 key->comp = xsltXPathCompileFlags(style, pattern, XML_XPATH_NOVAR);
356#else
358#endif
359 if (key->comp == NULL) {
361 "xsl:key : 'match' pattern compilation failed '%s'\n",
362 pattern);
363 if (style != NULL) style->errors++;
364 }
365#ifdef XML_XPATH_NOVAR
366 key->usecomp = xsltXPathCompileFlags(style, use, XML_XPATH_NOVAR);
367#else
368 key->usecomp = xsltXPathCompile(style, use);
369#endif
370 if (key->usecomp == NULL) {
372 "xsl:key : 'use' expression compilation failed '%s'\n",
373 use);
374 if (style != NULL) style->errors++;
375 }
376
377 /*
378 * Sometimes the stylesheet writer use the order to ease the
379 * resolution of keys when they are dependant, keep the provided
380 * order so add the new one at the end.
381 */
382 if (style->keys == NULL) {
383 style->keys = key;
384 } else {
385 xsltKeyDefPtr prev = style->keys;
386
387 while (prev->next != NULL)
388 prev = prev->next;
389
390 prev->next = key;
391 }
392 key->next = NULL;
393 key = NULL;
394
395error:
396 if (pattern != NULL)
398 if (key != NULL)
400 return(0);
401}
Arabic default style
Definition: afstyles.h:94
#define xmlIsBlank_ch(c)
Definition: chvalid.h:88
GLuint start
Definition: gl.h:1545
GLubyte * pattern
Definition: glext.h:7787
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static xsltKeyDefPtr xsltNewKeyDef(const xmlChar *name, const xmlChar *nameURI)
Definition: keys.c:38
static int skipPredicate(const xmlChar *cur, int end)
Definition: keys.c:225
static void xsltFreeKeyDef(xsltKeyDefPtr keyd)
Definition: keys.c:63
#define error(str)
Definition: mkdosfs.c:1605
struct task_struct * current
Definition: linux.c:32
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
struct _xmlDoc * doc
Definition: tree.h:498
struct _xsltKeyDef * next
Definition: copy.c:22
Definition: match.c:28
Definition: name.c:39
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
XMLPUBFUN xmlChar *XMLCALL xmlStrncat(xmlChar *cur, const xmlChar *add, int len)
Definition: xmlstring.c:446
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678
xmlXPathCompExprPtr xsltXPathCompileFlags(xsltStylesheetPtr style, const xmlChar *str, int flags)
Definition: xsltutils.c:2313
xmlXPathCompExprPtr xsltXPathCompile(xsltStylesheetPtr style, const xmlChar *str)
Definition: xsltutils.c:2356
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:548
void * xsltGenericDebugContext
Definition: xsltutils.c:549

Referenced by xsltParseStylesheetKey().

◆ xsltFreeDocumentKeys()

void xsltFreeDocumentKeys ( xsltDocumentPtr  idoc)

xsltFreeDocumentKeys: @idoc: a XSLT document

Free the keys associated to a document

Definition at line 925 of file keys.c.

925 {
926 if (idoc != NULL)
928}
static void xsltFreeKeyTableList(xsltKeyTablePtr keyt)
Definition: keys.c:161

Referenced by xsltFreeDocuments(), xsltFreeRVTs(), xsltFreeStyleDocuments(), xsltReleaseRVT(), and xsltTransformCacheFree().

◆ xsltFreeKeyDef()

static void xsltFreeKeyDef ( xsltKeyDefPtr  keyd)
static

xsltFreeKeyDef: @keyd: an XSLT key definition

Free up the memory allocated by @keyd

Definition at line 63 of file keys.c.

63 {
64 if (keyd == NULL)
65 return;
66 if (keyd->comp != NULL)
67 xmlXPathFreeCompExpr(keyd->comp);
68 if (keyd->usecomp != NULL)
69 xmlXPathFreeCompExpr(keyd->usecomp);
70 if (keyd->name != NULL)
71 xmlFree(keyd->name);
72 if (keyd->nameURI != NULL)
73 xmlFree(keyd->nameURI);
74 if (keyd->match != NULL)
75 xmlFree(keyd->match);
76 if (keyd->use != NULL)
77 xmlFree(keyd->use);
78 if (keyd->nsList != NULL)
79 xmlFree(keyd->nsList);
80 memset(keyd, -1, sizeof(xsltKeyDef));
81 xmlFree(keyd);
82}
#define memset(x, y, z)
Definition: compat.h:39
xmlNsPtr * nsList
xmlChar * use
xmlChar * match
xmlXPathCompExprPtr comp
xmlChar * nameURI
xmlXPathCompExprPtr usecomp
xmlChar * name

Referenced by xsltAddKey(), and xsltFreeKeyDefList().

◆ xsltFreeKeyDefList()

static void xsltFreeKeyDefList ( xsltKeyDefPtr  keyd)
static

xsltFreeKeyDefList: @keyd: an XSLT key definition list

Free up the memory allocated by all the elements of @keyd

Definition at line 91 of file keys.c.

91 {
93
94 while (keyd != NULL) {
95 cur = keyd;
96 keyd = keyd->next;
98 }
99}

Referenced by xsltFreeKeys().

◆ xsltFreeKeys()

void xsltFreeKeys ( xsltStylesheetPtr  style)

xsltFreeKeys: @style: an XSLT stylesheet

Free up the memory used by XSLT keys in a stylesheet

Definition at line 185 of file keys.c.

185 {
186 if (style->keys)
188}
static void xsltFreeKeyDefList(xsltKeyDefPtr keyd)
Definition: keys.c:91

Referenced by xsltFreeStylesheet().

◆ xsltFreeKeyTable()

static void xsltFreeKeyTable ( xsltKeyTablePtr  keyt)
static

xsltFreeKeyTable: @keyt: an XSLT key table

Free up the memory allocated by @keyt

Definition at line 141 of file keys.c.

141 {
142 if (keyt == NULL)
143 return;
144 if (keyt->name != NULL)
145 xmlFree(keyt->name);
146 if (keyt->nameURI != NULL)
147 xmlFree(keyt->nameURI);
148 if (keyt->keys != NULL)
150 memset(keyt, -1, sizeof(xsltKeyTable));
151 xmlFree(keyt);
152}
static void xsltFreeNodeSetEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: keys.c:130
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:322
xmlChar * nameURI
xmlHashTablePtr keys
xmlChar * name

Referenced by xsltFreeKeyTableList().

◆ xsltFreeKeyTableList()

static void xsltFreeKeyTableList ( xsltKeyTablePtr  keyt)
static

xsltFreeKeyTableList: @keyt: an XSLT key table list

Free up the memory allocated by all the elements of @keyt

Definition at line 161 of file keys.c.

161 {
163
164 while (keyt != NULL) {
165 cur = keyt;
166 keyt = keyt->next;
168 }
169}
static void xsltFreeKeyTable(xsltKeyTablePtr keyt)
Definition: keys.c:141
struct _xsltKeyTable * next

Referenced by xsltFreeDocumentKeys().

◆ xsltFreeNodeSetEntry()

static void xsltFreeNodeSetEntry ( void payload,
const xmlChar *name  ATTRIBUTE_UNUSED 
)
static

Definition at line 130 of file keys.c.

130 {
131 xmlXPathFreeNodeSet((xmlNodeSetPtr) payload);
132}

Referenced by xsltFreeKeyTable().

◆ xsltGetKey()

xmlNodeSetPtr xsltGetKey ( xsltTransformContextPtr  ctxt,
const xmlChar name,
const xmlChar nameURI,
const xmlChar value 
)

Definition at line 417 of file keys.c.

418 {
419 xmlNodeSetPtr ret;
421 int init_table = 0;
422
423 if ((ctxt == NULL) || (name == NULL) || (value == NULL) ||
424 (ctxt->document == NULL))
425 return(NULL);
426
427#ifdef WITH_XSLT_DEBUG_KEYS
429 "Get key %s, value %s\n", name, value);
430#endif
431
432 /*
433 * keys are computed only on-demand on first key access for a document
434 */
435 if ((ctxt->document->nbKeysComputed < ctxt->nbKeys) &&
436 (ctxt->keyInitLevel == 0)) {
437 /*
438 * If non-recursive behaviour, just try to initialize all keys
439 */
440 if (xsltInitAllDocKeys(ctxt))
441 return(NULL);
442 }
443
444retry:
446 while (table != NULL) {
447 if (((nameURI != NULL) == (table->nameURI != NULL)) &&
449 xmlStrEqual(table->nameURI, nameURI))
450 {
451 ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value);
452 return(ret);
453 }
454 table = table->next;
455 }
456
457 if ((ctxt->keyInitLevel != 0) && (init_table == 0)) {
458 /*
459 * Apparently one key is recursive and this one is needed,
460 * initialize just it, that time and retry
461 */
462 xsltInitDocKeyTable(ctxt, name, nameURI);
463 init_table = 1;
464 goto retry;
465 }
466
467 return(NULL);
468}
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
static int xsltInitDocKeyTable(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI)
Definition: keys.c:479
int xsltInitAllDocKeys(xsltTransformContextPtr ctxt)
Definition: keys.c:535
XMLPUBFUN void *XMLCALL xmlHashLookup(xmlHashTablePtr table, const xmlChar *name)
Definition: hash.c:461
xsltDocumentPtr document
const WCHAR * name
Definition: pdh_main.c:94
int ret
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
xsltKeyTable * xsltKeyTablePtr

Referenced by xsltKeyFunction(), and xsltTestStepMatch().

◆ xsltInitAllDocKeys()

int xsltInitAllDocKeys ( xsltTransformContextPtr  ctxt)

xsltInitAllDocKeys: @ctxt: transformation context

INTERNAL ROUTINE ONLY

Check if any keys on the current document need to be computed

Returns 0 in case of success, -1 in case of failure

Definition at line 535 of file keys.c.

536{
538 xsltKeyDefPtr keyd;
540
541 if (ctxt == NULL)
542 return(-1);
543
544#ifdef KEY_INIT_DEBUG
545fprintf(stderr, "xsltInitAllDocKeys %d %d\n",
546 ctxt->document->nbKeysComputed, ctxt->nbKeys);
547#endif
548
549 if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
550 return(0);
551
552
553 /*
554 * TODO: This could be further optimized
555 */
556 style = ctxt->style;
557 while (style) {
558 keyd = (xsltKeyDefPtr) style->keys;
559 while (keyd != NULL) {
560#ifdef KEY_INIT_DEBUG
561fprintf(stderr, "Init key %s\n", keyd->name);
562#endif
563 /*
564 * Check if keys with this QName have been already
565 * computed.
566 */
568 while (table) {
569 if (((keyd->nameURI != NULL) == (table->nameURI != NULL)) &&
570 xmlStrEqual(keyd->name, table->name) &&
571 xmlStrEqual(keyd->nameURI, table->nameURI))
572 {
573 break;
574 }
575 table = table->next;
576 }
577 if (table == NULL) {
578 /*
579 * Keys with this QName have not been yet computed.
580 */
581 xsltInitDocKeyTable(ctxt, keyd->name, keyd->nameURI);
582 }
583 keyd = keyd->next;
584 }
586 }
587#ifdef KEY_INIT_DEBUG
588fprintf(stderr, "xsltInitAllDocKeys: done\n");
589#endif
590 return(0);
591}
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:251
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
xsltStylesheetPtr style
xsltKeyDef * xsltKeyDefPtr

Referenced by xsltComputeAllKeys(), and xsltGetKey().

◆ xsltInitCtxtKey()

int xsltInitCtxtKey ( xsltTransformContextPtr  ctxt,
xsltDocumentPtr  idoc,
xsltKeyDefPtr  keyDef 
)

xsltInitCtxtKey: @ctxt: an XSLT transformation context @idoc: the document information (holds key values) @keyDef: the key definition

Computes the key tables this key and for the current input document.

Returns: 0 on success, -1 on error

Multiple key definitions for the same name are allowed, so we must check if the key is already present for this doc

If the key was not previously defined, create it now and chain it to the list of keys for the doc

Definition at line 604 of file keys.c.

606{
607 int i, len, k;
608 xmlNodeSetPtr matchList = NULL, keylist;
609 xmlXPathObjectPtr matchRes = NULL, useRes = NULL;
610 xmlChar *str = NULL;
612 xmlNodePtr oldInst, cur;
613 xmlNodePtr oldContextNode;
614 xsltDocumentPtr oldDocInfo;
615 int oldXPPos, oldXPSize;
616 xmlNodePtr oldXPNode;
617 xmlDocPtr oldXPDoc;
618 int oldXPNsNr;
619 xmlNsPtr *oldXPNamespaces;
620 xmlXPathContextPtr xpctxt;
621
622#ifdef KEY_INIT_DEBUG
623fprintf(stderr, "xsltInitCtxtKey %s : %d\n", keyDef->name, ctxt->keyInitLevel);
624#endif
625
626 if ((keyDef->comp == NULL) || (keyDef->usecomp == NULL))
627 return(-1);
628
629 /*
630 * Detect recursive keys
631 */
632 if (ctxt->keyInitLevel > ctxt->nbKeys) {
633#ifdef WITH_XSLT_DEBUG_KEYS
636 "xsltInitCtxtKey: key definition of %s is recursive\n",
637 keyDef->name));
638#endif
639 xsltTransformError(ctxt, NULL, keyDef->inst,
640 "Key definition for %s is recursive\n", keyDef->name);
642 return(-1);
643 }
644 ctxt->keyInitLevel++;
645
646 xpctxt = ctxt->xpathCtxt;
647 idoc->nbKeysComputed++;
648 /*
649 * Save context state.
650 */
651 oldInst = ctxt->inst;
652 oldDocInfo = ctxt->document;
653 oldContextNode = ctxt->node;
654
655 oldXPNode = xpctxt->node;
656 oldXPDoc = xpctxt->doc;
657 oldXPPos = xpctxt->proximityPosition;
658 oldXPSize = xpctxt->contextSize;
659 oldXPNsNr = xpctxt->nsNr;
660 oldXPNamespaces = xpctxt->namespaces;
661
662 /*
663 * Set up contexts.
664 */
665 ctxt->document = idoc;
666 ctxt->node = (xmlNodePtr) idoc->doc;
667 ctxt->inst = keyDef->inst;
668
669 xpctxt->doc = idoc->doc;
670 xpctxt->node = (xmlNodePtr) idoc->doc;
671 /* TODO : clarify the use of namespaces in keys evaluation */
672 xpctxt->namespaces = keyDef->nsList;
673 xpctxt->nsNr = keyDef->nsNr;
674
675 /*
676 * Evaluate the 'match' expression of the xsl:key.
677 * TODO: The 'match' is a *pattern*.
678 */
679 matchRes = xmlXPathCompiledEval(keyDef->comp, xpctxt);
680 if (matchRes == NULL) {
681
682#ifdef WITH_XSLT_DEBUG_KEYS
684 "xsltInitCtxtKey: %s evaluation failed\n", keyDef->match));
685#endif
686 xsltTransformError(ctxt, NULL, keyDef->inst,
687 "Failed to evaluate the 'match' expression.\n");
689 goto error;
690 } else {
691 if (matchRes->type == XPATH_NODESET) {
692 matchList = matchRes->nodesetval;
693
694#ifdef WITH_XSLT_DEBUG_KEYS
695 if (matchList != NULL)
697 "xsltInitCtxtKey: %s evaluates to %d nodes\n",
698 keyDef->match, matchList->nodeNr));
699#endif
700 } else {
701 /*
702 * Is not a node set, but must be.
703 */
704#ifdef WITH_XSLT_DEBUG_KEYS
706 "xsltInitCtxtKey: %s is not a node set\n", keyDef->match));
707#endif
708 xsltTransformError(ctxt, NULL, keyDef->inst,
709 "The 'match' expression did not evaluate to a node set.\n");
711 goto error;
712 }
713 }
714 if ((matchList == NULL) || (matchList->nodeNr <= 0))
715 goto exit;
716
721 table = (xsltKeyTablePtr) idoc->keys;
722 while (table != NULL) {
723 if (xmlStrEqual(table->name, keyDef->name) &&
724 (((keyDef->nameURI == NULL) && (table->nameURI == NULL)) ||
725 ((keyDef->nameURI != NULL) && (table->nameURI != NULL) &&
726 (xmlStrEqual(table->nameURI, keyDef->nameURI)))))
727 break;
728 table = table->next;
729 }
734 if (table == NULL) {
735 table = xsltNewKeyTable(keyDef->name, keyDef->nameURI);
736 if (table == NULL)
737 goto error;
738 table->next = idoc->keys;
739 idoc->keys = table;
740 }
741
742 /*
743 * SPEC XSLT 1.0 (XSLT 2.0 does not clarify the context size!)
744 * "...the use attribute of the xsl:key element is evaluated with x as
745 " the current node and with a node list containing just x as the
746 * current node list"
747 */
748 xpctxt->contextSize = 1;
749 xpctxt->proximityPosition = 1;
750
751 for (i = 0; i < matchList->nodeNr; i++) {
752 cur = matchList->nodeTab[i];
753 if (! IS_XSLT_REAL_NODE(cur))
754 continue;
755 ctxt->node = cur;
756 xpctxt->node = cur;
757 /*
758 * Process the 'use' of the xsl:key.
759 * SPEC XSLT 1.0:
760 * "The use attribute is an expression specifying the values of
761 * the key; the expression is evaluated once for each node that
762 * matches the pattern."
763 */
764 if (useRes != NULL)
765 xmlXPathFreeObject(useRes);
766 useRes = xmlXPathCompiledEval(keyDef->usecomp, xpctxt);
767 if (useRes == NULL) {
768 xsltTransformError(ctxt, NULL, keyDef->inst,
769 "Failed to evaluate the 'use' expression.\n");
771 break;
772 }
773 if (useRes->type == XPATH_NODESET) {
774 if ((useRes->nodesetval != NULL) &&
775 (useRes->nodesetval->nodeNr != 0))
776 {
777 len = useRes->nodesetval->nodeNr;
778 str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[0]);
779 } else {
780 continue;
781 }
782 } else {
783 len = 1;
784 if (useRes->type == XPATH_STRING) {
785 /*
786 * Consume the string value.
787 */
788 str = useRes->stringval;
789 useRes->stringval = NULL;
790 } else {
791 str = xmlXPathCastToString(useRes);
792 }
793 }
794 /*
795 * Process all strings.
796 */
797 k = 0;
798 while (1) {
799 if (str == NULL)
800 goto next_string;
801
802#ifdef WITH_XSLT_DEBUG_KEYS
804 "xsl:key : node associated to ('%s', '%s')\n", keyDef->name, str));
805#endif
806
807 keylist = xmlHashLookup(table->keys, str);
808 if (keylist == NULL) {
809 keylist = xmlXPathNodeSetCreate(cur);
810 if (keylist == NULL)
811 goto error;
813 } else {
814 /*
815 * TODO: How do we know if this function failed?
816 */
817 xmlXPathNodeSetAdd(keylist, cur);
818 }
819 switch (cur->type) {
820 case XML_ELEMENT_NODE:
821 case XML_TEXT_NODE:
823 case XML_PI_NODE:
824 case XML_COMMENT_NODE:
825 cur->psvi = keyDef;
826 break;
828 ((xmlAttrPtr) cur)->psvi = keyDef;
829 break;
832 ((xmlDocPtr) cur)->psvi = keyDef;
833 break;
834 default:
835 break;
836 }
837 xmlFree(str);
838 str = NULL;
839
840next_string:
841 k++;
842 if (k >= len)
843 break;
844 str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[k]);
845 }
846 }
847
848exit:
849error:
850 ctxt->keyInitLevel--;
851 /*
852 * Restore context state.
853 */
854 xpctxt->node = oldXPNode;
855 xpctxt->doc = oldXPDoc;
856 xpctxt->nsNr = oldXPNsNr;
857 xpctxt->namespaces = oldXPNamespaces;
858 xpctxt->proximityPosition = oldXPPos;
859 xpctxt->contextSize = oldXPSize;
860
861 ctxt->node = oldContextNode;
862 ctxt->document = oldDocInfo;
863 ctxt->inst = oldInst;
864
865 if (str)
866 xmlFree(str);
867 if (useRes != NULL)
868 xmlXPathFreeObject(useRes);
869 if (matchRes != NULL)
870 xmlXPathFreeObject(matchRes);
871 return(0);
872}
GLenum GLsizei len
Definition: glext.h:6722
static xsltKeyTablePtr xsltNewKeyTable(const xmlChar *name, const xmlChar *nameURI)
Definition: keys.c:111
int k
Definition: mpi.c:3369
const WCHAR * str
XMLPUBFUN int XMLCALL xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata)
Definition: hash.c:389
xmlNode * xmlNodePtr
Definition: tree.h:488
xmlDoc * xmlDocPtr
Definition: tree.h:550
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
@ XML_DOCUMENT_NODE
Definition: tree.h:168
@ XML_CDATA_SECTION_NODE
Definition: tree.h:163
@ XML_TEXT_NODE
Definition: tree.h:162
@ XML_PI_NODE
Definition: tree.h:166
@ XML_COMMENT_NODE
Definition: tree.h:167
@ XML_HTML_DOCUMENT_NODE
Definition: tree.h:172
@ XML_ELEMENT_NODE
Definition: tree.h:160
xmlAttr * xmlAttrPtr
Definition: tree.h:433
#define exit(n)
Definition: config.h:202
Definition: tree.h:551
struct _xmlDoc * doc
Definition: tree.h:560
Definition: tree.h:489
Definition: tree.h:389
xmlDocPtr doc
xmlNodePtr inst
xsltTransformState state
xmlXPathContextPtr xpathCtxt
Definition: path.c:35
@ XSLT_STATE_STOPPED
@ XSLT_TRACE_KEYS
Definition: xsltutils.h:116
#define IS_XSLT_REAL_NODE(n)
Definition: xsltutils.h:68
#define XSLT_TRACE(ctxt, code, call)
Definition: xsltutils.h:125

Referenced by xsltInitCtxtKeys(), and xsltInitDocKeyTable().

◆ xsltInitCtxtKeys()

void xsltInitCtxtKeys ( xsltTransformContextPtr  ctxt,
xsltDocumentPtr  idoc 
)

xsltInitCtxtKeys: @ctxt: an XSLT transformation context @idoc: a document info

Computes all the keys tables for the current input document. Should be done before global varibales are initialized. NOTE: Not used anymore in the refactored code.

Definition at line 884 of file keys.c.

884 {
886 xsltKeyDefPtr keyDef;
887
888 if ((ctxt == NULL) || (idoc == NULL))
889 return;
890
891#ifdef KEY_INIT_DEBUG
892fprintf(stderr, "xsltInitCtxtKeys on document\n");
893#endif
894
895#ifdef WITH_XSLT_DEBUG_KEYS
896 if ((idoc->doc != NULL) && (idoc->doc->URL != NULL))
897 XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n",
898 idoc->doc->URL));
899#endif
900 style = ctxt->style;
901 while (style != NULL) {
902 keyDef = (xsltKeyDefPtr) style->keys;
903 while (keyDef != NULL) {
904 xsltInitCtxtKey(ctxt, idoc, keyDef);
905
906 keyDef = keyDef->next;
907 }
908
910 }
911
912#ifdef KEY_INIT_DEBUG
913fprintf(stderr, "xsltInitCtxtKeys on document: done\n");
914#endif
915
916}
int xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc, xsltKeyDefPtr keyDef)
Definition: keys.c:604
const xmlChar * URL
Definition: tree.h:577

◆ xsltInitDocKeyTable()

static int xsltInitDocKeyTable ( xsltTransformContextPtr  ctxt,
const xmlChar name,
const xmlChar nameURI 
)
static

xsltInitDocKeyTable:

INTERNAL ROUTINE ONLY

Check if any keys on the current document need to be computed

Definition at line 479 of file keys.c.

481{
483 xsltKeyDefPtr keyd = NULL;
484 int found = 0;
485
486#ifdef KEY_INIT_DEBUG
487fprintf(stderr, "xsltInitDocKeyTable %s\n", name);
488#endif
489
490 style = ctxt->style;
491 while (style != NULL) {
492 keyd = (xsltKeyDefPtr) style->keys;
493 while (keyd != NULL) {
494 if (((keyd->nameURI != NULL) ==
495 (nameURI != NULL)) &&
496 xmlStrEqual(keyd->name, name) &&
497 xmlStrEqual(keyd->nameURI, nameURI))
498 {
499 xsltInitCtxtKey(ctxt, ctxt->document, keyd);
500 if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
501 return(0);
502 found = 1;
503 }
504 keyd = keyd->next;
505 }
507 }
508 if (found == 0) {
509#ifdef WITH_XSLT_DEBUG_KEYS
511 "xsltInitDocKeyTable: did not found %s\n", name));
512#endif
513 xsltTransformError(ctxt, NULL, keyd? keyd->inst : NULL,
514 "Failed to find key definition for %s\n", name);
516 return(-1);
517 }
518#ifdef KEY_INIT_DEBUG
519fprintf(stderr, "xsltInitDocKeyTable %s done\n", name);
520#endif
521 return(0);
522}

Referenced by xsltGetKey(), and xsltInitAllDocKeys().

◆ xsltNewKeyDef()

static xsltKeyDefPtr xsltNewKeyDef ( const xmlChar name,
const xmlChar nameURI 
)
static

Definition at line 38 of file keys.c.

38 {
40
42 if (cur == NULL) {
44 "xsltNewKeyDef : malloc failed\n");
45 return(NULL);
46 }
47 memset(cur, 0, sizeof(xsltKeyDef));
48 if (name != NULL)
49 cur->name = xmlStrdup(name);
50 if (nameURI != NULL)
51 cur->nameURI = xmlStrdup(nameURI);
52 cur->nsList = NULL;
53 return(cur);
54}
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248

Referenced by xsltAddKey().

◆ xsltNewKeyTable()

static xsltKeyTablePtr xsltNewKeyTable ( const xmlChar name,
const xmlChar nameURI 
)
static

Definition at line 111 of file keys.c.

111 {
113
115 if (cur == NULL) {
117 "xsltNewKeyTable : malloc failed\n");
118 return(NULL);
119 }
120 memset(cur, 0, sizeof(xsltKeyTable));
121 if (name != NULL)
122 cur->name = xmlStrdup(name);
123 if (nameURI != NULL)
124 cur->nameURI = xmlStrdup(nameURI);
125 cur->keys = xmlHashCreate(0);
126 return(cur);
127}
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate(int size)
Definition: hash.c:176

Referenced by xsltInitCtxtKey().