I generate a root node, I assume it's significant progress !
authorDaniel Veillard <veillard@src.gnome.org>
Thu, 11 Jan 2001 20:13:26 +0000 (20:13 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Thu, 11 Jan 2001 20:13:26 +0000 (20:13 +0000)
* libxslt/transform.[ch] Makefile.am: started adding the
  transformation module
* pattern.[ch] xslt.c: more work...
Daniel

ChangeLog
libxslt/Makefile.am
libxslt/pattern.c
libxslt/pattern.h
libxslt/transform.c [new file with mode: 0644]
libxslt/transform.h [new file with mode: 0644]
libxslt/xslt.c
libxslt/xsltproc.c

index 86f5fbb..4142397 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Thu Jan 11 21:10:59 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+       * 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 <Daniel.Veillard@imag.fr>
 
        * libxslt/pattern.c: started adding xsltTestCompMatch()
index 44dc34d..91acb91 100644 (file)
@@ -8,6 +8,8 @@ libxslt_la_SOURCES =                    \
        xslt.h                          \
        pattern.c                       \
        pattern.h                       \
+       transform.c                     \
+       transform.h                     \
        xsltInternals.h
 
 
index fd79f17..b8b5ea3 100644 (file)
@@ -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);
+}
+
index 5c79c4c..0a7d143 100644 (file)
@@ -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 (file)
index 0000000..e0a6aca
--- /dev/null
@@ -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 <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/hash.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xpath.h>
+#include <libxml/HTMLtree.h>
+#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 (file)
index 0000000..1f8f9f2
--- /dev/null
@@ -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 <libxml/tree.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Interfaces
+ */
+xmlDocPtr      xsltApplyStylesheet     (xsltStylesheetPtr style,
+                                        xmlDocPtr doc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __XML_XSLT_TRANSFORM_H__ */
+
index b7e4e2c..d855f36 100644 (file)
@@ -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);
index e0690ce..eb42e72 100644 (file)
@@ -7,9 +7,12 @@
  */
 
 #include <string.h>
+#include <libxml/xmlversion.h>
 #include <libxml/xmlmemory.h>
+#include <libxml/debugXML.h>
 #include <libxslt/xslt.h>
 #include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
 
 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);