1
0
mirror of https://gitlab.gnome.org/GNOME/libxslt synced 2025-08-07 10:42:55 +03:00

cleaning up Result Value Tree handling fixed a pair of implementations.

* libxslt/transform.c libxslt/variables.c libxslt/xsltInternals.h:
  cleaning up Result Value Tree handling
* libexslt/functions.c libexslt/strings.c: fixed a pair of
  implementations.
* tests/exslt/strings/Makefile.am tests/exslt/strings/tokenize.2.*:
  added Mark Vakoc test combining for-each and exslt:tokenize
Daniel
This commit is contained in:
Daniel Veillard
2003-04-30 20:47:47 +00:00
parent 95cc2c1cef
commit 4f5120741e
10 changed files with 200 additions and 44 deletions

View File

@@ -1,3 +1,12 @@
Wed Apr 30 22:44:49 CEST 2003 Daniel Veillard <daniel@veillard.com>
* libxslt/transform.c libxslt/variables.c libxslt/xsltInternals.h:
cleaning up Result Value Tree handling
* libexslt/functions.c libexslt/strings.c: fixed a pair of
implementations.
* tests/exslt/strings/Makefile.am tests/exslt/strings/tokenize.2.*:
added Mark Vakoc test combining for-each and exslt:tokenize
Wed Apr 30 15:23:33 CEST 2003 Daniel Veillard <daniel@veillard.com>
* libxslt/transform.c: fixing bug #111755 when a template is

View File

