ReactOS 0.4.16-dev-2208-g6350669
keys.c File Reference
#include "libxslt.h"
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#include <libxml/valid.h>
#include <libxml/hash.h>
#include <libxml/xmlerror.h>
#include <libxml/parserInternals.h>
#include <libxml/xpathInternals.h>
#include <libxml/xpath.h>
#include "xslt.h"
#include "xsltInternals.h"
#include "xsltutils.h"
#include "imports.h"
#include "templates.h"
#include "keys.h"
Include dependency graph for keys.c:

Go to the source code of this file.

Macros

#define IN_LIBXSLT
 

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)
 

Macro Definition Documentation

◆ IN_LIBXSLT

#define IN_LIBXSLT

Definition at line 12 of file keys.c.

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 243 of file keys.c.

243 {
244 int level = 0;
245
246 if ((cur == NULL) || (end < 0)) return(-1);
247 if (cur[end] != '[') return(end);
248 end++;
249 while (cur[end] != 0) {
250 if ((cur[end] == '\'') || (cur[end] == '"')) {
251 end = skipString(cur, end);
252 if (end <= 0)
253 return(-1);
254 continue;
255 } else if (cur[end] == '[') {
256 level += 1;
257 } else if (cur[end] == ']') {
258 if (level == 0)
259 return(end + 1);
260 level -= 1;
261 }
262 end++;
263 }
264 return(-1);
265}
#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:218

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 218 of file keys.c.

218 {
220
221 if ((cur == NULL) || (end < 0)) return(-1);
222 if ((cur[end] == '\'') || (cur[end] == '"')) limit = cur[end];
223 else return(end);
224 end++;
225 while (cur[end] != 0) {
226 if (cur[end] == limit)
227 return(end + 1);
228 end++;
229 }
230 return(-1);
231}
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 281 of file keys.c.

283 {
286 int current, end, start, i = 0;
287
288 if ((style == NULL) || (name == NULL) || (match == NULL) || (use == NULL))
289 return(-1);
290
291#ifdef WITH_XSLT_DEBUG_KEYS
293 "Add key %s, match %s, use %s\n", name, match, use);
294#endif
295
296 key = xsltNewKeyDef(name, nameURI);
297 if (key == NULL)
298 return(-1);
299 key->match = xmlStrdup(match);
300 key->use = xmlStrdup(use);
301 key->inst = inst;
302 key->nsList = xmlGetNsList(inst->doc, inst);
303 if (key->nsList != NULL) {
304 while (key->nsList[i] != NULL)
305 i++;
306 }
307 key->nsNr = i;
308
309 /*
310 * Split the | and register it as as many keys
311 */
312 current = end = 0;
313 while (match[current] != 0) {
314 start = current;
315 while (xmlIsBlank_ch(match[current]))
316 current++;
317 end = current;
318 while ((match[end] != 0) && (match[end] != '|')) {
319 if (match[end] == '[') {
321 if (end <= 0) {
323 "xsl:key : 'match' pattern is malformed: %s",
324 key->match);
325 if (style != NULL) style->errors++;
326 goto error;
327 }
328 } else
329 end++;
330 }
331 if (current == end) {
333 "xsl:key : 'match' pattern is empty\n");
334 if (style != NULL) style->errors++;
335 goto error;
336 }
337 if (match[start] != '/') {
338 pattern = xmlStrcat(pattern, (xmlChar *)"//");
339 if (pattern == NULL) {
340 if (style != NULL) style->errors++;
341 goto error;
342 }
343 }
345 if (pattern == NULL) {
346 if (style != NULL) style->errors++;
347 goto error;
348 }
349
350 if (match[end] == '|') {
351 pattern = xmlStrcat(pattern, (xmlChar *)"|");
352 end++;
353 }
354 current = end;
355 }
356 if (pattern == NULL) {
358 "xsl:key : 'match' pattern is empty\n");
359 if (style != NULL) style->errors++;
360 goto error;
361 }
362#ifdef WITH_XSLT_DEBUG_KEYS
364 " resulting pattern %s\n", pattern);
365#endif
366 /*
367 * XSLT-1: "It is an error for the value of either the use
368 * attribute or the match attribute to contain a
369 * VariableReference."
370 * TODO: We should report a variable-reference at compile-time.
371 * Maybe a search for "$", if it occurs outside of quotation
372 * marks, could be sufficient.
373 */
374#ifdef XML_XPATH_NOVAR
375 key->comp = xsltXPathCompileFlags(style, pattern, XML_XPATH_NOVAR);
376#else
378#endif
379 if (key->comp == NULL) {
381 "xsl:key : 'match' pattern compilation failed '%s'\n",
382 pattern);
383 if (style != NULL) style->errors++;
384 }
385#ifdef XML_XPATH_NOVAR
386 key->usecomp = xsltXPathCompileFlags(style, use, XML_XPATH_NOVAR);
387#else
388 key->usecomp = xsltXPathCompile(style, use);
389#endif
390 if (key->usecomp == NULL) {
392 "xsl:key : 'use' expression compilation failed '%s'\n",
393 use);
394 if (style != NULL) style->errors++;
395 }
396
397 /*
398 * Sometimes the stylesheet writer use the order to ease the
399 * resolution of keys when they are dependant, keep the provided
400 * order so add the new one at the end.
401 */
402 if (style->keys == NULL) {
403 style->keys = key;
404 } else {
405 xsltKeyDefPtr prev = style->keys;
406
407 while (prev->next != NULL)
408 prev = prev->next;
409
410 prev->next = key;
411 }
412 key->next = NULL;
413 key = NULL;
414
415error:
416 if (pattern != NULL)
418 if (key != NULL)
420 return(0);
421}
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:56
static int skipPredicate(const xmlChar *cur, int end)
Definition: keys.c:243
static void xsltFreeKeyDef(xsltKeyDefPtr keyd)
Definition: keys.c:81
#define error(str)
Definition: mkdosfs.c:1605
struct task_struct * current
Definition: linux.c:32
xmlFreeFunc xmlFree
Definition: globals.c:184
struct _xsltKeyDef * next
Definition: copy.c:22
Definition: match.c:28
Definition: name.c:39
XMLPUBFUN xmlChar * xmlStrncat(xmlChar *cur, const xmlChar *add, int len)
Definition: xmlstring.c:448
XMLPUBFUN xmlChar * xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:762
xmlXPathCompExprPtr xsltXPathCompileFlags(xsltStylesheetPtr style, const xmlChar *str, int flags)
Definition: xsltutils.c:2550
xmlXPathCompExprPtr xsltXPathCompile(xsltStylesheetPtr style, const xmlChar *str)
Definition: xsltutils.c:2593
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:632
void * xsltGenericDebugContext
Definition: xsltutils.c:633

