mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-11-08 11:02:18 +03:00
I generate a root node, I assume it's significant progress !
* libxslt/transform.[ch] Makefile.am: started adding the transformation module * pattern.[ch] xslt.c: more work... Daniel
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -8,6 +8,8 @@ libxslt_la_SOURCES = \
|
||||
xslt.h \
|
||||
pattern.c \
|
||||
pattern.h \
|
||||
transform.c \
|
||||
transform.h \
|
||||
xsltInternals.h
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ int xsltAddTemplate (xsltStylesheetPtr style,
|
||||
xsltTemplatePtr cur);
|
||||
xsltTemplatePtr xsltGetTemplate (xsltStylesheetPtr style,
|
||||
xmlNodePtr node);
|
||||
|
||||
void xsltFreeTemplateHashes (xsltStylesheetPtr style);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
187
libxslt/transform.c
Normal file
187
libxslt/transform.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
30
libxslt/transform.h
Normal file
30
libxslt/transform.h
Normal file
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user