From 2d430b16ee34615faa63f2e1e75bc37b791e46b0 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Thu, 11 Jan 2001 20:13:26 +0000 Subject: [PATCH] I generate a root node, I assume it's significant progress ! * libxslt/transform.[ch] Makefile.am: started adding the transformation module * pattern.[ch] xslt.c: more work... Daniel --- ChangeLog | 6 ++ libxslt/Makefile.am | 2 + libxslt/pattern.c | 93 +++++++++++++++++++++++++- libxslt/pattern.h | 2 +- libxslt/transform.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++ libxslt/transform.h | 30 +++++++++ libxslt/xslt.c | 7 ++ libxslt/xsltproc.c | 31 ++++++++- 8 files changed, 353 insertions(+), 5 deletions(-) create mode 100644 libxslt/transform.c create mode 100644 libxslt/transform.h diff --git a/ChangeLog b/ChangeLog index 86f5fbb..4142397 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Thu Jan 11 21:10:59 CET 2001 Daniel Veillard + + * libxslt/transform.[ch] Makefile.am: started adding the + transformation module + * pattern.[ch] xslt.c: more work... + Thu Jan 11 14:02:03 CET 2001 Daniel Veillard * libxslt/pattern.c: started adding xsltTestCompMatch() diff --git a/libxslt/Makefile.am b/libxslt/Makefile.am index 44dc34d..91acb91 100644 --- a/libxslt/Makefile.am +++ b/libxslt/Makefile.am @@ -8,6 +8,8 @@ libxslt_la_SOURCES = \ xslt.h \ pattern.c \ pattern.h \ + transform.c \ + transform.h \ xsltInternals.h diff --git a/libxslt/pattern.c b/libxslt/pattern.c index fd79f17..b8b5ea3 100644 --- a/libxslt/pattern.c +++ b/libxslt/pattern.c @@ -73,6 +73,7 @@ typedef xsltCompMatch *xsltCompMatchPtr; struct _xsltCompMatch { struct _xsltCompMatch *next; /* siblings in the name hash */ int priority; /* the priority */ + xsltTemplatePtr template; /* the associated template */ /* TODO fix the statically allocated size */ int nbStep; @@ -125,8 +126,18 @@ xsltNewCompMatch(void) { */ void xsltFreeCompMatch(xsltCompMatchPtr comp) { + xsltStepOpPtr op; + int i; + if (comp == NULL) return; + for (i = 0;i < comp->nbStep;i++) { + op = &comp->steps[i]; + if (op->value != NULL) + xmlFree(op->value); + if (op->value2 != NULL) + xmlFree(op->value2); + } memset(comp, -1, sizeof(xsltCompMatch)); xmlFree(comp); } @@ -680,6 +691,7 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) { pat = xsltCompilePattern(cur->match); if (pat == NULL) return(-1); + pat->template = cur; if (cur->priority != XSLT_PAT_NO_PRIORITY) pat->priority = cur->priority; @@ -746,14 +758,14 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) { */ if (list->priority <= pat->priority) { pat->next = list; - xmlHashAddEntry(style->templatesHash, name, pat); + xmlHashUpdateEntry(style->templatesHash, name, pat, NULL); #ifdef DEBUG_PARSING xsltGenericError(xsltGenericErrorContext, "xsltAddTemplate: added head hash for %s\n", name); #endif } else { while (list->next != NULL) { - if (list->next->priority < pat->priority) + if (list->next->priority <= pat->priority) break; } pat->next = list->next; @@ -775,6 +787,83 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) { */ xsltTemplatePtr xsltGetTemplate(xsltStylesheetPtr style, xmlNodePtr node) { + const xmlChar *name; + xsltCompMatchPtr list; + + if ((style == NULL) || (node == NULL)) + return(NULL); + + /* TODO : handle IDs/keys here ! */ + if (style->templatesHash == NULL) + return(NULL); + + /* + * Use a name as selector + */ + switch (node->type) { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + case XML_PI_NODE: + name = node->name; + break; + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + name = (const xmlChar *)"/"; + break; + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_COMMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + return(NULL); + default: + return(NULL); + + } + if (name == NULL) + return(NULL); + + /* + * find the list of appliable expressions based on the name + */ + list = (xsltCompMatchPtr) xmlHashLookup(style->templatesHash, name); + if (list == NULL) { +#ifdef DEBUG_MATCHING + xsltGenericError(xsltGenericErrorContext, + "xsltGetTemplate: empty set for %s\n", name); +#endif + return(NULL); + } + while (list != NULL) { + if (xsltTestCompMatch(list, node)) + return(list->template); + list = list->next; + } + return(NULL); } + +/** + * xsltFreeTemplateHashes: + * @style: an XSLT stylesheet + * + * Free up the memory used by xsltAddTemplate/xsltGetTemplate mechanism + */ +void +xsltFreeTemplateHashes(xsltStylesheetPtr style) { + if (style->templatesHash != NULL) + xmlHashFree((xmlHashTablePtr) style->templatesHash, + (xmlHashDeallocator) xsltFreeCompMatchList); +} + diff --git a/libxslt/pattern.h b/libxslt/pattern.h index 5c79c4c..0a7d143 100644 --- a/libxslt/pattern.h +++ b/libxslt/pattern.h @@ -19,7 +19,7 @@ int xsltAddTemplate (xsltStylesheetPtr style, xsltTemplatePtr cur); xsltTemplatePtr xsltGetTemplate (xsltStylesheetPtr style, xmlNodePtr node); - +void xsltFreeTemplateHashes (xsltStylesheetPtr style); #ifdef __cplusplus } #endif diff --git a/libxslt/transform.c b/libxslt/transform.c new file mode 100644 index 0000000..e0a6aca --- /dev/null +++ b/libxslt/transform.c @@ -0,0 +1,187 @@ +/* + * transform.c: Implemetation of the XSL Transformation 1.0 engine + * transform part, i.e. applying a Stylesheet to a document + * + * Reference: + * http://www.w3.org/TR/1999/REC-xslt-19991116 + * + * See Copyright for the status of this software. + * + * Daniel.Veillard@imag.fr + */ + +#include "xsltconfig.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "xslt.h" +#include "xsltInternals.h" +#include "pattern.h" +#include "transform.h" + +#define DEBUG_PROCESS + +/* + * To cleanup + */ +xmlChar *xmlSplitQName2(const xmlChar *name, xmlChar **prefix); + +/* + * There is no XSLT specific error reporting module yet + */ +#define xsltGenericError xmlGenericError +#define xsltGenericErrorContext xmlGenericErrorContext + +/* + * Useful macros + */ + +#define TODO \ + xsltGenericError(xsltGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +#define STRANGE \ + xsltGenericError(xsltGenericErrorContext, \ + "Internal error at %s:%d\n", \ + __FILE__, __LINE__); + +/* + * Types are private: + */ + +typedef enum xsltOutputType { + XSLT_OUTPUT_XML = 0, + XSLT_OUTPUT_HTML, + XSLT_OUTPUT_TEXT +} xsltOutputType; + +typedef struct _xsltTransformContext xsltTransformContext; +typedef xsltTransformContext *xsltTransformContextPtr; +struct _xsltTransformContext { + xsltOutputType type; /* the type of output */ + xmlNodePtr node; /* the current node */ + xmlNodeSetPtr nodeList; /* the current node list */ + + xmlNodePtr output; /* output node */ + + xmlXPathContextPtr xpathCtxt; /* the XPath context */ +}; + +/************************************************************************ + * * + * + * * + ************************************************************************/ + +/** + * xsltNewTransformContext: + * + * Create a new XSLT TransformContext + * + * Returns the newly allocated xsltTransformContextPtr or NULL in case of error + */ +xsltTransformContextPtr +xsltNewTransformContext(void) { + xsltTransformContextPtr cur; + + cur = (xsltTransformContextPtr) xmlMalloc(sizeof(xsltTransformContext)); + if (cur == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsltNewTransformContext : malloc failed\n"); + return(NULL); + } + memset(cur, 0, sizeof(xsltTransformContext)); + return(cur); +} + +/** + * xsltFreeTransformContext: + * @ctxt: an XSLT parser context + * + * Free up the memory allocated by @ctxt + */ +void +xsltFreeTransformContext(xsltTransformContextPtr ctxt) { + if (ctxt == NULL) + return; + memset(ctxt, -1, sizeof(xsltTransformContext)); + xmlFree(ctxt); +} + +/************************************************************************ + * * + * + * * + ************************************************************************/ + +/** + * xsltApplyStylesheet: + * @style: a parsed XSLT stylesheet + * @doc: a parsed XML document + * + * Apply the stylesheet to the document + * NOTE: This may lead to a non-wellformed output XML wise ! + * + * Returns the result document or NULL in case of error + */ +xmlDocPtr +xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc) { + xmlDocPtr res = NULL; + xsltTransformContextPtr ctxt = NULL; + + if ((style == NULL) || (doc == NULL)) + return(NULL); + ctxt = xsltNewTransformContext(); + if (ctxt == NULL) + return(NULL); + if ((style->method != NULL) && + (!xmlStrEqual(style->method, (const xmlChar *) "xml"))) { + if (xmlStrEqual(style->method, (const xmlChar *) "html")) { + ctxt->type = XSLT_OUTPUT_HTML; + res = htmlNewDoc(style->doctypePublic, style->doctypeSystem); + if (res == NULL) + goto error; + } else if (xmlStrEqual(style->method, (const xmlChar *) "text")) { + ctxt->type = XSLT_OUTPUT_TEXT; + TODO + goto error; + } else { + xsltGenericError(xsltGenericErrorContext, + "xsltApplyStylesheet: insupported method %s\n", + style->method); + goto error; + } + } else { + ctxt->type = XSLT_OUTPUT_XML; + res = xmlNewDoc(style->version); + if (res == NULL) + goto error; + } + if (style->encoding != NULL) + doc->encoding = xmlStrdup(style->encoding); + + + /* + res->intSubset = xmlCreateIntSubset( + */ + + xsltFreeTransformContext(ctxt); + return(res); + +error: + if (res != NULL) + xmlFreeDoc(res); + if (ctxt != NULL) + xsltFreeTransformContext(ctxt); + return(NULL); +} + diff --git a/libxslt/transform.h b/libxslt/transform.h new file mode 100644 index 0000000..1f8f9f2 --- /dev/null +++ b/libxslt/transform.h @@ -0,0 +1,30 @@ +/* + * transform.h: Interfaces, constants and types related to the XSLT engine + * transform part. + * + * See Copyright for the status of this software. + * + * Daniel.Veillard@imag.fr + */ + +#ifndef __XML_XSLT_TRANSFORM_H__ +#define __XML_XSLT_TRANSFORM_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Interfaces + */ +xmlDocPtr xsltApplyStylesheet (xsltStylesheetPtr style, + xmlDocPtr doc); + +#ifdef __cplusplus +} +#endif + +#endif /* __XML_XSLT_TRANSFORM_H__ */ + diff --git a/libxslt/xslt.c b/libxslt/xslt.c index b7e4e2c..d855f36 100644 --- a/libxslt/xslt.c +++ b/libxslt/xslt.c @@ -123,6 +123,11 @@ void xsltFreeTemplate(xsltTemplatePtr template) { if (template == NULL) return; + if (template->match) xmlFree(template->match); + if (template->name) xmlFree(template->name); + if (template->nameURI) xmlFree(template->nameURI); + if (template->mode) xmlFree(template->mode); + if (template->modeURI) xmlFree(template->modeURI); memset(template, -1, sizeof(xsltTemplate)); xmlFree(template); } @@ -178,6 +183,8 @@ void xsltFreeStylesheet(xsltStylesheetPtr sheet) { if (sheet == NULL) return; + + xsltFreeTemplateHashes(sheet); xsltFreeTemplateList(sheet->templates); if (sheet->doc != NULL) xmlFreeDoc(sheet->doc); diff --git a/libxslt/xsltproc.c b/libxslt/xsltproc.c index e0690ce..eb42e72 100644 --- a/libxslt/xsltproc.c +++ b/libxslt/xsltproc.c @@ -7,9 +7,12 @@ */ #include +#include #include +#include #include #include +#include static int debug = 0; @@ -17,6 +20,7 @@ int main(int argc, char **argv) { int i; xsltStylesheetPtr cur; + xmlDocPtr doc, res; LIBXML_TEST_VERSION for (i = 1; i < argc ; i++) { @@ -26,11 +30,34 @@ main(int argc, char **argv) { xmlSubstituteEntitiesDefault(1); for (i = 1; i < argc ; i++) { if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) { - cur = xsltParseStylesheetFile(argv[i]); - xsltFreeStylesheet(cur); + cur = xsltParseStylesheetFile((const xmlChar *)argv[i]); + i++; break; } } + for (;i < argc ; i++) { + doc = xmlParseFile(argv[i]); + if (doc == NULL) { + fprintf(stderr, "unable to parse %s\n", argv[i]); + continue; + } + res = xsltApplyStylesheet(cur, doc); + xmlFreeDoc(doc); + if (res == NULL) { + fprintf(stderr, "no result for %s\n", argv[i]); + continue; + } +#ifdef LIBXML_DEBUG_ENABLED + if (debug) + xmlDebugDumpDocument(stdout, res); + else +#endif + xmlDocDump(stdout, res); + + xmlFreeDoc(res); + } + if (cur != NULL) + xsltFreeStylesheet(cur); xmlCleanupParser(); xmlMemoryDump(); return(0); -- 2.7.4