From 90e2d014883c8ff8deffa1b72480309aa522ef13 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Fri, 12 Jan 2001 12:45:09 +0000 Subject: [PATCH] This start being interesting... - transform.c: basic processing in place - xsltInternals.h: exported one xslt.c function Daniel --- ChangeLog | 5 ++ libxslt/transform.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++- libxslt/xsltInternals.h | 1 + 3 files changed, 217 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4142397..200d7ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Fri Jan 12 13:43:30 CET 2001 Daniel Veillard + + * transform.c: basic processing in place + * xsltInternals.h: exported one xslt.c function + Thu Jan 11 21:10:59 CET 2001 Daniel Veillard * libxslt/transform.[ch] Makefile.am: started adding the diff --git a/libxslt/transform.c b/libxslt/transform.c index e0a6aca..c011281 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,15 @@ xmlChar *xmlSplitQName2(const xmlChar *name, xmlChar **prefix); "Internal error at %s:%d\n", \ __FILE__, __LINE__); +#define IS_XSLT_ELEM(n) \ + ((n)->ns != NULL) && (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE)) + +#define IS_XSLT_NAME(n, val) \ + (xmlStrEqual((n)->name, (const xmlChar *) (val))) + +#define IS_BLANK_NODE(n) \ + (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content))) + /* * Types are private: */ @@ -67,11 +77,14 @@ typedef enum xsltOutputType { typedef struct _xsltTransformContext xsltTransformContext; typedef xsltTransformContext *xsltTransformContextPtr; struct _xsltTransformContext { + xsltStylesheetPtr style; /* the stylesheet used */ xsltOutputType type; /* the type of output */ + xmlNodePtr node; /* the current node */ xmlNodeSetPtr nodeList; /* the current node list */ - xmlNodePtr output; /* output node */ + xmlDocPtr output; /* the resulting document */ + xmlNodePtr insert; /* the insertion node */ xmlXPathContextPtr xpathCtxt; /* the XPath context */ }; @@ -123,6 +136,177 @@ xsltFreeTransformContext(xsltTransformContextPtr ctxt) { * * ************************************************************************/ +void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node); + +/** + * xsltDefaultProcessOneNode: + * @ctxt: a XSLT process context + * @node: the node in the source tree. + * + * Process the source node with the default built-in template rule: + * + * + * + */ +void +xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) { + xmlNodePtr copy; + switch (node->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_ELEMENT_NODE: + break; + default: + return; + } + node = node->children; + while (node != NULL) { + switch (node->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_ELEMENT_NODE: + xsltProcessOneNode(ctxt, node); + break; + case XML_TEXT_NODE: + /* TODO: check the whitespace stripping rules ! */ + if (IS_BLANK_NODE(node)) + break; + case XML_CDATA_SECTION_NODE: + copy = xmlCopyNode(node, 0); + if (copy != NULL) { + xmlAddChild(ctxt->insert, copy); + } else { + xsltGenericError(xsltGenericErrorContext, + "xsltProcessOneNode: text copy failed\n"); + } + break; + default: + TODO + } + node = node->next; + } +} + +/** + * xsltApplyTemplates: + * @ctxt: a XSLT process context + * @node: the node in the source tree. + * @inst: the apply-templates node + * + * Process the apply-templates node on the source node + */ +void +xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node, + xmlNodePtr inst) { + xmlChar *prop; + + if ((ctxt == NULL) || (node == NULL) || (inst == NULL)) + return; + +#ifdef DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "xsltApplyTemplates: node: %s\n", node->name); +#endif + prop = xmlGetNsProp(inst, (const xmlChar *)"select", XSLT_NAMESPACE); + if (prop != NULL) { + TODO + } else { + xsltDefaultProcessOneNode(ctxt, node); + } +} + +/** + * xsltProcessOneNode: + * @ctxt: a XSLT process context + * @node: the node in the source tree. + * + * Process the source node. + */ +void +xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) { + xsltTemplatePtr template; + xmlNodePtr cur, insert, copy; + xmlNodePtr oldInsert; + + oldInsert = insert = ctxt->insert; + template = xsltGetTemplate(ctxt->style, node); + /* + * If no template is found, apply the deafult rule. + */ + if (template == NULL) { +#ifdef DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "xsltProcessOneNode: no template found for %s\n", node->name); +#endif + + xsltDefaultProcessOneNode(ctxt, node); + return; + } + + /* + * Insert all non-XSLT nodes found in the template + */ + cur = template->content; + while (cur != NULL) { + if (IS_XSLT_ELEM(cur)) { + if (IS_XSLT_NAME(cur, "apply-templates")) { + ctxt->insert = insert; + xsltApplyTemplates(ctxt, node, cur); + ctxt->insert = oldInsert; + } else { +#ifdef DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "xsltProcessOneNode: found xslt:%s\n", cur->name); +#endif + TODO + } + } else if (!(IS_BLANK_NODE(cur))) { +#ifdef DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "xsltProcessOneNode: copy %s\n", cur->name); +#endif + copy = xmlCopyNode(cur, 0); + if (copy != NULL) { + xmlAddChild(insert, copy); + } else { + xsltGenericError(xsltGenericErrorContext, + "xsltProcessOneNode: copy %s failed\n", cur->name); + return; + } + } + /* + * Skip to next node + */ + + if (cur->children != NULL) { + if (cur->children->type != XML_ENTITY_DECL) { + cur = cur->children; + insert = copy; + continue; + } + } + if (cur->next != NULL) { + cur = cur->next; + continue; + } + + do { + cur = cur->parent; + insert = insert->parent; + if (cur == NULL) + break; + if (cur == template->content) { + cur = NULL; + break; + } + if (cur->next != NULL) { + cur = cur->next; + break; + } + } while (cur != NULL); + } +} + /** * xsltApplyStylesheet: * @style: a parsed XSLT stylesheet @@ -137,12 +321,14 @@ xmlDocPtr xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc) { xmlDocPtr res = NULL; xsltTransformContextPtr ctxt = NULL; + xmlNodePtr root; if ((style == NULL) || (doc == NULL)) return(NULL); ctxt = xsltNewTransformContext(); if (ctxt == NULL) return(NULL); + ctxt->style = style; if ((style->method != NULL) && (!xmlStrEqual(style->method, (const xmlChar *) "xml"))) { if (xmlStrEqual(style->method, (const xmlChar *) "html")) { @@ -166,14 +352,35 @@ xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc) { if (res == NULL) goto error; } + res->charset = XML_CHAR_ENCODING_UTF8; if (style->encoding != NULL) - doc->encoding = xmlStrdup(style->encoding); - + res->encoding = xmlStrdup(style->encoding); /* - res->intSubset = xmlCreateIntSubset( + * Start. */ + root = xmlDocGetRootElement(doc); + if (root == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsltApplyStylesheet: document has no root\n"); + goto error; + } + ctxt->output = res; + ctxt->insert = (xmlNodePtr) res; + ctxt->node = root; + ctxt->nodeList = xmlXPathNodeSetCreate(root); + xsltProcessOneNode(ctxt, root); + + if ((ctxt->type = XSLT_OUTPUT_XML) && + ((style->doctypePublic != NULL) || + (style->doctypeSystem != NULL))) { + root = xmlDocGetRootElement(res); + if (root != NULL) + res->intSubset = xmlCreateIntSubset(res, root->name, + style->doctypePublic, style->doctypeSystem); + } + xmlXPathFreeNodeSet(ctxt->nodeList); xsltFreeTransformContext(ctxt); return(res); diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h index d698499..68dbed6 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -77,6 +77,7 @@ struct _xsltStylesheet { */ xsltStylesheetPtr xsltParseStylesheetFile (const xmlChar* filename); void xsltFreeStylesheet (xsltStylesheetPtr sheet); +int xsltIsBlank (xmlChar *str); #ifdef __cplusplus } -- 2.7.4