+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()
xslt.h \
pattern.c \
pattern.h \
+ transform.c \
+ transform.h \
xsltInternals.h
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;
*/
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);
}
pat = xsltCompilePattern(cur->match);
if (pat == NULL)
return(-1);
+ pat->template = cur;
if (cur->priority != XSLT_PAT_NO_PRIORITY)
pat->priority = cur->priority;
*/
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;
*/
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);
+}
+
xsltTemplatePtr cur);
xsltTemplatePtr xsltGetTemplate (xsltStylesheetPtr style,
xmlNodePtr node);
-
+void xsltFreeTemplateHashes (xsltStylesheetPtr style);
#ifdef __cplusplus
}
#endif
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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__ */
+
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);
}
xsltFreeStylesheet(xsltStylesheetPtr sheet) {
if (sheet == NULL)
return;
+
+ xsltFreeTemplateHashes(sheet);
xsltFreeTemplateList(sheet->templates);
if (sheet->doc != NULL)
xmlFreeDoc(sheet->doc);
*/
#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;
main(int argc, char **argv) {
int i;
xsltStylesheetPtr cur;
+ xmlDocPtr doc, res;
LIBXML_TEST_VERSION
for (i = 1; i < argc ; i++) {
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);