Referenced by xsltParseStylesheetKey().

◆ xsltFreeDocumentKeys()

void xsltFreeDocumentKeys ( xsltDocumentPtr  idoc)

xsltFreeDocumentKeys: @idoc: a XSLT document

Free the keys associated to a document

Definition at line 931 of file keys.c.

931 {
932 if (idoc != NULL)
934}
static void xsltFreeKeyTableList(xsltKeyTablePtr keyt)
Definition: keys.c:179

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 81 of file keys.c.

81 {
82 if (keyd == NULL)
83 return;
84 if (keyd->comp != NULL)
85 xmlXPathFreeCompExpr(keyd->comp);
86 if (keyd->usecomp != NULL)
87 xmlXPathFreeCompExpr(keyd->usecomp);
88 if (keyd->name != NULL)
89 xmlFree(keyd->name);
90 if (keyd->nameURI != NULL)
91 xmlFree(keyd->nameURI);
92 if (keyd->match != NULL)
93 xmlFree(keyd->match);
94 if (keyd->use != NULL)
95 xmlFree(keyd->use);
96 if (keyd->nsList != NULL)
97 xmlFree(keyd->nsList);
98 memset(keyd, -1, sizeof(xsltKeyDef));
99 xmlFree(keyd);
100}
#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 109 of file keys.c.

109 {
111
112 while (keyd != NULL) {
113 cur = keyd;
114 keyd = keyd->next;
116 }
117}

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 203 of file keys.c.

203 {
204 if (style->keys)
206}
static void xsltFreeKeyDefList(xsltKeyDefPtr keyd)
Definition: keys.c:109

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 159 of file keys.c.

159 {
160 if (keyt == NULL)
161 return;
162 if (keyt->name != NULL)
163 xmlFree(keyt->name);
164 if (keyt->nameURI != NULL)
165 xmlFree(keyt->nameURI);
166 if (keyt->keys != NULL)
168 memset(keyt, -1, sizeof(xsltKeyTable));
169 xmlFree(keyt);
170}
static void xsltFreeNodeSetEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: keys.c:148
void xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc)
Definition: hash.c:229
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 179 of file keys.c.

