From: Daniel Veillard Date: Mon, 19 Feb 2001 15:06:07 +0000 (+0000) Subject: Hacking on namespaces support: X-Git-Tag: v1.1.28~1450 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=15914df0127555e00ab58d6dba94a752a38577a7;p=platform%2Fupstream%2Flibxslt.git Hacking on namespaces support: - libxslt/numbers.c libxslt/numbersInternals.h libxslt/xslt.c libxslt/pattern.[ch] libxslt/xsltInternals.h: more work on support of namespaces, both in templates and in XPath subexpressions Daniel --- diff --git a/ChangeLog b/ChangeLog index 85e0b43..3f42564 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Mon Feb 19 18:05:47 CET 2001 Daniel Veillard + + * libxslt/numbers.c libxslt/numbersInternals.h libxslt/xslt.c + libxslt/pattern.[ch] libxslt/xsltInternals.h: more work on + support of namespaces, both in templates and in XPath subexpressions + Sun Feb 18 19:11:26 CET 2001 Bjorn Reese * libxslt/xsltutils.c: xsltSortFunction uses Shell's sort diff --git a/libxslt/numbers.c b/libxslt/numbers.c index 34a89f4..bc38c5c 100644 --- a/libxslt/numbers.c +++ b/libxslt/numbers.c @@ -398,7 +398,9 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context, xmlChar *count, xmlChar *from, double *array, - int max) + int max, + xmlDocPtr doc, + xmlNodePtr elem) { int amount = 0; int cnt = 0; @@ -410,11 +412,11 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context, xsltCompMatchPtr fromPat; if (count != NULL) - countPat = xsltCompilePattern(count); + countPat = xsltCompilePattern(count, doc, elem); else countPat = NULL; if (from != NULL) - fromPat = xsltCompilePattern(from); + fromPat = xsltCompilePattern(from, doc, elem); else fromPat = NULL; context->xpathCtxt->node = node; @@ -474,7 +476,9 @@ xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context, xmlChar *count, xmlChar *from, double *array, - int max) + int max, + xmlDocPtr doc, + xmlNodePtr elem) { int amount = 0; int cnt; @@ -485,11 +489,11 @@ xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context, xsltCompMatchPtr fromPat; if (count != NULL) - countPat = xsltCompilePattern(count); + countPat = xsltCompilePattern(count, doc, elem); else countPat = NULL; if (from != NULL) - fromPat = xsltCompilePattern(from); + fromPat = xsltCompilePattern(from, doc, elem); else fromPat = NULL; context->xpathCtxt->node = node; @@ -608,7 +612,9 @@ xsltNumberFormat(xsltTransformContextPtr ctxt, data->count, data->from, &number, - 1); + 1, + data->doc, + data->node); if (amount == 1) { xsltNumberFormatInsertNumbers(data, &number, @@ -625,7 +631,9 @@ xsltNumberFormat(xsltTransformContextPtr ctxt, data->count, data->from, numarray, - max); + max, + data->doc, + data->node); if (amount > 0) { xsltNumberFormatInsertNumbers(data, numarray, @@ -640,7 +648,9 @@ xsltNumberFormat(xsltTransformContextPtr ctxt, data->count, data->from, &number, - 1); + 1, + data->doc, + data->node); if (amount > 0) { xsltNumberFormatInsertNumbers(data, &number, diff --git a/libxslt/numbersInternals.h b/libxslt/numbersInternals.h index a112d23..a20dec1 100644 --- a/libxslt/numbersInternals.h +++ b/libxslt/numbersInternals.h @@ -28,6 +28,8 @@ typedef struct _xsltNumberData { xmlChar *format; int digitsPerGroup; xmlChar groupingCharacter; + xmlDocPtr doc; + xmlNodePtr node; } xsltNumberData, *xsltNumberDataPtr; xmlXPathError xsltFormatNumberConversion(xsltDecimalFormatPtr, xmlChar *, diff --git a/libxslt/pattern.c b/libxslt/pattern.c index a6413b2..231fe1c 100644 --- a/libxslt/pattern.c +++ b/libxslt/pattern.c @@ -27,7 +27,7 @@ #include "keys.h" #include "pattern.h" -/* #define DEBUG_PARSING */ +#define DEBUG_PATTERN /* * Types are private: @@ -80,6 +80,8 @@ typedef xsltParserContext *xsltParserContextPtr; struct _xsltParserContext { const xmlChar *cur; /* the current char being parsed */ const xmlChar *base; /* the full expression */ + xmlDocPtr doc; /* the source document */ + xmlNodePtr elem; /* the source element */ int error; /* error code */ xsltCompMatchPtr comp; /* the result */ }; @@ -333,10 +335,10 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, case XSLT_OP_END: return(1); case XSLT_OP_ROOT: - if ((node->type != XML_DOCUMENT_NODE) && - (node->type != XML_HTML_DOCUMENT_NODE)) - return(0); - continue; + if ((node->type == XML_DOCUMENT_NODE) || + (node->type == XML_HTML_DOCUMENT_NODE)) + continue; + return(0); case XSLT_OP_ELEM: if (node->type != XML_ELEMENT_NODE) return(0); @@ -493,7 +495,7 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, (node->type == XML_ELEMENT_NODE) && (node->parent != NULL)) { - /* TODO: cache those informations ?!? */ + /* TODO: cache those informations !!! */ xmlNodePtr siblings = node->parent->children; while (siblings != NULL) { @@ -905,6 +907,9 @@ error: void xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) { xmlChar *name = NULL; + xmlChar *prefix = NULL; + xmlChar *ncname = NULL; + xmlChar *URL = NULL; SKIP_BLANKS; if ((token == NULL) && (CUR == '@')) { @@ -938,6 +943,8 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) { goto error; } } + + SKIP_BLANKS; if (CUR == '(') { xsltCompileIdKeyPattern(ctxt, token, 0); @@ -953,7 +960,6 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) { } NEXT; if (xmlStrEqual(token, (const xmlChar *) "child")) { - /* TODO: handle namespace */ name = xsltScanName(ctxt); if (name == NULL) { xsltGenericError(xsltGenericErrorContext, @@ -961,9 +967,26 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) { ctxt->error = 1; goto error; } - PUSH(XSLT_OP_CHILD, name, NULL); + ncname = xmlSplitQName2(name, &prefix); + if (ncname != NULL) { + if (prefix != NULL) { + xmlNsPtr ns; + + ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix); + if (ns == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl: pattern, no namespace bound to prefix %s\n", + prefix); + } else { + URL = xmlStrdup(ns->href); + } + xmlFree(prefix); + } + xmlFree(name); + name = ncname; + } + PUSH(XSLT_OP_CHILD, name, URL); } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) { - /* TODO: handle namespace */ name = xsltScanName(ctxt); if (name == NULL) { xsltGenericError(xsltGenericErrorContext, @@ -971,7 +994,25 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) { ctxt->error = 1; goto error; } - PUSH(XSLT_OP_ATTR, name, NULL); + ncname = xmlSplitQName2(name, &prefix); + if (ncname != NULL) { + if (prefix != NULL) { + xmlNsPtr ns; + + ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix); + if (ns == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl: pattern, no namespace bound to prefix %s\n", + prefix); + } else { + URL = xmlStrdup(ns->href); + } + xmlFree(prefix); + } + xmlFree(name); + name = ncname; + } + PUSH(XSLT_OP_ATTR, name, URL); } else { xsltGenericError(xsltGenericErrorContext, "xsltCompileStepPattern : 'child' or 'attribute' expected\n"); @@ -983,8 +1024,25 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) { NEXT; PUSH(XSLT_OP_ALL, token, NULL); } else { - /* TODO: handle namespace */ - PUSH(XSLT_OP_ELEM, token, NULL); + ncname = xmlSplitQName2(token, &prefix); + if (ncname != NULL) { + if (prefix != NULL) { + xmlNsPtr ns; + + ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix); + if (ns == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl: pattern, no namespace bound to prefix %s\n", + prefix); + } else { + URL = xmlStrdup(ns->href); + } + xmlFree(prefix); + } + xmlFree(token); + token = ncname; + } + PUSH(XSLT_OP_ELEM, token, URL); } parse_predicate: SKIP_BLANKS; @@ -1132,6 +1190,8 @@ error: /** * xsltCompilePattern: * @pattern an XSLT pattern + * @doc: the containing document + * @node: the containing element * * Compile the XSLT pattern and generates a list of precompiled form suitable * for fast matching. @@ -1142,7 +1202,7 @@ error: */ xsltCompMatchPtr -xsltCompilePattern(const xmlChar *pattern) { +xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc, xmlNodePtr node) { xsltParserContextPtr ctxt = NULL; xsltCompMatchPtr element, first = NULL, previous = NULL; int current, start, end; @@ -1153,7 +1213,7 @@ xsltCompilePattern(const xmlChar *pattern) { return(NULL); } -#ifdef DEBUG_PARSING +#ifdef DEBUG_PATTERN xsltGenericDebug(xsltGenericDebugContext, "xsltCompilePattern : parsing '%s'\n", pattern); #endif @@ -1161,6 +1221,8 @@ xsltCompilePattern(const xmlChar *pattern) { ctxt = xsltNewParserContext(); if (ctxt == NULL) return(NULL); + ctxt->doc = doc; + ctxt->elem = node; current = end = 0; while (pattern[current] != 0) { start = current; @@ -1206,6 +1268,9 @@ xsltCompilePattern(const xmlChar *pattern) { (element->steps[0].value != NULL) && (element->steps[1].op == XSLT_OP_END)) { element->priority = 0; + } else if ((element->steps[0].op == XSLT_OP_ROOT) && + (element->steps[1].op == XSLT_OP_END)) { + element->priority = 0; } else if ((element->steps[0].op == XSLT_OP_PI) && (element->steps[0].value != NULL) && (element->steps[1].op == XSLT_OP_END)) { @@ -1271,7 +1336,7 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur, if ((style == NULL) || (cur == NULL) || (cur->match == NULL)) return(-1); - pat = xsltCompilePattern(cur->match); + pat = xsltCompilePattern(cur->match, style->doc, cur->elem); while (pat) { next = pat->next; pat->next = NULL; @@ -1281,7 +1346,7 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur, pat->mode = xmlStrdup(mode); if (modeURI != NULL) pat->modeURI = xmlStrdup(modeURI); - if (pat->priority != XSLT_PAT_NO_PRIORITY) + if (cur->priority == XSLT_PAT_NO_PRIORITY) cur->priority = pat->priority; else pat->priority = cur->priority; @@ -1351,25 +1416,13 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur, xsltFreeCompMatch(pat); return(-1); } -#ifdef DEBUG_PARSING - xsltGenericDebug(xsltGenericDebugContext, - "xsltAddTemplate: created template hash\n"); -#endif xmlHashAddEntry3(style->templatesHash, name, mode, modeURI, pat); -#ifdef DEBUG_PARSING - xsltGenericDebug(xsltGenericDebugContext, - "xsltAddTemplate: added new hash %s\n", name); -#endif } else { list = (xsltCompMatchPtr) xmlHashLookup3(style->templatesHash, name, mode, modeURI); if (list == NULL) { xmlHashAddEntry3(style->templatesHash, name, mode, modeURI, pat); -#ifdef DEBUG_PARSING - xsltGenericDebug(xsltGenericDebugContext, - "xsltAddTemplate: added new hash %s\n", name); -#endif } else { /* * Note '<=' since one must choose among the matching @@ -1380,10 +1433,6 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur, pat->next = list; xmlHashUpdateEntry3(style->templatesHash, name, mode, modeURI, pat, NULL); -#ifdef DEBUG_PARSING - xsltGenericDebug(xsltGenericDebugContext, - "xsltAddTemplate: added head hash for %s\n", name); -#endif } else { while (list->next != NULL) { if (list->next->priority <= pat->priority) @@ -1418,6 +1467,12 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur, xsltFreeCompMatch(pat); return(-1); } +#ifdef DEBUG_PATTERN + xsltGenericDebug(xsltGenericDebugContext, + "added pattern : '%s' priority %f\n", + pat->template->match, pat->priority); +#endif + pat = next; } return(0); @@ -1565,7 +1620,6 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, list = list->next; } } - if (ret != NULL) return(ret); @@ -1607,6 +1661,7 @@ xsltFreeTemplateHashes(xsltStylesheetPtr style) { xsltFreeCompMatchList(style->commentMatch); } +#if 0 /** * xsltMatchPattern * @node: a node in the source tree @@ -1634,4 +1689,4 @@ xsltMatchPattern(xsltTransformContextPtr context, } return match; } - +#endif diff --git a/libxslt/pattern.h b/libxslt/pattern.h index 105c143..00b944b 100644 --- a/libxslt/pattern.h +++ b/libxslt/pattern.h @@ -25,7 +25,9 @@ typedef xsltCompMatch *xsltCompMatchPtr; * Pattern related interfaces */ -xsltCompMatchPtr xsltCompilePattern (const xmlChar *pattern); +xsltCompMatchPtr xsltCompilePattern (const xmlChar *pattern, + xmlDocPtr doc, + xmlNodePtr node); void xsltFreeCompMatchList (xsltCompMatchPtr comp); int xsltTestCompMatchList (xsltTransformContextPtr ctxt, xmlNodePtr node, @@ -42,10 +44,11 @@ xsltTemplatePtr xsltGetTemplate (xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStylesheetPtr style); void xsltFreeTemplateHashes (xsltStylesheetPtr style); +#if 0 int xsltMatchPattern (xsltTransformContextPtr ctxt, xmlNodePtr node, const xmlChar *pattern); - +#endif #ifdef __cplusplus } #endif diff --git a/libxslt/transform.c b/libxslt/transform.c index 6956cda..fc31b95 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -165,6 +165,7 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) { return(NULL); } XSLT_REGISTER_VARIABLE_LOOKUP(cur); + cur->xpathCtxt->nsHash = style->nsHash; docu = xsltNewDocument(cur, doc); if (docu == NULL) { xsltGenericError(xsltGenericErrorContext, @@ -189,8 +190,10 @@ void xsltFreeTransformContext(xsltTransformContextPtr ctxt) { if (ctxt == NULL) return; - if (ctxt->xpathCtxt != NULL) + if (ctxt->xpathCtxt != NULL) { + ctxt->xpathCtxt->nsHash = NULL; xmlXPathFreeContext(ctxt->xpathCtxt); + } if (ctxt->templTab != NULL) xmlFree(ctxt->templTab); if (ctxt->varsTab != NULL) @@ -977,6 +980,8 @@ xsltNumber(xsltTransformContextPtr ctxt, memset(&numdata, 0, sizeof(numdata)); + numdata.doc = cur->doc; + numdata.node = cur; numdata.value = xmlGetNsProp(cur, (const xmlChar *)"value", XSLT_NAMESPACE); prop = xmlGetNsProp(cur, (const xmlChar *)"format", XSLT_NAMESPACE); @@ -2337,9 +2342,9 @@ xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc) { */ ctxt->output = res; ctxt->insert = (xmlNodePtr) res; + xsltEvalGlobalVariables(ctxt); ctxt->node = (xmlNodePtr) doc; varsPush(ctxt, NULL); - xsltEvalGlobalVariables(ctxt); xsltProcessOneNode(ctxt, ctxt->node); xsltFreeStackElemList(varsPop(ctxt)); diff --git a/libxslt/xslt.c b/libxslt/xslt.c index 3565b7c..d09ac0e 100644 --- a/libxslt/xslt.c +++ b/libxslt/xslt.c @@ -295,6 +295,8 @@ xsltFreeStylesheet(xsltStylesheetPtr sheet) { xsltFreeStackElemList(sheet->variables); if (sheet->stripSpaces != NULL) xmlHashFree(sheet->stripSpaces, NULL); + if (sheet->nsHash != NULL) + xmlHashFree(sheet->nsHash, NULL); if (sheet->method != NULL) xmlFree(sheet->method); if (sheet->methodURI != NULL) xmlFree(sheet->methodURI); @@ -762,6 +764,86 @@ skip_children: } /** + * xsltGatherNamespaces: + * @style: the XSLT stylesheet + * + * Browse the stylesheet and buit the namspace hash table which + * will be used for XPath interpretation. If needed do a bit of normalization + */ + +void +xsltGatherNamespaces(xsltStylesheetPtr style) { + xmlNodePtr cur; + const xmlChar *URI; + + /* + * TODO: basically if the stylesheet uses the same prefix for different + * patterns, well they may be in problem, hopefully they will get + * a warning first. + */ + cur = xmlDocGetRootElement(style->doc); + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + xmlNsPtr ns = cur->nsDef; + while (ns != NULL) { + if (ns->prefix != NULL) { + if (style->nsHash == NULL) { + style->nsHash = xmlHashCreate(10); + if (style->nsHash == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsltGatherNamespaces: failed to create hash table\n"); + return; + } + } + URI = xmlHashLookup(style->nsHash, ns->prefix); + if ((URI != NULL) && (!xmlStrEqual(URI, ns->href))) { + xsltGenericError(xsltGenericErrorContext, + "Namespaces prefix %s used for multiple namespaces\n"); + } else if (URI == NULL) { + xmlHashUpdateEntry(style->nsHash, ns->prefix, + (void *) ns->href, (xmlHashDeallocator)xmlFree); + +#ifdef DEBUG_PARSING + xsltGenericDebug(xsltGenericDebugContext, + "Added namespace: %s mapped to %s\n", ns->prefix, ns->href); +#endif + } + } + ns = ns->next; + } + } + + /* + * Skip to next node + */ + if (cur->children != NULL) { + if (cur->children->type != XML_ENTITY_DECL) { + cur = cur->children; + continue; + } + } + if (cur->next != NULL) { + cur = cur->next; + continue; + } + + do { + cur = cur->parent; + if (cur == NULL) + break; + if (cur == (xmlNodePtr) style->doc) { + cur = NULL; + break; + } + if (cur->next != NULL) { + cur = cur->next; + break; + } + } while (cur != NULL); + } +} + +/** * xsltParseTemplateContent: * @style: the XSLT stylesheet * @ret: the "template" structure @@ -781,6 +863,7 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xsltTemplatePtr ret, * For stylesheets, the set of whitespace-preserving * element names consists of just xsl:text. */ + ret->elem = template; cur = template->children; delete = NULL; while (cur != NULL) { @@ -1334,6 +1417,7 @@ xsltParseStylesheetDoc(xmlDocPtr doc) { return(NULL); ret->doc = doc; + xsltGatherNamespaces(ret); xsltParseStylesheetProcess(ret, doc); return(ret); diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h index 3cdbdf2..908e6a9 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -53,12 +53,13 @@ struct _xsltTemplate { struct _xsltTemplate *next;/* chained list sorted by priority */ struct _xsltStylesheet *style;/* the containing stylesheet */ xmlChar *match; /* the matching string */ - int priority; /* as given from the stylesheet, not computed */ + float priority; /* as given from the stylesheet, not computed */ xmlChar *name; /* the local part of the name QName */ xmlChar *nameURI; /* the URI part of the name QName */ xmlChar *mode; /* the local part of the mode QName */ xmlChar *modeURI; /* the URI part of the mode QName */ xmlNodePtr content; /* the template replacement value */ + xmlNodePtr elem; /* the source element */ }; /* @@ -150,6 +151,11 @@ struct _xsltStylesheet { xmlHashTablePtr attributeSets;/* the attribute sets hash tables */ /* + * Attribute sets + */ + xmlHashTablePtr nsHash; /* the set of namespaces in use */ + + /* * Key definitions */ void *keys; /* key definitions */