# HG changeset patch
# User Daniel Veillard <veillard@src.gnome.org>
# Date 979830805 0
#      Thu Jan 18 15:13:25 2001 +0000
# Node ID 2ba2d52a199b759efe1a1a9ae86f9ab52f389e48
# Parent  f5f01a9086ff7d30c31a284cc89f3c82a500ac0e
Hacking, mostly on the output support:
- libxslt/xslt.c: added support for disable-output-escaping
  will need libxml version > 20211
- libxslt/transform.c: cleanup
- libxslt/xsltutils.[ch]: added output functions
- libxslt/xsltproc.c: reuse the output function
- tests/REC2/Makefile.am tests/REC2/vrml.xml: added VRML output test
Daniel

diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Thu Jan 18 16:08:38 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+	* libxslt/xslt.c: added support for disable-output-escaping
+	  will need libxml version > 20211
+	* libxslt/transform.c: cleanup
+	* libxslt/xsltutils.[ch]: added output functions
+	* libxslt/xsltproc.c: reuse the output function
+	* tests/REC2/Makefile.am tests/REC2/vrml.xml: added VRML output
+	  test
+
 Wed Jan 17 21:03:01 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
 
 	* libxslt/transform.c libxslt/xslt.c: avoiding some problems
diff --git a/libxslt/transform.c b/libxslt/transform.c
--- a/libxslt/transform.c
+++ b/libxslt/transform.c
@@ -329,7 +329,7 @@
     } else {
 	/* TODO: attribute value template */
 	if (ns) {
-#if LIBXML_VERSION > 202111
+#if LIBXML_VERSION > 20211
 	    attr = xmlSetNsProp(ctxt->insert, ncname, ns->href, value);
 #else
 	    xsltGenericError(xsltGenericErrorContext,
@@ -773,7 +773,7 @@
 void
 xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
 	             xmlNodePtr list) {
-    xmlNodePtr cur, insert, copy, delete = NULL;
+    xmlNodePtr cur, insert, copy;
     xmlNodePtr oldInsert;
 
     oldInsert = insert = ctxt->insert;
diff --git a/libxslt/xslt.c b/libxslt/xslt.c
--- a/libxslt/xslt.c
+++ b/libxslt/xslt.c
@@ -19,6 +19,7 @@
 #include <libxml/valid.h>
 #include <libxml/hash.h>
 #include <libxml/xmlerror.h>
+#include <libxml/parserInternals.h>
 #include "xslt.h"
 #include "xsltInternals.h"
 #include "pattern.h"
@@ -481,7 +482,28 @@
 			xsltGenericError(xsltGenericErrorContext,
 	     "xsltParseStylesheetTemplate: xslt:text content problem\n");
 		    } else {
+			xmlChar *prop;
 			xmlNodePtr text = cur->children;
+			
+			prop = xmlGetNsProp(cur,
+				(const xmlChar *)"disable-output-escaping",
+				            XSLT_NAMESPACE);
+			if (prop != NULL) {
+			    if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
+#if LIBXML_VERSION > 20211
+				text->name = xmlStringTextNoenc;
+#else
+				xsltGenericError(xsltGenericErrorContext,
+"xsl:text disable-output-escaping need newer > 20211 libxml version\n");
+#endif
+			    } else if (!xmlStrEqual(prop,
+					            (const xmlChar *)"no")){
+				xsltGenericError(xsltGenericErrorContext,
+		 "xslt:text: disable-output-escaping allow only yes or no\n");
+
+			    }
+			    xmlFree(prop);
+			}
 			xmlUnlinkNode(text);
 			xmlAddPrevSibling(cur, text);
 		    }
diff --git a/libxslt/xsltproc.c b/libxslt/xsltproc.c
--- a/libxslt/xsltproc.c
+++ b/libxslt/xsltproc.c
@@ -10,12 +10,14 @@
 #include <libxml/xmlversion.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/debugXML.h>
+#include <libxml/HTMLtree.h>
 #include <libxslt/xslt.h>
 #include <libxslt/xsltInternals.h>
 #include <libxslt/transform.h>
 #include <libxslt/xsltutils.h>
 
 static int debug = 0;
+static int repeat = 0;
 
 int
 main(int argc, char **argv) {
@@ -23,6 +25,7 @@
     xsltStylesheetPtr cur;
     xmlDocPtr doc, res;
 
+    /* --repeat : repeat 100 times, for timing or profiling */
     LIBXML_TEST_VERSION
     for (i = 1; i < argc ; i++) {
 	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
@@ -31,6 +34,9 @@
 		   (!strcmp(argv[i], "-verbose")) ||
 		   (!strcmp(argv[i], "--verbose"))) {
 	    xsltSetGenericDebugFunc(stderr, NULL);
+	} else if ((!strcmp(argv[i], "-repeat")) ||
+		   (!strcmp(argv[i], "--repeat"))) {
+	    repeat++;
 	}
     }
     xmlSubstituteEntitiesDefault(1);
@@ -53,18 +59,29 @@
 	    fprintf(stderr, "unable to parse %s\n", argv[i]);
 	    continue;
 	}
