Skip to content
Snippets Groups Projects
Commit 63a938aeca4e authored by Daniel Veillard's avatar Daniel Veillard
Browse files

Hack, debug, read, hack, debug, read ....

- transform.c, xslt.c, xsltproc.c: lots of fixes, added
  support of xslt:if and xslt:attribute, need libxml2 interfaces
  present only in CVS.
Daniel
parent a835fc05e776
Branches
No related tags found
No related merge requests found
Mon Jan 15 15:31:41 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* transform.c, xslt.c, xsltproc.c: lots of fixes, added
support of xslt:if and xslt:attribute, need libxml2 interfaces
present only in CVS.
Sat Jan 13 23:26:21 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr> Sat Jan 13 23:26:21 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* test/Makefile.am test/REC*/Makefile.am: added first test * test/Makefile.am test/REC*/Makefile.am: added first test
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include "pattern.h" #include "pattern.h"
#include "transform.h" #include "transform.h"
/* #define DEBUG_PROCESS */ #define DEBUG_PROCESS
/* /*
* To cleanup * To cleanup
...@@ -143,6 +143,92 @@ ...@@ -143,6 +143,92 @@
void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node); void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node);
void xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node, void xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr inst); xmlNodePtr inst);
void xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst);
/**
* xsltAttribute:
* @ctxt: a XSLT process context
* @node: the node in the source tree.
* @inst: the xslt attribute node
*
* Process the xslt attribute node on the source node
*/
void
xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr inst) {
xmlChar *prop = NULL;
xmlChar *ncname = NULL;
xmlChar *prefix = NULL;
xmlChar *value = NULL;
xmlNsPtr ns = NULL;
xmlAttrPtr attr;
if (ctxt->insert == NULL)
return;
if (ctxt->insert->children != NULL) {
xsltGenericError(xsltGenericErrorContext,
"xslt:attribute : node has already children\n");
return;
}
prop = xmlGetNsProp(inst, (const xmlChar *)"namespace", XSLT_NAMESPACE);
if (prop != NULL) {
/* TODO: attribute value template */
TODO
xmlFree(prop);
return;
}
prop = xmlGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
if (prop == NULL) {
xsltGenericError(xsltGenericErrorContext,
"xslt:attribute : name is missing\n");
goto error;
}
ncname = xmlSplitQName2(prop, &prefix);
if (ncname == NULL) {
ncname = prop;
prop = NULL;
prefix = NULL;
}
if (xmlStrEqual(ncname, (const xmlChar *) "xmlns")) {
xsltGenericError(xsltGenericErrorContext,
"xslt:attribute : xmlns forbidden\n");
goto error;
}
if ((prefix != NULL) && (ns == NULL)) {
ns = xmlSearchNs(ctxt->insert->doc, ctxt->insert, prefix);
if (ns == NULL) {
xsltGenericError(xsltGenericErrorContext,
"no namespace bound to prefix %s\n", prefix);
}
}
value = xmlNodeListGetString(inst->doc, inst->children, 1);
if (value == NULL) {
if (ns)
attr = xmlSetNsProp(ctxt->insert, ncname, ns->href,
(const xmlChar *)"");
else
attr = xmlSetProp(ctxt->insert, ncname, (const xmlChar *)"");
} else {
/* TODO: attribute value template */
if (ns)
attr = xmlSetNsProp(ctxt->insert, ncname, ns->href, value);
else
attr = xmlSetProp(ctxt->insert, ncname, value);
}
error:
if (prop != NULL)
xmlFree(prop);
if (ncname != NULL)
xmlFree(ncname);
if (prefix != NULL)
xmlFree(prefix);
if (value != NULL)
xmlFree(value);
}
/** /**
* xsltValueOf: * xsltValueOf:
...@@ -469,7 +555,11 @@ ...@@ -469,7 +555,11 @@
ctxt->insert = insert; ctxt->insert = insert;
xsltValueOf(ctxt, node, cur); xsltValueOf(ctxt, node, cur);
ctxt->insert = oldInsert; ctxt->insert = oldInsert;
} else if (IS_XSLT_NAME(cur, "if")) {
ctxt->insert = insert;
xsltIf(ctxt, node, cur);
ctxt->insert = oldInsert;
} else if (IS_XSLT_NAME(cur, "for-each")) { } else if (IS_XSLT_NAME(cur, "for-each")) {
ctxt->insert = insert; ctxt->insert = insert;
xsltForEach(ctxt, node, cur); xsltForEach(ctxt, node, cur);
ctxt->insert = oldInsert; ctxt->insert = oldInsert;
...@@ -472,7 +562,11 @@ ...@@ -472,7 +562,11 @@
} else if (IS_XSLT_NAME(cur, "for-each")) { } else if (IS_XSLT_NAME(cur, "for-each")) {
ctxt->insert = insert; ctxt->insert = insert;
xsltForEach(ctxt, node, cur); xsltForEach(ctxt, node, cur);
ctxt->insert = oldInsert; ctxt->insert = oldInsert;
} else if (IS_XSLT_NAME(cur, "attribute")) {
ctxt->insert = insert;
xsltAttribute(ctxt, node, cur);
ctxt->insert = oldInsert;
} else { } else {
#ifdef DEBUG_PROCESS #ifdef DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext, xsltGenericError(xsltGenericErrorContext,
...@@ -551,6 +645,86 @@ ...@@ -551,6 +645,86 @@
} }
/** /**
* xsltIf:
* @ctxt: a XSLT process context
* @node: the node in the source tree.
* @inst: the xslt if node
*
* Process the xslt if node on the source node
*/
void
xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr inst) {
xmlChar *prop;
xmlXPathObjectPtr res, tmp;
xmlXPathParserContextPtr xpathParserCtxt;
int doit;
if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
return;
prop = xmlGetNsProp(inst, (const xmlChar *)"test", XSLT_NAMESPACE);
if (prop == NULL) {
xsltGenericError(xsltGenericErrorContext,
"xsltIf: test is not defined\n");
return;
}
#ifdef DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"xsltIf: test %s\n", prop);
#endif
if (ctxt->xpathCtxt == NULL) {
xmlXPathInit();
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
if (ctxt->xpathCtxt == NULL)
goto error;
}
xpathParserCtxt = xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
if (xpathParserCtxt == NULL)
goto error;
ctxt->xpathCtxt->node = node;
valuePush(xpathParserCtxt, xmlXPathNewNodeSet(node));
xmlXPathEvalExpr(xpathParserCtxt);
xmlXPathBooleanFunction(xpathParserCtxt, 1);
res = valuePop(xpathParserCtxt);
do {
tmp = valuePop(xpathParserCtxt);
if (tmp != NULL) {
xmlXPathFreeObject(tmp);
}
} while (tmp != NULL);
if (res != NULL) {
if (res->type == XPATH_BOOLEAN)
doit = res->boolval;
else {
#ifdef DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"xsltIf: test didn't evaluate to a boolean\n");
#endif
goto error;
}
}
#ifdef DEBUG_PROCESS
xsltGenericError(xsltGenericErrorContext,
"xsltIf: test evaluate to %d\n", doit);
#endif
if (doit) {
xsltApplyOneTemplate(ctxt, ctxt->node, inst->children);
}
error:
if (xpathParserCtxt != NULL)
xmlXPathFreeParserContext(xpathParserCtxt);
if (prop != NULL)
xmlFree(prop);
if (res != NULL)
xmlXPathFreeObject(res);
}
/**
* xsltForEach: * xsltForEach:
* @ctxt: a XSLT process context * @ctxt: a XSLT process context
* @node: the node in the source tree. * @node: the node in the source tree.
...@@ -702,7 +876,8 @@ ...@@ -702,7 +876,8 @@
goto error; goto error;
} else if (xmlStrEqual(style->method, (const xmlChar *) "text")) { } else if (xmlStrEqual(style->method, (const xmlChar *) "text")) {
ctxt->type = XSLT_OUTPUT_TEXT; ctxt->type = XSLT_OUTPUT_TEXT;
TODO res = xmlNewDoc(style->version);
if (res == NULL)
goto error; goto error;
} else { } else {
xsltGenericError(xsltGenericErrorContext, xsltGenericError(xsltGenericErrorContext,
......
...@@ -467,5 +467,5 @@ ...@@ -467,5 +467,5 @@
} }
/** /**
* xsltParseStylesheetTemplate: * xsltParseTemplateContent:
* @style: the XSLT stylesheet * @style: the XSLT stylesheet
...@@ -471,3 +471,4 @@ ...@@ -471,3 +471,4 @@
* @style: the XSLT stylesheet * @style: the XSLT stylesheet
* @template: the "template" element * @ret: the "template" structure
* @template: the container node (can be a document for literal results)
* *
...@@ -473,5 +474,7 @@ ...@@ -473,5 +474,7 @@
* *
* parse an XSLT stylesheet template building the associated structures * parse an XSLT template element content
* Clean-up the template content from unwanted ignorable blank nodes
* and process xslt:text
*/ */
void void
...@@ -475,6 +478,6 @@ ...@@ -475,6 +478,6 @@
*/ */
void void
xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) { xsltParseTemplateContent(xsltStylesheetPtr style, xsltTemplatePtr ret,
xsltTemplatePtr ret; xmlNodePtr template) {
xmlNodePtr cur, delete; xmlNodePtr cur, delete;
...@@ -480,17 +483,2 @@ ...@@ -480,17 +483,2 @@
xmlNodePtr cur, delete; xmlNodePtr cur, delete;
xmlChar *prop;
if (template == NULL)
return;
/*
* Create and link the structure
*/
ret = xsltNewTemplate();
if (ret == NULL)
return;
ret->next = style->templates;
style->templates = ret;
/* /*
...@@ -496,51 +484,4 @@ ...@@ -496,51 +484,4 @@
/* /*
* Get arguments
*/
prop = xmlGetNsProp(template, (const xmlChar *)"match", XSLT_NAMESPACE);
if (prop != NULL) {
if (ret->match != NULL) xmlFree(ret->match);
ret->match = prop;
}
prop = xmlGetNsProp(template, (const xmlChar *)"name", XSLT_NAMESPACE);
if (prop != NULL) {
xmlChar *ncname;
xmlChar *prefix = NULL;
if (ret->name != NULL) xmlFree(ret->name);
ret->name = NULL;
if (ret->nameURI != NULL) xmlFree(ret->nameURI);
ret->nameURI = NULL;
ncname = xmlSplitQName2(prop, &prefix);
if (ncname != NULL) {
if (prefix != NULL) {
xmlNsPtr ns;
ns = xmlSearchNs(cur->doc, cur, prefix);
if (ns == NULL) {
xsltGenericError(xsltGenericErrorContext,
"no namespace bound to prefix %s\n", prefix);
xmlFree(prefix);
xmlFree(ncname);
ret->name = prop;
} else {
ret->nameURI = xmlStrdup(ns->href);
ret->name = ncname;
xmlFree(prefix);
xmlFree(prop);
}
} else {
ret->name = ncname;
xmlFree(prop);
}
} else {
ret->name = prop;
}
}
/*
* Clean-up the template content from unwanted ignorable blank nodes
* This content comes from the stylesheet * This content comes from the stylesheet
* For stylesheets, the set of whitespace-preserving * For stylesheets, the set of whitespace-preserving
* element names consists of just xsl:text. * element names consists of just xsl:text.
...@@ -558,5 +499,17 @@ ...@@ -558,5 +499,17 @@
delete = NULL; delete = NULL;
} }
if (IS_XSLT_ELEM(cur)) { if (IS_XSLT_ELEM(cur)) {
if (IS_XSLT_NAME(cur, "text")) if (IS_XSLT_NAME(cur, "text")) {
if (cur->children != NULL) {
if ((cur->children->type != XML_TEXT_NODE) ||
(cur->children->next != NULL)) {
xsltGenericError(xsltGenericErrorContext,
"xsltParseStylesheetTemplate: xslt:text content problem\n");
} else {
xmlNodePtr text = cur->children;
xmlUnlinkNode(text);
xmlAddPrevSibling(cur, text);
}
}
delete = cur;
goto skip_children; goto skip_children;
...@@ -562,4 +515,5 @@ ...@@ -562,4 +515,5 @@
goto skip_children; goto skip_children;
}
} else if (cur->type == XML_TEXT_NODE) { } else if (cur->type == XML_TEXT_NODE) {
if (IS_BLANK_NODE(cur)) { if (IS_BLANK_NODE(cur)) {
delete = cur; delete = cur;
...@@ -597,6 +551,15 @@ ...@@ -597,6 +551,15 @@
} }
} while (cur != NULL); } while (cur != NULL);
} }
if (delete != NULL) {
#ifdef DEBUG_PARSING
xsltGenericError(xsltGenericErrorContext,
"xsltParseStylesheetTemplate: removing ignorable blank node\n");
#endif
xmlUnlinkNode(delete);
xmlFreeNode(delete);
delete = NULL;
}
/* /*
* Find and handle the params * Find and handle the params
...@@ -651,5 +614,31 @@ ...@@ -651,5 +614,31 @@
} }
ret->content = template->children; ret->content = template->children;
}
/**
* xsltParseStylesheetTemplate:
* @style: the XSLT stylesheet
* @template: the "template" element
*
* parse an XSLT stylesheet template building the associated structures
*/
void
xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
xsltTemplatePtr ret;
xmlChar *prop;
if (template == NULL)
return;
/*
* Create and link the structure
*/
ret = xsltNewTemplate();
if (ret == NULL)
return;
ret->next = style->templates;
style->templates = ret;
/* /*
...@@ -654,4 +643,4 @@ ...@@ -654,4 +643,4 @@
/* /*
* Register pattern * Get arguments
*/ */
...@@ -657,4 +646,51 @@ ...@@ -657,4 +646,51 @@
*/ */
prop = xmlGetNsProp(template, (const xmlChar *)"match", XSLT_NAMESPACE);
if (prop != NULL) {
if (ret->match != NULL) xmlFree(ret->match);
ret->match = prop;
}
prop = xmlGetNsProp(template, (const xmlChar *)"name", XSLT_NAMESPACE);
if (prop != NULL) {
xmlChar *ncname;
xmlChar *prefix = NULL;
if (ret->name != NULL) xmlFree(ret->name);
ret->name = NULL;
if (ret->nameURI != NULL) xmlFree(ret->nameURI);
ret->nameURI = NULL;
ncname = xmlSplitQName2(prop, &prefix);
if (ncname != NULL) {
if (prefix != NULL) {
xmlNsPtr ns;
ns = xmlSearchNs(template->doc, template, prefix);
if (ns == NULL) {
xsltGenericError(xsltGenericErrorContext,
"no namespace bound to prefix %s\n", prefix);
xmlFree(prefix);
xmlFree(ncname);
ret->name = prop;
} else {
ret->nameURI = xmlStrdup(ns->href);
ret->name = ncname;
xmlFree(prefix);
xmlFree(prop);
}
} else {
ret->name = ncname;
xmlFree(prop);
}
} else {
ret->name = prop;
}
}
/*
* parse the content and register the pattern
*/
xsltParseTemplateContent(style, ret, template);
xsltAddTemplate(style, ret); xsltAddTemplate(style, ret);
} }
...@@ -794,4 +830,7 @@ ...@@ -794,4 +830,7 @@
xsltParseStylesheetTop(ret, cur); xsltParseStylesheetTop(ret, cur);
} else { } else {
xmlChar *prop;
xsltTemplatePtr template;
/* /*
...@@ -797,3 +836,3 @@ ...@@ -797,3 +836,3 @@
/* /*
* the document itself is the template. * the document itself might be the template, check xsl:version
*/ */
...@@ -799,5 +838,13 @@ ...@@ -799,5 +838,13 @@
*/ */
prop = xmlGetNsProp(cur, (const xmlChar *)"version", XSLT_NAMESPACE);
if (prop == NULL) {
xsltGenericError(xsltGenericErrorContext,
"xsltParseStylesheetDoc : document is not a stylesheet\n");
xsltFreeStylesheet(ret);
return(NULL);
}
#ifdef DEBUG_PARSING #ifdef DEBUG_PARSING
xsltGenericError(xsltGenericErrorContext, xsltGenericError(xsltGenericErrorContext,
"xsltParseStylesheetDoc : document is stylesheet\n"); "xsltParseStylesheetDoc : document is stylesheet\n");
#endif #endif
...@@ -800,8 +847,28 @@ ...@@ -800,8 +847,28 @@
#ifdef DEBUG_PARSING #ifdef DEBUG_PARSING
xsltGenericError(xsltGenericErrorContext, xsltGenericError(xsltGenericErrorContext,
"xsltParseStylesheetDoc : document is stylesheet\n"); "xsltParseStylesheetDoc : document is stylesheet\n");
#endif #endif
TODO
/* TODO: check the version */
xmlFree(prop);
/*
* Create and link the template
*/
template = xsltNewTemplate();
if (template == NULL) {
xsltFreeStylesheet(ret);
return(NULL);
}
template->next = ret->templates;
ret->templates = template;
template->match = xmlStrdup((const xmlChar *)"/");
/*
* parse the content and register the pattern
*/
xsltParseTemplateContent(ret, template, (xmlNodePtr) doc);
xsltAddTemplate(ret, template);
} }
return(ret); return(ret);
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) { if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
cur = xsltParseStylesheetFile((const xmlChar *)argv[i]); cur = xsltParseStylesheetFile((const xmlChar *)argv[i]);
if (cur != NULL) { if (cur != NULL) {
if (cur->indent) if (cur->indent == 1)
xmlIndentTreeOutput = 1; xmlIndentTreeOutput = 1;
else else
xmlIndentTreeOutput = 0; xmlIndentTreeOutput = 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment