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