+	if (repeat) {
+	    int j;
+	    for (j = 0;j < 99; j++) {
+		res = xsltApplyStylesheet(cur, doc);
+		xmlFreeDoc(res);
+		xmlFreeDoc(doc);
+		doc = xmlParseFile(argv[i]);
+	    }
+	}
 	res = xsltApplyStylesheet(cur, doc);
 	xmlFreeDoc(doc);
 	if (res == NULL) {
 	    fprintf(stderr, "no result for %s\n", argv[i]);
 	    continue;
 	}
+	if (cur->methodURI == NULL) {
 #ifdef LIBXML_DEBUG_ENABLED
-	if (debug)
-            xmlDebugDumpDocument(stdout, res);
-	else
+	    if (debug)
+		xmlDebugDumpDocument(stdout, res);
+	    else
 #endif
-	    xmlDocDump(stdout, res);
+		xsltSaveResultToFile(stdout, res, cur);
+	}
 
 	xmlFreeDoc(res);
     }
diff --git a/libxslt/xsltutils.c b/libxslt/xsltutils.c
--- a/libxslt/xsltutils.c
+++ b/libxslt/xsltutils.c
@@ -17,7 +17,9 @@
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
 #include <libxml/xmlerror.h>
+#include <libxml/xmlIO.h>
 #include "xsltutils.h"
+#include "xsltInternals.h"
 
 
 /************************************************************************
@@ -174,3 +176,181 @@
 	}
     }
 }
+
+/************************************************************************
+ * 									*
+ * 				Output					*
+ * 									*
+ ************************************************************************/
+
+/**
+ * xsltSaveResultTo:
+ * @buf:  an output buffer
+ * @result:  the result xmlDocPtr
+ * @style:  the stylesheet
+ *
+ * Save the result @result obtained by applying the @style stylesheet
+ * to an I/O output channel @buf
+ *
+ * Returns the number of byte written or -1 in case of failure.
+ */
+int
+xsltSaveResultTo(xmlOutputBufferPtr buf, xmlDocPtr result,
+	       xsltStylesheetPtr style) {
+    const xmlChar *encoding;
+    int base;
+
+    if ((buf == NULL) || (result == NULL) || (style == NULL))
+	return(-1);
+
+    if (style->methodURI != NULL) {
+        xsltGenericError(xsltGenericErrorContext,
+		"xsltSaveResultTo : unknown ouput method\n");
+        return(-1);
+    }
+
+    /* TODO: when outputing and having imported stylesheets, apply cascade */
+    base = buf->written;
+    encoding = style->encoding;
+    if (xmlStrEqual(style->method, (const xmlChar *) "html")) {
+	TODO /* HTML dump ... */
+    } else if (xmlStrEqual(style->method, (const xmlChar *) "text")) {
+	xmlNodePtr cur;
+
+	cur = result->children;
+	while (cur != NULL) {
+	    if (cur->type == XML_TEXT_NODE)
+		xmlOutputBufferWriteString(buf, (const char *) cur->content);
+	    cur = cur->next;
+	}
+    } else {
+	if (style->omitXmlDeclaration != 1) {
+	    xmlOutputBufferWriteString(buf, "<?xml version=");
+	    if (result->version != NULL) 
+		xmlBufferWriteQuotedString(buf->buffer, result->version);
+	    else
+		xmlOutputBufferWriteString(buf, "\"1.0\"");
+	    if (encoding == NULL) {
+		if (result->encoding != NULL)
+		    encoding = result->encoding;
+		else if (result->charset != XML_CHAR_ENCODING_UTF8)
+		    encoding = (const xmlChar *)
+			       xmlGetCharEncodingName((xmlCharEncoding)
+			                              result->charset);
+	    }
+	    if (encoding != NULL) {
+		xmlOutputBufferWriteString(buf, " encoding=");
+		xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
+	    }
+	    switch (style->standalone) {
+		case 0:
+		    xmlOutputBufferWriteString(buf, " standalone=\"no\"");
+		    break;
+		case 1:
+		    xmlOutputBufferWriteString(buf, " standalone=\"yes\"");
+		    break;
+		default:
+		    break;
+	    }
+	    xmlOutputBufferWriteString(buf, "?>\n");
+	}
+	if (result->children != NULL) {
+	    xmlNodePtr child = result->children;
+
+	    while (child != NULL) {
+		xmlNodeDumpOutput(buf, result, child, 0, style->indent,
+			          (const char *) encoding);
+		xmlOutputBufferWriteString(buf, "\n");
+		child = child->next;
+	    }
+	}
+	xmlOutputBufferFlush(buf);
+    }
+    return(buf->written - base);
+}
+
+/**
+ * xsltSaveResultToFilename:
+ * @URL:  a filename or URL
+ * @result:  the result xmlDocPtr
+ * @style:  the stylesheet
+ * @compression:  the compression factor (0 - 9 included)
+ *
+ * Save the result @result obtained by applying the @style stylesheet
+ * to a file or URL @URL
+ *
+ * Returns the number of byte written or -1 in case of failure.
+ */
+int
+xsltSaveResultToFilename(const char *URL, xmlDocPtr result,
+			 xsltStylesheetPtr style, int compression) {
+    xmlOutputBufferPtr buf;
+    int ret;
+
+    if ((URL == NULL) || (result == NULL) || (style == NULL))
+	return(-1);
+
+    buf = xmlOutputBufferCreateFilename(URL, NULL, compression);
+    if (buf == NULL)
+	return(-1);
+    xsltSaveResultTo(buf, result, style);
+    ret = xmlOutputBufferClose(buf);
+    return(ret);
+}
+
+/**
+ * xsltSaveResultToFile:
+ * @file:  a FILE * I/O
+ * @result:  the result xmlDocPtr
+ * @style:  the stylesheet
+ *
+ * Save the result @result obtained by applying the @style stylesheet
+ * to an open FILE * I/O.
+ * This does not close the FILE @file
+ *
+ * Returns the number of byte written or -1 in case of failure.
+ */
+int
+xsltSaveResultToFile(FILE *file, xmlDocPtr result, xsltStylesheetPtr style) {
+    xmlOutputBufferPtr buf;
+    int ret;
+
+    if ((file == NULL) || (result == NULL) || (style == NULL))
+	return(-1);
+
+    buf = xmlOutputBufferCreateFile(file, NULL);
+    if (buf == NULL)
+	return(-1);
+    xsltSaveResultTo(buf, result, style);
+    ret = xmlOutputBufferClose(buf);
+    return(ret);
+}
+
+/**
+ * xsltSaveResultToFd:
+ * @fd:  a file descriptor
+ * @result:  the result xmlDocPtr
+ * @style:  the stylesheet
+ *
+ * Save the result @result obtained by applying the @style stylesheet
+ * to an open file descriptor
+ * This does not close the descriptor.
+ *
+ * Returns the number of byte written or -1 in case of failure.
+ */
+int
+xsltSaveResultToFd(int fd, xmlDocPtr result, xsltStylesheetPtr style) {
+    xmlOutputBufferPtr buf;
+    int ret;
+
+    if ((fd < 0) || (result == NULL) || (style == NULL))
+	return(-1);
+
+    buf = xmlOutputBufferCreateFd(fd, NULL);
+    if (buf == NULL)
+	return(-1);
+    xsltSaveResultTo(buf, result, style);
+    ret = xmlOutputBufferClose(buf);
+    return(ret);
+}
+
diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h
--- a/libxslt/xsltutils.h
+++ b/libxslt/xsltutils.h
@@ -11,6 +11,7 @@
 
 #include <libxml/xpath.h>
 #include <libxml/xmlerror.h>