@@ -511,21 +511,30 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
* one or more child nodes), then the content of the
* func:result element specifies the value.
*/
xmlNodePtr container, oldInsert;
xmlNodePtr oldInsert;
xmlDocPtr container;
container = xmlNewDocNode (ctxt->output, NULL,
(const xmlChar *) "fake", NULL);
container = xsltCreateRVT(ctxt);
if (container == NULL) {
xsltGenericError(xsltGenericErrorContext,
"exsltFuncResultElem: out of memory\n");
data->error = 1;
return;
}
xsltRegisterTmpRVT(ctxt, container);
oldInsert = ctxt->insert;
ctxt->insert = container;
ctxt->insert = (xmlNodePtr) container;
xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node,
inst->children, NULL, NULL);
ctxt->insert = oldInsert;
ret = xmlXPathNewValueTree(container);
ret = xmlXPathNewValueTree((xmlNodePtr) container);
if (ret == NULL) {
xsltGenericError(xsltGenericErrorContext,
"exsltFuncResultElem: ret == NULL\n");
data->error = 1;
} else {
ret->boolval = 0; /* Freeing is not handled there anymore */
}
} else {
/* If the func:result element has empty content and does not

View File

@@ -32,12 +32,12 @@
static void
exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs)
{
xsltTransformContextPtr tctxt;
xmlChar *str, *delimiters, *cur;
const xmlChar *token, *delimiter;
xmlNodePtr node;
xmlDocPtr container;
xmlXPathObjectPtr ret;
xmlXPathObjectPtr ret = NULL;
if ((nargs < 1) || (nargs > 2)) {
xmlXPathSetArityError(ctxt);
@@ -61,17 +61,19 @@ exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs)
}
/* Return a result tree fragment */
tctxt = xsltXPathGetTransformContext(ctxt);
if (tctxt == NULL) {
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
"exslt:tokenize : internal error tctxt == NULL\n");
goto fail;
}
container = xmlNewDoc(NULL);
container = xsltCreateRVT(tctxt);
if (container != NULL) {
container->name =
(char *) xmlStrdup(BAD_CAST " fake node libxslt");
container->doc = container;
ret = xmlXPathNewValueTree((xmlNodePtr) container);
xsltRegisterTmpRVT(tctxt, container);
ret = xmlXPathNewNodeSet(NULL);
if (ret != NULL) {
/* Tag the subtree for removal once consumed */
ret->boolval = 1;
ret->type = XPATH_XSLT_TREE;
ret->boolval = 0; /* Freeing is not handled there anymore */
for (cur = str, token = str; *cur != 0; cur++) {
for (delimiter = delimiters; *delimiter != 0; delimiter++) {
if (*cur == *delimiter) {
@@ -83,6 +85,7 @@ exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs)
node = xmlNewChild((xmlNodePtr) container, NULL,
(const xmlChar *) "token",
token);
xmlXPathNodeSetAddUnique(ret->nodesetval, node);
*cur = *delimiter;
token = cur + 1;
break;
@@ -92,9 +95,11 @@ exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs)
node =
xmlNewChild((xmlNodePtr) container, NULL,
(const xmlChar *) "token", token);
xmlXPathNodeSetAddUnique(ret->nodesetval, node);
}
}
fail:
if (str != NULL)
xmlFree(str);
if (delimiters != NULL)

View File

@@ -463,6 +463,7 @@ xsltFreeTransformContext(xsltTransformContextPtr ctxt) {
xsltFreeGlobalVariables(ctxt);
xsltFreeDocuments(ctxt);
xsltFreeCtxtExts(ctxt);
xsltFreeRVTs(ctxt);
memset(ctxt, -1, sizeof(xsltTransformContext));
xmlFree(ctxt);
}
@@ -1251,18 +1252,6 @@ xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
xsltTemplatePtr template;
xmlNodePtr oldNode;
#if 0
if (xmlStrEqual(node->name, BAD_CAST " fake node libxslt")) {
xmlNodePtr children;
children = node->children;
while (children != NULL) {
xsltProcessOneNode(ctxt, children, params);
children = children->next;
}
return;
}
#endif
template = xsltGetTemplate(ctxt, node, NULL);
/*
* If no template is found, apply the default rule.
@@ -1336,6 +1325,7 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr oldInst = NULL;
xmlAttrPtr attrs;
int oldBase;
xmlDocPtr tmpRVT = NULL;
int level = 0;
@@ -1404,6 +1394,8 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
start = xsltTimestamp();
profPush(ctxt, 0);
}
tmpRVT = ctxt->tmpRVT;
ctxt->tmpRVT = NULL;
templPush(ctxt, templ);
#ifdef WITH_XSLT_DEBUG_PROCESS
if (templ->name != NULL)
@@ -1694,6 +1686,19 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
if (templ != NULL) {
ctxt->varsBase = oldBase;
templPop(ctxt);
/*
* Free up all the unreferenced RVT
*/
if (ctxt->tmpRVT != NULL) {
xmlDocPtr tmp = ctxt->tmpRVT, next;
while (tmp != NULL) {
next = (xmlDocPtr) tmp->next;
xmlFreeDoc(tmp);
tmp = next;
}
}
ctxt->tmpRVT = tmpRVT;
if (ctxt->profile) {
long spent, child, total, end;

View File

@@ -34,6 +34,106 @@
#define WITH_XSLT_DEBUG_VARIABLE
#endif
/************************************************************************
* *
* Result Value Tree interfaces *
* *
************************************************************************/
/**
* xsltCreateRVT:
* @ctxt: an XSLT transformation context
*
* Create a result value tree
*
* Returns the result value tree or NULL in case of error
*/
xmlDocPtr
xsltCreateRVT(xsltTransformContextPtr ctxt)
{
xmlDocPtr container;
if (ctxt == NULL) return(NULL);
container = xmlNewDoc(NULL);
if (container == NULL)
return(NULL);
container->name = (char *) xmlStrdup(BAD_CAST " fake node libxslt");
container->doc = container;
container->parent = NULL;
return(container);
}
/**
* xsltRegisterTmpRVT:
* @ctxt: an XSLT transformation context
* @RVT: a result value tree
*
* Register the result value tree for destruction at the end of the context
*
* Returns 0 in case of success and -1 in case of error.
*/
int
xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
{
if ((ctxt == NULL) || (RVT == NULL)) return(-1);
RVT->next = (xmlNodePtr) ctxt->tmpRVT;
if (ctxt->tmpRVT != NULL)
ctxt->tmpRVT->prev = (xmlNodePtr) RVT;
ctxt->tmpRVT = RVT;
return(0);
}
/**
* xsltRegisterPersistRVT:
* @ctxt: an XSLT transformation context
* @RVT: a result value tree
*
* Register the result value tree for destruction at the end of the processing
*
* Returns 0 in case of success and -1 in case of error.
*/
int
xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
{
if ((ctxt == NULL) || (RVT == NULL)) return(-1);
RVT->next = (xmlNodePtr) ctxt->persistRVT;
if (ctxt->persistRVT != NULL)
ctxt->persistRVT->prev = (xmlNodePtr) RVT;
ctxt->persistRVT = RVT;
return(0);
}
/**
* xsltFreeRVTs:
* @ctxt: an XSLT transformation context
*
* Free all the registered result value tree of the transformation
*/
void
xsltFreeRVTs(xsltTransformContextPtr ctxt)
{
xmlDocPtr cur, next;
if (ctxt == NULL) return;
cur = ctxt->tmpRVT;
while (cur != NULL) {
next = (xmlDocPtr) cur->next;
xmlFreeDoc(cur);
cur = next;
}
cur = ctxt->persistRVT;
while (cur != NULL) {
next = (xmlDocPtr) cur->next;
xmlFreeDoc(cur);
cur = next;
}
}
/************************************************************************
* *
* Module interfaces *
@@ -364,12 +464,13 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem,
xmlNodePtr oldInsert;
xmlDocPtr oldoutput;
container = xmlNewDoc(NULL);
container = xsltCreateRVT(ctxt);
if (container == NULL)
return(NULL);
container->name = (char *) xmlStrdup(BAD_CAST " fake node libxslt");
container->doc = container;
container->parent = NULL;
/*
* Tag the subtree for removal once consumed
*/
xsltRegisterTmpRVT(ctxt, container);
oldoutput = ctxt->output;
ctxt->output = container;
@@ -383,10 +484,7 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem,
if (result == NULL) {
result = xmlXPathNewCString("");
} else {
/*
* Tag the subtree for removal once consumed
*/
result->boolval = 1;
result->boolval = 0; /* Freeing is not handled there anymore */
}
#ifdef WITH_XSLT_DEBUG_VARIABLE
#ifdef LIBXML_DEBUG_ENABLED
@@ -501,12 +599,13 @@ xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt) {
xmlNodePtr oldInsert;
xmlDocPtr oldoutput;
container = xmlNewDoc(NULL);
container = xsltCreateRVT(ctxt);
if (container == NULL)
return(NULL);
container->name = (char *) xmlStrdup(BAD_CAST " fake node libxslt");
container->doc = container;
container->parent = NULL;
/*
* Tag the subtree for removal once consumed
*/
xsltRegisterTmpRVT(ctxt, container);
oldoutput = ctxt->output;
ctxt->output = container;
@@ -520,10 +619,7 @@ xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt) {
if (result == NULL) {
result = xmlXPathNewCString("");
} else {
/*
* Tag the subtree for removal once consumed
*/
result->boolval = 1;
result->boolval = 0; /* Freeing is not handled there anymore */
}
#ifdef WITH_XSLT_DEBUG_VARIABLE
#ifdef LIBXML_DEBUG_ENABLED

View File

@@ -498,6 +498,12 @@ struct _xsltTransformContext {
void * errctx; /* context for the error handler */
xsltSortFunc sortfunc; /* a ctxt specific sort routine */
/*
* handling of temporary Result Value Tree
*/
xmlDocPtr tmpRVT; /* list of RVT without persistance */
xmlDocPtr persistRVT; /* list of persistant RVTs */
};
/**
@@ -556,6 +562,15 @@ void xsltParseTemplateContent(xsltStylesheetPtr style,
xmlNodePtr templ);
int xsltAllocateExtra (xsltStylesheetPtr style);
int xsltAllocateExtraCtxt (xsltTransformContextPtr ctxt);
/*
* Extra functions for Result Value Trees
*/
xmlDocPtr xsltCreateRVT (xsltTransformContextPtr ctxt);
int xsltRegisterTmpRVT (xsltTransformContextPtr ctxt,
xmlDocPtr RVT);
int xsltRegisterPersistRVT (xsltTransformContextPtr ctxt,
xmlDocPtr RVT);
void xsltFreeRVTs (xsltTransformContextPtr ctxt);
#ifdef __cplusplus
}
#endif

View File

@@ -4,7 +4,8 @@ $(top_builddir)/xsltproc/xsltproc:
@(cd ../../../xsltproc ; $(MAKE) xsltproc)
EXTRA_DIST = \
tokenize.1.xml tokenize.1.xsl tokenize.1.out
tokenize.1.xml tokenize.1.xsl tokenize.1.out \
tokenize.2.xml tokenize.2.xsl tokenize.2.out
all:

View File

@@ -0,0 +1,2 @@
<?xml version="1.0"?>
<tok>This</tok><tok>is</tok><tok>strange</tok><tok>behavior</tok>

View File

@@ -0,0 +1 @@
<doc/>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:template match="/">
<xsl:for-each select="str:tokenize('This is strange behavior', ' ')" >
<tok><xsl:value-of select="."/></tok>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>