Code done on the plane, untested Ankh sound the ideal guinea pig:
authorDaniel Veillard <veillard@src.gnome.org>
Wed, 28 Feb 2001 15:31:00 +0000 (15:31 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Wed, 28 Feb 2001 15:31:00 +0000 (15:31 +0000)
- libxslt/extra.[ch] libxslt/transform.[ch] libxslt/xsltInternals.h:
  added xsltDocumentElem implementing multiple file output,
  including 1.1 xsl:document but yet untested.
Daniel

ChangeLog
libxslt/extra.c
libxslt/extra.h
libxslt/transform.c
libxslt/transform.h
libxslt/xsltInternals.h

index 5881c57..77ac4a5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Wed Feb 28 19:24:51 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+       * libxslt/extra.[ch] libxslt/transform.[ch] libxslt/xsltInternals.h:
+         added xsltDocumentElem implementing multiple file output,
+         including 1.1 xsl:document but yet untested.
+
 Wed Feb 28 00:03:44 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
 
        * libxslt/extensions.c: fixed stoopid bug
index 4c9c9eb..3aa42d2 100644 (file)
@@ -3,7 +3,6 @@
  *
  * Reference:
  *   Michael Kay "XSLT Programmer's Reference" pp 637-643
- *   Writing Multiple Output Files
  *   The node-set() extension function
  *
  * See Copyright for the status of this software.
@@ -24,6 +23,8 @@
 #include "xsltInternals.h"
 #include "xsltutils.h"
 #include "extensions.h"
+#include "variables.h"
+#include "transform.h"
 #include "extra.h"
 
 #define DEBUG_EXTRA
@@ -95,7 +96,6 @@ xsltDebug(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst) {
  *                                                                     *
  ************************************************************************/
 
-
 /**
  * xsltFunctionNodeSet:
  * @ctxt:  the XPath Parser context
@@ -140,4 +140,10 @@ xsltRegisterExtras(xsltTransformContextPtr ctxt) {
                            XSLT_XT_NAMESPACE, xsltFunctionNodeSet);
     xsltRegisterExtElement(ctxt, (const xmlChar *) "debug",
                            XSLT_LIBXSLT_NAMESPACE, xsltDebug);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "output",
+                           XSLT_SAXON_NAMESPACE, xsltDocumentElem);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "write",
+                           XSLT_SAXON_NAMESPACE, xsltDocumentElem);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "document",
+                           XSLT_XT_NAMESPACE, xsltDocumentElem);
 }
index e14e4d5..8afae54 100644 (file)
@@ -19,6 +19,8 @@ extern "C" {
 #define XSLT_LIBXSLT_NAMESPACE ((xmlChar *) "http://xmlsoft.org/XSLT/namespace")
 #define XSLT_SAXON_NAMESPACE ((xmlChar *) "http://icl.com/saxon")
 #define XSLT_XT_NAMESPACE ((xmlChar *) "http://www.jclark.com/xt")
+#define XSLT_XALAN_NAMESPACE ((xmlChar *)      \
+                               "org.apache.xalan.xslt.extensions.Redirect")
 
 void           xsltFunctionNodeSet     (xmlXPathParserContextPtr ctxt,
                                         int nargs);
index 6e5aaf1..7417e72 100644 (file)
@@ -2,9 +2,15 @@
  * transform.c: Implemetation of the XSL Transformation 1.0 engine
  *            transform part, i.e. applying a Stylesheet to a document
  *
- * Reference:
+ * References:
  *   http://www.w3.org/TR/1999/REC-xslt-19991116
  *
+ *   Michael Kay "XSLT Programmer's Reference" pp 637-643
+ *   Writing Multiple Output Files
+ *
+ *   XSLT-1.1 Working Draft
+ *   http://www.w3.org/TR/xslt11#multiple-output
+ *
  * See Copyright for the status of this software.
  *
  * Daniel.Veillard@imag.fr
@@ -25,6 +31,7 @@
 #include <libxml/parserInternals.h>
 #include <libxml/xpathInternals.h>
 #include <libxml/HTMLtree.h>
+#include <libxml/uri.h>
 #include "xslt.h"
 #include "xsltInternals.h"
 #include "xsltutils.h"
@@ -320,9 +327,143 @@ xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr node,
     }
     return(copy);
 }
+
 /************************************************************************
  *                                                                     *
- *                     
+ *                 XSLT-1.1 extensions                                 *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltDocumentElem:
+ * @ctxt:  an XSLT processing context
+ * @node:  The current node
+ * @inst:  the instruction in the stylesheet
+ *
+ * Process an XSLT-1.1 document element
+ */
+void 
+xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                xmlNodePtr inst) {
+    xmlChar *filename = NULL;
+    xmlChar *base = NULL;
+    xmlChar *URL = NULL;
+    xsltStylesheetPtr style = NULL;
+    int ver11 = 0, ret;
+    xmlDocPtr result = NULL;
+    xmlDocPtr oldOutput;
+    xmlNodePtr oldInsert;
+
+    oldOutput = ctxt->output;
+    oldInsert = ctxt->insert;
+    if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {
+#ifdef DEBUG_EXTRA
+       xsltGenericDebug(xsltGenericDebugContext,
+           "Found saxon:output extension\n");
+#endif
+       filename = xmlGetNsProp(inst, (const xmlChar *)"file",
+                       XSLT_SAXON_NAMESPACE);
+    } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {
+#ifdef DEBUG_EXTRA
+       xsltGenericDebug(xsltGenericDebugContext,
+           "Found xalan:write extension\n");
+#endif
+       filename = xmlGetNsProp(inst, (const xmlChar *)"select",
+                       XSLT_XALAN_NAMESPACE);
+    } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {
+       filename = xmlGetNsProp(inst, (const xmlChar *)"href",
+                       XSLT_XT_NAMESPACE);
+       if (filename == NULL) {
+#ifdef DEBUG_EXTRA
+           xsltGenericDebug(xsltGenericDebugContext,
+               "Found xslt11:document construct\n");
+#endif
+           filename = xmlGetNsProp(inst, (const xmlChar *)"href",
+                           XSLT_NAMESPACE);
+           ver11 = 1;
+       } else {
+#ifdef DEBUG_EXTRA
+           xsltGenericDebug(xsltGenericDebugContext,
+               "Found xt:document extension\n");
+#endif
+           ver11 = 0;
+       }
+    }
+    if (filename == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+           "xsltDocumentElem: could not find the href\n");
+       goto error;
+    }
+    style = xsltNewStylesheet();
+    if (style == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+           "xsltDocumentElem: out of memory\n");
+       goto error;
+    }
+    if (ver11) {
+       /*
+        * Version described in 1.1 draft allows full parametrization
+        * of the output.
+        */
+       xsltParseStylesheetOutput(style, inst);
+    }
+
+    /*
+     * Create a new document tree and process the element template
+     */
+    result = xmlNewDoc(style->version);
+    if (result == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+           "xsltDocumentElem: out of memory\n");
+       goto error;
+    }
+    ctxt->output = result;
+    ctxt->insert = (xmlNodePtr) result;
+    varsPush(ctxt, NULL);
+    xsltApplyOneTemplate(ctxt, node, inst->children, 0);
+    xsltFreeStackElemList(varsPop(ctxt));
+
+    /*
+     * Save the result
+     */
+    base = xmlNodeGetBase(inst->doc, inst);
+    URL = xmlBuildURI(base, filename);
+    if (URL == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+           "xsltDocumentElem: URL computation failed %s\n", filename);
+       ret = xsltSaveResultToFilename((const char *)filename,
+                                      result, style, 0);
+    } else {
+       ret = xsltSaveResultToFilename((const char *)URL, result, style, 0);
+    }
+    if (ret < 0) {
+       xsltGenericError(xsltGenericErrorContext,
+           "xsltDocumentElem: unable to save to %s\n");
+    } else {
+#ifdef DEBUG_EXTRA
+       xsltGenericDebug(xsltGenericDebugContext,
+           "Wrote %d bytes to %s\n", ret, URL);
+#endif
+    }
+
+error:
+    ctxt->output = oldOutput;
+    ctxt->insert = oldInsert;
+    if (base != NULL)
+       xmlFree(base);
+    if (URL != NULL)
+       xmlFree(URL);
+    if (style != NULL)
+       xsltFreeStylesheet(style);
+    if (filename != NULL)
+       xmlFree(filename);
+    if (result != NULL)
+       xmlFreeDoc(result);
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Most of the XSLT-1.0 transformations                    *
  *                                                                     *
  ************************************************************************/
 
