diff --git a/ChangeLog b/ChangeLog index 599d0cf40b07f7d6590abbe215b8caf20fcc1538_Q2hhbmdlTG9n..98ddb4e13c1e61b09c4b43cf9cd6c24c49ae2ff7_Q2hhbmdlTG9n 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Fri Jan 12 13:43:30 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr> + + * transform.c: basic processing in place + * xsltInternals.h: exported one xslt.c function + Thu Jan 11 21:10:59 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr> * libxslt/transform.[ch] Makefile.am: started adding the diff --git a/libxslt/transform.c b/libxslt/transform.c index 599d0cf40b07f7d6590abbe215b8caf20fcc1538_bGlieHNsdC90cmFuc2Zvcm0uYw==..98ddb4e13c1e61b09c4b43cf9cd6c24c49ae2ff7_bGlieHNsdC90cmFuc2Zvcm0uYw== 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -19,6 +19,7 @@ #include <libxml/tree.h> #include <libxml/valid.h> #include <libxml/hash.h> +#include <libxml/encoding.h> #include <libxml/xmlerror.h> #include <libxml/xpath.h> #include <libxml/HTMLtree.h> @@ -54,6 +55,15 @@ "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,4 +77,5 @@ typedef struct _xsltTransformContext xsltTransformContext; typedef xsltTransformContext *xsltTransformContextPtr; struct _xsltTransformContext { + xsltStylesheetPtr style; /* the stylesheet used */ xsltOutputType type; /* the type of output */ @@ -70,4 +81,5 @@ xsltOutputType type; /* the type of output */ + xmlNodePtr node; /* the current node */ xmlNodeSetPtr nodeList; /* the current node list */ @@ -71,7 +83,8 @@ 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 @@ * * ************************************************************************/ +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: + * <xsl:template match="*|/"> + * <xsl:apply-templates/> + * </xsl:template> + */ +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,9 +321,10 @@ 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); @@ -140,9 +325,10 @@ 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,4 +352,5 @@ if (res == NULL) goto error; } + res->charset = XML_CHAR_ENCODING_UTF8; if (style->encoding != NULL) @@ -169,4 +356,19 @@ if (style->encoding != NULL) - doc->encoding = xmlStrdup(style->encoding); + res->encoding = xmlStrdup(style->encoding); + + /* + * 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); @@ -171,9 +373,14 @@ - /* - res->intSubset = xmlCreateIntSubset( - */ - + 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 599d0cf40b07f7d6590abbe215b8caf20fcc1538_bGlieHNsdC94c2x0SW50ZXJuYWxzLmg=..98ddb4e13c1e61b09c4b43cf9cd6c24c49ae2ff7_bGlieHNsdC94c2x0SW50ZXJuYWxzLmg= 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -77,6 +77,7 @@ */ xsltStylesheetPtr xsltParseStylesheetFile (const xmlChar* filename); void xsltFreeStylesheet (xsltStylesheetPtr sheet); +int xsltIsBlank (xmlChar *str); #ifdef __cplusplus }