+#include "xsltInternals.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -65,6 +66,22 @@
 						 xmlXPathObjectPtr *results,
 						 int descending,
 						 int number);
+/*
+ * Output, reuse libxml I/O buffers
+ */
+int		xsltSaveResultTo		(xmlOutputBufferPtr buf,
+						 xmlDocPtr result,
+						 xsltStylesheetPtr style);
+int		xsltSaveResultToFilename	(const char *URI,
+						 xmlDocPtr result,
+						 xsltStylesheetPtr style,
+						 int compression);
+int		xsltSaveResultToFile		(FILE *file,
+						 xmlDocPtr result,
+						 xsltStylesheetPtr style);
+int		xsltSaveResultToFd		(int fd,
+						 xmlDocPtr result,
+						 xsltStylesheetPtr style);
 #ifdef __cplusplus
 }
 #endif
diff --git a/tests/REC2/Makefile.am b/tests/REC2/Makefile.am
--- a/tests/REC2/Makefile.am
+++ b/tests/REC2/Makefile.am
@@ -5,8 +5,8 @@
 
 test: $(top_builddir)/libxslt/xsltproc
 	@(rm -f .memdump ; touch .memdump)
-	@($(top_builddir)/libxslt/xsltproc doc.xsl doc.xml > doc.res ; \
-	diff result.xml doc.res ; \
+	@($(top_builddir)/libxslt/xsltproc vrml.xsl data.xml > vrml.res ; \
+	diff vrml.xml vrml.res ; \
 	grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	rm -f doc.res)
 
diff --git a/tests/REC2/vrml.xml b/tests/REC2/vrml.xml
--- a/tests/REC2/vrml.xml
+++ b/tests/REC2/vrml.xml
@@ -35,3 +35,4 @@
         z 2
         name "West" 
         }
+                
\ No newline at end of file