179 {
181
182 while (keyt != NULL) {
183 cur = keyt;
184 keyt = keyt->next;
186 }
187}
static void xsltFreeKeyTable(xsltKeyTablePtr keyt)
Definition: keys.c:159
struct _xsltKeyTable * next

Referenced by xsltFreeDocumentKeys().

◆ xsltFreeNodeSetEntry()

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

Definition at line 148 of file keys.c.

148 {
149 xmlXPathFreeNodeSet((xmlNodeSetPtr) payload);
150}

Referenced by xsltFreeKeyTable().

◆ xsltGetKey()

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

Definition at line 437 of file keys.c.

438 {
439 xmlNodeSetPtr ret;
441 int init_table = 0;
442
443 if ((ctxt == NULL) || (name == NULL) || (value == NULL) ||
444 (ctxt->document == NULL))
445 return(NULL);
446
447#ifdef WITH_XSLT_DEBUG_KEYS
449 "Get key %s, value %s\n", name, value);
450#endif
451
452 /*
453 * keys are computed only on-demand on first key access for a document
454 */
455 if ((ctxt->document->nbKeysComputed < ctxt->nbKeys) &&
456 (ctxt->keyInitLevel == 0)) {
457 /*
458 * If non-recursive behaviour, just try to initialize all keys
459 */
460 if (xsltInitAllDocKeys(ctxt))
461 return(NULL);
462 }
463
464retry:
466 while (table != NULL) {
467 if (((nameURI != NULL) == (table->nameURI != NULL)) &&
469 xmlStrEqual(table->nameURI, nameURI))
470 {
471 ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value);
472 return(ret);
473 }
474 table = table->next;
475 }
476
477 if ((ctxt->keyInitLevel != 0) && (init_table == 0)) {
478 /*
479 * Apparently one key is recursive and this one is needed,
480 * initialize just it, that time and retry
481 */
482 xsltInitDocKeyTable(ctxt, name, nameURI);
483 init_table = 1;
484 goto retry;
485 }
486
487 return(NULL);
488}
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
return ret
Definition: mutex.c:146
static int xsltInitDocKeyTable(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI)
Definition: keys.c:499
int xsltInitAllDocKeys(xsltTransformContextPtr ctxt)
Definition: keys.c:555
void * xmlHashLookup(xmlHashTablePtr hash, const xmlChar *key)
Definition: hash.c:739
xsltDocumentPtr document
const WCHAR * name
Definition: pdh_main.c:96
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
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 555 of file keys.c.

556{
558 xsltKeyDefPtr keyd;
560
561 if (ctxt == NULL)
562 return(-1);
563
564#ifdef KEY_INIT_DEBUG
565fprintf(stderr, "xsltInitAllDocKeys %d %d\n",
566 ctxt->document->nbKeysComputed, ctxt->nbKeys);
567#endif
568
569 if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
570 return(0);
571
572
573 /*
574 * TODO: This could be further optimized
575 */
576 style = ctxt->style;
577 while (style) {
578 keyd = (xsltKeyDefPtr) style->keys;
579 while (keyd != NULL) {
580#ifdef KEY_INIT_DEBUG
581fprintf(stderr, "Init key %s\n", keyd->name);
582#endif
583 /*
584 * Check if keys with this QName have been already
585 * computed.
586 */
588 while (table) {
589 if (((keyd->nameURI != NULL) == (table->nameURI != NULL)) &&
590 xmlStrEqual(keyd->name, table->name) &&
591 xmlStrEqual(keyd->nameURI, table->nameURI))
592 {
593 break;
594 }
595 table = table->next;
596 }
597 if (table == NULL) {
598 /*
599 * Keys with this QName have not been yet computed.
600 */
601 xsltInitDocKeyTable(ctxt, keyd->name, keyd->nameURI);
602 }
603 keyd = keyd->next;
604 }
606 }
607#ifdef KEY_INIT_DEBUG
608fprintf(stderr, "xsltInitAllDocKeys: done\n");
609#endif
610 return(0);
611}
int WINAPIV fprintf(FILE *file, const char *format,...)
Definition: file.c:5549
#define stderr
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:297
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 624 of file keys.c.

