[xslt] extension APIs returning a node-set



What is the proper method to return a node-set from an extension function?

I've got an extension API function that returns a potentially large nodeset
of newly allocated nodes.  It seems that in order for these nodes to be
properly freed I understand you have make the XPathObject ret->user be a
node, and the nodeset be children of that node.  

Libexslt (example:  str:tokenize) creates ret->user as
xmlNewDocNode(doc,NULL,(const xmlChar*)"fake",NULL) where doc is retrieved
from:
xsktXPathGetTransformContext(ctxt)->output;

However, this cause a segv in xsltForEach because when processing these
nodes xsltFindDocument() will return NULL because doc is not contained in 
xsltXPathGetTransformContext(ctxt)->docList.  This generates a simple
warning error on the following stylesheet, but will cause crashes elsewhere
when context->document is assumed to be valid.

<xsl:stylesheet version="1.0" 
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
	xmlns:str="http://exslt.org/strings" 
	>
<xsl:template match="/">
<xsl:for-each select="str:tokenize('This Is A Test')">
<xsl:value-of select="./RESULTS/R"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

F:\>xsltproc test.xsl gsstools.xml
runtime error: file test.xsl line 6 element for-each
xsl:for-each : can't find doc


If I use doc = xsltXPathGetTransformContext(ctxt)->document->doc then
everything works and there doesn't seem to be any memory leaks, but is this
the correct document to add the nodes to?

This is my extension API (processNodeSet() makes database calls and adds
children to the nodes in the nodeset passed to it).  Is this the correct
approach?

void gsstoolsProcessNodeset(xmlXPathParserContextPtr ctxt, int nargs)
{
	xmlXPathObjectPtr ret,obj;
	xmlDocPtr doc;
	int i;

	if (!nargs)
		return;

	doc = xsltXPathGetTransformContext(ctxt)->document->doc;
	ret = xmlXPathNewNodeSet(NULL);
	ret->boolval = 1;
	ret->user = (void*)xmlNewDocNode(doc,NULL,
		(const xmlChar*) "fake",NULL);

	for (i=0;i<obj->nodesetval->nodeNr;i++)
	{
		xmlXPathNodeSetAdd(ret->nodesetval,
			xmlAddChild(ret->user,
	
xmlCopyNode(obj->nodesetval->nodeTab[i],1)));
	}
	xmlXPathFreeObject(obj);
	gssGenericError(gssGenericTraceContext,
		"gsstools:process-node-set() : processing node-set
containing %d nodes\n",
			ret->nodesetval->nodeNr);
	processNodeSet(ret,NULL);
	valuePush(ctxt,ret);
	return;
}




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]