@@ -1855,6 +1996,13 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
                ctxt->insert = oldInsert;
            } else if (IS_XSLT_NAME(cur, "message")) {
                xsltMessage(ctxt, node, cur);
+           } else if (IS_XSLT_NAME(cur, "document")) {
+               /*
+                * Okay this is really added only in 1.1
+                */
+               ctxt->insert = insert;
+               xsltDocumentElem(ctxt, node, cur);
+               ctxt->insert = oldInsert;
            } else {
                xsltGenericError(xsltGenericDebugContext,
                     "xsltApplyOneTemplate: found xslt:%s\n", cur->name);
index 63afb31..bfc9e05 100644 (file)
@@ -25,6 +25,9 @@ void          xsltApplyOneTemplate    (xsltTransformContextPtr ctxt,
                                         xmlNodePtr node,
                                         xmlNodePtr list,
                                         int real);
+void           xsltDocumentElem        (xsltTransformContextPtr ctxt,
+                                        xmlNodePtr node,
+                                        xmlNodePtr inst);
 #ifdef __cplusplus
 }
 #endif
index 43bb807..ae00895 100644 (file)
@@ -246,6 +246,7 @@ typedef void (*xsltTransformFunction) (xsltTransformContextPtr ctxt,
 xsltDecimalFormatPtr   xsltDecimalFormatGetByName(xsltStylesheetPtr sheet,
                                                   xmlChar *name);
  */
+xsltStylesheetPtr      xsltNewStylesheet       (void);
 xsltStylesheetPtr      xsltParseStylesheetFile (const xmlChar* filename);
 void                   xsltFreeStylesheet      (xsltStylesheetPtr sheet);
 int                    xsltIsBlank             (xmlChar *str);
@@ -255,6 +256,8 @@ xsltDecimalFormatPtr        xsltDecimalFormatGetByName(xsltStylesheetPtr sheet,
 
 xsltStylesheetPtr      xsltParseStylesheetProcess(xsltStylesheetPtr ret,
                                                 xmlDocPtr doc);
+void                   xsltParseStylesheetOutput(xsltStylesheetPtr style,
+                                                 xmlNodePtr cur);
 xsltStylesheetPtr      xsltParseStylesheetDoc  (xmlDocPtr doc);
 #ifdef __cplusplus
 }