626{
627 int i, len, k;
628 xmlNodeSetPtr matchList = NULL, keylist;
629 xmlXPathObjectPtr matchRes = NULL, useRes = NULL;
630 xmlChar *str = NULL;
632 xmlNodePtr oldInst, cur;
633 xmlNodePtr oldContextNode;
634 xsltDocumentPtr oldDocInfo;
635 int oldXPPos, oldXPSize;
636 xmlNodePtr oldXPNode;
637 xmlDocPtr oldXPDoc;
638 int oldXPNsNr;
639 xmlNsPtr *oldXPNamespaces;
640 xmlXPathContextPtr xpctxt;
641
642#ifdef KEY_INIT_DEBUG
643fprintf(stderr, "xsltInitCtxtKey %s : %d\n", keyDef->name, ctxt->keyInitLevel);
644#endif
645
646 if ((keyDef->comp == NULL) || (keyDef->usecomp == NULL))
647 return(-1);
648
649 /*
650 * Detect recursive keys
651 */
652 if (ctxt->keyInitLevel > ctxt->nbKeys) {
653#ifdef WITH_XSLT_DEBUG_KEYS
656 "xsltInitCtxtKey: key definition of %s is recursive\n",
657 keyDef->name));
658#endif
659 xsltTransformError(ctxt, NULL, keyDef->inst,
660 "Key definition for %s is recursive\n", keyDef->name);
662 return(-1);
663 }
664 ctxt->keyInitLevel++;
665
666 xpctxt = ctxt->xpathCtxt;
667 idoc->nbKeysComputed++;
668 /*
669 * Save context state.
670 */
671 oldInst = ctxt->inst;
672 oldDocInfo = ctxt->document;
673 oldContextNode = ctxt->node;
674
675 oldXPNode = xpctxt->node;
676 oldXPDoc = xpctxt->doc;
677 oldXPPos = xpctxt->proximityPosition;
678 oldXPSize = xpctxt->contextSize;
679 oldXPNsNr = xpctxt->nsNr;
680 oldXPNamespaces = xpctxt->namespaces;
681
682 /*
683 * Set up contexts.
684 */
685 ctxt->document = idoc;
686 ctxt->node = (xmlNodePtr) idoc->doc;
687 ctxt->inst = keyDef->inst;
688
689 xpctxt->doc = idoc->doc;
690 xpctxt->node = (xmlNodePtr) idoc->doc;
691 /* TODO : clarify the use of namespaces in keys evaluation */
692 xpctxt->namespaces = keyDef->nsList;
693 xpctxt->nsNr = keyDef->nsNr;
694
695 /*
696 * Evaluate the 'match' expression of the xsl:key.
697 * TODO: The 'match' is a *pattern*.
698 */
699 matchRes = xmlXPathCompiledEval(keyDef->comp, xpctxt);
700 if (matchRes == NULL) {
701
702#ifdef WITH_XSLT_DEBUG_KEYS
704 "xsltInitCtxtKey: %s evaluation failed\n", keyDef->match));
705#endif
706 xsltTransformError(ctxt, NULL, keyDef->inst,
707 "Failed to evaluate the 'match' expression.\n");
709 goto error;
710 } else {
711 if (matchRes->type == XPATH_NODESET) {
712 matchList = matchRes->nodesetval;
713
714#ifdef WITH_XSLT_DEBUG_KEYS
715 if (matchList != NULL)
717 "xsltInitCtxtKey: %s evaluates to %d nodes\n",
718 keyDef->match, matchList->nodeNr));
719#endif
720 } else {
721 /*
722 * Is not a node set, but must be.
723 */
724#ifdef WITH_XSLT_DEBUG_KEYS
726 "xsltInitCtxtKey: %s is not a node set\n", keyDef->match));
727#endif
728 xsltTransformError(ctxt, NULL, keyDef->inst,
729 "The 'match' expression did not evaluate to a node set.\n");
731 goto error;
732 }
733 }
734 if ((matchList == NULL) || (matchList->nodeNr <= 0))
735 goto exit;
736
741 table = (xsltKeyTablePtr) idoc->keys;
742 while (table != NULL) {
743 if (xmlStrEqual(table->name, keyDef->name) &&
744 (((keyDef->nameURI == NULL) && (table->nameURI == NULL)) ||
745 ((keyDef->nameURI != NULL) && (table->nameURI != NULL) &&
746 (xmlStrEqual(table->nameURI, keyDef->nameURI)))))
747 break;
748 table = table->next;
749 }
754 if (table == NULL) {
755 table = xsltNewKeyTable(keyDef->name, keyDef->nameURI);
756 if (table == NULL)
757 goto error;
758 table->next = idoc->keys;
759 idoc->keys = table;
760 }
761
762 /*
763 * SPEC XSLT 1.0 (XSLT 2.0 does not clarify the context size!)
764 * "...the use attribute of the xsl:key element is evaluated with x as
765 " the current node and with a node list containing just x as the
766 * current node list"
767 */
768 xpctxt->contextSize = 1;
769 xpctxt->proximityPosition = 1;
770
771 for (i = 0; i < matchList->nodeNr; i++) {
772 cur = matchList->nodeTab[i];
773 if (! IS_XSLT_REAL_NODE(cur))
774 continue;
775 ctxt->node = cur;
776 xpctxt->node = cur;
777 /*
778 * Process the 'use' of the xsl:key.
779 * SPEC XSLT 1.0:
780 * "The use attribute is an expression specifying the values of
781 * the key; the expression is evaluated once for each node that
782 * matches the pattern."
783 */
784 if (useRes != NULL)
785 xmlXPathFreeObject(useRes);
786 useRes = xmlXPathCompiledEval(keyDef->usecomp, xpctxt);
787 if (useRes == NULL) {
788 xsltTransformError(ctxt, NULL, keyDef->inst,
789 "Failed to evaluate the 'use' expression.\n");
791 break;
792 }
793 if (useRes->type == XPATH_NODESET) {
794 if ((useRes->nodesetval != NULL) &&
795 (useRes->nodesetval->nodeNr != 0))
796 {
797 len = useRes->nodesetval->nodeNr;
798 str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[0]);
799 } else {
800 continue;
801 }
802 } else {
803 len = 1;
804 if (useRes->type == XPATH_STRING) {
805 /*
806 * Consume the string value.
807 */
808 str = useRes->stringval;
809 useRes->stringval = NULL;
810 } else {
811 str = xmlXPathCastToString(useRes);
812 }
813 }
814 /*
815 * Process all strings.
816 */
817 k = 0;
818 while (1) {
819 if (str == NULL)
820 goto next_string;
821
822#ifdef WITH_XSLT_DEBUG_KEYS
824 "xsl:key : node associated to ('%s', '%s')\n", keyDef->name, str));
825#endif
826
827 keylist = xmlHashLookup(table->keys, str);
828 if (keylist == NULL) {
829 keylist = xmlXPathNodeSetCreate(cur);
830 if (keylist == NULL)
831 goto error;
832 if (xmlHashAddEntry(table->keys, str, keylist) < 0) {
833 xmlXPathFreeNodeSet(keylist);
834 goto error;
835 }
836 } else {
837 /*
838 * TODO: How do we know if this function failed?
839 */
840 xmlXPathNodeSetAdd(keylist, cur);
841 }
842 xsltSetSourceNodeFlags(ctxt, cur, XSLT_SOURCE_NODE_HAS_KEY);
843 xmlFree(str);
844 str = NULL;
845
846next_string:
847 k++;
848 if (k >= len)
849 break;
850 str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[k]);
851 }
852 }
853
854exit:
855error:
856 ctxt->keyInitLevel--;
857 /*
858 * Restore context state.
859 */
860 xpctxt->node = oldXPNode;
861 xpctxt->doc = oldXPDoc;
862 xpctxt->nsNr = oldXPNsNr;
863 xpctxt->namespaces = oldXPNamespaces;
864 xpctxt->proximityPosition = oldXPPos;
865 xpctxt->contextSize = oldXPSize;
866
867 ctxt->node = oldContextNode;
868 ctxt->document = oldDocInfo;
869 ctxt->inst = oldInst;
870
871 if (str)
872 xmlFree(str);
873 if (useRes != NULL)
874 xmlXPathFreeObject(useRes);
875 if (matchRes != NULL)
876 xmlXPathFreeObject(matchRes);
877 return(0);
878}
GLenum GLsizei len
Definition: glext.h:6722
static xsltKeyTablePtr xsltNewKeyTable(const xmlChar *name, const xmlChar *nameURI)
Definition: keys.c:129
int k
Definition: mpi.c:3369
const WCHAR * str
#define exit(n)
Definition: config.h:202
int xmlHashAddEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload)
Definition: hash.c:621
xmlDocPtr doc
xmlNodePtr inst
xsltTransformState state
xmlXPathContextPtr xpathCtxt
Definition: path.c:35
@ XSLT_STATE_STOPPED
int xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node, int flags)
Definition: xsltutils.c:1961
@ XSLT_TRACE_KEYS
Definition: xsltutils.h:123
#define IS_XSLT_REAL_NODE(n)
Definition: xsltutils.h:68
#define XSLT_TRACE(ctxt, code, call)
Definition: xsltutils.h:132

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 890 of file keys.c.

