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
 }