From 9700cf32b245e6a1c38cae92f13eb4f2fc1c8949 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Fri, 9 Feb 2001 14:52:32 +0000 Subject: [PATCH] Messing with document related structures, keys, etc ...: - libxslt/Makefile.am libxslt/documents.[ch]: added a new module to deal with documents - libxslt/functions.c: fixed document() to return the same set for teh same URL - libxslt/keys.[ch] libxslt/templates.c libxslt/transform.c libxslt/variables.c libxslt/xsltInternals.h: keys are really associated to loaded documents, not to the transformation context, made the change, this impacted a number of modules Daniel --- ChangeLog | 11 ++++ libxslt/Makefile.am | 2 + libxslt/documents.c | 113 ++++++++++++++++++++++++++++++++++++++++ libxslt/documents.h | 30 +++++++++++ libxslt/functions.c | 33 +++++------- libxslt/keys.c | 53 +++++++++++-------- libxslt/keys.h | 6 ++- libxslt/templates.c | 5 +- libxslt/transform.c | 30 ++++++----- libxslt/variables.c | 2 +- libxslt/xsltInternals.h | 19 +++++-- 11 files changed, 239 insertions(+), 65 deletions(-) create mode 100644 libxslt/documents.c create mode 100644 libxslt/documents.h diff --git a/ChangeLog b/ChangeLog index 8918c19a..6049cd42 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Fri Feb 9 15:49:19 CET 2001 Daniel Veillard + + * libxslt/Makefile.am libxslt/documents.[ch]: added a new module + to deal with documents + * libxslt/functions.c: fixed document() to return the same set + for teh same URL + * libxslt/keys.[ch] libxslt/templates.c libxslt/transform.c + libxslt/variables.c libxslt/xsltInternals.h: keys are really + associated to loaded documents, not to the transformation + context, made the change, this impacted a number of modules + Thu Feb 8 12:51:00 CET 2001 Daniel Veillard * doc/libxslt.sgml doc/html/*.html: updated and rebuilt the doc list diff --git a/libxslt/Makefile.am b/libxslt/Makefile.am index d52b079f..5365bf7d 100644 --- a/libxslt/Makefile.am +++ b/libxslt/Makefile.am @@ -17,6 +17,7 @@ xsltinc_HEADERS = \ namespaces.h \ imports.h \ attributes.h \ + documents.h \ transform.h \ xsltInternals.h @@ -32,6 +33,7 @@ libxslt_la_SOURCES = \ namespaces.c \ imports.c \ attributes.c \ + documents.c \ transform.c diff --git a/libxslt/documents.c b/libxslt/documents.c new file mode 100644 index 00000000..556e8d2d --- /dev/null +++ b/libxslt/documents.c @@ -0,0 +1,113 @@ +/* + * documents.c: Implementation of the documents handling + * + * See Copyright for the status of this software. + * + * Daniel.Veillard@imag.fr + */ + +#include "xsltconfig.h" + +#include + +#include +#include +#include +#include "xslt.h" +#include "xsltInternals.h" +#include "xsltutils.h" +#include "documents.h" +#include "keys.h" + +#define DEBUG_DOCUMENTS + + +/************************************************************************ + * * + * Module interfaces * + * * + ************************************************************************/ + +/** + * xsltNewDocument: + * @ctxt: an XSLT transformation context + * @doc: a parsed XML document + * + * Register a new document, apply key computations + */ +xsltDocumentPtr +xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc) { + xsltDocumentPtr cur; + + cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument)); + if (cur == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsltNewDocument : malloc failed\n"); + return(NULL); + } + memset(cur, 0, sizeof(xsltDocument)); + cur->doc = doc; + cur->next = ctxt->docList; + ctxt->docList = cur; + xsltInitCtxtKeys(ctxt, cur); + return(cur); +} + +/** + * xsltFreeDocuments: + * @ctxt: an XSLT transformation context + * + * Free up all the space used by the loaded documents + */ +void +xsltFreeDocuments(xsltTransformContextPtr ctxt) { + xsltDocumentPtr doc, cur; + + cur = ctxt->document; + while (cur != NULL) { + doc = cur; + cur = cur->next; + xsltFreeDocumentKeys(doc); + if (!doc->main) + xmlFreeDoc(doc->doc); + xmlFree(doc); + } +} + + +/** + * xsltLoadDocument: + * @ctxt: an XSLT transformation context + * @URI: the computed URI of the document + * + * Try to load a document within the XSLT transformation context + * + * Returns the new xsltDocumentPtr or NULL in case of error + */ +xsltDocumentPtr +xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) { + xsltDocumentPtr ret; + xmlDocPtr doc; + + if ((ctxt == NULL) || (URI == NULL)) + return(NULL); + + /* + * Walk the context list to find the document if preparsed + */ + ret = ctxt->docList; + while (ret != NULL) { + if ((ret->doc != NULL) && (ret->doc->URL != NULL) && + (xmlStrEqual(ret->doc->URL, URI))) + return(ret); + ret = ret->next; + } + + doc = xmlParseFile((const char *) URI); + if (doc == NULL) + return(NULL); + + ret = xsltNewDocument(ctxt, doc); + return(ret); +} + diff --git a/libxslt/documents.h b/libxslt/documents.h new file mode 100644 index 00000000..19d55f77 --- /dev/null +++ b/libxslt/documents.h @@ -0,0 +1,30 @@ +/* + * document.h: interface for the document handling + * + * See Copyright for the status of this software. + * + * Daniel.Veillard@imag.fr + */ + +#ifndef __XML_XSLT_DOCUMENTS_H__ +#define __XML_XSLT_DOCUMENTS_H__ + +#include +#include "xsltInternals.h" + +#ifdef __cplusplus +extern "C" { +#endif + +xsltDocumentPtr xsltNewDocument (xsltTransformContextPtr ctxt, + xmlDocPtr doc); +xsltDocumentPtr xsltLoadDocument (xsltTransformContextPtr ctxt, + const xmlChar *URI); +void xsltFreeDocuments (xsltTransformContextPtr ctxt); + +#ifdef __cplusplus +} +#endif + +#endif /* __XML_XSLT_DOCUMENTS_H__ */ + diff --git a/libxslt/functions.c b/libxslt/functions.c index 29d8b571..12939f1d 100644 --- a/libxslt/functions.c +++ b/libxslt/functions.c @@ -37,6 +37,7 @@ #include "functions.h" #include "numbersInternals.h" #include "keys.h" +#include "documents.h" #define DEBUG_FUNCTION @@ -57,7 +58,7 @@ */ void xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs){ - xmlDocPtr doc; + xsltDocumentPtr doc; xmlXPathObjectPtr obj; xmlChar *base, *URI; @@ -101,31 +102,21 @@ xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs){ if (URI == NULL) { valuePush(ctxt, xmlXPathNewNodeSet(NULL)); } else { - doc = xmlParseDoc(URI); - if (doc == NULL) - valuePush(ctxt, xmlXPathNewNodeSet(NULL)); - else { - xsltTransformContextPtr tctxt; + xsltTransformContextPtr tctxt; - /* - * link it to the context for cleanup when done - */ - tctxt = (xsltTransformContextPtr) ctxt->context->extra; - if (tctxt == NULL) { - xsltGenericError(xsltGenericErrorContext, + tctxt = (xsltTransformContextPtr) ctxt->context->extra; + if (tctxt == NULL) { + xsltGenericError(xsltGenericErrorContext, "document() : internal error tctxt == NULL\n"); - xmlFreeDoc(doc); + valuePush(ctxt, xmlXPathNewNodeSet(NULL)); + } else { + doc = xsltLoadDocument(tctxt, URI); + if (doc == NULL) valuePush(ctxt, xmlXPathNewNodeSet(NULL)); - } else { - /* - * Keep a link from the context to be able to deallocate - */ - doc->next = (xmlNodePtr) tctxt->extraDocs; - tctxt->extraDocs = doc; - + else { /* TODO: use XPointer of HTML location for fragment ID */ /* pbm #xxx can lead to location sets, not nodesets :-) */ - valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc)); + valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc->doc)); } } } diff --git a/libxslt/keys.c b/libxslt/keys.c index e310f5e9..798b13ff 100644 --- a/libxslt/keys.c +++ b/libxslt/keys.c @@ -263,7 +263,7 @@ xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name, "Get key %s, value %s\n", name, value); #endif - table = (xsltKeyTablePtr) ctxt->keys; + table = (xsltKeyTablePtr) ctxt->document->keys; while (table != NULL) { if (xmlStrEqual(table->name, name) && (((nameURI == NULL) && (table->nameURI == NULL)) || @@ -280,12 +280,14 @@ xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name, /** * xsltInitCtxtKey: * @ctxt: an XSLT transformation context + * @doc: an XSLT document * @keyd: the key definition * * Computes the key tables this key and for the current input document. */ void -xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltKeyDefPtr keyd) { +xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc, + xsltKeyDefPtr keyd) { int i; xmlChar *pattern = NULL; xmlNodeSetPtr nodelist = NULL, keylist; @@ -312,8 +314,9 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltKeyDefPtr keyd) { xmlXPathNewParserContext(pattern, ctxt->xpathCtxt); if (xpathParserCtxt == NULL) goto error; - ctxt->node = (xmlNodePtr) ctxt->doc; - ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->doc; + ctxt->document = doc; + ctxt->node = (xmlNodePtr) doc->doc; + ctxt->xpathCtxt->node = (xmlNodePtr) doc->doc; xmlXPathEvalExpr(xpathParserCtxt); res = valuePop(xpathParserCtxt); do { @@ -382,8 +385,8 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltKeyDefPtr keyd) { } } - table->next = ctxt->keys; - ctxt->keys = table; + table->next = doc->keys; + doc->keys = table; error: if (res != NULL) @@ -396,23 +399,28 @@ error: /** * xsltInitCtxtKeys: - * @ctxt: an XSLT transformation context + * @ctxt: an XSLT transformation context + * @doc: an XSLT document * * Computes all the keys tables for the current input document. * Should be done before global varibales are initialized. */ void -xsltInitCtxtKeys(xsltTransformContextPtr ctxt) { +xsltInitCtxtKeys(xsltTransformContextPtr ctxt, xsltDocumentPtr doc) { xsltStylesheetPtr style; xsltKeyDefPtr keyd; - if (ctxt == NULL) + if ((ctxt == NULL) || (doc == NULL)) return; +#ifdef DEBUG_KEYS + xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n", + doc->doc->URL); +#endif style = ctxt->style; while (style != NULL) { keyd = (xsltKeyDefPtr) style->keys; while (keyd != NULL) { - xsltInitCtxtKey(ctxt, keyd); + xsltInitCtxtKey(ctxt, doc, keyd); keyd = keyd->next; } @@ -421,18 +429,6 @@ xsltInitCtxtKeys(xsltTransformContextPtr ctxt) { } } -/** - * xsltFreeCtxtKeys: - * @ctxt: an XSLT transformation context - * - * Free up all the space used by the key tables - */ -void -xsltFreeCtxtKeys(xsltTransformContextPtr ctxt) { - if (ctxt->keys) - xsltFreeKeyTableList((xsltKeyTablePtr) ctxt->keys); -} - /* * xsltIsKey: * @ctxt: an XSLT transformation context @@ -454,3 +450,16 @@ xsltIsKey(xsltTransformContextPtr ctxt, xmlNodePtr node) { return(1); return(0); } + +/* + * xsltFreeDocumentKeys: + * @doc: a XSLT document + * + * Free the keys associated to a document + */ +void +xsltFreeDocumentKeys(xsltDocumentPtr doc) { + if (doc != NULL) + xsltFreeKeyTableList(doc->keys); +} + diff --git a/libxslt/keys.h b/libxslt/keys.h index 8f0d7e53..1d37efb2 100644 --- a/libxslt/keys.h +++ b/libxslt/keys.h @@ -25,9 +25,11 @@ xmlNodeSetPtr xsltGetKey (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI, const xmlChar *value); -void xsltInitCtxtKeys (xsltTransformContextPtr ctxt); +void xsltInitCtxtKeys (xsltTransformContextPtr ctxt, + xsltDocumentPtr doc); void xsltFreeKeys (xsltStylesheetPtr style); -void xsltFreeCtxtKeys (xsltTransformContextPtr ctxt); +void xsltFreeDocumentKeys (xsltDocumentPtr doc); + #ifdef __cplusplus } #endif diff --git a/libxslt/templates.c b/libxslt/templates.c index 9bc20950..6e2fe6f2 100644 --- a/libxslt/templates.c +++ b/libxslt/templates.c @@ -291,7 +291,7 @@ xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target, if (xmlStrEqual(cur->name, (const xmlChar *)"use-attribute-sets")) { xmlChar *in; - in = xmlNodeListGetString(ctxt->doc, cur->children, 1); + in = xmlNodeListGetString(ctxt->document->doc, cur->children, 1); if (in != NULL) { xsltApplyAttributeSet(ctxt, ctxt->node, NULL, in); xmlFree(in); @@ -309,7 +309,8 @@ xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target, ret->ns = NULL; if (cur->children != NULL) { - xmlChar *in = xmlNodeListGetString(ctxt->doc, cur->children, 1); + xmlChar *in = xmlNodeListGetString(ctxt->document->doc, + cur->children, 1); xmlChar *out; /* TODO: optimize if no template value was detected */ diff --git a/libxslt/transform.c b/libxslt/transform.c index 27fb015e..49576d8a 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -36,6 +36,7 @@ #include "templates.h" #include "imports.h" #include "keys.h" +#include "documents.h" #define DEBUG_PROCESS @@ -60,6 +61,7 @@ /** * xsltNewTransformContext: + * @style: a parsed XSLT stylesheet * @doc: the input document * * Create a new XSLT TransformContext @@ -67,8 +69,9 @@ * Returns the newly allocated xsltTransformContextPtr or NULL in case of error */ xsltTransformContextPtr -xsltNewTransformContext(xmlDocPtr doc) { +xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) { xsltTransformContextPtr cur; + xsltDocumentPtr docu; cur = (xsltTransformContextPtr) xmlMalloc(sizeof(xsltTransformContext)); if (cur == NULL) { @@ -77,8 +80,8 @@ xsltNewTransformContext(xmlDocPtr doc) { return(NULL); } memset(cur, 0, sizeof(xsltTransformContext)); + cur->style = style; xmlXPathInit(); - cur->doc = doc; cur->xpathCtxt = xmlXPathNewContext(doc); if (cur->xpathCtxt == NULL) { xsltGenericError(xsltGenericErrorContext, @@ -87,6 +90,15 @@ xsltNewTransformContext(xmlDocPtr doc) { return(NULL); } XSLT_REGISTER_VARIABLE_LOOKUP(cur); + docu = xsltNewDocument(cur, doc); + if (docu == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsltNewTransformContext : xsltNewDocument failed\n"); + xmlFree(cur); + return(NULL); + } + docu->main = 1; + cur->document = docu; return(cur); } @@ -98,20 +110,12 @@ xsltNewTransformContext(xmlDocPtr doc) { */ void xsltFreeTransformContext(xsltTransformContextPtr ctxt) { - xmlDocPtr doc, next; - if (ctxt == NULL) return; - doc = ctxt->extraDocs; - while (doc != NULL) { - next = (xmlDocPtr) doc->next; - xmlFreeDoc(doc); - doc = next; - } if (ctxt->xpathCtxt != NULL) xmlXPathFreeContext(ctxt->xpathCtxt); xsltFreeVariableHashes(ctxt); - xsltFreeCtxtKeys(ctxt); + xsltFreeDocuments(ctxt); memset(ctxt, -1, sizeof(xsltTransformContext)); xmlFree(ctxt); } @@ -1983,11 +1987,9 @@ xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc) { if ((style == NULL) || (doc == NULL)) return(NULL); - ctxt = xsltNewTransformContext(doc); + ctxt = xsltNewTransformContext(style, doc); if (ctxt == NULL) return(NULL); - ctxt->style = style; - xsltInitCtxtKeys(ctxt); xsltEvalGlobalVariables(ctxt); if ((style->method != NULL) && (!xmlStrEqual(style->method, (const xmlChar *) "xml"))) { diff --git a/libxslt/variables.c b/libxslt/variables.c index 006e92d5..e19a0301 100644 --- a/libxslt/variables.c +++ b/libxslt/variables.c @@ -379,7 +379,7 @@ xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) { xsltGenericDebug(xsltGenericDebugContext, "Evaluating global variables\n"); #endif - ctxt->node = (xmlNodePtr) ctxt->doc; + ctxt->node = (xmlNodePtr) ctxt->document->doc; style = ctxt->style; /* TODO: handle the stylesheet cascade */ if (style != NULL) { diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h index 0989f4cb..76b9fdc0 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -158,6 +158,19 @@ struct _xsltStylesheet { }; +/* + * Data structure associated to a document + */ + +typedef struct _xsltDocument xsltDocument; +typedef xsltDocument *xsltDocumentPtr; +struct _xsltDocument { + struct _xsltDocument *next; /* documents are kept in a chained list */ + int main; /* is this the main document */ + xmlDocPtr doc; /* the parsed document */ + void *keys; /* key tables storage */ +}; + /* * The in-memory structure corresponding to an XSLT Transformation */ @@ -182,7 +195,9 @@ struct _xsltTransformContext { const xmlChar *mode; /* the current mode */ const xmlChar *modeURI; /* the current mode URI */ - xmlDocPtr doc; /* the current doc */ + xsltDocumentPtr docList; /* the document list */ + + xsltDocumentPtr document; /* the current document */ xmlNodePtr node; /* the current node */ xmlNodeSetPtr nodeList; /* the current node list */ @@ -192,8 +207,6 @@ struct _xsltTransformContext { xmlXPathContextPtr xpathCtxt; /* the XPath context */ void *variablesHash; /* hash table or wherever variables informations are stored */ - void *keys; /* key tables storage */ - xmlDocPtr extraDocs; /* extra docs parsed by document() */ xsltTransformState state; /* the current state */ };