890 {
892 xsltKeyDefPtr keyDef;
893
894 if ((ctxt == NULL) || (idoc == NULL))
895 return;
896
897#ifdef KEY_INIT_DEBUG
898fprintf(stderr, "xsltInitCtxtKeys on document\n");
899#endif
900
901#ifdef WITH_XSLT_DEBUG_KEYS
902 if ((idoc->doc != NULL) && (idoc->doc->URL != NULL))
903 XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n",
904 idoc->doc->URL));
905#endif
906 style = ctxt->style;
907 while (style != NULL) {
908 keyDef = (xsltKeyDefPtr) style->keys;
909 while (keyDef != NULL) {
910 xsltInitCtxtKey(ctxt, idoc, keyDef);
911
912 keyDef = keyDef->next;
913 }
914
916 }
917
918#ifdef KEY_INIT_DEBUG
919fprintf(stderr, "xsltInitCtxtKeys on document: done\n");
920#endif
921
922}
int xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc, xsltKeyDefPtr keyDef)
Definition: keys.c:624

◆ 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 499 of file keys.c.

501{
503 xsltKeyDefPtr keyd = NULL;
504 int found = 0;
505
506#ifdef KEY_INIT_DEBUG
507fprintf(stderr, "xsltInitDocKeyTable %s\n", name);
508#endif
509
510 style = ctxt->style;
511 while (style != NULL) {
512 keyd = (xsltKeyDefPtr) style->keys;
513 while (keyd != NULL) {
514 if (((keyd->nameURI != NULL) ==
515 (nameURI != NULL)) &&
516 xmlStrEqual(keyd->name, name) &&
517 xmlStrEqual(keyd->nameURI, nameURI))
518 {
519 xsltInitCtxtKey(ctxt, ctxt->document, keyd);
520 if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
521 return(0);
522 found = 1;
523 }
524 keyd = keyd->next;
525 }
527 }
528 if (found == 0) {
529#ifdef WITH_XSLT_DEBUG_KEYS
531 "xsltInitDocKeyTable: did not found %s\n", name));
532#endif
533 xsltTransformError(ctxt, NULL, keyd? keyd->inst : NULL,
534 "Failed to find key definition for %s\n", name);
536 return(-1);
537 }
538#ifdef KEY_INIT_DEBUG
539fprintf(stderr, "xsltInitDocKeyTable %s done\n", name);
540#endif
541 return(0);
542}

