mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-11-08 11:02:18 +03:00
More general work, added for-each:
- test/Makefile.am test/REC*/Makefile.am: added first test - libxslt/pattern.c libxslt/transform.c libxslt/xslt.c: cleanup of nodes at reading of stylesheet, added support for xsl:for-each and fixed a few recursion bugs Daniel
This commit is contained in:
@@ -1,3 +1,10 @@
|
|||||||
|
Sat Jan 13 23:26:21 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
|
* test/Makefile.am test/REC*/Makefile.am: added first test
|
||||||
|
* libxslt/pattern.c libxslt/transform.c libxslt/xslt.c:
|
||||||
|
cleanup of nodes at reading of stylesheet, added support
|
||||||
|
for xsl:for-each and fixed a few recursion bugs
|
||||||
|
|
||||||
Fri Jan 12 22:33:07 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
Fri Jan 12 22:33:07 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
* pattern.c, xslt.c: removed debug
|
* pattern.c, xslt.c: removed debug
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ xsltConf.sh: xsltConf.sh.in Makefile
|
|||||||
< $(srcdir)/xsltConf.sh.in > xsltConf.tmp \
|
< $(srcdir)/xsltConf.sh.in > xsltConf.tmp \
|
||||||
&& mv xsltConf.tmp xsltConf.sh
|
&& mv xsltConf.tmp xsltConf.sh
|
||||||
|
|
||||||
|
test:
|
||||||
|
@(cd tests ; make test)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -120,5 +120,7 @@ Makefile
|
|||||||
libxslt/Makefile
|
libxslt/Makefile
|
||||||
libxslt/xsltconfig.h
|
libxslt/xsltconfig.h
|
||||||
tests/Makefile
|
tests/Makefile
|
||||||
|
tests/REC1/Makefile
|
||||||
|
tests/REC2/Makefile
|
||||||
xslt-config
|
xslt-config
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -571,8 +571,8 @@ xsltCompileLocationPathPattern(xsltParserContextPtr ctxt) {
|
|||||||
NEXT;
|
NEXT;
|
||||||
SKIP_BLANKS;
|
SKIP_BLANKS;
|
||||||
PUSH(XSLT_OP_ROOT, NULL, NULL);
|
PUSH(XSLT_OP_ROOT, NULL, NULL);
|
||||||
PUSH(XSLT_OP_PARENT, NULL, NULL);
|
|
||||||
if ((CUR != 0) || (CUR == '|')) {
|
if ((CUR != 0) || (CUR == '|')) {
|
||||||
|
PUSH(XSLT_OP_PARENT, NULL, NULL);
|
||||||
xsltCompileRelativePathPattern(ctxt, NULL);
|
xsltCompileRelativePathPattern(ctxt, NULL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ struct _xsltTransformContext {
|
|||||||
xmlNodePtr insert; /* the insertion node */
|
xmlNodePtr insert; /* the insertion node */
|
||||||
|
|
||||||
xmlXPathContextPtr xpathCtxt; /* the XPath context */
|
xmlXPathContextPtr xpathCtxt; /* the XPath context */
|
||||||
xmlXPathParserContextPtr xpathParserCtxt;/* the XPath parser context */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -142,6 +141,8 @@ xsltFreeTransformContext(xsltTransformContextPtr ctxt) {
|
|||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node);
|
void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node);
|
||||||
|
void xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
||||||
|
xmlNodePtr inst);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltValueOf:
|
* xsltValueOf:
|
||||||
@@ -157,6 +158,7 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
xmlChar *prop;
|
xmlChar *prop;
|
||||||
int disableEscaping = 0;
|
int disableEscaping = 0;
|
||||||
xmlXPathObjectPtr res, tmp;
|
xmlXPathObjectPtr res, tmp;
|
||||||
|
xmlXPathParserContextPtr xpathParserCtxt;
|
||||||
xmlNodePtr copy = NULL;
|
xmlNodePtr copy = NULL;
|
||||||
|
|
||||||
if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
|
if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
|
||||||
@@ -181,7 +183,7 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
prop = xmlGetNsProp(inst, (const xmlChar *)"select", XSLT_NAMESPACE);
|
prop = xmlGetNsProp(inst, (const xmlChar *)"select", XSLT_NAMESPACE);
|
||||||
if (prop == NULL) {
|
if (prop == NULL) {
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsltValueOf: select is not defined\n", prop);
|
"xsltValueOf: select is not defined\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_PROCESS
|
#ifdef DEBUG_PROCESS
|
||||||
@@ -195,17 +197,17 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
if (ctxt->xpathCtxt == NULL)
|
if (ctxt->xpathCtxt == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
ctxt->xpathParserCtxt =
|
xpathParserCtxt =
|
||||||
xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
|
xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
|
||||||
if (ctxt->xpathParserCtxt == NULL)
|
if (xpathParserCtxt == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
ctxt->xpathCtxt->node = node;
|
ctxt->xpathCtxt->node = node;
|
||||||
valuePush(ctxt->xpathParserCtxt, xmlXPathNewNodeSet(node));
|
valuePush(xpathParserCtxt, xmlXPathNewNodeSet(node));
|
||||||
xmlXPathEvalExpr(ctxt->xpathParserCtxt);
|
xmlXPathEvalExpr(xpathParserCtxt);
|
||||||
xmlXPathStringFunction(ctxt->xpathParserCtxt, 1);
|
xmlXPathStringFunction(xpathParserCtxt, 1);
|
||||||
res = valuePop(ctxt->xpathParserCtxt);
|
res = valuePop(xpathParserCtxt);
|
||||||
do {
|
do {
|
||||||
tmp = valuePop(ctxt->xpathParserCtxt);
|
tmp = valuePop(xpathParserCtxt);
|
||||||
if (tmp != NULL) {
|
if (tmp != NULL) {
|
||||||
xmlXPathFreeObject(tmp);
|
xmlXPathFreeObject(tmp);
|
||||||
}
|
}
|
||||||
@@ -228,8 +230,10 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
"xsltValueOf: result %s\n", res->stringval);
|
"xsltValueOf: result %s\n", res->stringval);
|
||||||
#endif
|
#endif
|
||||||
error:
|
error:
|
||||||
if (ctxt->xpathParserCtxt != NULL)
|
if (xpathParserCtxt != NULL) {
|
||||||
xmlXPathFreeParserContext(ctxt->xpathParserCtxt);
|
xmlXPathFreeParserContext(xpathParserCtxt);
|
||||||
|
xpathParserCtxt = NULL;
|
||||||
|
}
|
||||||
if (prop != NULL)
|
if (prop != NULL)
|
||||||
xmlFree(prop);
|
xmlFree(prop);
|
||||||
if (res != NULL)
|
if (res != NULL)
|
||||||
@@ -253,6 +257,7 @@ xsltCopyNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
xmlNodePtr copy;
|
xmlNodePtr copy;
|
||||||
|
|
||||||
copy = xmlCopyNode(node, 0);
|
copy = xmlCopyNode(node, 0);
|
||||||
|
copy->doc = ctxt->output;
|
||||||
if (copy != NULL) {
|
if (copy != NULL) {
|
||||||
xmlAddChild(insert, copy);
|
xmlAddChild(insert, copy);
|
||||||
/*
|
/*
|
||||||
@@ -290,7 +295,7 @@ xsltCopyNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsltProcessOneNode: copy %s failed\n", node->name);
|
"xsltCopyNode: copy %s failed\n", node->name);
|
||||||
}
|
}
|
||||||
return(copy);
|
return(copy);
|
||||||
}
|
}
|
||||||
@@ -319,6 +324,7 @@ xsltCopyNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
void
|
void
|
||||||
xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
||||||
xmlNodePtr copy;
|
xmlNodePtr copy;
|
||||||
|
xmlNodePtr delete = NULL;
|
||||||
|
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case XML_DOCUMENT_NODE:
|
case XML_DOCUMENT_NODE:
|
||||||
@@ -347,9 +353,11 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
|||||||
xmlHashLookup(ctxt->style->stripSpaces,
|
xmlHashLookup(ctxt->style->stripSpaces,
|
||||||
node->parent->name);
|
node->parent->name);
|
||||||
if ((val != NULL) &&
|
if ((val != NULL) &&
|
||||||
(xmlStrEqual(val, (xmlChar *) "strip")))
|
(xmlStrEqual(val, (xmlChar *) "strip"))) {
|
||||||
|
delete = node;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* no break on purpose */
|
/* no break on purpose */
|
||||||
case XML_CDATA_SECTION_NODE:
|
case XML_CDATA_SECTION_NODE:
|
||||||
copy = xmlCopyNode(node, 0);
|
copy = xmlCopyNode(node, 0);
|
||||||
@@ -361,9 +369,23 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TODO
|
#ifdef DEBUG_PROCESS
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltDefaultProcessOneNode: skipping node type %d\n",
|
||||||
|
node->type);
|
||||||
|
#endif
|
||||||
|
delete = node;
|
||||||
}
|
}
|
||||||
node = node->next;
|
node = node->next;
|
||||||
|
if (delete != NULL) {
|
||||||
|
#ifdef DEBUG_PROCESS
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltDefaultProcessOneNode: removing ignorable blank node\n");
|
||||||
|
#endif
|
||||||
|
xmlUnlinkNode(delete);
|
||||||
|
xmlFreeNode(delete);
|
||||||
|
delete = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,38 +418,48 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltProcessOneNode:
|
* xsltApplyOneTemplate:
|
||||||
* @ctxt: a XSLT process context
|
* @ctxt: a XSLT process context
|
||||||
* @node: the node in the source tree.
|
* @node: the node in the source tree.
|
||||||
|
* @list: the template replacement nodelist
|
||||||
*
|
*
|
||||||
* Process the source node.
|
* Process the apply-templates node on the source node
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
||||||
xsltTemplatePtr template;
|
xmlNodePtr list) {
|
||||||
xmlNodePtr cur, insert, copy;
|
xmlNodePtr cur, insert, copy, delete = NULL;
|
||||||
xmlNodePtr oldInsert;
|
xmlNodePtr oldInsert;
|
||||||
|
|
||||||
oldInsert = insert = ctxt->insert;
|
oldInsert = insert = ctxt->insert;
|
||||||
template = xsltGetTemplate(ctxt->style, node);
|
|
||||||
/*
|
/*
|
||||||
* If no template is found, apply the deafult rule.
|
* Insert all non-XSLT nodes found in the template
|
||||||
*/
|
*/
|
||||||
if (template == NULL) {
|
cur = list;
|
||||||
|
while (cur != NULL) {
|
||||||
|
/*
|
||||||
|
* test, we must have a valid insertion point
|
||||||
|
*/
|
||||||
|
if (insert == NULL) {
|
||||||
#ifdef DEBUG_PROCESS
|
#ifdef DEBUG_PROCESS
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsltProcessOneNode: no template found for %s\n", node->name);
|
"xsltApplyOneTemplate: insert == NULL !\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xsltDefaultProcessOneNode(ctxt, node);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert all non-XSLT nodes found in the template
|
* Cleanup of ignorable blank node detected
|
||||||
*/
|
*/
|
||||||
cur = template->content;
|
if (delete != NULL) {
|
||||||
while (cur != NULL) {
|
#ifdef DEBUG_PROCESS
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltApplyOneTemplate: removing ignorable blank node\n");
|
||||||
|
#endif
|
||||||
|
xmlUnlinkNode(delete);
|
||||||
|
xmlFreeNode(delete);
|
||||||
|
delete = NULL;
|
||||||
|
}
|
||||||
if (IS_XSLT_ELEM(cur)) {
|
if (IS_XSLT_ELEM(cur)) {
|
||||||
if (IS_XSLT_NAME(cur, "apply-templates")) {
|
if (IS_XSLT_NAME(cur, "apply-templates")) {
|
||||||
ctxt->insert = insert;
|
ctxt->insert = insert;
|
||||||
@@ -437,13 +469,18 @@ xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
|||||||
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, "for-each")) {
|
||||||
|
ctxt->insert = insert;
|
||||||
|
xsltForEach(ctxt, node, cur);
|
||||||
|
ctxt->insert = oldInsert;
|
||||||
} else {
|
} else {
|
||||||
#ifdef DEBUG_PROCESS
|
#ifdef DEBUG_PROCESS
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsltProcessOneNode: found xslt:%s\n", cur->name);
|
"xsltApplyOneTemplate: found xslt:%s\n", cur->name);
|
||||||
#endif
|
#endif
|
||||||
TODO
|
TODO
|
||||||
}
|
}
|
||||||
|
goto skip_children;
|
||||||
} else if (cur->type == XML_TEXT_NODE) {
|
} else if (cur->type == XML_TEXT_NODE) {
|
||||||
/*
|
/*
|
||||||
* This text comes from the stylesheet
|
* This text comes from the stylesheet
|
||||||
@@ -453,20 +490,22 @@ xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
|||||||
if (!(IS_BLANK_NODE(cur))) {
|
if (!(IS_BLANK_NODE(cur))) {
|
||||||
#ifdef DEBUG_PROCESS
|
#ifdef DEBUG_PROCESS
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsltProcessOneNode: copy text %s\n", cur->content);
|
"xsltApplyOneTemplate: copy text %s\n", cur->content);
|
||||||
#endif
|
#endif
|
||||||
copy = xmlCopyNode(cur, 0);
|
copy = xmlCopyNode(cur, 0);
|
||||||
if (copy != NULL) {
|
if (copy != NULL) {
|
||||||
xmlAddChild(insert, copy);
|
xmlAddChild(insert, copy);
|
||||||
} else {
|
} else {
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsltProcessOneNode: text copy failed\n");
|
"xsltApplyOneTemplate: text copy failed\n");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
delete = cur;
|
||||||
|
}
|
||||||
|
} else if (cur->type == XML_ELEMENT_NODE) {
|
||||||
#ifdef DEBUG_PROCESS
|
#ifdef DEBUG_PROCESS
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsltProcessOneNode: copy node %s\n", cur->name);
|
"xsltApplyOneTemplate: copy node %s\n", cur->name);
|
||||||
#endif
|
#endif
|
||||||
copy = xsltCopyNode(ctxt, cur, insert);
|
copy = xsltCopyNode(ctxt, cur, insert);
|
||||||
/*
|
/*
|
||||||
@@ -476,17 +515,19 @@ xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
|||||||
if (cur->properties != NULL)
|
if (cur->properties != NULL)
|
||||||
copy->properties = xmlCopyPropList(copy, cur->properties);
|
copy->properties = xmlCopyPropList(copy, cur->properties);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Skip to next node
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip to next node, in document order.
|
||||||
|
*/
|
||||||
if (cur->children != NULL) {
|
if (cur->children != NULL) {
|
||||||
if (cur->children->type != XML_ENTITY_DECL) {
|
if (cur->children->type != XML_ENTITY_DECL) {
|
||||||
cur = cur->children;
|
cur = cur->children;
|
||||||
|
if (copy != NULL)
|
||||||
insert = copy;
|
insert = copy;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
skip_children:
|
||||||
if (cur->next != NULL) {
|
if (cur->next != NULL) {
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
continue;
|
continue;
|
||||||
@@ -497,7 +538,7 @@ xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
|||||||
insert = insert->parent;
|
insert = insert->parent;
|
||||||
if (cur == NULL)
|
if (cur == NULL)
|
||||||
break;
|
break;
|
||||||
if (cur == template->content) {
|
if (cur == list->parent) {
|
||||||
cur = NULL;
|
cur = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -507,13 +548,126 @@ xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
|||||||
}
|
}
|
||||||
} while (cur != NULL);
|
} while (cur != NULL);
|
||||||
}
|
}
|
||||||
/********
|
}
|
||||||
if (ctxt->style->indent) {
|
|
||||||
copy = xmlNewText("\n");
|
/**
|
||||||
if (copy != NULL)
|
* xsltForEach:
|
||||||
xmlAddChild(ctxt->insert, copy);
|
* @ctxt: a XSLT process context
|
||||||
|
* @node: the node in the source tree.
|
||||||
|
* @inst: the xslt for-each node
|
||||||
|
*
|
||||||
|
* Process the xslt for-each node on the source node
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
||||||
|
xmlNodePtr inst) {
|
||||||
|
xmlChar *prop;
|
||||||
|
xmlXPathObjectPtr res, tmp;
|
||||||
|
xmlNodePtr replacement;
|
||||||
|
xmlNodeSetPtr list = NULL, oldlist;
|
||||||
|
xmlXPathParserContextPtr xpathParserCtxt;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
prop = xmlGetNsProp(inst, (const xmlChar *)"select", XSLT_NAMESPACE);
|
||||||
|
if (prop == NULL) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltForEach: select is not defined\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
********/
|
#ifdef DEBUG_PROCESS
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltForEach: select %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);
|
||||||
|
res = valuePop(xpathParserCtxt);
|
||||||
|
do {
|
||||||
|
tmp = valuePop(xpathParserCtxt);
|
||||||
|
if (tmp != NULL) {
|
||||||
|
xmlXPathFreeObject(tmp);
|
||||||
|
}
|
||||||
|
} while (tmp != NULL);
|
||||||
|
|
||||||
|
if (res != NULL) {
|
||||||
|
if (res->type == XPATH_NODESET)
|
||||||
|
list = res->nodesetval;
|
||||||
|
else {
|
||||||
|
#ifdef DEBUG_PROCESS
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltForEach: select didn't evaluate to a node list\n");
|
||||||
|
#endif
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_PROCESS
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltForEach: select evaluate to %d nodes\n", list->nodeNr);
|
||||||
|
#endif
|
||||||
|
/* TODO: handle and skip the xsl:sort */
|
||||||
|
replacement = inst->children;
|
||||||
|
|
||||||
|
oldlist = ctxt->nodeList;
|
||||||
|
ctxt->nodeList = list;
|
||||||
|
for (i = 0;i < list->nodeNr;i++) {
|
||||||
|
ctxt->node = list->nodeTab[i];
|
||||||
|
xsltApplyOneTemplate(ctxt, list->nodeTab[i], replacement);
|
||||||
|
}
|
||||||
|
ctxt->nodeList = oldlist;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (xpathParserCtxt != NULL)
|
||||||
|
xmlXPathFreeParserContext(xpathParserCtxt);
|
||||||
|
if (prop != NULL)
|
||||||
|
xmlFree(prop);
|
||||||
|
if (res != NULL)
|
||||||
|
xmlXPathFreeObject(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
template = xsltGetTemplate(ctxt->style, node);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no template is found, apply the default rule.
|
||||||
|
*/
|
||||||
|
if (template == NULL) {
|
||||||
|
#ifdef DEBUG_PROCESS
|
||||||
|
if (node->type == XML_DOCUMENT_NODE)
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltProcessOneNode: no template found for /\n");
|
||||||
|
else
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltProcessOneNode: no template found for %s\n", node->name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
xsltDefaultProcessOneNode(ctxt, node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xsltApplyOneTemplate(ctxt, node, template->content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -569,17 +723,10 @@ xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc) {
|
|||||||
/*
|
/*
|
||||||
* Start.
|
* Start.
|
||||||
*/
|
*/
|
||||||
root = xmlDocGetRootElement(doc);
|
|
||||||
if (root == NULL) {
|
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
|
||||||
"xsltApplyStylesheet: document has no root\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
ctxt->output = res;
|
ctxt->output = res;
|
||||||
ctxt->insert = (xmlNodePtr) res;
|
ctxt->insert = (xmlNodePtr) res;
|
||||||
ctxt->node = root;
|
ctxt->node = (xmlNodePtr) doc;
|
||||||
ctxt->nodeList = xmlXPathNodeSetCreate(root);
|
xsltProcessOneNode(ctxt, ctxt->node);
|
||||||
xsltProcessOneNode(ctxt, root);
|
|
||||||
|
|
||||||
|
|
||||||
if ((ctxt->type = XSLT_OUTPUT_XML) &&
|
if ((ctxt->type = XSLT_OUTPUT_XML) &&
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ xsltParseStylesheetStripSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
|
|||||||
void
|
void
|
||||||
xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
|
xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
|
||||||
xsltTemplatePtr ret;
|
xsltTemplatePtr ret;
|
||||||
xmlNodePtr cur;
|
xmlNodePtr cur, delete;
|
||||||
xmlChar *prop;
|
xmlChar *prop;
|
||||||
|
|
||||||
if (template == NULL)
|
if (template == NULL)
|
||||||
@@ -539,6 +539,65 @@ xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean-up the template content from unwanted ignorable blank nodes
|
||||||
|
* This content comes from the stylesheet
|
||||||
|
* For stylesheets, the set of whitespace-preserving
|
||||||
|
* element names consists of just xsl:text.
|
||||||
|
*/
|
||||||
|
cur = template->children;
|
||||||
|
delete = 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;
|
||||||
|
}
|
||||||
|
if (IS_XSLT_ELEM(cur)) {
|
||||||
|
if (IS_XSLT_NAME(cur, "text"))
|
||||||
|
goto skip_children;
|
||||||
|
} else if (cur->type == XML_TEXT_NODE) {
|
||||||
|
if (IS_BLANK_NODE(cur)) {
|
||||||
|
delete = cur;
|
||||||
|
}
|
||||||
|
} else if (cur->type != XML_ELEMENT_NODE) {
|
||||||
|
delete = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip to next node
|
||||||
|
*/
|
||||||
|
if (cur->children != NULL) {
|
||||||
|
if (cur->children->type != XML_ENTITY_DECL) {
|
||||||
|
cur = cur->children;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip_children:
|
||||||
|
if (cur->next != NULL) {
|
||||||
|
cur = cur->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
cur = cur->parent;
|
||||||
|
if (cur == NULL)
|
||||||
|
break;
|
||||||
|
if (cur == template) {
|
||||||
|
cur = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cur->next != NULL) {
|
||||||
|
cur = cur->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (cur != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find and handle the params
|
* Find and handle the params
|
||||||
*/
|
*/
|
||||||
@@ -726,22 +785,24 @@ xsltParseStylesheetDoc(xmlDocPtr doc) {
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret->doc = doc;
|
||||||
if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "stylesheet"))) {
|
if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "stylesheet"))) {
|
||||||
#ifdef DEBUG_PARSING
|
#ifdef DEBUG_PARSING
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsltParseStylesheetDoc : found stylesheet\n");
|
"xsltParseStylesheetDoc : found stylesheet\n");
|
||||||
#endif
|
#endif
|
||||||
} else {
|
|
||||||
|
|
||||||
TODO /* lookup the stylesheet element down in the tree */
|
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
|
||||||
"xsltParseStylesheetDoc : root is not stylesheet\n");
|
|
||||||
xsltFreeStylesheet(ret);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
ret->doc = doc;
|
|
||||||
|
|
||||||
xsltParseStylesheetTop(ret, cur);
|
xsltParseStylesheetTop(ret, cur);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* the document itself is the template.
|
||||||
|
*/
|
||||||
|
#ifdef DEBUG_PARSING
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltParseStylesheetDoc : document is stylesheet\n");
|
||||||
|
#endif
|
||||||
|
TODO
|
||||||
|
}
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,3 +17,7 @@ LDADDS = $(top_builddir)/libxslt/libxslt.la $(LIBXML_LIBS)
|
|||||||
#testevents_LDFLAGS =
|
#testevents_LDFLAGS =
|
||||||
#testevents_DEPENDENCIES = $(DEPS)
|
#testevents_DEPENDENCIES = $(DEPS)
|
||||||
#testevents_LDADD = $(LDADDS)
|
#testevents_LDADD = $(LDADDS)
|
||||||
|
|
||||||
|
test: $(top_builddir)/libxslt/xsltproc
|
||||||
|
@(cd REC1 ; make test)
|
||||||
|
@(cd REC2 ; make test)
|
||||||
|
|||||||
13
tests/REC1/Makefile.am
Normal file
13
tests/REC1/Makefile.am
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
$(top_builddir)/libxslt/xsltproc:
|
||||||
|
@(cd ../../libxslt ; make xsltproc)
|
||||||
|
|
||||||
|
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 ; \
|
||||||
|
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
|
||||||
|
rm -f doc.res)
|
||||||
|
|
||||||
|
|
||||||
@@ -1,18 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
<html xmlns="http://www.w3.org/TR/xhtml1/strict">
|
<html xmlns="http://www.w3.org/TR/xhtml1/strict">
|
||||||
<head>
|
<head>
|
||||||
<title>Document Title</title>
|
<title>Document Title</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Document Title</h1>
|
<h1>Document Title</h1>
|
||||||
<h2>Chapter Title</h2>
|
<h2>Chapter Title</h2>
|
||||||
<h3>Section Title</h3>
|
<h3>Section Title</h3>
|
||||||
<p>This is a test.</p>
|
<p>This is a test.</p>
|
||||||
<p class="note">
|
<p class="note"><b>NOTE: </b>This is a note.</p>
|
||||||
<b>NOTE: </b>This is a note.</p>
|
<h3>Another Section Title</h3>
|
||||||
<h3>Another Section Title</h3>
|
<p>This is <em>another</em> test.</p>
|
||||||
<p>This is <em>another</em> test.</p>
|
<p class="note"><b>NOTE: </b>This is another note.</p>
|
||||||
<p class="note">
|
</body>
|
||||||
<b>NOTE: </b>This is another note.</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
13
tests/REC2/Makefile.am
Normal file
13
tests/REC2/Makefile.am
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
$(top_builddir)/libxslt/xsltproc:
|
||||||
|
@(cd ../../libxslt ; make xsltproc)
|
||||||
|
|
||||||
|
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 ; \
|
||||||
|
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
|
||||||
|
rm -f doc.res)
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user