17d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/*
27d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * keys.c: Implemetation of the keys support
37d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
47d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Reference:
57d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *   http://www.w3.org/TR/1999/REC-xslt-19991116
67d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
77d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * See Copyright for the status of this software.
87d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
97d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * daniel@veillard.com
107d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
117d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
127d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#define IN_LIBXSLT
137d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include "libxslt.h"
147d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
157d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include <string.h>
167d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
177d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include <libxml/xmlmemory.h>
187d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include <libxml/tree.h>
197d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include <libxml/valid.h>
207d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include <libxml/hash.h>
217d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include <libxml/xmlerror.h>
227d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include <libxml/parserInternals.h>
237d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include <libxml/xpathInternals.h>
247d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include "xslt.h"
257d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include "xsltInternals.h"
267d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include "xsltutils.h"
277d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include "imports.h"
287d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include "templates.h"
297d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#include "keys.h"
307d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
317d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG
327d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#define WITH_XSLT_DEBUG_KEYS
337d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
347d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
357d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangstatic int
367d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltInitDocKeyTable(xsltTransformContextPtr ctxt, const xmlChar *name,
377d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang                    const xmlChar *nameURI);
387d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
397d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/************************************************************************
407d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * 									*
417d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * 			Type functions 					*
427d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * 									*
437d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang ************************************************************************/
447d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
457d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
467d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltNewKeyDef:
477d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @name:  the key name or NULL
487d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @nameURI:  the name URI or NULL
497d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
507d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Create a new XSLT KeyDef
517d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
527d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Returns the newly allocated xsltKeyDefPtr or NULL in case of error
537d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
547d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangstatic xsltKeyDefPtr
557d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltNewKeyDef(const xmlChar *name, const xmlChar *nameURI) {
567d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyDefPtr cur;
577d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
587d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    cur = (xsltKeyDefPtr) xmlMalloc(sizeof(xsltKeyDef));
597d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (cur == NULL) {
607d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xsltTransformError(NULL, NULL, NULL,
617d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		"xsltNewKeyDef : malloc failed\n");
627d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	return(NULL);
637d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
647d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    memset(cur, 0, sizeof(xsltKeyDef));
657d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (name != NULL)
667d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	cur->name = xmlStrdup(name);
677d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (nameURI != NULL)
687d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	cur->nameURI = xmlStrdup(nameURI);
697d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    cur->nsList = NULL;
707d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    return(cur);
717d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
727d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
737d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
747d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltFreeKeyDef:
757d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @keyd:  an XSLT key definition
767d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
777d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Free up the memory allocated by @keyd
787d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
797d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangstatic void
807d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltFreeKeyDef(xsltKeyDefPtr keyd) {
817d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyd == NULL)
827d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	return;
837d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyd->comp != NULL)
847d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlXPathFreeCompExpr(keyd->comp);
857d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyd->usecomp != NULL)
867d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlXPathFreeCompExpr(keyd->usecomp);
877d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyd->name != NULL)
887d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlFree(keyd->name);
897d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyd->nameURI != NULL)
907d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlFree(keyd->nameURI);
917d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyd->match != NULL)
927d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlFree(keyd->match);
937d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyd->use != NULL)
947d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlFree(keyd->use);
957d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyd->nsList != NULL)
967d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        xmlFree(keyd->nsList);
977d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    memset(keyd, -1, sizeof(xsltKeyDef));
987d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlFree(keyd);
997d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
1007d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
1017d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
1027d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltFreeKeyDefList:
1037d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @keyd:  an XSLT key definition list
1047d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
1057d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Free up the memory allocated by all the elements of @keyd
1067d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
1077d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangstatic void
1087d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltFreeKeyDefList(xsltKeyDefPtr keyd) {
1097d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyDefPtr cur;
1107d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
1117d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    while (keyd != NULL) {
1127d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	cur = keyd;
1137d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	keyd = keyd->next;
1147d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xsltFreeKeyDef(cur);
1157d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
1167d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
1177d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
1187d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
1197d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltNewKeyTable:
1207d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @name:  the key name or NULL
1217d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @nameURI:  the name URI or NULL
1227d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
1237d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Create a new XSLT KeyTable
1247d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
1257d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Returns the newly allocated xsltKeyTablePtr or NULL in case of error
1267d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
1277d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangstatic xsltKeyTablePtr
1287d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltNewKeyTable(const xmlChar *name, const xmlChar *nameURI) {
1297d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyTablePtr cur;
1307d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
1317d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    cur = (xsltKeyTablePtr) xmlMalloc(sizeof(xsltKeyTable));
1327d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (cur == NULL) {
1337d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xsltTransformError(NULL, NULL, NULL,
1347d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		"xsltNewKeyTable : malloc failed\n");
1357d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	return(NULL);
1367d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
1377d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    memset(cur, 0, sizeof(xsltKeyTable));
1387d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (name != NULL)
1397d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	cur->name = xmlStrdup(name);
1407d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (nameURI != NULL)
1417d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	cur->nameURI = xmlStrdup(nameURI);
1427d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    cur->keys = xmlHashCreate(0);
1437d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    return(cur);
1447d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
1457d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
1467d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
1477d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltFreeKeyTable:
1487d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @keyt:  an XSLT key table
1497d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
1507d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Free up the memory allocated by @keyt
1517d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
1527d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangstatic void
1537d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltFreeKeyTable(xsltKeyTablePtr keyt) {
1547d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyt == NULL)
1557d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	return;
1567d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyt->name != NULL)
1577d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlFree(keyt->name);
1587d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyt->nameURI != NULL)
1597d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlFree(keyt->nameURI);
1607d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (keyt->keys != NULL)
1617d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlHashFree(keyt->keys,
1627d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    (xmlHashDeallocator) xmlXPathFreeNodeSet);
1637d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    memset(keyt, -1, sizeof(xsltKeyTable));
1647d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlFree(keyt);
1657d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
1667d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
1677d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
1687d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltFreeKeyTableList:
1697d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @keyt:  an XSLT key table list
1707d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
1717d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Free up the memory allocated by all the elements of @keyt
1727d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
1737d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangstatic void
1747d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltFreeKeyTableList(xsltKeyTablePtr keyt) {
1757d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyTablePtr cur;
1767d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
1777d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    while (keyt != NULL) {
1787d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	cur = keyt;
1797d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	keyt = keyt->next;
1807d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xsltFreeKeyTable(cur);
1817d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
1827d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
1837d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
1847d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/************************************************************************
1857d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * 									*
1867d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * 		The interpreter for the precompiled patterns		*
1877d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * 									*
1887d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang ************************************************************************/
1897d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
1907d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
1917d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
1927d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltFreeKeys:
1937d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @style: an XSLT stylesheet
1947d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
1957d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Free up the memory used by XSLT keys in a stylesheet
1967d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
1977d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangvoid
1987d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltFreeKeys(xsltStylesheetPtr style) {
1997d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (style->keys)
2007d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xsltFreeKeyDefList((xsltKeyDefPtr) style->keys);
2017d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
2027d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
2037d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
2047d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * skipString:
2057d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @cur: the current pointer
2067d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @end: the current offset
2077d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
2087d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * skip a string delimited by " or '
2097d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
2107d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Returns the byte after the string or -1 in case of error
2117d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
2127d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangstatic int
2137d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangskipString(const xmlChar *cur, int end) {
2147d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlChar limit;
2157d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
2167d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((cur == NULL) || (end < 0)) return(-1);
2177d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((cur[end] == '\'') || (cur[end] == '"')) limit = cur[end];
2187d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    else return(end);
2197d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    end++;
2207d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    while (cur[end] != 0) {
2217d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        if (cur[end] == limit)
2227d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    return(end + 1);
2237d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	end++;
2247d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
2257d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    return(-1);
2267d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
2277d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
2287d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
2297d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * skipPredicate:
2307d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @cur: the current pointer
2317d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @end: the current offset
2327d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
2337d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * skip a predicate
2347d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
2357d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Returns the byte after the predicate or -1 in case of error
2367d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
2377d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangstatic int
2387d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangskipPredicate(const xmlChar *cur, int end) {
2397d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((cur == NULL) || (end < 0)) return(-1);
2407d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (cur[end] != '[') return(end);
2417d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    end++;
2427d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    while (cur[end] != 0) {
2437d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        if ((cur[end] == '\'') || (cur[end] == '"')) {
2447d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    end = skipString(cur, end);
2457d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (end <= 0)
2467d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	        return(-1);
2477d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    continue;
2487d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	} else if (cur[end] == '[') {
2497d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    end = skipPredicate(cur, end);
2507d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (end <= 0)
2517d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	        return(-1);
2527d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    continue;
2537d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	} else if (cur[end] == ']')
2547d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    return(end + 1);
2557d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	end++;
2567d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
2577d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    return(-1);
2587d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
2597d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
2607d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
2617d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltAddKey:
2627d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @style: an XSLT stylesheet
2637d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @name:  the key name or NULL
2647d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @nameURI:  the name URI or NULL
2657d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @match:  the match value
2667d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @use:  the use value
2677d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @inst: the key instruction
2687d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
2697d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * add a key definition to a stylesheet
2707d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
2717d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Returns 0 in case of success, and -1 in case of failure.
2727d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
2737d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangint
2747d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltAddKey(xsltStylesheetPtr style, const xmlChar *name,
2757d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	   const xmlChar *nameURI, const xmlChar *match,
2767d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	   const xmlChar *use, xmlNodePtr inst) {
2777d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyDefPtr key;
2787d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlChar *pattern = NULL;
2797d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    int current, end, start, i = 0;
2807d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
2817d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((style == NULL) || (name == NULL) || (match == NULL) || (use == NULL))
2827d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	return(-1);
2837d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
2847d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG_KEYS
2857d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltGenericDebug(xsltGenericDebugContext,
2867d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	"Add key %s, match %s, use %s\n", name, match, use);
2877d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
2887d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
2897d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    key = xsltNewKeyDef(name, nameURI);
2907d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    key->match = xmlStrdup(match);
2917d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    key->use = xmlStrdup(use);
2927d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    key->inst = inst;
2937d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    key->nsList = xmlGetNsList(inst->doc, inst);
2947d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (key->nsList != NULL) {
2957d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        while (key->nsList[i] != NULL)
2967d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    i++;
2977d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
2987d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    key->nsNr = i;
2997d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
3007d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
3017d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     * Split the | and register it as as many keys
3027d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     */
3037d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    current = end = 0;
3047d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    while (match[current] != 0) {
3057d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	start = current;
3067d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	while (IS_BLANK_CH(match[current]))
3077d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    current++;
3087d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	end = current;
3097d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	while ((match[end] != 0) && (match[end] != '|')) {
3107d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (match[end] == '[') {
3117d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	        end = skipPredicate(match, end);
3127d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		if (end <= 0) {
3137d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    xsltTransformError(NULL, style, inst,
3147d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		                       "key pattern is malformed: %s",
3157d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang				       key->match);
3167d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    if (style != NULL) style->errors++;
3177d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    goto error;
3187d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		}
3197d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    } else
3207d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		end++;
3217d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
3227d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (current == end) {
3237d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    xsltTransformError(NULL, style, inst,
3247d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang			       "key pattern is empty\n");
3257d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (style != NULL) style->errors++;
3267d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    goto error;
3277d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
3287d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (match[start] != '/') {
3297d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    pattern = xmlStrcat(pattern, (xmlChar *)"//");
3307d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (pattern == NULL) {
3317d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		if (style != NULL) style->errors++;
3327d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		goto error;
3337d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    }
3347d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
3357d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	pattern = xmlStrncat(pattern, &match[start], end - start);
3367d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (pattern == NULL) {
3377d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (style != NULL) style->errors++;
3387d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    goto error;
3397d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
3407d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
3417d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (match[end] == '|') {
3427d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    pattern = xmlStrcat(pattern, (xmlChar *)"|");
3437d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    end++;
3447d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
3457d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	current = end;
3467d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
3477d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG_KEYS
3487d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltGenericDebug(xsltGenericDebugContext,
3497d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	"   resulting pattern %s\n", pattern);
3507d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
3517d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
3527d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    * XSLT-1: "It is an error for the value of either the use
3537d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    *  attribute or the match attribute to contain a
3547d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    *  VariableReference."
3557d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    * TODO: We should report a variable-reference at compile-time.
3567d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    *   Maybe a search for "$", if it occurs outside of quotation
3577d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    *   marks, could be sufficient.
3587d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    */
3597d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    key->comp = xsltXPathCompile(style, pattern);
3607d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (key->comp == NULL) {
3617d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xsltTransformError(NULL, style, inst,
3627d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		"xsl:key : XPath pattern compilation failed '%s'\n",
3637d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		         pattern);
3647d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (style != NULL) style->errors++;
3657d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
3667d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    key->usecomp = xsltXPathCompile(style, use);
3677d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (key->usecomp == NULL) {
3687d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xsltTransformError(NULL, style, inst,
3697d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		"xsl:key : XPath pattern compilation failed '%s'\n",
3707d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		         use);
3717d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (style != NULL) style->errors++;
3727d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
3737d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
3747d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
3757d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     * Sometimes the stylesheet writer use the order to ease the
3767d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     * resolution of keys when they are dependant, keep the provided
3777d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     * order so add the new one at the end.
3787d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     */
3797d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (style->keys == NULL) {
3807d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	style->keys = key;
3817d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    } else {
3827d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        xsltKeyDefPtr prev = style->keys;
3837d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
3847d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	while (prev->next != NULL)
3857d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    prev = prev->next;
3867d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
3877d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	prev->next = key;
3887d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
3897d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    key->next = NULL;
3907d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
3917d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangerror:
3927d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (pattern != NULL)
3937d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlFree(pattern);
3947d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    return(0);
3957d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
3967d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
3977d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
3987d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltGetKey:
3997d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @ctxt: an XSLT transformation context
4007d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @name:  the key name or NULL
4017d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @nameURI:  the name URI or NULL
4027d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @value:  the key value to look for
4037d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
4047d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Looks up a key of the in current source doc (the document info
4057d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * on @ctxt->document). Computes the key if not already done
4067d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * for the current source doc.
4077d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
4087d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Returns the nodeset resulting from the query or NULL
4097d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
4107d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxmlNodeSetPtr
4117d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name,
4127d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	   const xmlChar *nameURI, const xmlChar *value) {
4137d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlNodeSetPtr ret;
4147d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyTablePtr table;
4157d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    int init_table = 0;
4167d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
4177d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((ctxt == NULL) || (name == NULL) || (value == NULL) ||
4187d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	(ctxt->document == NULL))
4197d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	return(NULL);
4207d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
4217d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG_KEYS
4227d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltGenericDebug(xsltGenericDebugContext,
4237d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	"Get key %s, value %s\n", name, value);
4247d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
4257d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
4267d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
4277d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     * keys are computed only on-demand on first key access for a document
4287d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     */
4297d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((ctxt->document->nbKeysComputed < ctxt->nbKeys) &&
4307d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        (ctxt->keyInitLevel == 0)) {
4317d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        /*
4327d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	 * If non-recursive behaviour, just try to initialize all keys
4337d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	 */
4347d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (xsltInitAllDocKeys(ctxt))
4357d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    return(NULL);
4367d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
4377d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
4387d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangretry:
4397d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    table = (xsltKeyTablePtr) ctxt->document->keys;
4407d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    while (table != NULL) {
4417d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (((nameURI != NULL) == (table->nameURI != NULL)) &&
4427d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    xmlStrEqual(table->name, name) &&
4437d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    xmlStrEqual(table->nameURI, nameURI))
4447d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	{
4457d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value);
4467d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    return(ret);
4477d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
4487d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	table = table->next;
4497d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
4507d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
4517d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((ctxt->keyInitLevel != 0) && (init_table == 0)) {
4527d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        /*
4537d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	 * Apparently one key is recursive and this one is needed,
4547d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	 * initialize just it, that time and retry
4557d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	 */
4567d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        xsltInitDocKeyTable(ctxt, name, nameURI);
4577d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	init_table = 1;
4587d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	goto retry;
4597d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
4607d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
4617d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    return(NULL);
4627d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
4637d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
4647d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
4657d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
4667d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltInitDocKeyTable:
4677d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
4687d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * INTERNAL ROUTINE ONLY
4697d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
4707d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Check if any keys on the current document need to be computed
4717d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
4727d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangstatic int
4737d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltInitDocKeyTable(xsltTransformContextPtr ctxt, const xmlChar *name,
4747d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang                    const xmlChar *nameURI)
4757d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang{
4767d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltStylesheetPtr style;
4777d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyDefPtr keyd = NULL;
4787d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    int found = 0;
4797d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
4807d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef KEY_INIT_DEBUG
4817d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangfprintf(stderr, "xsltInitDocKeyTable %s\n", name);
4827d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
4837d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
4847d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    style = ctxt->style;
4857d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    while (style != NULL) {
4867d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	keyd = (xsltKeyDefPtr) style->keys;
4877d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	while (keyd != NULL) {
4887d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (((keyd->nameURI != NULL) ==
4897d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		 (nameURI != NULL)) &&
4907d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		xmlStrEqual(keyd->name, name) &&
4917d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		xmlStrEqual(keyd->nameURI, nameURI))
4927d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    {
4937d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		xsltInitCtxtKey(ctxt, ctxt->document, keyd);
4947d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
4957d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    return(0);
4967d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		found = 1;
4977d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    }
4987d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    keyd = keyd->next;
4997d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
5007d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	style = xsltNextImport(style);
5017d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
5027d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (found == 0) {
5037d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG_KEYS
5047d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
5057d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	     "xsltInitDocKeyTable: did not found %s\n", name));
5067d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
5077d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xsltTransformError(ctxt, NULL, keyd? keyd->inst : NULL,
5087d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    "Failed to find key definition for %s\n", name);
5097d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	ctxt->state = XSLT_STATE_STOPPED;
5107d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        return(-1);
5117d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
5127d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef KEY_INIT_DEBUG
5137d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangfprintf(stderr, "xsltInitDocKeyTable %s done\n", name);
5147d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
5157d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    return(0);
5167d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
5177d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
5187d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
5197d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltInitAllDocKeys:
5207d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @ctxt: transformation context
5217d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
5227d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * INTERNAL ROUTINE ONLY
5237d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
5247d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Check if any keys on the current document need to be computed
5257d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
5267d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Returns 0 in case of success, -1 in case of failure
5277d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
5287d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangint
5297d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltInitAllDocKeys(xsltTransformContextPtr ctxt)
5307d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang{
5317d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltStylesheetPtr style;
5327d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyDefPtr keyd;
5337d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyTablePtr table;
5347d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
5357d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (ctxt == NULL)
5367d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	return(-1);
5377d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
5387d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef KEY_INIT_DEBUG
5397d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangfprintf(stderr, "xsltInitAllDocKeys %d %d\n",
5407d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        ctxt->document->nbKeysComputed, ctxt->nbKeys);
5417d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
5427d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
5437d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
5447d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	return(0);
5457d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
5467d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
5477d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
5487d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    * TODO: This could be further optimized
5497d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    */
5507d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    style = ctxt->style;
5517d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    while (style) {
5527d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	keyd = (xsltKeyDefPtr) style->keys;
5537d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	while (keyd != NULL) {
5547d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef KEY_INIT_DEBUG
5557d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangfprintf(stderr, "Init key %s\n", keyd->name);
5567d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
5577d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    /*
5587d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    * Check if keys with this QName have been already
5597d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    * computed.
5607d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    */
5617d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    table = (xsltKeyTablePtr) ctxt->document->keys;
5627d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    while (table) {
5637d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		if (((keyd->nameURI != NULL) == (table->nameURI != NULL)) &&
5647d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    xmlStrEqual(keyd->name, table->name) &&
5657d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    xmlStrEqual(keyd->nameURI, table->nameURI))
5667d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		{
5677d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    break;
5687d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		}
5697d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		table = table->next;
5707d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    }
5717d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (table == NULL) {
5727d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		/*
5737d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		* Keys with this QName have not been yet computed.
5747d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		*/
5757d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		xsltInitDocKeyTable(ctxt, keyd->name, keyd->nameURI);
5767d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    }
5777d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    keyd = keyd->next;
5787d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
5797d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	style = xsltNextImport(style);
5807d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
5817d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef KEY_INIT_DEBUG
5827d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangfprintf(stderr, "xsltInitAllDocKeys: done\n");
5837d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
5847d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    return(0);
5857d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
5867d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
5877d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
5887d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltInitCtxtKey:
5897d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @ctxt: an XSLT transformation context
5907d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @idoc:  the document information (holds key values)
5917d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @keyDef: the key definition
5927d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
5937d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Computes the key tables this key and for the current input document.
5947d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
5957d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Returns: 0 on success, -1 on error
5967d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
5977d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangint
5987d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc,
5997d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	        xsltKeyDefPtr keyDef)
6007d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang{
6017d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    int i, len, k;
6027d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlNodeSetPtr matchList = NULL, keylist;
6037d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlXPathObjectPtr matchRes = NULL, useRes = NULL;
6047d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlChar *str = NULL;
6057d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyTablePtr table;
6067d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlNodePtr oldInst, cur;
6077d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlNodePtr oldContextNode;
6087d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltDocumentPtr oldDocInfo;
6097d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    int	oldXPPos, oldXPSize;
6107d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlDocPtr oldXPDoc;
6117d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    int oldXPNsNr;
6127d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlNsPtr *oldXPNamespaces;
6137d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xmlXPathContextPtr xpctxt;
6147d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
6157d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef KEY_INIT_DEBUG
6167d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangfprintf(stderr, "xsltInitCtxtKey %s : %d\n", keyDef->name, ctxt->keyInitLevel);
6177d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
6187d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
6197d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((keyDef->comp == NULL) || (keyDef->usecomp == NULL))
6207d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	return(-1);
6217d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
6227d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
6237d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     * Detect recursive keys
6247d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     */
6257d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (ctxt->keyInitLevel > ctxt->nbKeys) {
6267d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG_KEYS
6277d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,
6287d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	           xsltGenericDebug(xsltGenericDebugContext,
6297d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		       "xsltInitCtxtKey: key definition of %s is recursive\n",
6307d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		       keyDef->name));
6317d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
6327d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xsltTransformError(ctxt, NULL, keyDef->inst,
6337d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    "Key definition for %s is recursive\n", keyDef->name);
6347d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	ctxt->state = XSLT_STATE_STOPPED;
6357d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        return(-1);
6367d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
6377d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    ctxt->keyInitLevel++;
6387d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
6397d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt = ctxt->xpathCtxt;
6407d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    idoc->nbKeysComputed++;
6417d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
6427d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    * Save context state.
6437d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    */
6447d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    oldInst = ctxt->inst;
6457d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    oldDocInfo = ctxt->document;
6467d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    oldContextNode = ctxt->node;
6477d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
6487d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    oldXPDoc = xpctxt->doc;
6497d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    oldXPPos = xpctxt->proximityPosition;
6507d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    oldXPSize = xpctxt->contextSize;
6517d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    oldXPNsNr = xpctxt->nsNr;
6527d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    oldXPNamespaces = xpctxt->namespaces;
6537d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
6547d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
6557d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    * Set up contexts.
6567d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    */
6577d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    ctxt->document = idoc;
6587d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    ctxt->node = (xmlNodePtr) idoc->doc;
6597d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    ctxt->inst = keyDef->inst;
6607d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
6617d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->doc = idoc->doc;
6627d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->node = (xmlNodePtr) idoc->doc;
6637d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /* TODO : clarify the use of namespaces in keys evaluation */
6647d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->namespaces = keyDef->nsList;
6657d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->nsNr = keyDef->nsNr;
6667d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
6677d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
6687d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    * Evaluate the 'match' expression of the xsl:key.
6697d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    * TODO: The 'match' is a *pattern*.
6707d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    */
6717d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    matchRes = xmlXPathCompiledEval(keyDef->comp, xpctxt);
6727d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (matchRes == NULL) {
6737d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
6747d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG_KEYS
6757d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
6767d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	     "xsltInitCtxtKey: %s evaluation failed\n", keyDef->match));
6777d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
6787d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xsltTransformError(ctxt, NULL, keyDef->inst,
6797d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    "Failed to evaluate the 'match' expression.\n");
6807d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	ctxt->state = XSLT_STATE_STOPPED;
6817d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	goto error;
6827d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    } else {
6837d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (matchRes->type == XPATH_NODESET) {
6847d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    matchList = matchRes->nodesetval;
6857d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
6867d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG_KEYS
6877d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (matchList != NULL)
6887d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
6897d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		     "xsltInitCtxtKey: %s evaluates to %d nodes\n",
6907d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang				 keyDef->match, matchList->nodeNr));
6917d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
6927d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	} else {
6937d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    /*
6947d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    * Is not a node set, but must be.
6957d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    */
6967d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG_KEYS
6977d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
6987d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		 "xsltInitCtxtKey: %s is not a node set\n", keyDef->match));
6997d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
7007d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    xsltTransformError(ctxt, NULL, keyDef->inst,
7017d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		"The 'match' expression did not evaluate to a node set.\n");
7027d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    ctxt->state = XSLT_STATE_STOPPED;
7037d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    goto error;
7047d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
7057d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
7067d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((matchList == NULL) || (matchList->nodeNr <= 0))
7077d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	goto exit;
7087d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
7097d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /**
7107d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     * Multiple key definitions for the same name are allowed, so
7117d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     * we must check if the key is already present for this doc
7127d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     */
7137d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    table = (xsltKeyTablePtr) idoc->keys;
7147d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    while (table != NULL) {
7157d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        if (xmlStrEqual(table->name, keyDef->name) &&
7167d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    (((keyDef->nameURI == NULL) && (table->nameURI == NULL)) ||
7177d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	     ((keyDef->nameURI != NULL) && (table->nameURI != NULL) &&
7187d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	      (xmlStrEqual(table->nameURI, keyDef->nameURI)))))
7197d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    break;
7207d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	table = table->next;
7217d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
7227d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /**
7237d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     * If the key was not previously defined, create it now and
7247d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     * chain it to the list of keys for the doc
7257d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang     */
7267d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (table == NULL) {
7277d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        table = xsltNewKeyTable(keyDef->name, keyDef->nameURI);
7287d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        if (table == NULL)
7297d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    goto error;
7307d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        table->next = idoc->keys;
7317d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        idoc->keys = table;
7327d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
7337d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
7347d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
7357d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    * SPEC XSLT 1.0 (XSLT 2.0 does not clarify the context size!)
7367d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    * "...the use attribute of the xsl:key element is evaluated with x as
7377d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    "  the current node and with a node list containing just x as the
7387d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    *  current node list"
7397d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    */
7407d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->contextSize = 1;
7417d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->proximityPosition = 1;
7427d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
7437d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    for (i = 0; i < matchList->nodeNr; i++) {
7447d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	cur = matchList->nodeTab[i];
7457d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (! IS_XSLT_REAL_NODE(cur))
7467d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    continue;
7477d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xpctxt->node = cur;
7487d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	/*
7497d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	* Process the 'use' of the xsl:key.
7507d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	* SPEC XSLT 1.0:
7517d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	* "The use attribute is an expression specifying the values of
7527d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	*  the key; the expression is evaluated once for each node that
7537d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	*  matches the pattern."
7547d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	*/
7557d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (useRes != NULL)
7567d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    xmlXPathFreeObject(useRes);
7577d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	useRes = xmlXPathCompiledEval(keyDef->usecomp, xpctxt);
7587d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (useRes == NULL) {
7597d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    xsltTransformError(ctxt, NULL, keyDef->inst,
7607d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		"Failed to evaluate the 'use' expression.\n");
7617d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    ctxt->state = XSLT_STATE_STOPPED;
7627d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    break;
7637d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
7647d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	if (useRes->type == XPATH_NODESET) {
7657d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if ((useRes->nodesetval != NULL) &&
7667d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		(useRes->nodesetval->nodeNr != 0))
7677d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    {
7687d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		len = useRes->nodesetval->nodeNr;
7697d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[0]);
7707d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    } else {
7717d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		continue;
7727d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    }
7737d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	} else {
7747d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    len = 1;
7757d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (useRes->type == XPATH_STRING) {
7767d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		/*
7777d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		* Consume the string value.
7787d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		*/
7797d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		str = useRes->stringval;
7807d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		useRes->stringval = NULL;
7817d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    } else {
7827d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		str = xmlXPathCastToString(useRes);
7837d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    }
7847d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
7857d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	/*
7867d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	* Process all strings.
7877d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	*/
7887d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	k = 0;
7897d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	while (1) {
7907d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (str == NULL)
7917d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		goto next_string;
7927d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
7937d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG_KEYS
7947d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
7957d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		"xsl:key : node associated to ('%s', '%s')\n", keyDef->name, str));
7967d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
7977d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
7987d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    keylist = xmlHashLookup(table->keys, str);
7997d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (keylist == NULL) {
8007d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		keylist = xmlXPathNodeSetCreate(cur);
8017d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		if (keylist == NULL)
8027d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    goto error;
8037d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		xmlHashAddEntry(table->keys, str, keylist);
8047d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    } else {
8057d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		/*
8067d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		* TODO: How do we know if this function failed?
8077d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		*/
8087d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		xmlXPathNodeSetAdd(keylist, cur);
8097d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    }
8107d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    switch (cur->type) {
8117d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		case XML_ELEMENT_NODE:
8127d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		case XML_TEXT_NODE:
8137d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		case XML_CDATA_SECTION_NODE:
8147d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		case XML_PI_NODE:
8157d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		case XML_COMMENT_NODE:
8167d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    cur->psvi = keyDef;
8177d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    break;
8187d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		case XML_ATTRIBUTE_NODE:
8197d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    ((xmlAttrPtr) cur)->psvi = keyDef;
8207d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    break;
8217d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		case XML_DOCUMENT_NODE:
8227d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		case XML_HTML_DOCUMENT_NODE:
8237d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    ((xmlDocPtr) cur)->psvi = keyDef;
8247d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    break;
8257d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		default:
8267d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		    break;
8277d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    }
8287d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    xmlFree(str);
8297d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    str = NULL;
8307d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
8317d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangnext_string:
8327d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    k++;
8337d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    if (k >= len)
8347d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		break;
8357d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[k]);
8367d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
8377d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
8387d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
8397d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangexit:
8407d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangerror:
8417d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    ctxt->keyInitLevel--;
8427d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    /*
8437d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    * Restore context state.
8447d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    */
8457d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->doc = oldXPDoc;
8467d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->nsNr = oldXPNsNr;
8477d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->namespaces = oldXPNamespaces;
8487d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->proximityPosition = oldXPPos;
8497d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xpctxt->contextSize = oldXPSize;
8507d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
8517d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    ctxt->node = oldContextNode;
8527d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    ctxt->document = oldDocInfo;
8537d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    ctxt->inst = oldInst;
8547d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
8557d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (str)
8567d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlFree(str);
8577d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (useRes != NULL)
8587d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlXPathFreeObject(useRes);
8597d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (matchRes != NULL)
8607d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	xmlXPathFreeObject(matchRes);
8617d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    return(0);
8627d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
8637d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
8647d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
8657d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltInitCtxtKeys:
8667d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @ctxt:  an XSLT transformation context
8677d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @idoc:  a document info
8687d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
8697d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Computes all the keys tables for the current input document.
8707d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Should be done before global varibales are initialized.
8717d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * NOTE: Not used anymore in the refactored code.
8727d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
8737d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangvoid
8747d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltInitCtxtKeys(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc) {
8757d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltStylesheetPtr style;
8767d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    xsltKeyDefPtr keyDef;
8777d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
8787d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((ctxt == NULL) || (idoc == NULL))
8797d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	return;
8807d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
8817d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef KEY_INIT_DEBUG
8827d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangfprintf(stderr, "xsltInitCtxtKeys on document\n");
8837d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
8847d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
8857d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef WITH_XSLT_DEBUG_KEYS
8867d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if ((idoc->doc != NULL) && (idoc->doc->URL != NULL))
8877d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n",
8887d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang		     idoc->doc->URL));
8897d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
8907d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    style = ctxt->style;
8917d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    while (style != NULL) {
8927d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	keyDef = (xsltKeyDefPtr) style->keys;
8937d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	while (keyDef != NULL) {
8947d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    xsltInitCtxtKey(ctxt, idoc, keyDef);
8957d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
8967d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	    keyDef = keyDef->next;
8977d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	}
8987d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
8997d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang	style = xsltNextImport(style);
9007d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    }
9017d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
9027d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#ifdef KEY_INIT_DEBUG
9037d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangfprintf(stderr, "xsltInitCtxtKeys on document: done\n");
9047d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang#endif
9057d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
9067d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
9077d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
9087d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang/**
9097d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * xsltFreeDocumentKeys:
9107d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * @idoc: a XSLT document
9117d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang *
9127d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang * Free the keys associated to a document
9137d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang */
9147d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wangvoid
9157d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) WangxsltFreeDocumentKeys(xsltDocumentPtr idoc) {
9167d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang    if (idoc != NULL)
9177d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang        xsltFreeKeyTableList(idoc->keys);
9187d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang}
9197d1dabff1598661db0018d89d16cca02f7c31ae2Shimeng (Simon) Wang
920