Referenced by xsltGetKey(), and xsltInitAllDocKeys().

◆ xsltNewKeyDef()

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

Definition at line 56 of file keys.c.

56 {
58
60 if (cur == NULL) {
62 "xsltNewKeyDef : malloc failed\n");
63 return(NULL);
64 }
65 memset(cur, 0, sizeof(xsltKeyDef));
66 if (name != NULL)
67 cur->name = xmlStrdup(name);
68 if (nameURI != NULL)
69 cur->nameURI = xmlStrdup(nameURI);
70 cur->nsList = NULL;
71 return(cur);
72}
xmlMallocFunc xmlMalloc
Definition: globals.c:193

Referenced by xsltAddKey().

◆ xsltNewKeyTable()

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

Definition at line 129 of file keys.c.

129 {
131
133 if (cur == NULL) {
135 "xsltNewKeyTable : malloc failed\n");
136 return(NULL);
137 }
138 memset(cur, 0, sizeof(xsltKeyTable));
139 if (name != NULL)
140 cur->name = xmlStrdup(name);
141 if (nameURI != NULL)
142 cur->nameURI = xmlStrdup(nameURI);
143 cur->keys = xmlHashCreate(0);
144 return(cur);
145}
xmlHashTablePtr xmlHashCreate(int size)
Definition: hash.c:160

Referenced by xsltInitCtxtKey().