mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-08-08 21:42:07 +03:00
Refactored xsltValueOf(). Changed to use xmlXPathCastToString() directly,
* libxslt/attributes.c libxslt/documents.c libxslt/functions.c libxslt/keys.c libxslt/namespaces.c libxslt/pattern.c libxslt/preproc.c libxslt/templates.c libxslt/templates.h libxslt/transform.c libxslt/variables.c libxslt/xslt.c libxslt/xsltInternals.h libxslt/xsltutils.c libxslt/xsltutils.h libexslt/common.c libexslt/dynamic.c libexslt/functions.c libexslt/strings.c: Refactored xsltValueOf(). Changed to use xmlXPathCastToString() directly, rather than creating an intermediate object with xmlXPathConvertString(). This now does not add a text-node to the result if the string is empty (this has impact on serialization, since an empty text-node is serialized as <foo></foo>, and now it will be serialized as <foo/>). Refactored other functions in transform.c: Mostly code cleanup/restructuring. Minimized number of function variables for instruction which eat up function stack memory when recursing templates (xsltIf(), xsltChoose(), xsltApplyTemplates(), xsltCallTemplate()). Changed XSLT tests to use xmlXPathCompiledEvalToBoolean(). Implemented redefinition checks at compilation-time and eliminating them at transformation time in the refactored code paths. Introduced the field @currentTemplateRule on xsltTransformContext to reflect the "Current Template Rule" as defined by the spec. NOTE that ctxt->currentTemplateRule and ctxt->templ is not the same; the former is the "Current Template Rule" as defined by the XSLT spec, the latter is simply the template struct being currently processed by Libxslt. Added XML_COMMENT_NODE and XML_CDATA_SECTION_NODE to the macro IS_XSLT_REAL_NODE. Misc code cleanup/restructuring and everything else I already forgot. Refactored lifetime of temporary result tree fragments. Substituted all calls to the now deprecated xsltRegisterTmpRVT() for the new xsltRegisterLocalRVT(). Fragments of xsl:variable and xsl:param are freed when the variable/pram is freed. Fragments created when evaluating a "select" of xsl:varible and xsl:param are also bound to the lifetime of the var/param. EXSLT's func:function now uses the following functions to let take care the transformation's garbage collector of returned tree fragments: xsltExtensionInstructionResultRegister(), xsltExtensionInstructionResultFinalize() Fixes: #339222 - xsl:param at invalid position inside an xsl:template is not catched #346015 - Non-declared caller-parameters are accepted #160400 - Compiles invalid XSLT; unbound variable accepted #308441 - namespaced parameters become unregistered #307103 - problem with proximity position in predicates of match patterns #328218 - problem with exsl:node-set() when converting strings to node sets #318088 - infinite recursion detection #321505 - Multiple contiguous CDATA in output #334493 - "--param" option does not have root context #114377 - weird func:result/xsl:variable/exsl:node-set interaction #150309 - Regression caused by fix for 142768
This commit is contained in:
61
ChangeLog
61
ChangeLog
@@ -1,3 +1,64 @@
|
|||||||
|
Fri Jul 14 17:55:42 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
|
||||||
|
|
||||||
|
* libxslt/attributes.c libxslt/documents.c
|
||||||
|
libxslt/functions.c libxslt/keys.c libxslt/namespaces.c
|
||||||
|
libxslt/pattern.c libxslt/preproc.c libxslt/templates.c
|
||||||
|
libxslt/templates.h libxslt/transform.c libxslt/variables.c
|
||||||
|
libxslt/xslt.c libxslt/xsltInternals.h libxslt/xsltutils.c
|
||||||
|
libxslt/xsltutils.h libexslt/common.c libexslt/dynamic.c
|
||||||
|
libexslt/functions.c libexslt/strings.c:
|
||||||
|
Refactored xsltValueOf(). Changed to use xmlXPathCastToString()
|
||||||
|
directly, rather than creating an intermediate object with
|
||||||
|
xmlXPathConvertString(). This now does not add a text-node to
|
||||||
|
the result if the string is empty (this has impact on
|
||||||
|
serialization, since an empty text-node is serialized as
|
||||||
|
<foo></foo>, and now it will be serialized as <foo/>).
|
||||||
|
Refactored other functions in transform.c:
|
||||||
|
Mostly code cleanup/restructuring. Minimized number of
|
||||||
|
function variables for instruction which eat up function stack
|
||||||
|
memory when recursing templates (xsltIf(), xsltChoose(),
|
||||||
|
xsltApplyTemplates(), xsltCallTemplate()).
|
||||||
|
Changed XSLT tests to use xmlXPathCompiledEvalToBoolean().
|
||||||
|
Implemented redefinition checks at compilation-time and
|
||||||
|
eliminating them at transformation time in the refactored code
|
||||||
|
paths.
|
||||||
|
Introduced the field @currentTemplateRule on xsltTransformContext to
|
||||||
|
reflect the "Current Template Rule" as defined by the spec.
|
||||||
|
NOTE that ctxt->currentTemplateRule and ctxt->templ is not the
|
||||||
|
same; the former is the "Current Template Rule" as defined by the
|
||||||
|
XSLT spec, the latter is simply the template struct being
|
||||||
|
currently processed by Libxslt.
|
||||||
|
Added XML_COMMENT_NODE and XML_CDATA_SECTION_NODE to the macro
|
||||||
|
IS_XSLT_REAL_NODE.
|
||||||
|
Misc code cleanup/restructuring and everything else I already forgot.
|
||||||
|
Refactored lifetime of temporary result tree fragments.
|
||||||
|
Substituted all calls to the now deprecated xsltRegisterTmpRVT()
|
||||||
|
for the new xsltRegisterLocalRVT().
|
||||||
|
Fragments of xsl:variable and xsl:param are freed when the
|
||||||
|
variable/pram is freed.
|
||||||
|
Fragments created when evaluating a "select" of xsl:varible and
|
||||||
|
xsl:param are also bound to the lifetime of the var/param.
|
||||||
|
EXSLT's func:function now uses the following functions to let take
|
||||||
|
care the transformation's garbage collector of returned tree
|
||||||
|
fragments:
|
||||||
|
xsltExtensionInstructionResultRegister(),
|
||||||
|
xsltExtensionInstructionResultFinalize()
|
||||||
|
Fixes:
|
||||||
|
#339222 - xsl:param at invalid position inside an xsl:template is
|
||||||
|
not catched
|
||||||
|
#346015 - Non-declared caller-parameters are accepted
|
||||||
|
#160400 - Compiles invalid XSLT; unbound variable accepted
|
||||||
|
#308441 - namespaced parameters become unregistered
|
||||||
|
#307103 - problem with proximity position in predicates of match
|
||||||
|
patterns
|
||||||
|
#328218 - problem with exsl:node-set() when converting strings
|
||||||
|
to node sets
|
||||||
|
#318088 - infinite recursion detection
|
||||||
|
#321505 - Multiple contiguous CDATA in output
|
||||||
|
#334493 - "--param" option does not have root context
|
||||||
|
#114377 - weird func:result/xsl:variable/exsl:node-set interaction
|
||||||
|
#150309 - Regression caused by fix for 142768
|
||||||
|
|
||||||
Wed Jun 21 15:13:27 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
|
Wed Jun 21 15:13:27 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
|
||||||
|
|
||||||
* tests/docs/bug-54.xml tests/general/bug-54.out
|
* tests/docs/bug-54.xml tests/general/bug-54.out
|
||||||
|
@@ -23,34 +23,49 @@
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
exsltNodeSetFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
exsltNodeSetFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
||||||
xmlChar *strval;
|
|
||||||
xmlNodePtr retNode;
|
|
||||||
xmlXPathObjectPtr ret;
|
|
||||||
|
|
||||||
if (nargs != 1) {
|
if (nargs != 1) {
|
||||||
xmlXPathSetArityError(ctxt);
|
xmlXPathSetArityError(ctxt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlXPathStackIsNodeSet (ctxt)) {
|
if (xmlXPathStackIsNodeSet (ctxt)) {
|
||||||
xsltFunctionNodeSet (ctxt, nargs);
|
xsltFunctionNodeSet (ctxt, nargs);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
strval = xmlXPathPopString (ctxt);
|
|
||||||
retNode = xmlNewDocText (NULL, strval);
|
|
||||||
ret = xmlXPathNewValueTree (retNode);
|
|
||||||
if (ret == NULL) {
|
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
|
||||||
"exsltNodeSetFunction: ret == NULL\n");
|
|
||||||
} else {
|
} else {
|
||||||
ret->type = XPATH_NODESET;
|
xmlDocPtr fragment;
|
||||||
|
xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
|
||||||
|
xmlNodePtr txt;
|
||||||
|
xmlChar *strval;
|
||||||
|
xmlXPathObjectPtr obj;
|
||||||
|
/*
|
||||||
|
* SPEC EXSLT:
|
||||||
|
* "You can also use this function to turn a string into a text
|
||||||
|
* node, which is helpful if you want to pass a string to a
|
||||||
|
* function that only accepts a node-set."
|
||||||
|
*/
|
||||||
|
fragment = xsltCreateRVT(tctxt);
|
||||||
|
if (fragment == NULL) {
|
||||||
|
xsltTransformError(tctxt, NULL, tctxt->inst,
|
||||||
|
"exsltNodeSetFunction: Failed to create a tree fragment.\n");
|
||||||
|
tctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xsltRegisterLocalRVT(tctxt, fragment);
|
||||||
|
|
||||||
|
strval = xmlXPathPopString (ctxt);
|
||||||
|
|
||||||
|
txt = xmlNewDocText (fragment, strval);
|
||||||
|
xmlAddChild((xmlNodePtr) fragment, txt);
|
||||||
|
obj = xmlXPathNewNodeSet(txt);
|
||||||
|
if (obj == NULL) {
|
||||||
|
xsltTransformError(tctxt, NULL, tctxt->inst,
|
||||||
|
"exsltNodeSetFunction: Failed to create a node set object.\n");
|
||||||
|
tctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
}
|
||||||
|
if (strval != NULL)
|
||||||
|
xmlFree (strval);
|
||||||
|
|
||||||
|
valuePush (ctxt, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strval != NULL)
|
|
||||||
xmlFree (strval);
|
|
||||||
|
|
||||||
valuePush (ctxt, ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -149,7 +149,7 @@ exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs)
|
|||||||
*/
|
*/
|
||||||
container = xsltCreateRVT(xsltXPathGetTransformContext(ctxt));
|
container = xsltCreateRVT(xsltXPathGetTransformContext(ctxt));
|
||||||
if (container != NULL)
|
if (container != NULL)
|
||||||
xsltRegisterTmpRVT(xsltXPathGetTransformContext(ctxt), container);
|
xsltRegisterLocalRVT(xsltXPathGetTransformContext(ctxt), container);
|
||||||
|
|
||||||
if (nodeset && nodeset->nodeNr > 0) {
|
if (nodeset && nodeset->nodeNr > 0) {
|
||||||
xmlXPathNodeSetSort(nodeset);
|
xmlXPathNodeSetSort(nodeset);
|
||||||
|
@@ -35,6 +35,7 @@ struct _exsltFuncData {
|
|||||||
xmlHashTablePtr funcs; /* pointer to the stylesheet module data */
|
xmlHashTablePtr funcs; /* pointer to the stylesheet module data */
|
||||||
xmlXPathObjectPtr result; /* returned by func:result */
|
xmlXPathObjectPtr result; /* returned by func:result */
|
||||||
int error; /* did an error occur? */
|
int error; /* did an error occur? */
|
||||||
|
xmlDocPtr RVT; /* result tree fragment */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;
|
typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;
|
||||||
@@ -56,6 +57,8 @@ static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,
|
|||||||
int nargs);
|
int nargs);
|
||||||
static exsltFuncFunctionData *exsltFuncNewFunctionData(void);
|
static exsltFuncFunctionData *exsltFuncNewFunctionData(void);
|
||||||
|
|
||||||
|
static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* exsltFuncRegisterFunc:
|
* exsltFuncRegisterFunc:
|
||||||
* @func: the #exsltFuncFunctionData for the function
|
* @func: the #exsltFuncFunctionData for the function
|
||||||
@@ -274,7 +277,7 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
xmlXPathObjectPtr obj, oldResult, ret;
|
xmlXPathObjectPtr obj, oldResult, ret;
|
||||||
exsltFuncData *data;
|
exsltFuncData *data;
|
||||||
exsltFuncFunctionData *func;
|
exsltFuncFunctionData *func;
|
||||||
xmlNodePtr paramNode, oldInsert, fake, content = NULL;
|
xmlNodePtr paramNode, oldInsert, fake;
|
||||||
int oldBase;
|
int oldBase;
|
||||||
xsltStackElemPtr params = NULL, param;
|
xsltStackElemPtr params = NULL, param;
|
||||||
xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
|
xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
|
||||||
@@ -304,7 +307,6 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
}
|
}
|
||||||
if (func->content != NULL) {
|
if (func->content != NULL) {
|
||||||
paramNode = func->content->prev;
|
paramNode = func->content->prev;
|
||||||
content = func->content;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
paramNode = NULL;
|
paramNode = NULL;
|
||||||
@@ -314,16 +316,36 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
"param == NULL\n");
|
"param == NULL\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
/* set params */
|
* Process xsl:param instructions which were not set by the
|
||||||
|
* invoking function call.
|
||||||
|
*/
|
||||||
for (i = func->nargs; (i > nargs) && (paramNode != NULL); i--) {
|
for (i = func->nargs; (i > nargs) && (paramNode != NULL); i--) {
|
||||||
|
/*
|
||||||
|
* Those are the xsl:param instructions, which were not
|
||||||
|
* set by the calling function.
|
||||||
|
*/
|
||||||
|
param = xsltParseStylesheetCallerParam (tctxt, paramNode);
|
||||||
|
param->next = params;
|
||||||
|
params = param;
|
||||||
paramNode = paramNode->prev;
|
paramNode = paramNode->prev;
|
||||||
if (content != NULL)
|
|
||||||
content = content->prev;
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Process xsl:param instructions which are set by the
|
||||||
|
* invoking function call.
|
||||||
|
*/
|
||||||
while ((i-- > 0) && (paramNode != NULL)) {
|
while ((i-- > 0) && (paramNode != NULL)) {
|
||||||
obj = valuePop(ctxt);
|
obj = valuePop(ctxt);
|
||||||
/* FIXME: this is a bit hackish */
|
/*
|
||||||
|
* TODO: Using xsltParseStylesheetCallerParam() is actually
|
||||||
|
* not correct, since we are processing an xsl:param; but
|
||||||
|
* using xsltParseStylesheetParam() won't work, as it puts
|
||||||
|
* the param on the varible stack and does not give access to
|
||||||
|
* the created xsltStackElemPtr.
|
||||||
|
* It's also not correct, as xsltParseStylesheetCallerParam()
|
||||||
|
* will report error messages indicating an "xsl:with-param" and
|
||||||
|
* not the actual "xsl:param".
|
||||||
|
*/
|
||||||
param = xsltParseStylesheetCallerParam (tctxt, paramNode);
|
param = xsltParseStylesheetCallerParam (tctxt, paramNode);
|
||||||
param->computed = 1;
|
param->computed = 1;
|
||||||
if (param->value != NULL)
|
if (param->value != NULL)
|
||||||
@@ -348,18 +370,18 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
oldBase = tctxt->varsBase;
|
oldBase = tctxt->varsBase;
|
||||||
tctxt->varsBase = tctxt->varsNr;
|
tctxt->varsBase = tctxt->varsNr;
|
||||||
xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt),
|
xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt),
|
||||||
content, NULL, params);
|
func->content, NULL, params);
|
||||||
tctxt->insert = oldInsert;
|
tctxt->insert = oldInsert;
|
||||||
tctxt->varsBase = oldBase; /* restore original scope */
|
tctxt->varsBase = oldBase; /* restore original scope */
|
||||||
if (params != NULL)
|
if (params != NULL)
|
||||||
xsltFreeStackElemList(params);
|
xsltFreeStackElemList(params);
|
||||||
|
|
||||||
if (data->error != 0)
|
if (data->error != 0)
|
||||||
return;
|
goto error;
|
||||||
|
|
||||||
if (data->result != NULL)
|
if (data->result != NULL) {
|
||||||
ret = data->result;
|
ret = data->result;
|
||||||
else
|
} else
|
||||||
ret = xmlXPathNewCString("");
|
ret = xmlXPathNewCString("");
|
||||||
|
|
||||||
data->result = oldResult;
|
data->result = oldResult;
|
||||||
@@ -377,10 +399,18 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
"executing a function\n",
|
"executing a function\n",
|
||||||
ctxt->context->functionURI, ctxt->context->function);
|
ctxt->context->functionURI, ctxt->context->function);
|
||||||
xmlFreeNode(fake);
|
xmlFreeNode(fake);
|
||||||
return;
|
goto error;
|
||||||
}
|
}
|
||||||
xmlFreeNode(fake);
|
xmlFreeNode(fake);
|
||||||
valuePush(ctxt, ret);
|
valuePush(ctxt, ret);
|
||||||
|
|
||||||
|
error:
|
||||||
|
/*
|
||||||
|
* IMPORTANT: This enables previously tree fragments marked as
|
||||||
|
* being results of a function, to be garbage-collected after
|
||||||
|
* the calling process exits.
|
||||||
|
*/
|
||||||
|
xsltExtensionInstructionResultFinalize(tctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -569,8 +599,7 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
|
|||||||
exsltFuncResultPreComp *comp) {
|
exsltFuncResultPreComp *comp) {
|
||||||
exsltFuncData *data;
|
exsltFuncData *data;
|
||||||
xmlXPathObjectPtr ret;
|
xmlXPathObjectPtr ret;
|
||||||
xmlNsPtr *oldNsList;
|
|
||||||
int oldNsNr;
|
|
||||||
|
|
||||||
/* It is an error if instantiating the content of the
|
/* It is an error if instantiating the content of the
|
||||||
* func:function element results in the instantiation of more than
|
* func:function element results in the instantiation of more than
|
||||||
@@ -592,6 +621,9 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
|
|||||||
* Processing
|
* Processing
|
||||||
*/
|
*/
|
||||||
if (comp->select != NULL) {
|
if (comp->select != NULL) {
|
||||||
|
xmlNsPtr *oldXPNsList;
|
||||||
|
int oldXPNsNr;
|
||||||
|
xmlNodePtr oldXPContextNode;
|
||||||
/* If the func:result element has a select attribute, then the
|
/* If the func:result element has a select attribute, then the
|
||||||
* value of the attribute must be an expression and the
|
* value of the attribute must be an expression and the
|
||||||
* returned value is the object that results from evaluating
|
* returned value is the object that results from evaluating
|
||||||
@@ -604,18 +636,29 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
|
|||||||
data->error = 1;
|
data->error = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
oldNsList = ctxt->xpathCtxt->namespaces;
|
oldXPNsList = ctxt->xpathCtxt->namespaces;
|
||||||
oldNsNr = ctxt->xpathCtxt->nsNr;
|
oldXPNsNr = ctxt->xpathCtxt->nsNr;
|
||||||
|
oldXPContextNode = ctxt->xpathCtxt->node;
|
||||||
|
|
||||||
ctxt->xpathCtxt->namespaces = comp->nsList;
|
ctxt->xpathCtxt->namespaces = comp->nsList;
|
||||||
ctxt->xpathCtxt->nsNr = comp->nsNr;
|
ctxt->xpathCtxt->nsNr = comp->nsNr;
|
||||||
|
|
||||||
ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);
|
ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);
|
||||||
ctxt->xpathCtxt->nsNr = oldNsNr;
|
|
||||||
ctxt->xpathCtxt->namespaces = oldNsList;
|
ctxt->xpathCtxt->node = oldXPContextNode;
|
||||||
|
ctxt->xpathCtxt->nsNr = oldXPNsNr;
|
||||||
|
ctxt->xpathCtxt->namespaces = oldXPNsList;
|
||||||
|
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"exsltFuncResultElem: ret == NULL\n");
|
"exsltFuncResultElem: ret == NULL\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Mark it as a function result in order to avoid garbage
|
||||||
|
* collecting of tree fragments before the function exits.
|
||||||
|
*/
|
||||||
|
xsltExtensionInstructionResultRegister(ctxt, ret);
|
||||||
} else if (inst->children != NULL) {
|
} else if (inst->children != NULL) {
|
||||||
/* If the func:result element does not have a select attribute
|
/* If the func:result element does not have a select attribute
|
||||||
* and has non-empty content (i.e. the func:result element has
|
* and has non-empty content (i.e. the func:result element has
|
||||||
@@ -632,7 +675,8 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
|
|||||||
data->error = 1;
|
data->error = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xsltRegisterTmpRVT(ctxt, container);
|
xsltRegisterLocalRVT(ctxt, container);
|
||||||
|
|
||||||
oldInsert = ctxt->insert;
|
oldInsert = ctxt->insert;
|
||||||
ctxt->insert = (xmlNodePtr) container;
|
ctxt->insert = (xmlNodePtr) container;
|
||||||
xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node,
|
xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node,
|
||||||
@@ -646,6 +690,11 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
|
|||||||
data->error = 1;
|
data->error = 1;
|
||||||
} else {
|
} else {
|
||||||
ret->boolval = 0; /* Freeing is not handled there anymore */
|
ret->boolval = 0; /* Freeing is not handled there anymore */
|
||||||
|
/*
|
||||||
|
* Mark it as a function result in order to avoid garbage
|
||||||
|
* collecting of tree fragments before the function exits.
|
||||||
|
*/
|
||||||
|
xsltExtensionInstructionResultRegister(ctxt, ret);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* If the func:result element has empty content and does not
|
/* If the func:result element has empty content and does not
|
||||||
|
@@ -71,10 +71,9 @@ exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs)
|
|||||||
|
|
||||||
container = xsltCreateRVT(tctxt);
|
container = xsltCreateRVT(tctxt);
|
||||||
if (container != NULL) {
|
if (container != NULL) {
|
||||||
xsltRegisterTmpRVT(tctxt, container);
|
xsltRegisterLocalRVT(tctxt, container);
|
||||||
ret = xmlXPathNewNodeSet(NULL);
|
ret = xmlXPathNewNodeSet(NULL);
|
||||||
if (ret != NULL) {
|
if (ret != NULL) {
|
||||||
ret->boolval = 0; /* Freeing is not handled there anymore */
|
|
||||||
for (cur = str, token = str; *cur != 0; cur += clen) {
|
for (cur = str, token = str; *cur != 0; cur += clen) {
|
||||||
clen = xmlUTF8Size(cur);
|
clen = xmlUTF8Size(cur);
|
||||||
if (*delimiters == 0) { /* empty string case */
|
if (*delimiters == 0) { /* empty string case */
|
||||||
@@ -174,12 +173,14 @@ exsltStrSplitFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OPTIMIZE TODO: We are creating an xmlDoc for every split!
|
||||||
|
*/
|
||||||
container = xsltCreateRVT(tctxt);
|
container = xsltCreateRVT(tctxt);
|
||||||
if (container != NULL) {
|
if (container != NULL) {
|
||||||
xsltRegisterTmpRVT(tctxt, container);
|
xsltRegisterLocalRVT(tctxt, container);
|
||||||
ret = xmlXPathNewNodeSet(NULL);
|
ret = xmlXPathNewNodeSet(NULL);
|
||||||
if (ret != NULL) {
|
if (ret != NULL) {
|
||||||
ret->boolval = 0; /* Freeing is not handled there anymore */
|
|
||||||
for (cur = str, token = str; *cur != 0; cur++) {
|
for (cur = str, token = str; *cur != 0; cur++) {
|
||||||
if (delimiterLength == 0) {
|
if (delimiterLength == 0) {
|
||||||
if (cur != token) {
|
if (cur != token) {
|
||||||
|
@@ -638,7 +638,7 @@ xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style) {
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
xsltAttributeInternal(xsltTransformContextPtr ctxt,
|
xsltAttributeInternal(xsltTransformContextPtr ctxt,
|
||||||
xmlNodePtr currentNode,
|
xmlNodePtr contextNode,
|
||||||
xmlNodePtr inst,
|
xmlNodePtr inst,
|
||||||
xsltStylePreCompPtr castedComp,
|
xsltStylePreCompPtr castedComp,
|
||||||
int fromAttributeSet)
|
int fromAttributeSet)
|
||||||
@@ -656,7 +656,7 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt,
|
|||||||
xmlNsPtr ns = NULL;
|
xmlNsPtr ns = NULL;
|
||||||
xmlAttrPtr attr;
|
xmlAttrPtr attr;
|
||||||
|
|
||||||
if ((ctxt == NULL) || (currentNode == NULL) || (inst == NULL))
|
if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -681,7 +681,7 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt,
|
|||||||
if (comp == NULL) {
|
if (comp == NULL) {
|
||||||
xsltTransformError(ctxt, NULL, inst,
|
xsltTransformError(ctxt, NULL, inst,
|
||||||
"Internal error in xsltAttributeInternal(): "
|
"Internal error in xsltAttributeInternal(): "
|
||||||
"The instruction was no compiled.\n");
|
"The XSLT 'attribute' instruction was not compiled.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -731,7 +731,7 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt,
|
|||||||
|
|
||||||
#ifdef WITH_DEBUGGER
|
#ifdef WITH_DEBUGGER
|
||||||
if (ctxt->debugStatus != XSLT_DEBUG_NONE)
|
if (ctxt->debugStatus != XSLT_DEBUG_NONE)
|
||||||
xslHandleDebugger(inst, currentNode, NULL, ctxt);
|
xslHandleDebugger(inst, contextNode, NULL, ctxt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (comp->name == NULL) {
|
if (comp->name == NULL) {
|
||||||
@@ -875,8 +875,10 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt,
|
|||||||
* tree fragment.
|
* tree fragment.
|
||||||
*/
|
*/
|
||||||
if (nsName != NULL) {
|
if (nsName != NULL) {
|
||||||
ns = xsltTreeAcquireStoredNs(ctxt->document->doc, nsName,
|
/*
|
||||||
prefix);
|
* TODO: Get the doc of @targetElem.
|
||||||
|
*/
|
||||||
|
ns = xsltTreeAcquireStoredNs(some doc, nsName, prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -980,7 +982,7 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt,
|
|||||||
/*
|
/*
|
||||||
* The sequence constructor might be complex, so instantiate it.
|
* The sequence constructor might be complex, so instantiate it.
|
||||||
*/
|
*/
|
||||||
value = xsltEvalTemplateString(ctxt, currentNode, inst);
|
value = xsltEvalTemplateString(ctxt, contextNode, inst);
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
attr = xmlSetNsProp(ctxt->insert, ns, name, value);
|
attr = xmlSetNsProp(ctxt->insert, ns, name, value);
|
||||||
xmlFree(value);
|
xmlFree(value);
|
||||||
|
@@ -410,7 +410,9 @@ xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {
|
|||||||
* @ctxt: an XSLT transformation context
|
* @ctxt: an XSLT transformation context
|
||||||
* @doc: a parsed XML document
|
* @doc: a parsed XML document
|
||||||
*
|
*
|
||||||
* Try to find a document within the XSLT transformation context
|
* Try to find a document within the XSLT transformation context.
|
||||||
|
* This will not find document infos for temporary
|
||||||
|
* Result Tree Fragments.
|
||||||
*
|
*
|
||||||
* Returns the desired xsltDocumentPtr or NULL in case of error
|
* Returns the desired xsltDocumentPtr or NULL in case of error
|
||||||
*/
|
*/
|
||||||
|
@@ -107,23 +107,23 @@ xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)
|
|||||||
xsltTransformContextPtr tctxt;
|
xsltTransformContextPtr tctxt;
|
||||||
xmlURIPtr uri;
|
xmlURIPtr uri;
|
||||||
xmlChar *fragment;
|
xmlChar *fragment;
|
||||||
xsltDocumentPtr xsltdoc;
|
xsltDocumentPtr idoc; /* document info */
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
xmlXPathContextPtr xptrctxt = NULL;
|
xmlXPathContextPtr xptrctxt = NULL;
|
||||||
xmlXPathObjectPtr object = NULL;
|
xmlXPathObjectPtr resObj = NULL;
|
||||||
|
|
||||||
tctxt = xsltXPathGetTransformContext(ctxt);
|
tctxt = xsltXPathGetTransformContext(ctxt);
|
||||||
if (tctxt == NULL) {
|
if (tctxt == NULL) {
|
||||||
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
xsltTransformError(NULL, NULL, NULL,
|
||||||
"document() : internal error tctxt == NULL\n");
|
"document() : internal error tctxt == NULL\n");
|
||||||
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uri = xmlParseURI((const char *) URI);
|
uri = xmlParseURI((const char *) URI);
|
||||||
if (uri == NULL) {
|
if (uri == NULL) {
|
||||||
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
xsltTransformError(tctxt, NULL, NULL,
|
||||||
"document() : failed to parse URI\n");
|
"document() : failed to parse URI\n");
|
||||||
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -135,16 +135,20 @@ xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)
|
|||||||
if (fragment != NULL) {
|
if (fragment != NULL) {
|
||||||
uri->fragment = NULL;
|
uri->fragment = NULL;
|
||||||
URI = xmlSaveUri(uri);
|
URI = xmlSaveUri(uri);
|
||||||
xsltdoc = xsltLoadDocument(tctxt, URI);
|
idoc = xsltLoadDocument(tctxt, URI);
|
||||||
xmlFree(URI);
|
xmlFree(URI);
|
||||||
} else
|
} else
|
||||||
xsltdoc = xsltLoadDocument(tctxt, URI);
|
idoc = xsltLoadDocument(tctxt, URI);
|
||||||
xmlFreeURI(uri);
|
xmlFreeURI(uri);
|
||||||
|
|
||||||
if (xsltdoc == NULL) {
|
if (idoc == NULL) {
|
||||||
if ((URI == NULL) ||
|
if ((URI == NULL) ||
|
||||||
(URI[0] == '#') ||
|
(URI[0] == '#') ||
|
||||||
(xmlStrEqual(tctxt->style->doc->URL, URI))) {
|
(xmlStrEqual(tctxt->style->doc->URL, URI)))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This selects the stylesheet's doc itself.
|
||||||
|
*/
|
||||||
doc = tctxt->style->doc;
|
doc = tctxt->style->doc;
|
||||||
} else {
|
} else {
|
||||||
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
||||||
@@ -155,11 +159,10 @@ xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
doc = xsltdoc->doc;
|
doc = idoc->doc;
|
||||||
|
|
||||||
if ( fragment == NULL ) {
|
if (fragment == NULL) {
|
||||||
valuePush(ctxt,
|
valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc));
|
||||||
xmlXPathNewNodeSet((xmlNodePtr) doc));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,43 +170,42 @@ xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)
|
|||||||
#ifdef LIBXML_XPTR_ENABLED
|
#ifdef LIBXML_XPTR_ENABLED
|
||||||
xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
|
xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
|
||||||
if (xptrctxt == NULL) {
|
if (xptrctxt == NULL) {
|
||||||
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
xsltTransformError(tctxt, NULL, NULL,
|
||||||
"document() : internal error xptrctxt == NULL\n");
|
"document() : internal error xptrctxt == NULL\n");
|
||||||
goto out_fragment;
|
goto out_fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
object = xmlXPtrEval(fragment, xptrctxt);
|
resObj = xmlXPtrEval(fragment, xptrctxt);
|
||||||
|
xmlXPathFreeContext(xptrctxt);
|
||||||
#endif
|
#endif
|
||||||
xmlFree(fragment);
|
xmlFree(fragment);
|
||||||
if (xptrctxt != NULL)
|
|
||||||
xmlXPathFreeContext(xptrctxt);
|
|
||||||
|
|
||||||
if (object == NULL)
|
if (resObj == NULL)
|
||||||
goto out_fragment;
|
goto out_fragment;
|
||||||
|
|
||||||
switch (object->type) {
|
switch (resObj->type) {
|
||||||
case XPATH_NODESET:
|
case XPATH_NODESET:
|
||||||
break;
|
break;
|
||||||
case XPATH_UNDEFINED:
|
case XPATH_UNDEFINED:
|
||||||
case XPATH_BOOLEAN:
|
case XPATH_BOOLEAN:
|
||||||
case XPATH_NUMBER:
|
case XPATH_NUMBER:
|
||||||
case XPATH_STRING:
|
case XPATH_STRING:
|
||||||
case XPATH_POINT:
|
case XPATH_POINT:
|
||||||
case XPATH_USERS:
|
case XPATH_USERS:
|
||||||
case XPATH_XSLT_TREE:
|
case XPATH_XSLT_TREE:
|
||||||
case XPATH_RANGE:
|
case XPATH_RANGE:
|
||||||
case XPATH_LOCATIONSET:
|
case XPATH_LOCATIONSET:
|
||||||
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
xsltTransformError(tctxt, NULL, NULL,
|
||||||
"document() : XPointer does not select a node set: #%s\n",
|
"document() : XPointer does not select a node set: #%s\n",
|
||||||
fragment);
|
fragment);
|
||||||
goto out_object;
|
goto out_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
valuePush(ctxt, object);
|
valuePush(ctxt, resObj);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
out_object:
|
out_object:
|
||||||
xmlXPathFreeObject(object);
|
xmlXPathFreeObject(resObj);
|
||||||
|
|
||||||
out_fragment:
|
out_fragment:
|
||||||
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
|
||||||
@@ -346,13 +348,7 @@ xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
|
xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
|
||||||
xmlNodeSetPtr nodelist;
|
|
||||||
xmlXPathObjectPtr obj1, obj2;
|
xmlXPathObjectPtr obj1, obj2;
|
||||||
xmlChar *key = NULL, *value;
|
|
||||||
const xmlChar *keyURI;
|
|
||||||
xsltTransformContextPtr tctxt;
|
|
||||||
xsltDocumentPtr oldDocumentPtr;
|
|
||||||
xmlDocPtr oldXPathDocPtr;
|
|
||||||
|
|
||||||
if (nargs != 2) {
|
if (nargs != 2) {
|
||||||
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
||||||
@@ -361,6 +357,9 @@ xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the key's value.
|
||||||
|
*/
|
||||||
obj2 = valuePop(ctxt);
|
obj2 = valuePop(ctxt);
|
||||||
xmlXPathStringFunction(ctxt, 1);
|
xmlXPathStringFunction(ctxt, 1);
|
||||||
if ((obj2 == NULL) ||
|
if ((obj2 == NULL) ||
|
||||||
@@ -372,6 +371,9 @@ xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Get the key's name.
|
||||||
|
*/
|
||||||
obj1 = valuePop(ctxt);
|
obj1 = valuePop(ctxt);
|
||||||
|
|
||||||
if ((obj2->type == XPATH_NODESET) || (obj2->type == XPATH_XSLT_TREE)) {
|
if ((obj2->type == XPATH_NODESET) || (obj2->type == XPATH_XSLT_TREE)) {
|
||||||
@@ -395,8 +397,26 @@ xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
|
|||||||
}
|
}
|
||||||
valuePush(ctxt, ret);
|
valuePush(ctxt, ret);
|
||||||
} else {
|
} else {
|
||||||
|
xmlNodeSetPtr nodelist = NULL;
|
||||||
|
xmlChar *key = NULL, *value;
|
||||||
|
const xmlChar *keyURI;
|
||||||
|
xsltTransformContextPtr tctxt;
|
||||||
xmlChar *qname, *prefix;
|
xmlChar *qname, *prefix;
|
||||||
|
xmlXPathContextPtr xpctxt = ctxt->context;
|
||||||
|
xmlNodePtr tmpNode = NULL;
|
||||||
|
xsltDocumentPtr oldDocInfo;
|
||||||
|
|
||||||
|
tctxt = xsltXPathGetTransformContext(ctxt);
|
||||||
|
|
||||||
|
oldDocInfo = tctxt->document;
|
||||||
|
|
||||||
|
if (xpctxt->node == NULL) {
|
||||||
|
xsltTransformError(tctxt, NULL, tctxt->inst,
|
||||||
|
"Internal error in xsltKeyFunction(): "
|
||||||
|
"The context node is not set on the XPath context.\n");
|
||||||
|
tctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Get the associated namespace URI if qualified name
|
* Get the associated namespace URI if qualified name
|
||||||
*/
|
*/
|
||||||
@@ -409,10 +429,13 @@ xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
|
|||||||
xmlFree(prefix);
|
xmlFree(prefix);
|
||||||
} else {
|
} else {
|
||||||
if (prefix != NULL) {
|
if (prefix != NULL) {
|
||||||
keyURI = xmlXPathNsLookup(ctxt->context, prefix);
|
keyURI = xmlXPathNsLookup(xpctxt, prefix);
|
||||||
if (keyURI == NULL) {
|
if (keyURI == NULL) {
|
||||||
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
xsltTransformError(tctxt, NULL, tctxt->inst,
|
||||||
"key() : prefix %s is not bound\n", prefix);
|
"key() : prefix %s is not bound\n", prefix);
|
||||||
|
/*
|
||||||
|
* TODO: Shouldn't we stop here?
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
xmlFree(prefix);
|
xmlFree(prefix);
|
||||||
} else {
|
} else {
|
||||||
@@ -426,59 +449,90 @@ xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
|
|||||||
valuePush(ctxt, obj2);
|
valuePush(ctxt, obj2);
|
||||||
xmlXPathStringFunction(ctxt, 1);
|
xmlXPathStringFunction(ctxt, 1);
|
||||||
if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
|
if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
|
||||||
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
xsltTransformError(tctxt, NULL, tctxt->inst,
|
||||||
"key() : invalid arg expecting a string\n");
|
"key() : invalid arg expecting a string\n");
|
||||||
ctxt->error = XPATH_INVALID_TYPE;
|
ctxt->error = XPATH_INVALID_TYPE;
|
||||||
xmlXPathFreeObject(obj1);
|
goto error;
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
obj2 = valuePop(ctxt);
|
obj2 = valuePop(ctxt);
|
||||||
value = obj2->stringval;
|
value = obj2->stringval;
|
||||||
|
|
||||||
tctxt = xsltXPathGetTransformContext(ctxt);
|
/*
|
||||||
oldDocumentPtr = tctxt->document;
|
* We need to ensure that ctxt->document is available for
|
||||||
oldXPathDocPtr = tctxt->xpathCtxt->doc;
|
* xsltGetKey().
|
||||||
if ((ctxt->context->doc != NULL) &&
|
* First find the relevant doc, which is the context node's
|
||||||
(tctxt->document->doc != ctxt->context->doc)) {
|
* owner doc; using context->doc is not safe, since
|
||||||
|
* the doc could have been acquired via the document() function,
|
||||||
|
* or the doc might be a Result Tree Fragment.
|
||||||
|
* FUTURE INFO: In XSLT 2.0 the key() function takes an additional
|
||||||
|
* argument indicating the doc to use.
|
||||||
|
*/
|
||||||
|
if (xpctxt->node->type == XML_NAMESPACE_DECL) {
|
||||||
/*
|
/*
|
||||||
* The xpath context document needs to be changed. If the
|
* REVISIT: This is a libxml hack! Check xpath.c for details.
|
||||||
* current context document is a node-set, we must use an
|
* The XPath module sets the owner element of a ns-node on
|
||||||
* xsltDocument associated with the node-set, which may or
|
* the ns->next field.
|
||||||
* may not currently exist.
|
*/
|
||||||
*/
|
if ((((xmlNsPtr) xpctxt->node)->next != NULL) &&
|
||||||
if (xmlStrEqual((const xmlChar *)ctxt->context->doc->name,
|
(((xmlNsPtr) xpctxt->node)->next->type == XML_ELEMENT_NODE))
|
||||||
BAD_CAST " fake node libxslt")) { /* node-set */
|
{
|
||||||
/*
|
tmpNode = (xmlNodePtr) ((xmlNsPtr) xpctxt->node)->next;
|
||||||
* Check whether we already have an xsltDocument set up
|
|
||||||
*/
|
|
||||||
if (ctxt->context->doc->_private == NULL) /* nope */
|
|
||||||
ctxt->context->doc->_private =
|
|
||||||
xsltNewDocument(tctxt, ctxt->context->doc);
|
|
||||||
tctxt->document = ctxt->context->doc->_private;
|
|
||||||
}
|
}
|
||||||
else {
|
} else
|
||||||
tctxt->document = xsltFindDocument(tctxt, ctxt->context->doc);
|
tmpNode = xpctxt->node;
|
||||||
if (tctxt->document == NULL)
|
|
||||||
tctxt->document = oldDocumentPtr;
|
if ((tmpNode == NULL) || (tmpNode->doc == NULL)) {
|
||||||
else
|
xsltTransformError(tctxt, NULL, tctxt->inst,
|
||||||
tctxt->xpathCtxt->doc = ctxt->context->doc;
|
"Internal error in xsltKeyFunction(): "
|
||||||
|
"Couldn't get the doc of the XPath context node.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tctxt->document == NULL) ||
|
||||||
|
(tctxt->document->doc != tmpNode->doc))
|
||||||
|
{
|
||||||
|
if (tmpNode->doc->name && (tmpNode->doc->name[0] == ' ')) {
|
||||||
|
/*
|
||||||
|
* This is a Result Tree Fragment.
|
||||||
|
*/
|
||||||
|
if (tmpNode->doc->_private == NULL) {
|
||||||
|
tmpNode->doc->_private = xsltNewDocument(tctxt, tmpNode->doc);
|
||||||
|
if (tmpNode->doc->_private == NULL)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
tctxt->document = (xsltDocumentPtr) tmpNode->doc->_private;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* May be the initial source doc or a doc acquired via the
|
||||||
|
* document() function.
|
||||||
|
*/
|
||||||
|
tctxt->document = xsltFindDocument(tctxt, tmpNode->doc);
|
||||||
|
}
|
||||||
|
if (tctxt->document == NULL) {
|
||||||
|
xsltTransformError(tctxt, NULL, tctxt->inst,
|
||||||
|
"Internal error in xsltKeyFunction(): "
|
||||||
|
"Could not get the document info of a context doc.\n");
|
||||||
|
tctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Get/compute the key value.
|
||||||
|
*/
|
||||||
nodelist = xsltGetKey(tctxt, key, keyURI, value);
|
nodelist = xsltGetKey(tctxt, key, keyURI, value);
|
||||||
tctxt->document = oldDocumentPtr;
|
|
||||||
tctxt->xpathCtxt->doc = oldXPathDocPtr;
|
|
||||||
valuePush(ctxt, xmlXPathWrapNodeSet(
|
|
||||||
xmlXPathNodeSetMerge(NULL, nodelist)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
error:
|
||||||
|
tctxt->document = oldDocInfo;
|
||||||
|
valuePush(ctxt, xmlXPathWrapNodeSet(
|
||||||
|
xmlXPathNodeSetMerge(NULL, nodelist)));
|
||||||
|
if (key != NULL)
|
||||||
|
xmlFree(key);
|
||||||
|
}
|
||||||
|
|
||||||
if (obj1 != NULL)
|
if (obj1 != NULL)
|
||||||
xmlXPathFreeObject(obj1);
|
xmlXPathFreeObject(obj1);
|
||||||
if (obj2 != NULL)
|
if (obj2 != NULL)
|
||||||
xmlXPathFreeObject(obj2);
|
xmlXPathFreeObject(obj2);
|
||||||
if (key != NULL)
|
|
||||||
xmlFree(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
371
libxslt/keys.c
371
libxslt/keys.c
@@ -382,7 +382,9 @@ error:
|
|||||||
* @nameURI: the name URI or NULL
|
* @nameURI: the name URI or NULL
|
||||||
* @value: the key value to look for
|
* @value: the key value to look for
|
||||||
*
|
*
|
||||||
* Lookup a key
|
* Looks up a key of the in current source doc (the document info
|
||||||
|
* on @ctxt->document). Computes the key if not already done
|
||||||
|
* for the current source doc.
|
||||||
*
|
*
|
||||||
* Returns the nodeset resulting from the query or NULL
|
* Returns the nodeset resulting from the query or NULL
|
||||||
*/
|
*/
|
||||||
@@ -403,6 +405,7 @@ xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name,
|
|||||||
xsltGenericDebug(xsltGenericDebugContext,
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
"Get key %s, value %s\n", name, value);
|
"Get key %s, value %s\n", name, value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
table = (xsltKeyTablePtr) ctxt->document->keys;
|
table = (xsltKeyTablePtr) ctxt->document->keys;
|
||||||
while (table != NULL) {
|
while (table != NULL) {
|
||||||
if (((nameURI != NULL) == (table->nameURI != NULL)) &&
|
if (((nameURI != NULL) == (table->nameURI != NULL)) &&
|
||||||
@@ -464,6 +467,7 @@ xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name,
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 /* Merged with xsltInitCtxtKey() */
|
||||||
/**
|
/**
|
||||||
* xsltEvalXPathKeys:
|
* xsltEvalXPathKeys:
|
||||||
* @ctxt: the XSLT transformation context
|
* @ctxt: the XSLT transformation context
|
||||||
@@ -547,104 +551,117 @@ xsltEvalXPathKeys(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
|
|||||||
ctxt->xpathCtxt->namespaces = oldNamespaces;
|
ctxt->xpathCtxt->namespaces = oldNamespaces;
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltInitCtxtKey:
|
* xsltInitCtxtKey:
|
||||||
* @ctxt: an XSLT transformation context
|
* @ctxt: an XSLT transformation context
|
||||||
* @doc: an XSLT document
|
* @idoc: the document information (holds key values)
|
||||||
* @keyd: the key definition
|
* @keyDef: the key definition
|
||||||
*
|
*
|
||||||
* Computes the key tables this key and for the current input document.
|
* Computes the key tables this key and for the current input document.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc,
|
xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc,
|
||||||
xsltKeyDefPtr keyd) {
|
xsltKeyDefPtr keyDef)
|
||||||
int i;
|
{
|
||||||
xmlNodeSetPtr nodelist = NULL, keylist;
|
int i, len, k;
|
||||||
xmlXPathObjectPtr res = NULL;
|
xmlNodeSetPtr matchList = NULL, keylist;
|
||||||
xmlChar *str, **list;
|
xmlXPathObjectPtr matchRes = NULL, useRes = NULL;
|
||||||
|
xmlChar *str = NULL;
|
||||||
xsltKeyTablePtr table;
|
xsltKeyTablePtr table;
|
||||||
int oldPos, oldSize;
|
xmlNodePtr oldInst, cur;
|
||||||
xmlNodePtr oldInst;
|
xmlNodePtr oldContextNode;
|
||||||
xmlNodePtr oldNode;
|
xsltDocumentPtr oldDocInfo;
|
||||||
xsltDocumentPtr oldDoc;
|
int oldXPPos, oldXPSize;
|
||||||
xmlDocPtr oldXDoc;
|
xmlDocPtr oldXPDoc;
|
||||||
int oldNsNr;
|
int oldXPNsNr;
|
||||||
xmlNsPtr *oldNamespaces;
|
xmlNsPtr *oldXPNamespaces;
|
||||||
|
xmlXPathContextPtr xpctxt;
|
||||||
|
|
||||||
doc->nbKeysComputed++;
|
if ((keyDef->comp == NULL) || (keyDef->usecomp == NULL))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
xpctxt = ctxt->xpathCtxt;
|
||||||
|
idoc->nbKeysComputed++;
|
||||||
/*
|
/*
|
||||||
* Evaluate the nodelist
|
* Save context state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
oldXDoc= ctxt->xpathCtxt->doc;
|
|
||||||
oldPos = ctxt->xpathCtxt->proximityPosition;
|
|
||||||
oldSize = ctxt->xpathCtxt->contextSize;
|
|
||||||
oldNsNr = ctxt->xpathCtxt->nsNr;
|
|
||||||
oldNamespaces = ctxt->xpathCtxt->namespaces;
|
|
||||||
oldInst = ctxt->inst;
|
oldInst = ctxt->inst;
|
||||||
oldDoc = ctxt->document;
|
oldDocInfo = ctxt->document;
|
||||||
oldNode = ctxt->node;
|
oldContextNode = ctxt->node;
|
||||||
|
|
||||||
if (keyd->comp == NULL)
|
oldXPDoc = xpctxt->doc;
|
||||||
goto error;
|
oldXPPos = xpctxt->proximityPosition;
|
||||||
if (keyd->usecomp == NULL)
|
oldXPSize = xpctxt->contextSize;
|
||||||
goto error;
|
oldXPNsNr = xpctxt->nsNr;
|
||||||
|
oldXPNamespaces = xpctxt->namespaces;
|
||||||
|
|
||||||
ctxt->document = doc;
|
/*
|
||||||
ctxt->xpathCtxt->doc = doc->doc;
|
* Set up contexts.
|
||||||
ctxt->xpathCtxt->node = (xmlNodePtr) doc->doc;
|
*/
|
||||||
ctxt->node = (xmlNodePtr) doc->doc;
|
ctxt->document = idoc;
|
||||||
|
ctxt->node = (xmlNodePtr) idoc->doc;
|
||||||
|
ctxt->inst = keyDef->inst;
|
||||||
|
|
||||||
|
xpctxt->doc = idoc->doc;
|
||||||
|
xpctxt->node = (xmlNodePtr) idoc->doc;
|
||||||
/* TODO : clarify the use of namespaces in keys evaluation */
|
/* TODO : clarify the use of namespaces in keys evaluation */
|
||||||
ctxt->xpathCtxt->namespaces = keyd->nsList;
|
xpctxt->namespaces = keyDef->nsList;
|
||||||
ctxt->xpathCtxt->nsNr = keyd->nsNr;
|
xpctxt->nsNr = keyDef->nsNr;
|
||||||
ctxt->inst = keyd->inst;
|
|
||||||
res = xmlXPathCompiledEval(keyd->comp, ctxt->xpathCtxt);
|
/*
|
||||||
ctxt->xpathCtxt->contextSize = oldSize;
|
* Evaluate the 'match' expression of the xsl:key.
|
||||||
ctxt->xpathCtxt->proximityPosition = oldPos;
|
* TODO: The 'match' is a *pattern*.
|
||||||
ctxt->inst = oldInst;
|
*/
|
||||||
|
matchRes = xmlXPathCompiledEval(keyDef->comp, xpctxt);
|
||||||
|
if (matchRes == NULL) {
|
||||||
|
|
||||||
if (res != NULL) {
|
|
||||||
if (res->type == XPATH_NODESET) {
|
|
||||||
nodelist = res->nodesetval;
|
|
||||||
#ifdef WITH_XSLT_DEBUG_KEYS
|
|
||||||
if (nodelist != NULL)
|
|
||||||
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
|
||||||
"xsltInitCtxtKey: %s evaluates to %d nodes\n",
|
|
||||||
keyd->match, nodelist->nodeNr));
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
#ifdef WITH_XSLT_DEBUG_KEYS
|
|
||||||
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
|
||||||
"xsltInitCtxtKey: %s is not a node set\n", keyd->match));
|
|
||||||
#endif
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#ifdef WITH_XSLT_DEBUG_KEYS
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
"xsltInitCtxtKey: %s evaluation failed\n", keyd->match));
|
"xsltInitCtxtKey: %s evaluation failed\n", keyDef->match));
|
||||||
#endif
|
#endif
|
||||||
|
xsltTransformError(ctxt, NULL, keyDef->inst,
|
||||||
|
"Failed to evaluate the 'match' expression.\n");
|
||||||
ctxt->state = XSLT_STATE_STOPPED;
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
} else {
|
||||||
|
if (matchRes->type == XPATH_NODESET) {
|
||||||
|
matchList = matchRes->nodesetval;
|
||||||
|
|
||||||
/*
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
* for each node in the list evaluate the key and insert the node
|
if (matchList != NULL)
|
||||||
*/
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
if ((nodelist == NULL) || (nodelist->nodeNr <= 0))
|
"xsltInitCtxtKey: %s evaluates to %d nodes\n",
|
||||||
goto error;
|
keyDef->match, matchList->nodeNr));
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Is not a node set, but must be.
|
||||||
|
*/
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltInitCtxtKey: %s is not a node set\n", keyDef->match));
|
||||||
|
#endif
|
||||||
|
xsltTransformError(ctxt, NULL, keyDef->inst,
|
||||||
|
"The 'match' expression did not evaluate to a node set.\n");
|
||||||
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((matchList == NULL) || (matchList->nodeNr <= 0))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiple key definitions for the same name are allowed, so
|
* Multiple key definitions for the same name are allowed, so
|
||||||
* we must check if the key is already present for this doc
|
* we must check if the key is already present for this doc
|
||||||
*/
|
*/
|
||||||
table = (xsltKeyTablePtr) doc->keys;
|
table = (xsltKeyTablePtr) idoc->keys;
|
||||||
while (table != NULL) {
|
while (table != NULL) {
|
||||||
if (xmlStrEqual(table->name, keyd->name) &&
|
if (xmlStrEqual(table->name, keyDef->name) &&
|
||||||
(((keyd->nameURI == NULL) && (table->nameURI == NULL)) ||
|
(((keyDef->nameURI == NULL) && (table->nameURI == NULL)) ||
|
||||||
((keyd->nameURI != NULL) && (table->nameURI != NULL) &&
|
((keyDef->nameURI != NULL) && (table->nameURI != NULL) &&
|
||||||
(xmlStrEqual(table->nameURI, keyd->nameURI)))))
|
(xmlStrEqual(table->nameURI, keyDef->nameURI)))))
|
||||||
break;
|
break;
|
||||||
table = table->next;
|
table = table->next;
|
||||||
}
|
}
|
||||||
@@ -653,112 +670,170 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc,
|
|||||||
* chain it to the list of keys for the doc
|
* chain it to the list of keys for the doc
|
||||||
*/
|
*/
|
||||||
if (table == NULL) {
|
if (table == NULL) {
|
||||||
table = xsltNewKeyTable(keyd->name, keyd->nameURI);
|
table = xsltNewKeyTable(keyDef->name, keyDef->nameURI);
|
||||||
if (table == NULL)
|
if (table == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
table->next = doc->keys;
|
table->next = idoc->keys;
|
||||||
doc->keys = table;
|
idoc->keys = table;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0;i < nodelist->nodeNr;i++) {
|
/*
|
||||||
if (IS_XSLT_REAL_NODE(nodelist->nodeTab[i])) {
|
* SPEC XSLT 1.0 (XSLT 2.0 does not clarify the context size!)
|
||||||
ctxt->node = nodelist->nodeTab[i];
|
* "...the use attribute of the xsl:key element is evaluated with x as
|
||||||
|
" the current node and with a node list containing just x as the
|
||||||
|
* current node list"
|
||||||
|
*/
|
||||||
|
xpctxt->contextSize = 1;
|
||||||
|
xpctxt->proximityPosition = 1;
|
||||||
|
|
||||||
list = xsltEvalXPathKeys(ctxt, keyd->usecomp, keyd);
|
for (i = 0; i < matchList->nodeNr; i++) {
|
||||||
if (list != NULL) {
|
cur = matchList->nodeTab[i];
|
||||||
int ix = 0;
|
if (! IS_XSLT_REAL_NODE(cur))
|
||||||
|
continue;
|
||||||
str = list[ix++];
|
xpctxt->node = cur;
|
||||||
while (str != NULL) {
|
/*
|
||||||
#ifdef WITH_XSLT_DEBUG_KEYS
|
* Process the 'use' of the xsl:key.
|
||||||
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
* SPEC XSLT 1.0:
|
||||||
"xsl:key : node associated to(%s,%s)\n",
|
* "The use attribute is an expression specifying the values of
|
||||||
keyd->name, str));
|
* the key; the expression is evaluated once for each node that
|
||||||
#endif
|
* matches the pattern."
|
||||||
keylist = xmlHashLookup(table->keys, str);
|
*/
|
||||||
if (keylist == NULL) {
|
if (useRes != NULL)
|
||||||
keylist = xmlXPathNodeSetCreate(nodelist->nodeTab[i]);
|
xmlXPathFreeObject(useRes);
|
||||||
xmlHashAddEntry(table->keys, str, keylist);
|
useRes = xmlXPathCompiledEval(keyDef->usecomp, xpctxt);
|
||||||
} else {
|
if (useRes == NULL) {
|
||||||
xmlXPathNodeSetAdd(keylist, nodelist->nodeTab[i]);
|
xsltTransformError(ctxt, NULL, keyDef->inst,
|
||||||
}
|
"Failed to evaluate the 'use' expression.\n");
|
||||||
switch (nodelist->nodeTab[i]->type) {
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
case XML_ELEMENT_NODE:
|
break;
|
||||||
case XML_TEXT_NODE:
|
}
|
||||||
case XML_CDATA_SECTION_NODE:
|
if (useRes->type == XPATH_NODESET) {
|
||||||
case XML_PI_NODE:
|
if ((useRes->nodesetval != NULL) &&
|
||||||
case XML_COMMENT_NODE:
|
(useRes->nodesetval->nodeNr != 0))
|
||||||
nodelist->nodeTab[i]->psvi = keyd;
|
{
|
||||||
break;
|
len = useRes->nodesetval->nodeNr;
|
||||||
case XML_ATTRIBUTE_NODE: {
|
str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[0]);
|
||||||
xmlAttrPtr attr = (xmlAttrPtr)
|
|
||||||
nodelist->nodeTab[i];
|
|
||||||
attr->psvi = keyd;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XML_DOCUMENT_NODE:
|
|
||||||
case XML_HTML_DOCUMENT_NODE: {
|
|
||||||
xmlDocPtr kdoc = (xmlDocPtr)
|
|
||||||
nodelist->nodeTab[i];
|
|
||||||
kdoc->psvi = keyd;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
xmlFree(str);
|
|
||||||
str = list[ix++];
|
|
||||||
}
|
|
||||||
xmlFree(list);
|
|
||||||
#ifdef WITH_XSLT_DEBUG_KEYS
|
|
||||||
} else {
|
} else {
|
||||||
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
continue;
|
||||||
"xsl:key : use %s failed to return strings\n",
|
|
||||||
keyd->use));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
len = 1;
|
||||||
|
if (useRes->type == XPATH_STRING) {
|
||||||
|
/*
|
||||||
|
* Consume the string value.
|
||||||
|
*/
|
||||||
|
str = useRes->stringval;
|
||||||
|
useRes->stringval = NULL;
|
||||||
|
} else {
|
||||||
|
str = xmlXPathCastToString(useRes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Process all strings.
|
||||||
|
*/
|
||||||
|
k = 0;
|
||||||
|
while (1) {
|
||||||
|
if (str == NULL)
|
||||||
|
goto next_string;
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsl:key : node associated to ('%s', '%s')\n", keyDef->name, str));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
keylist = xmlHashLookup(table->keys, str);
|
||||||
|
if (keylist == NULL) {
|
||||||
|
keylist = xmlXPathNodeSetCreate(cur);
|
||||||
|
if (keylist == NULL)
|
||||||
|
goto error;
|
||||||
|
xmlHashAddEntry(table->keys, str, keylist);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* TODO: How do we know if this function failed?
|
||||||
|
*/
|
||||||
|
xmlXPathNodeSetAdd(keylist, cur);
|
||||||
|
}
|
||||||
|
switch (cur->type) {
|
||||||
|
case XML_ELEMENT_NODE:
|
||||||
|
case XML_TEXT_NODE:
|
||||||
|
case XML_CDATA_SECTION_NODE:
|
||||||
|
case XML_PI_NODE:
|
||||||
|
case XML_COMMENT_NODE:
|
||||||
|
cur->psvi = keyDef;
|
||||||
|
break;
|
||||||
|
case XML_ATTRIBUTE_NODE:
|
||||||
|
((xmlAttrPtr) cur)->psvi = keyDef;
|
||||||
|
break;
|
||||||
|
case XML_DOCUMENT_NODE:
|
||||||
|
case XML_HTML_DOCUMENT_NODE:
|
||||||
|
((xmlDocPtr) cur)->psvi = keyDef;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xmlFree(str);
|
||||||
|
str = NULL;
|
||||||
|
|
||||||
|
next_string:
|
||||||
|
k++;
|
||||||
|
if (k >= len)
|
||||||
|
break;
|
||||||
|
str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
error:
|
error:
|
||||||
ctxt->document = oldDoc;
|
/*
|
||||||
ctxt->xpathCtxt->doc = oldXDoc;
|
* Restore context state.
|
||||||
ctxt->xpathCtxt->nsNr = oldNsNr;
|
*/
|
||||||
ctxt->xpathCtxt->namespaces = oldNamespaces;
|
xpctxt->doc = oldXPDoc;
|
||||||
ctxt->node = oldNode;
|
xpctxt->nsNr = oldXPNsNr;
|
||||||
if (res != NULL)
|
xpctxt->namespaces = oldXPNamespaces;
|
||||||
xmlXPathFreeObject(res);
|
xpctxt->proximityPosition = oldXPPos;
|
||||||
|
xpctxt->contextSize = oldXPSize;
|
||||||
|
|
||||||
|
ctxt->node = oldContextNode;
|
||||||
|
ctxt->document = oldDocInfo;
|
||||||
|
ctxt->inst = oldInst;
|
||||||
|
|
||||||
|
if (str)
|
||||||
|
xmlFree(str);
|
||||||
|
if (useRes != NULL)
|
||||||
|
xmlXPathFreeObject(useRes);
|
||||||
|
if (matchRes != NULL)
|
||||||
|
xmlXPathFreeObject(matchRes);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltInitCtxtKeys:
|
* xsltInitCtxtKeys:
|
||||||
* @ctxt: an XSLT transformation context
|
* @ctxt: an XSLT transformation context
|
||||||
* @doc: an XSLT document
|
* @idoc: a document info
|
||||||
*
|
*
|
||||||
* Computes all the keys tables for the current input document.
|
* Computes all the keys tables for the current input document.
|
||||||
* Should be done before global varibales are initialized.
|
* Should be done before global varibales are initialized.
|
||||||
* NOTE: Not used anymore in the refactored code.
|
* NOTE: Not used anymore in the refactored code.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xsltInitCtxtKeys(xsltTransformContextPtr ctxt, xsltDocumentPtr doc) {
|
xsltInitCtxtKeys(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc) {
|
||||||
xsltStylesheetPtr style;
|
xsltStylesheetPtr style;
|
||||||
xsltKeyDefPtr keyd;
|
xsltKeyDefPtr keyDef;
|
||||||
|
|
||||||
if ((ctxt == NULL) || (doc == NULL))
|
if ((ctxt == NULL) || (idoc == NULL))
|
||||||
return;
|
return;
|
||||||
#ifdef WITH_XSLT_DEBUG_KEYS
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
if ((doc->doc != NULL) && (doc->doc->URL != NULL))
|
if ((idoc->doc != NULL) && (idoc->doc->URL != NULL))
|
||||||
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n",
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n",
|
||||||
doc->doc->URL));
|
idoc->doc->URL));
|
||||||
#endif
|
#endif
|
||||||
style = ctxt->style;
|
style = ctxt->style;
|
||||||
while (style != NULL) {
|
while (style != NULL) {
|
||||||
keyd = (xsltKeyDefPtr) style->keys;
|
keyDef = (xsltKeyDefPtr) style->keys;
|
||||||
while (keyd != NULL) {
|
while (keyDef != NULL) {
|
||||||
xsltInitCtxtKey(ctxt, doc, keyd);
|
xsltInitCtxtKey(ctxt, idoc, keyDef);
|
||||||
|
|
||||||
keyd = keyd->next;
|
keyDef = keyDef->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
style = xsltNextImport(style);
|
style = xsltNextImport(style);
|
||||||
@@ -772,8 +847,8 @@ xsltInitCtxtKeys(xsltTransformContextPtr ctxt, xsltDocumentPtr doc) {
|
|||||||
* Free the keys associated to a document
|
* Free the keys associated to a document
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xsltFreeDocumentKeys(xsltDocumentPtr doc) {
|
xsltFreeDocumentKeys(xsltDocumentPtr idoc) {
|
||||||
if (doc != NULL)
|
if (idoc != NULL)
|
||||||
xsltFreeKeyTableList(doc->keys);
|
xsltFreeKeyTableList(idoc->keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,8 +44,6 @@
|
|||||||
#include "namespaces.h"
|
#include "namespaces.h"
|
||||||
#include "imports.h"
|
#include "imports.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* *
|
* *
|
||||||
* Module interfaces *
|
* Module interfaces *
|
||||||
@@ -617,7 +615,7 @@ declare_new_prefix:
|
|||||||
* - xsltCopyPropList() (*not* anymore)
|
* - xsltCopyPropList() (*not* anymore)
|
||||||
* - xsltShallowCopyElement()
|
* - xsltShallowCopyElement()
|
||||||
* - xsltCopyTreeInternal() (*not* anymore)
|
* - xsltCopyTreeInternal() (*not* anymore)
|
||||||
* - xsltApplyOneTemplateInt() (*not* in the refactored code),
|
* - xsltApplySequenceConstructor() (*not* in the refactored code),
|
||||||
* - xsltElement() (*not* anymore)
|
* - xsltElement() (*not* anymore)
|
||||||
*
|
*
|
||||||
* Returns a namespace declaration or NULL in case of
|
* Returns a namespace declaration or NULL in case of
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
#include "pattern.h"
|
#include "pattern.h"
|
||||||
|
#include "documents.h"
|
||||||
|
|
||||||
#ifdef WITH_XSLT_DEBUG
|
#ifdef WITH_XSLT_DEBUG
|
||||||
#define WITH_XSLT_DEBUG_PATTERN
|
#define WITH_XSLT_DEBUG_PATTERN
|
||||||
@@ -858,7 +859,8 @@ restart:
|
|||||||
(previous->name != NULL) &&
|
(previous->name != NULL) &&
|
||||||
(sibling->name != NULL) &&
|
(sibling->name != NULL) &&
|
||||||
(previous->name[0] == sibling->name[0]) &&
|
(previous->name[0] == sibling->name[0]) &&
|
||||||
(xmlStrEqual(previous->name, sibling->name))) {
|
(xmlStrEqual(previous->name, sibling->name)))
|
||||||
|
{
|
||||||
if ((sel->value2 == NULL) ||
|
if ((sel->value2 == NULL) ||
|
||||||
((sibling->ns != NULL) &&
|
((sibling->ns != NULL) &&
|
||||||
(xmlStrEqual(sel->value2,
|
(xmlStrEqual(sel->value2,
|
||||||
@@ -874,11 +876,20 @@ restart:
|
|||||||
while (sibling != NULL) {
|
while (sibling != NULL) {
|
||||||
if (sibling == previous)
|
if (sibling == previous)
|
||||||
break;
|
break;
|
||||||
if ((sel->value2 == NULL) ||
|
if ((previous->type == XML_ELEMENT_NODE) &&
|
||||||
((sibling->ns != NULL) &&
|
(previous->name != NULL) &&
|
||||||
(xmlStrEqual(sel->value2,
|
(sibling->name != NULL) &&
|
||||||
sibling->ns->href))))
|
(previous->name[0] == sibling->name[0]) &&
|
||||||
indx--;
|
(xmlStrEqual(previous->name, sibling->name)))
|
||||||
|
{
|
||||||
|
if ((sel->value2 == NULL) ||
|
||||||
|
((sibling->ns != NULL) &&
|
||||||
|
(xmlStrEqual(sel->value2,
|
||||||
|
sibling->ns->href))))
|
||||||
|
{
|
||||||
|
indx--;
|
||||||
|
}
|
||||||
|
}
|
||||||
sibling = sibling->next;
|
sibling = sibling->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2211,17 +2222,34 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur,
|
|||||||
|
|
||||||
#ifdef XSLT_REFACTORED_KEYCOMP
|
#ifdef XSLT_REFACTORED_KEYCOMP
|
||||||
static int
|
static int
|
||||||
xsltComputeAllKeys(xsltTransformContextPtr ctxt,
|
xsltComputeAllKeys(xsltTransformContextPtr ctxt, xmlNodePtr contextNode)
|
||||||
xsltDocumentPtr document)
|
|
||||||
{
|
{
|
||||||
xsltStylesheetPtr style, style2;
|
xsltStylesheetPtr style, style2;
|
||||||
xsltKeyDefPtr keyd, keyd2;
|
xsltKeyDefPtr keyd, keyd2;
|
||||||
xsltKeyTablePtr table;
|
xsltKeyTablePtr table;
|
||||||
|
|
||||||
if ((ctxt == NULL) || (document == NULL))
|
if ((ctxt == NULL) || (contextNode == NULL)) {
|
||||||
|
xsltTransformError(ctxt, NULL, ctxt->inst,
|
||||||
|
"Internal error in xsltComputeAllKeys(): "
|
||||||
|
"Bad arguments.\n");
|
||||||
return(-1);
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
if (document->nbKeysComputed == ctxt->nbKeys)
|
if (ctxt->document == NULL) {
|
||||||
|
/*
|
||||||
|
* The document info will only be NULL if we have a RTF.
|
||||||
|
*/
|
||||||
|
if (contextNode->doc->_private != NULL)
|
||||||
|
goto doc_info_mismatch;
|
||||||
|
/*
|
||||||
|
* On-demand creation of the document info (needed for keys).
|
||||||
|
*/
|
||||||
|
ctxt->document = xsltNewDocument(ctxt, contextNode->doc);
|
||||||
|
if (ctxt->document == NULL)
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
|
||||||
return(0);
|
return(0);
|
||||||
/*
|
/*
|
||||||
* TODO: This could be further optimized
|
* TODO: This could be further optimized
|
||||||
@@ -2234,7 +2262,7 @@ xsltComputeAllKeys(xsltTransformContextPtr ctxt,
|
|||||||
* Check if keys with this QName have been already
|
* Check if keys with this QName have been already
|
||||||
* computed.
|
* computed.
|
||||||
*/
|
*/
|
||||||
table = (xsltKeyTablePtr) document->keys;
|
table = (xsltKeyTablePtr) ctxt->document->keys;
|
||||||
while (table) {
|
while (table) {
|
||||||
if (((keyd->nameURI != NULL) == (table->nameURI != NULL)) &&
|
if (((keyd->nameURI != NULL) == (table->nameURI != NULL)) &&
|
||||||
xmlStrEqual(keyd->name, table->name) &&
|
xmlStrEqual(keyd->name, table->name) &&
|
||||||
@@ -2257,8 +2285,8 @@ xsltComputeAllKeys(xsltTransformContextPtr ctxt,
|
|||||||
xmlStrEqual(keyd2->name, keyd->name) &&
|
xmlStrEqual(keyd2->name, keyd->name) &&
|
||||||
xmlStrEqual(keyd2->nameURI, keyd->nameURI))
|
xmlStrEqual(keyd2->nameURI, keyd->nameURI))
|
||||||
{
|
{
|
||||||
xsltInitCtxtKey(ctxt, document, keyd2);
|
xsltInitCtxtKey(ctxt, ctxt->document, keyd2);
|
||||||
if (document->nbKeysComputed == ctxt->nbKeys)
|
if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
keyd2 = keyd2->next;
|
keyd2 = keyd2->next;
|
||||||
@@ -2271,6 +2299,14 @@ xsltComputeAllKeys(xsltTransformContextPtr ctxt,
|
|||||||
style = xsltNextImport(style);
|
style = xsltNextImport(style);
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
|
doc_info_mismatch:
|
||||||
|
xsltTransformError(ctxt, NULL, ctxt->inst,
|
||||||
|
"Internal error in xsltComputeAllKeys(): "
|
||||||
|
"The context's document info doesn't match the "
|
||||||
|
"document info of the current result tree.\n");
|
||||||
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
return(-1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2287,7 +2323,8 @@ xsltComputeAllKeys(xsltTransformContextPtr ctxt,
|
|||||||
*/
|
*/
|
||||||
xsltTemplatePtr
|
xsltTemplatePtr
|
||||||
xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
||||||
xsltStylesheetPtr style) {
|
xsltStylesheetPtr style)
|
||||||
|
{
|
||||||
xsltStylesheetPtr curstyle;
|
xsltStylesheetPtr curstyle;
|
||||||
xsltTemplatePtr ret = NULL;
|
xsltTemplatePtr ret = NULL;
|
||||||
const xmlChar *name = NULL;
|
const xmlChar *name = NULL;
|
||||||
@@ -2478,14 +2515,16 @@ keyed_match:
|
|||||||
}
|
}
|
||||||
#ifdef XSLT_REFACTORED_KEYCOMP
|
#ifdef XSLT_REFACTORED_KEYCOMP
|
||||||
else if (ctxt->hasTemplKeyPatterns &&
|
else if (ctxt->hasTemplKeyPatterns &&
|
||||||
(ctxt->document->nbKeysComputed < ctxt->nbKeys))
|
((ctxt->document == NULL) ||
|
||||||
|
(ctxt->document->nbKeysComputed < ctxt->nbKeys)))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Compute all remaining keys for this document.
|
* Compute all remaining keys for this document.
|
||||||
*
|
*
|
||||||
* REVISIT TODO: I think this could be further optimized.
|
* REVISIT TODO: I think this could be further optimized.
|
||||||
*/
|
*/
|
||||||
xsltComputeAllKeys(ctxt, ctxt->document);
|
if (xsltComputeAllKeys(ctxt, node) == -1)
|
||||||
|
goto error;
|
||||||
|
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case XML_ELEMENT_NODE:
|
case XML_ELEMENT_NODE:
|
||||||
@@ -2519,6 +2558,8 @@ keyed_match:
|
|||||||
*/
|
*/
|
||||||
curstyle = xsltNextImport(curstyle);
|
curstyle = xsltNextImport(curstyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1007,7 +1007,7 @@ xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
|
|||||||
NULL, &comp->has_name);
|
NULL, &comp->has_name);
|
||||||
if (! comp->has_name) {
|
if (! comp->has_name) {
|
||||||
xsltTransformError(NULL, style, inst,
|
xsltTransformError(NULL, style, inst,
|
||||||
"xsl:attribute: The attribute 'name' is missing.\n");
|
"XSLT-attribute: The attribute 'name' is missing.\n");
|
||||||
style->errors++;
|
style->errors++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1303,6 +1303,9 @@ xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
|
|||||||
} else {
|
} else {
|
||||||
const xmlChar *URI;
|
const xmlChar *URI;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @prop will be in the string dict afterwards, @URI not.
|
||||||
|
*/
|
||||||
URI = xsltGetQNameURI2(style, inst, &prop);
|
URI = xsltGetQNameURI2(style, inst, &prop);
|
||||||
if (prop == NULL) {
|
if (prop == NULL) {
|
||||||
if (style != NULL) style->errors++;
|
if (style != NULL) style->errors++;
|
||||||
@@ -1310,7 +1313,12 @@ xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
|
|||||||
comp->name = prop;
|
comp->name = prop;
|
||||||
comp->has_name = 1;
|
comp->has_name = 1;
|
||||||
if (URI != NULL) {
|
if (URI != NULL) {
|
||||||
comp->ns = xmlStrdup(URI);
|
/*
|
||||||
|
* Fixes bug #308441: Put the ns-name in the dict
|
||||||
|
* in order to pointer compare names during XPath's
|
||||||
|
* variable lookup.
|
||||||
|
*/
|
||||||
|
comp->ns = xmlDictLookup(style->dict, URI, -1);
|
||||||
comp->has_ns = 1;
|
comp->has_ns = 1;
|
||||||
} else {
|
} else {
|
||||||
comp->has_ns = 0;
|
comp->has_ns = 0;
|
||||||
@@ -1530,7 +1538,7 @@ xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
|
|||||||
comp->name = prop;
|
comp->name = prop;
|
||||||
comp->has_name = 1;
|
comp->has_name = 1;
|
||||||
if (URI != NULL) {
|
if (URI != NULL) {
|
||||||
comp->ns = URI;
|
comp->ns = xmlDictLookup(style->dict, URI, -1);
|
||||||
comp->has_ns = 1;
|
comp->has_ns = 1;
|
||||||
} else {
|
} else {
|
||||||
comp->has_ns = 0;
|
comp->has_ns = 0;
|
||||||
@@ -1791,6 +1799,7 @@ xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
|
|||||||
xsltStylePreCompPtr comp;
|
xsltStylePreCompPtr comp;
|
||||||
#endif
|
#endif
|
||||||
const xmlChar *prop;
|
const xmlChar *prop;
|
||||||
|
const xmlChar *URI;
|
||||||
|
|
||||||
if ((style == NULL) || (inst == NULL))
|
if ((style == NULL) || (inst == NULL))
|
||||||
return;
|
return;
|
||||||
@@ -1804,51 +1813,65 @@ xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
|
|||||||
|
|
||||||
if (comp == NULL)
|
if (comp == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
inst->psvi = comp;
|
inst->psvi = comp;
|
||||||
comp->inst = inst;
|
comp->inst = inst;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The full template resolution can be done statically
|
* The full template resolution can be done statically
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attribute "name".
|
||||||
|
*/
|
||||||
prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
|
prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
|
||||||
if (prop == NULL) {
|
if (prop == NULL) {
|
||||||
xsltTransformError(NULL, style, inst,
|
xsltTransformError(NULL, style, inst,
|
||||||
"xsl:variable : name is missing\n");
|
"XSLT-variable: The attribute 'name' is missing.\n");
|
||||||
if (style != NULL) style->errors++;
|
style->errors++;
|
||||||
} else {
|
goto error;
|
||||||
const xmlChar *URI;
|
|
||||||
|
|
||||||
URI = xsltGetQNameURI2(style, inst, &prop);
|
|
||||||
if (prop == NULL) {
|
|
||||||
if (style != NULL) style->errors++;
|
|
||||||
} else {
|
|
||||||
comp->name = prop;
|
|
||||||
comp->has_name = 1;
|
|
||||||
if (URI != NULL) {
|
|
||||||
comp->ns = xmlDictLookup(style->dict, URI, -1);
|
|
||||||
comp->has_ns = 1;
|
|
||||||
} else {
|
|
||||||
comp->has_ns = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (xmlValidateQName(prop, 0)) {
|
||||||
|
xsltTransformError(NULL, style, inst,
|
||||||
|
"XSLT-variable: The value '%s' of the attribute 'name' is "
|
||||||
|
"not a valid QName.\n", prop);
|
||||||
|
style->errors++;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
URI = xsltGetQNameURI2(style, inst, &prop);
|
||||||
|
if (prop == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
comp->name = prop;
|
||||||
|
comp->has_name = 1;
|
||||||
|
|
||||||
|
if (URI != NULL) {
|
||||||
|
comp->ns = xmlDictLookup(style->dict, URI, -1);
|
||||||
|
comp->has_ns = 1;
|
||||||
|
} else {
|
||||||
|
comp->has_ns = 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Attribute "select".
|
||||||
|
*/
|
||||||
comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
|
comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
|
||||||
XSLT_NAMESPACE);
|
XSLT_NAMESPACE);
|
||||||
if (comp->select != NULL) {
|
if (comp->select != NULL) {
|
||||||
comp->comp = xsltXPathCompile(style, comp->select);
|
comp->comp = xsltXPathCompile(style, comp->select);
|
||||||
if (comp->comp == NULL) {
|
if (comp->comp == NULL) {
|
||||||
xsltTransformError(NULL, style, inst,
|
xsltTransformError(NULL, style, inst,
|
||||||
"xsl:variable : could not compile select expression '%s'\n",
|
"XSLT-variable: Failed to compile the XPath expression '%s'.\n",
|
||||||
comp->select);
|
comp->select);
|
||||||
if (style != NULL) style->errors++;
|
style->errors++;
|
||||||
}
|
}
|
||||||
if (inst->children != NULL) {
|
if (inst->children != NULL) {
|
||||||
xsltTransformError(NULL, style, inst,
|
xsltTransformError(NULL, style, inst,
|
||||||
"xsl:variable : content should be empty since select is present \n");
|
"XSLT-variable: The must be no child nodes, since the "
|
||||||
if (style != NULL) style->warnings++;
|
"attribute 'select' was specified.\n");
|
||||||
|
style->errors++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
error:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1900,7 +1923,7 @@ xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
|
|||||||
comp->name = prop;
|
comp->name = prop;
|
||||||
comp->has_name = 1;
|
comp->has_name = 1;
|
||||||
if (URI != NULL) {
|
if (URI != NULL) {
|
||||||
comp->ns = xmlStrdup(URI);
|
comp->ns = xmlDictLookup(style->dict, URI, -1);
|
||||||
comp->has_ns = 1;
|
comp->has_ns = 1;
|
||||||
} else {
|
} else {
|
||||||
comp->has_ns = 0;
|
comp->has_ns = 0;
|
||||||
|
@@ -180,28 +180,28 @@ xsltEvalXPathString(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp) {
|
|||||||
/**
|
/**
|
||||||
* xsltEvalTemplateString:
|
* xsltEvalTemplateString:
|
||||||
* @ctxt: the XSLT transformation context
|
* @ctxt: the XSLT transformation context
|
||||||
* @currentNode: the current node in the source tree
|
* @contextNode: the current node in the source tree
|
||||||
* @parent: the content parent
|
* @inst: the XSLT instruction (xsl:comment, xsl:processing-instruction)
|
||||||
*
|
*
|
||||||
* Evaluate a template string value, i.e. the parent list is interpreted
|
* Processes the sequence constructor of the given instruction on
|
||||||
* as template content and the resulting tree string value is returned
|
* @contextNode and converts the resulting tree to a string.
|
||||||
* This is needed for example by xsl:comment and xsl:processing-instruction
|
* This is needed by e.g. xsl:comment and xsl:processing-instruction.
|
||||||
*
|
*
|
||||||
* Returns the computed string value or NULL, must be deallocated by the
|
* Returns the computed string value or NULL; it's up to the caller to
|
||||||
* caller.
|
* free the result.
|
||||||
*/
|
*/
|
||||||
xmlChar *
|
xmlChar *
|
||||||
xsltEvalTemplateString(xsltTransformContextPtr ctxt,
|
xsltEvalTemplateString(xsltTransformContextPtr ctxt,
|
||||||
xmlNodePtr currentNode,
|
xmlNodePtr contextNode,
|
||||||
xmlNodePtr parent)
|
xmlNodePtr inst)
|
||||||
{
|
{
|
||||||
xmlNodePtr oldInsert, insert = NULL;
|
xmlNodePtr oldInsert, insert = NULL;
|
||||||
xmlChar *ret;
|
xmlChar *ret;
|
||||||
|
|
||||||
if ((ctxt == NULL) || (currentNode == NULL) || (parent == NULL))
|
if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
||||||
if (parent->children == NULL)
|
if (inst->children == NULL)
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -213,14 +213,16 @@ xsltEvalTemplateString(xsltTransformContextPtr ctxt,
|
|||||||
insert = xmlNewDocNode(ctxt->output, NULL,
|
insert = xmlNewDocNode(ctxt->output, NULL,
|
||||||
(const xmlChar *)"fake", NULL);
|
(const xmlChar *)"fake", NULL);
|
||||||
if (insert == NULL) {
|
if (insert == NULL) {
|
||||||
xsltTransformError(ctxt, NULL, currentNode,
|
xsltTransformError(ctxt, NULL, contextNode,
|
||||||
"Failed to create temporary node\n");
|
"Failed to create temporary node\n");
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
oldInsert = ctxt->insert;
|
oldInsert = ctxt->insert;
|
||||||
ctxt->insert = insert;
|
ctxt->insert = insert;
|
||||||
/* OPTIMIZE TODO: if parent->children consists only of text-nodes. */
|
/*
|
||||||
xsltApplyOneTemplate(ctxt, currentNode, parent->children, NULL, NULL);
|
* OPTIMIZE TODO: if inst->children consists only of text-nodes.
|
||||||
|
*/
|
||||||
|
xsltApplyOneTemplate(ctxt, contextNode, inst->children, NULL, NULL);
|
||||||
|
|
||||||
ctxt->insert = oldInsert;
|
ctxt->insert = oldInsert;
|
||||||
|
|
||||||
@@ -603,7 +605,7 @@ xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
|
|||||||
* Copies all non XSLT-attributes over to the @target element
|
* Copies all non XSLT-attributes over to the @target element
|
||||||
* and evaluates Attribute Value Templates.
|
* and evaluates Attribute Value Templates.
|
||||||
*
|
*
|
||||||
* Called by xsltApplyOneTemplateInt() (transform.c).
|
* Called by xsltApplySequenceConstructor() (transform.c).
|
||||||
*
|
*
|
||||||
* Returns a new list of attribute nodes, or NULL in case of error.
|
* Returns a new list of attribute nodes, or NULL in case of error.
|
||||||
* (Don't assign the result to @target->properties; if
|
* (Don't assign the result to @target->properties; if
|
||||||
|
@@ -27,8 +27,8 @@ XSLTPUBFUN int XSLTCALL
|
|||||||
int nsNr);
|
int nsNr);
|
||||||
XSLTPUBFUN xmlChar * XSLTCALL
|
XSLTPUBFUN xmlChar * XSLTCALL
|
||||||
xsltEvalTemplateString (xsltTransformContextPtr ctxt,
|
xsltEvalTemplateString (xsltTransformContextPtr ctxt,
|
||||||
xmlNodePtr node,
|
xmlNodePtr contextNode,
|
||||||
xmlNodePtr parent);
|
xmlNodePtr inst);
|
||||||
XSLTPUBFUN xmlChar * XSLTCALL
|
XSLTPUBFUN xmlChar * XSLTCALL
|
||||||
xsltEvalAttrValueTemplate (xsltTransformContextPtr ctxt,
|
xsltEvalAttrValueTemplate (xsltTransformContextPtr ctxt,
|
||||||
xmlNodePtr node,
|
xmlNodePtr node,
|
||||||
|
2834
libxslt/transform.c
2834
libxslt/transform.c
File diff suppressed because it is too large
Load Diff
1336
libxslt/variables.c
1336
libxslt/variables.c
File diff suppressed because it is too large
Load Diff
326
libxslt/xslt.c
326
libxslt/xslt.c
@@ -54,7 +54,7 @@ const int xsltLibxmlVersion = LIBXML_VERSION;
|
|||||||
|
|
||||||
#ifdef XSLT_REFACTORED
|
#ifdef XSLT_REFACTORED
|
||||||
|
|
||||||
const xmlChar *xsltConstNamespaceNameXSLT= (const xmlChar *) XSLT_NAMESPACE;
|
const xmlChar *xsltConstNamespaceNameXSLT = (const xmlChar *) XSLT_NAMESPACE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xsltLiteralResultMarker:
|
* xsltLiteralResultMarker:
|
||||||
@@ -485,6 +485,24 @@ xsltNewNamespaceMapItem(xsltCompilerCtxtPtr cctxt,
|
|||||||
}
|
}
|
||||||
#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
|
#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCompilerVarInfoFree:
|
||||||
|
* @cctxt: the compilation context
|
||||||
|
*
|
||||||
|
* Frees the list of information for vars/params.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xsltCompilerVarInfoFree(xsltCompilerCtxtPtr cctxt)
|
||||||
|
{
|
||||||
|
xsltVarInfoPtr ivar = cctxt->ivars, ivartmp;
|
||||||
|
|
||||||
|
while (ivar) {
|
||||||
|
ivartmp = ivar;
|
||||||
|
ivar = ivar->next;
|
||||||
|
xmlFree(ivartmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltCompilerCtxtFree:
|
* xsltCompilerCtxtFree:
|
||||||
*
|
*
|
||||||
@@ -523,6 +541,9 @@ xsltCompilationCtxtFree(xsltCompilerCtxtPtr cctxt)
|
|||||||
if (cctxt->nsAliases != NULL)
|
if (cctxt->nsAliases != NULL)
|
||||||
xsltFreeNsAliasList(cctxt->nsAliases);
|
xsltFreeNsAliasList(cctxt->nsAliases);
|
||||||
|
|
||||||
|
if (cctxt->ivars)
|
||||||
|
xsltCompilerVarInfoFree(cctxt);
|
||||||
|
|
||||||
xmlFree(cctxt);
|
xmlFree(cctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1024,16 +1045,6 @@ xsltGetInheritedNsList(xsltStylesheetPtr style,
|
|||||||
int maxns = 10;
|
int maxns = 10;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: This will gather the ns-decls of elements even if
|
|
||||||
* outside xsl:stylesheet. Example:
|
|
||||||
* <doc xmlns:foo="urn:test:foo">
|
|
||||||
* <xsl:stylesheet ...
|
|
||||||
* </doc>
|
|
||||||
* Will have foo="urn:test:foo" in the list.
|
|
||||||
* Is this OK?
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((style == NULL) || (template == NULL) || (node == NULL) ||
|
if ((style == NULL) || (template == NULL) || (node == NULL) ||
|
||||||
(template->inheritedNsNr != 0) || (template->inheritedNs != NULL))
|
(template->inheritedNsNr != 0) || (template->inheritedNs != NULL))
|
||||||
return(0);
|
return(0);
|
||||||
@@ -2027,6 +2038,63 @@ xsltLREBuildEffectiveNsNodes(xsltCompilerCtxtPtr cctxt,
|
|||||||
if (xmlStrEqual(ns->href, XSLT_NAMESPACE))
|
if (xmlStrEqual(ns->href, XSLT_NAMESPACE))
|
||||||
goto skip_ns;
|
goto skip_ns;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Apply namespace aliasing
|
||||||
|
* ------------------------
|
||||||
|
*
|
||||||
|
* SPEC XSLT 2.0
|
||||||
|
* "- A namespace node whose string value is a literal namespace
|
||||||
|
* URI is not copied to the result tree.
|
||||||
|
* - A namespace node whose string value is a target namespace URI
|
||||||
|
* is copied to the result tree, whether or not the URI
|
||||||
|
* identifies an excluded namespace."
|
||||||
|
*
|
||||||
|
* NOTE: The ns-aliasing machanism is non-cascading.
|
||||||
|
* (checked with Saxon, Xalan and MSXML .NET).
|
||||||
|
* URGENT TODO: is style->nsAliases the effective list of
|
||||||
|
* ns-aliases, or do we need to lookup the whole
|
||||||
|
* import-tree?
|
||||||
|
* TODO: Get rid of import-tree lookup.
|
||||||
|
*/
|
||||||
|
if (cctxt->hasNsAliases) {
|
||||||
|
xsltNsAliasPtr alias;
|
||||||
|
/*
|
||||||
|
* First check for being a target namespace.
|
||||||
|
*/
|
||||||
|
alias = cctxt->nsAliases;
|
||||||
|
do {
|
||||||
|
/*
|
||||||
|
* TODO: Is xmlns="" handled already?
|
||||||
|
*/
|
||||||
|
if ((alias->targetNs != NULL) &&
|
||||||
|
(xmlStrEqual(alias->targetNs->href, ns->href)))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Recognized as a target namespace; use it regardless
|
||||||
|
* if excluded otherwise.
|
||||||
|
*/
|
||||||
|
goto add_effective_ns;
|
||||||
|
}
|
||||||
|
alias = alias->next;
|
||||||
|
} while (alias != NULL);
|
||||||
|
|
||||||
|
alias = cctxt->nsAliases;
|
||||||
|
do {
|
||||||
|
/*
|
||||||
|
* TODO: Is xmlns="" handled already?
|
||||||
|
*/
|
||||||
|
if ((alias->literalNs != NULL) &&
|
||||||
|
(xmlStrEqual(alias->literalNs->href, ns->href)))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Recognized as an namespace alias; do not use it.
|
||||||
|
*/
|
||||||
|
goto skip_ns;
|
||||||
|
}
|
||||||
|
alias = alias->next;
|
||||||
|
} while (alias != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exclude excluded result namespaces.
|
* Exclude excluded result namespaces.
|
||||||
*/
|
*/
|
||||||
@@ -2043,6 +2111,8 @@ xsltLREBuildEffectiveNsNodes(xsltCompilerCtxtPtr cctxt,
|
|||||||
if (xmlStrEqual(ns->href, BAD_CAST extElemNs->items[j]))
|
if (xmlStrEqual(ns->href, BAD_CAST extElemNs->items[j]))
|
||||||
goto skip_ns;
|
goto skip_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_effective_ns:
|
||||||
/*
|
/*
|
||||||
* OPTIMIZE TODO: This information may not be needed.
|
* OPTIMIZE TODO: This information may not be needed.
|
||||||
*/
|
*/
|
||||||
@@ -2058,43 +2128,7 @@ xsltLREBuildEffectiveNsNodes(xsltCompilerCtxtPtr cctxt,
|
|||||||
} while (tmpns != NULL);
|
} while (tmpns != NULL);
|
||||||
} else
|
} else
|
||||||
holdByElem = 0;
|
holdByElem = 0;
|
||||||
/*
|
|
||||||
* Apply namespace aliasing
|
|
||||||
* ------------------------
|
|
||||||
*
|
|
||||||
* NOTE: The ns-aliasing machanism is non-cascading.
|
|
||||||
* (checked with Saxon, Xalan and MSXML .NET).
|
|
||||||
* URGENT TODO: is style->nsAliases the effective list of
|
|
||||||
* ns-aliases, or do we need to lookup the whole
|
|
||||||
* import-tree?
|
|
||||||
* TODO: Get rid of import-tree lookup.
|
|
||||||
*/
|
|
||||||
if (cctxt->hasNsAliases) {
|
|
||||||
xsltNsAliasPtr alias = cctxt->nsAliases;
|
|
||||||
do {
|
|
||||||
/*
|
|
||||||
* TODO: What to do with xmlns="" ?
|
|
||||||
*/
|
|
||||||
if ((alias->literalNs != NULL) &&
|
|
||||||
(xmlStrEqual(alias->literalNs->href, ns->href)))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Recognized as an namespace alias; convert it to
|
|
||||||
* the target namespace.
|
|
||||||
*/
|
|
||||||
if (alias->targetNs != NULL)
|
|
||||||
ns = alias->literalNs;
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
* The target is the NULL namespace.
|
|
||||||
*/
|
|
||||||
goto skip_ns;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
alias = alias->next;
|
|
||||||
} while (alias != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the effective namespace declaration.
|
* Add the effective namespace declaration.
|
||||||
@@ -2181,6 +2215,69 @@ xsltLREInfoCreate(xsltCompilerCtxtPtr cctxt,
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCompilerVarInfoPush:
|
||||||
|
* @cctxt: the compilation context
|
||||||
|
*
|
||||||
|
* Pushes a new var/param info onto the stack.
|
||||||
|
*
|
||||||
|
* Returns the acquired variable info.
|
||||||
|
*/
|
||||||
|
static xsltVarInfoPtr
|
||||||
|
xsltCompilerVarInfoPush(xsltCompilerCtxtPtr cctxt,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *nsName)
|
||||||
|
{
|
||||||
|
xsltVarInfoPtr ivar;
|
||||||
|
|
||||||
|
if ((cctxt->ivar != NULL) && (cctxt->ivar->next != NULL)) {
|
||||||
|
ivar = cctxt->ivar->next;
|
||||||
|
} else if ((cctxt->ivar == NULL) && (cctxt->ivars != NULL)) {
|
||||||
|
ivar = cctxt->ivars;
|
||||||
|
} else {
|
||||||
|
ivar = (xsltVarInfoPtr) xmlMalloc(sizeof(xsltVarInfo));
|
||||||
|
if (ivar == NULL) {
|
||||||
|
xsltTransformError(NULL, cctxt->style, inst,
|
||||||
|
"xsltParseInScopeVarPush: xmlMalloc() failed!\n");
|
||||||
|
cctxt->style->errors++;
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
/* memset(retVar, 0, sizeof(xsltInScopeVar)); */
|
||||||
|
if (cctxt->ivars == NULL) {
|
||||||
|
cctxt->ivars = ivar;
|
||||||
|
ivar->prev = NULL;
|
||||||
|
} else {
|
||||||
|
cctxt->ivar->next = ivar;
|
||||||
|
ivar->prev = cctxt->ivar;
|
||||||
|
}
|
||||||
|
cctxt->ivar = ivar;
|
||||||
|
ivar->next = NULL;
|
||||||
|
}
|
||||||
|
ivar->depth = cctxt->depth;
|
||||||
|
ivar->name = name;
|
||||||
|
ivar->nsName = nsName;
|
||||||
|
return(ivar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCompilerVarInfoPop:
|
||||||
|
* @cctxt: the compilation context
|
||||||
|
*
|
||||||
|
* Pops all var/param infos from the stack, which
|
||||||
|
* have the current depth.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xsltCompilerVarInfoPop(xsltCompilerCtxtPtr cctxt)
|
||||||
|
{
|
||||||
|
|
||||||
|
while ((cctxt->ivar != NULL) &&
|
||||||
|
(cctxt->ivar->depth > cctxt->depth))
|
||||||
|
{
|
||||||
|
cctxt->ivar = cctxt->ivar->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xsltCompilerNodePush:
|
* xsltCompilerNodePush:
|
||||||
*
|
*
|
||||||
@@ -2316,6 +2413,12 @@ xsltCompilerNodePop(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
|
|||||||
"xsltCompilerNodePop: Depth mismatch.\n");
|
"xsltCompilerNodePop: Depth mismatch.\n");
|
||||||
goto mismatch;
|
goto mismatch;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Pop information of variables.
|
||||||
|
*/
|
||||||
|
if ((cctxt->ivar) && (cctxt->ivar->depth > cctxt->depth))
|
||||||
|
xsltCompilerVarInfoPop(cctxt);
|
||||||
|
|
||||||
cctxt->depth--;
|
cctxt->depth--;
|
||||||
cctxt->inode = cctxt->inode->prev;
|
cctxt->inode = cctxt->inode->prev;
|
||||||
if (cctxt->inode != NULL)
|
if (cctxt->inode != NULL)
|
||||||
@@ -2421,7 +2524,7 @@ xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i >= nsi->totalNumber) {
|
if (i >= nsi->totalNumber) {
|
||||||
if (nsi->totalNumber >= maxns) {
|
if (nsi->totalNumber +1 >= maxns) {
|
||||||
maxns *= 2;
|
maxns *= 2;
|
||||||
nsi->list =
|
nsi->list =
|
||||||
(xmlNsPtr *) xmlRealloc(nsi->list,
|
(xmlNsPtr *) xmlRealloc(nsi->list,
|
||||||
@@ -3684,6 +3787,17 @@ xsltGetXSLTElementTypeByNode(xsltCompilerCtxtPtr cctxt,
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltParseAnyXSLTElem:
|
||||||
|
*
|
||||||
|
* @cctxt: the compilation context
|
||||||
|
* @elem: the element node of the XSLT instruction
|
||||||
|
*
|
||||||
|
* Parses, validates the content models and compiles XSLT instructions.
|
||||||
|
*
|
||||||
|
* Returns 0 if everything's fine;
|
||||||
|
* -1 on API or internal errors.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
|
xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
|
||||||
{
|
{
|
||||||
@@ -3718,12 +3832,16 @@ xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
|
|||||||
cctxt->inode->inScopeNs =
|
cctxt->inode->inScopeNs =
|
||||||
xsltCompilerBuildInScopeNsList(cctxt, elem);
|
xsltCompilerBuildInScopeNsList(cctxt, elem);
|
||||||
/*
|
/*
|
||||||
* xsltStylePreCompute(): Precompute the XSLT-instruction.
|
* xsltStylePreCompute():
|
||||||
* This will compile the information found on the current
|
* This will compile the information found on the current
|
||||||
* element's attributes. NOTE that this won't process the
|
* element's attributes. NOTE that this won't process the
|
||||||
* children of the current element.
|
* children of the instruction.
|
||||||
*/
|
*/
|
||||||
xsltStylePreCompute(cctxt->style, elem);
|
xsltStylePreCompute(cctxt->style, elem);
|
||||||
|
/*
|
||||||
|
* TODO: How to react on errors in xsltStylePreCompute() ?
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validate the content model of the XSLT-element.
|
* Validate the content model of the XSLT-element.
|
||||||
*/
|
*/
|
||||||
@@ -3777,6 +3895,28 @@ xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
|
|||||||
/* EMPTY */
|
/* EMPTY */
|
||||||
goto empty_content;
|
goto empty_content;
|
||||||
case XSLT_FUNC_PARAM:
|
case XSLT_FUNC_PARAM:
|
||||||
|
/*
|
||||||
|
* Check for redefinition.
|
||||||
|
*/
|
||||||
|
if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
|
||||||
|
xsltVarInfoPtr ivar = cctxt->ivar;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ((ivar->name ==
|
||||||
|
((xsltStyleItemParamPtr) elem->psvi)->name) &&
|
||||||
|
(ivar->nsName ==
|
||||||
|
((xsltStyleItemParamPtr) elem->psvi)->ns))
|
||||||
|
{
|
||||||
|
elem->psvi = NULL;
|
||||||
|
xsltTransformError(NULL, cctxt->style, elem,
|
||||||
|
"Redefinition of variable or parameter '%s'.\n",
|
||||||
|
ivar->name);
|
||||||
|
cctxt->style->errors++;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
ivar = ivar->prev;
|
||||||
|
} while (ivar != NULL);
|
||||||
|
}
|
||||||
/* <!-- Content: template --> */
|
/* <!-- Content: template --> */
|
||||||
goto sequence_constructor;
|
goto sequence_constructor;
|
||||||
case XSLT_FUNC_PI:
|
case XSLT_FUNC_PI:
|
||||||
@@ -3792,6 +3932,28 @@ xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
|
|||||||
/* EMPTY */
|
/* EMPTY */
|
||||||
goto empty_content;
|
goto empty_content;
|
||||||
case XSLT_FUNC_VARIABLE:
|
case XSLT_FUNC_VARIABLE:
|
||||||
|
/*
|
||||||
|
* Check for redefinition.
|
||||||
|
*/
|
||||||
|
if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
|
||||||
|
xsltVarInfoPtr ivar = cctxt->ivar;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ((ivar->name ==
|
||||||
|
((xsltStyleItemVariablePtr) elem->psvi)->name) &&
|
||||||
|
(ivar->nsName ==
|
||||||
|
((xsltStyleItemVariablePtr) elem->psvi)->ns))
|
||||||
|
{
|
||||||
|
elem->psvi = NULL;
|
||||||
|
xsltTransformError(NULL, cctxt->style, elem,
|
||||||
|
"Redefinition of variable or parameter '%s'.\n",
|
||||||
|
ivar->name);
|
||||||
|
cctxt->style->errors++;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
ivar = ivar->prev;
|
||||||
|
} while (ivar != NULL);
|
||||||
|
}
|
||||||
/* <!-- Content: template --> */
|
/* <!-- Content: template --> */
|
||||||
goto sequence_constructor;
|
goto sequence_constructor;
|
||||||
case XSLT_FUNC_WHEN:
|
case XSLT_FUNC_WHEN:
|
||||||
@@ -3998,9 +4160,30 @@ for_each:
|
|||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
sequence_constructor:
|
sequence_constructor:
|
||||||
|
/*
|
||||||
|
* Parse the sequence constructor.
|
||||||
|
*/
|
||||||
if (elem->children != NULL)
|
if (elem->children != NULL)
|
||||||
xsltParseSequenceConstructor(cctxt, elem->children);
|
xsltParseSequenceConstructor(cctxt, elem->children);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register information for vars/params. Only needed if there
|
||||||
|
* are any following siblings.
|
||||||
|
*/
|
||||||
|
if ((elem->next != NULL) &&
|
||||||
|
((cctxt->inode->type == XSLT_FUNC_VARIABLE) ||
|
||||||
|
(cctxt->inode->type == XSLT_FUNC_PARAM)))
|
||||||
|
{
|
||||||
|
if ((elem->psvi != NULL) &&
|
||||||
|
(((xsltStyleBasicItemVariablePtr) elem->psvi)->name))
|
||||||
|
{
|
||||||
|
xsltCompilerVarInfoPush(cctxt, elem,
|
||||||
|
((xsltStyleBasicItemVariablePtr) elem->psvi)->name,
|
||||||
|
((xsltStyleBasicItemVariablePtr) elem->psvi)->ns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
exit:
|
exit:
|
||||||
xsltCompilerNodePop(cctxt, elem);
|
xsltCompilerNodePop(cctxt, elem);
|
||||||
return(0);
|
return(0);
|
||||||
@@ -4010,6 +4193,16 @@ internal_err:
|
|||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltForwardsCompatUnkownItemCreate:
|
||||||
|
*
|
||||||
|
* @cctxt: the compilation context
|
||||||
|
*
|
||||||
|
* Creates a compiled representation of the unknown
|
||||||
|
* XSLT instruction.
|
||||||
|
*
|
||||||
|
* Returns the compiled representation.
|
||||||
|
*/
|
||||||
static xsltStyleItemUknownPtr
|
static xsltStyleItemUknownPtr
|
||||||
xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)
|
xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)
|
||||||
{
|
{
|
||||||
@@ -4033,6 +4226,20 @@ xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)
|
|||||||
return(item);
|
return(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltParseUnknownXSLTElem:
|
||||||
|
*
|
||||||
|
* @cctxt: the compilation context
|
||||||
|
* @node: the element of the unknown XSLT instruction
|
||||||
|
*
|
||||||
|
* Parses an unknown XSLT element.
|
||||||
|
* If forwards compatible mode is enabled this will allow
|
||||||
|
* such an unknown XSLT and; otherwise it is rejected.
|
||||||
|
*
|
||||||
|
* Returns 1 in the unknown XSLT instruction is rejected,
|
||||||
|
* 0 if everything's fine and
|
||||||
|
* -1 on API or internal errors.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,
|
xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,
|
||||||
xmlNodePtr node)
|
xmlNodePtr node)
|
||||||
@@ -4053,7 +4260,7 @@ xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,
|
|||||||
xsltTransformError(NULL, cctxt->style, node,
|
xsltTransformError(NULL, cctxt->style, node,
|
||||||
"Unknown XSLT element '%s'.\n", node->name);
|
"Unknown XSLT element '%s'.\n", node->name);
|
||||||
cctxt->style->errors++;
|
cctxt->style->errors++;
|
||||||
return(0);
|
return(1);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Forwards-compatible mode.
|
* Forwards-compatible mode.
|
||||||
@@ -4106,6 +4313,7 @@ xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,
|
|||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltParseSequenceConstructor:
|
* xsltParseSequenceConstructor:
|
||||||
*
|
*
|
||||||
@@ -4374,10 +4582,12 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
|
|||||||
|
|
||||||
if (cur->psvi == NULL) {
|
if (cur->psvi == NULL) {
|
||||||
/*
|
/*
|
||||||
* OLD COMMENT: "Unknown element, maybe registered at the
|
* OLD COMMENT: "Unknown element, maybe registered
|
||||||
* context level. Mark it for later recognition."
|
* at the context level. Mark it for later
|
||||||
|
* recognition."
|
||||||
* QUESTION: What does the xsltExtMarker mean?
|
* QUESTION: What does the xsltExtMarker mean?
|
||||||
* ANSWER: It is used in xsltApplyOneTemplateInt() at
|
* ANSWER: It is used in
|
||||||
|
* xsltApplySequenceConstructor() at
|
||||||
* transformation-time to look out for extension
|
* transformation-time to look out for extension
|
||||||
* registered in the transformation context.
|
* registered in the transformation context.
|
||||||
*/
|
*/
|
||||||
@@ -4400,7 +4610,7 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
|
|||||||
* transformation-time only, then there's no way of
|
* transformation-time only, then there's no way of
|
||||||
* knowing that content shall be valid, and we'll
|
* knowing that content shall be valid, and we'll
|
||||||
* process the content the same way.
|
* process the content the same way.
|
||||||
* 2) If author *does* set the flag, then we'll assume
|
* 2) If the author *does* set the flag, then we'll assume
|
||||||
* that the author has handled the parsing him/herself
|
* that the author has handled the parsing him/herself
|
||||||
* (e.g. called xsltParseSequenceConstructor(), etc.
|
* (e.g. called xsltParseSequenceConstructor(), etc.
|
||||||
* explicitely in his/her code).
|
* explicitely in his/her code).
|
||||||
@@ -4526,8 +4736,8 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
|
|||||||
* @templ: the node containing the content to be parsed
|
* @templ: the node containing the content to be parsed
|
||||||
*
|
*
|
||||||
* Parses and compiles the content-model of an xsl:template element.
|
* Parses and compiles the content-model of an xsl:template element.
|
||||||
* Note that this is *not* the "template" (or "sequence constructor"
|
* Note that this is *not* the "template" content model (or "sequence
|
||||||
* in XSLT 2.0) content model. Since it allows addional xsl:param
|
* constructor" in XSLT 2.0); it it allows addional xsl:param
|
||||||
* elements as immediate children of @templ.
|
* elements as immediate children of @templ.
|
||||||
*
|
*
|
||||||
* Called by:
|
* Called by:
|
||||||
|
@@ -27,32 +27,19 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* #define XSLT_DEBUG_PROFILE_CACHE */
|
||||||
|
|
||||||
#define XSLT_IS_TEXT_NODE(n) ((n != NULL) && \
|
#define XSLT_IS_TEXT_NODE(n) ((n != NULL) && \
|
||||||
(((n)->type == XML_TEXT_NODE) || \
|
(((n)->type == XML_TEXT_NODE) || \
|
||||||
((n)->type == XML_CDATA_SECTION_NODE)))
|
((n)->type == XML_CDATA_SECTION_NODE)))
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
extern const xmlChar *xsltDocFragFake;
|
|
||||||
|
|
||||||
#define XSLT_MARK_RES_TREE_FRAG(n) (n)->psvi = (void *) xsltDocFragFake;
|
|
||||||
|
|
||||||
#define XSLT_IS_RES_TREE_FRAG(n) \
|
|
||||||
((n != NULL) && ((n)->type == XML_DOCUMENT_NODE) && \
|
|
||||||
((n)->psvi == xsltDocFragFake))
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define XSLT_MARK_RES_TREE_FRAG(n) \
|
#define XSLT_MARK_RES_TREE_FRAG(n) \
|
||||||
(n)->name = (char *) xmlStrdup(BAD_CAST " fake node libxslt");
|
(n)->name = (char *) xmlStrdup(BAD_CAST " fake node libxslt");
|
||||||
|
|
||||||
#define XSLT_IS_RES_TREE_FRAG(n) \
|
#define XSLT_IS_RES_TREE_FRAG(n) \
|
||||||
((n != NULL) && ((n)->type == XML_DOCUMENT_NODE) && \
|
((n != NULL) && ((n)->type == XML_DOCUMENT_NODE) && \
|
||||||
((n)->name != NULL) && ((n)->name[0] == ' ') && \
|
((n)->name != NULL) && ((n)->name[0] == ' '))
|
||||||
xmlStrEqual(BAD_CAST (n)->name, BAD_CAST " fake node libxslt"))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XSLT_REFACTORED_KEYCOMP:
|
* XSLT_REFACTORED_KEYCOMP:
|
||||||
@@ -61,6 +48,14 @@ extern const xmlChar *xsltDocFragFake;
|
|||||||
*/
|
*/
|
||||||
#define XSLT_REFACTORED_KEYCOMP
|
#define XSLT_REFACTORED_KEYCOMP
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_FAST_IF:
|
||||||
|
*
|
||||||
|
* Internal define to enable usage of xmlXPathCompiledEvalToBoolean()
|
||||||
|
* for XSLT "tests"; e.g. in <xsl:if test="/foo/bar">
|
||||||
|
*/
|
||||||
|
#define XSLT_FAST_IF
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XSLT_REFACTORED:
|
* XSLT_REFACTORED:
|
||||||
*
|
*
|
||||||
@@ -69,10 +64,13 @@ extern const xmlChar *xsltDocFragFake;
|
|||||||
/* #define XSLT_REFACTORED */
|
/* #define XSLT_REFACTORED */
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
|
||||||
|
#define XSLT_REFACTORED_VARS
|
||||||
|
|
||||||
#ifdef XSLT_REFACTORED
|
#ifdef XSLT_REFACTORED
|
||||||
|
|
||||||
extern const xmlChar *xsltXSLTAttrMarker;
|
extern const xmlChar *xsltXSLTAttrMarker;
|
||||||
|
|
||||||
|
|
||||||
/* TODO: REMOVE: #define XSLT_REFACTORED_EXCLRESNS */
|
/* TODO: REMOVE: #define XSLT_REFACTORED_EXCLRESNS */
|
||||||
|
|
||||||
/* TODO: REMOVE: #define XSLT_REFACTORED_NSALIAS */
|
/* TODO: REMOVE: #define XSLT_REFACTORED_NSALIAS */
|
||||||
@@ -243,6 +241,7 @@ struct _xsltTemplate {
|
|||||||
/* Profiling informations */
|
/* Profiling informations */
|
||||||
int nbCalls; /* the number of time the template was called */
|
int nbCalls; /* the number of time the template was called */
|
||||||
unsigned long time; /* the time spent in this template */
|
unsigned long time; /* the time spent in this template */
|
||||||
|
void *params; /* xsl:param instructions */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -275,7 +274,6 @@ struct _xsltDecimalFormat {
|
|||||||
*
|
*
|
||||||
* Data structure associated to a parsed document.
|
* Data structure associated to a parsed document.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct _xsltDocument xsltDocument;
|
typedef struct _xsltDocument xsltDocument;
|
||||||
typedef xsltDocument *xsltDocumentPtr;
|
typedef xsltDocument *xsltDocumentPtr;
|
||||||
struct _xsltDocument {
|
struct _xsltDocument {
|
||||||
@@ -478,6 +476,8 @@ struct _xsltNsListContainer {
|
|||||||
*
|
*
|
||||||
* Fields for API compatibility to the structure
|
* Fields for API compatibility to the structure
|
||||||
* _xsltElemPreComp which is used for extension functions.
|
* _xsltElemPreComp which is used for extension functions.
|
||||||
|
* Note that @next is used for storage; it does not reflect a next
|
||||||
|
* sibling in the tree.
|
||||||
* TODO: Evaluate if we really need such a compatibility.
|
* TODO: Evaluate if we really need such a compatibility.
|
||||||
*/
|
*/
|
||||||
#define XSLT_ITEM_COMPATIBILITY_FIELDS \
|
#define XSLT_ITEM_COMPATIBILITY_FIELDS \
|
||||||
@@ -940,9 +940,21 @@ typedef xsltStyleItemVariable *xsltStyleItemVariablePtr;
|
|||||||
* <!-- Content: template -->
|
* <!-- Content: template -->
|
||||||
* </xsl:param>
|
* </xsl:param>
|
||||||
*/
|
*/
|
||||||
typedef xsltStyleBasicItemVariable xsltStyleItemParam;
|
typedef struct _xsltStyleItemParam xsltStyleItemParam;
|
||||||
typedef xsltStyleItemParam *xsltStyleItemParamPtr;
|
typedef xsltStyleItemParam *xsltStyleItemParamPtr;
|
||||||
|
|
||||||
|
struct _xsltStyleItemParam {
|
||||||
|
XSLT_ITEM_COMMON_FIELDS
|
||||||
|
|
||||||
|
const xmlChar *select;
|
||||||
|
xmlXPathCompExprPtr comp;
|
||||||
|
|
||||||
|
const xmlChar *name;
|
||||||
|
int has_name;
|
||||||
|
const xmlChar *ns;
|
||||||
|
int has_ns;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltStyleItemWithParam:
|
* xsltStyleItemWithParam:
|
||||||
*
|
*
|
||||||
@@ -1167,6 +1179,21 @@ struct _xsltNsList {
|
|||||||
xmlNsPtr ns;
|
xmlNsPtr ns;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* xsltVarInfo:
|
||||||
|
*
|
||||||
|
* Used at compilation time for parameters and variables.
|
||||||
|
*/
|
||||||
|
typedef struct _xsltVarInfo xsltVarInfo;
|
||||||
|
typedef xsltVarInfo *xsltVarInfoPtr;
|
||||||
|
struct _xsltVarInfo {
|
||||||
|
xsltVarInfoPtr next; /* next in the list */
|
||||||
|
xsltVarInfoPtr prev;
|
||||||
|
int depth; /* the depth in the tree */
|
||||||
|
const xmlChar *name;
|
||||||
|
const xmlChar *nsName;
|
||||||
|
};
|
||||||
|
|
||||||
#define XSLT_ELEMENT_CATEGORY_XSLT 0
|
#define XSLT_ELEMENT_CATEGORY_XSLT 0
|
||||||
#define XSLT_ELEMENT_CATEGORY_EXTENSION 1
|
#define XSLT_ELEMENT_CATEGORY_EXTENSION 1
|
||||||
#define XSLT_ELEMENT_CATEGORY_LRE 2
|
#define XSLT_ELEMENT_CATEGORY_LRE 2
|
||||||
@@ -1194,6 +1221,7 @@ struct _xsltCompilerNodeInfo {
|
|||||||
xsltPointerListPtr exclResultNs;
|
xsltPointerListPtr exclResultNs;
|
||||||
/* The current extension instruction namespaces */
|
/* The current extension instruction namespaces */
|
||||||
xsltPointerListPtr extElemNs;
|
xsltPointerListPtr extElemNs;
|
||||||
|
|
||||||
/* The current info for literal result elements. */
|
/* The current info for literal result elements. */
|
||||||
xsltStyleItemLRElementInfoPtr litResElemInfo;
|
xsltStyleItemLRElementInfoPtr litResElemInfo;
|
||||||
/*
|
/*
|
||||||
@@ -1263,6 +1291,8 @@ struct _xsltCompilerCtxt {
|
|||||||
xsltStyleItemUknownPtr unknownItem;
|
xsltStyleItemUknownPtr unknownItem;
|
||||||
int hasNsAliases; /* Indicator if there was an xsl:namespace-alias. */
|
int hasNsAliases; /* Indicator if there was an xsl:namespace-alias. */
|
||||||
xsltNsAliasPtr nsAliases;
|
xsltNsAliasPtr nsAliases;
|
||||||
|
xsltVarInfoPtr ivars; /* Storage of local in-scope variables/params. */
|
||||||
|
xsltVarInfoPtr ivar; /* topmost local variable/param. */
|
||||||
};
|
};
|
||||||
|
|
||||||
#else /* XSLT_REFACTORED */
|
#else /* XSLT_REFACTORED */
|
||||||
@@ -1329,6 +1359,10 @@ struct _xsltStylePreComp {
|
|||||||
|
|
||||||
#endif /* XSLT_REFACTORED */
|
#endif /* XSLT_REFACTORED */
|
||||||
|
|
||||||
|
|
||||||
|
#define XSLT_VAR_GLOBAL 1<<0
|
||||||
|
#define XSLT_VAR_IN_SELECT 1<<1
|
||||||
|
#define XSLT_TCTXT_VARIABLE(c) ((xsltStackElemPtr) (c)->contextVariable)
|
||||||
/*
|
/*
|
||||||
* The in-memory structure corresponding to an XSLT Variable
|
* The in-memory structure corresponding to an XSLT Variable
|
||||||
* or Param.
|
* or Param.
|
||||||
@@ -1342,8 +1376,16 @@ struct _xsltStackElem {
|
|||||||
const xmlChar *name; /* the local part of the name QName */
|
const xmlChar *name; /* the local part of the name QName */
|
||||||
const xmlChar *nameURI; /* the URI part of the name QName */
|
const xmlChar *nameURI; /* the URI part of the name QName */
|
||||||
const xmlChar *select; /* the eval string */
|
const xmlChar *select; /* the eval string */
|
||||||
xmlNodePtr tree; /* the tree if no eval string or the location */
|
xmlNodePtr tree; /* the sequence constructor if no eval
|
||||||
|
string or the location */
|
||||||
xmlXPathObjectPtr value; /* The value if computed */
|
xmlXPathObjectPtr value; /* The value if computed */
|
||||||
|
xmlDocPtr fragment; /* The Result Tree Fragments (needed for XSLT 1.0)
|
||||||
|
which are bound to the variable's lifetime. */
|
||||||
|
int level; /* the depth in the tree;
|
||||||
|
-1 if persistent (e.g. a given xsl:with-param) */
|
||||||
|
xsltTransformContextPtr context; /* The transformation context; needed to cache
|
||||||
|
the variables */
|
||||||
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef XSLT_REFACTORED
|
#ifdef XSLT_REFACTORED
|
||||||
@@ -1537,6 +1579,21 @@ struct _xsltStylesheet {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _xsltTransformCache xsltTransformCache;
|
||||||
|
typedef xsltTransformCache *xsltTransformCachePtr;
|
||||||
|
struct _xsltTransformCache {
|
||||||
|
xmlDocPtr RVT;
|
||||||
|
int nbRVT;
|
||||||
|
xsltStackElemPtr stackItems;
|
||||||
|
int nbStackItems;
|
||||||
|
#ifdef XSLT_DEBUG_PROFILE_CACHE
|
||||||
|
int dbgCachedRVTs;
|
||||||
|
int dbgReusedRVTs;
|
||||||
|
int dbgCachedVars;
|
||||||
|
int dbgReusedVars;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The in-memory structure corresponding to an XSLT Transformation.
|
* The in-memory structure corresponding to an XSLT Transformation.
|
||||||
*/
|
*/
|
||||||
@@ -1579,7 +1636,7 @@ struct _xsltTransformContext {
|
|||||||
|
|
||||||
xsltDocumentPtr docList; /* the document list */
|
xsltDocumentPtr docList; /* the document list */
|
||||||
|
|
||||||
xsltDocumentPtr document; /* the current document */
|
xsltDocumentPtr document; /* the current source document; can be NULL if an RTF */
|
||||||
xmlNodePtr node; /* the current node being processed */
|
xmlNodePtr node; /* the current node being processed */
|
||||||
xmlNodeSetPtr nodeList; /* the current node list */
|
xmlNodeSetPtr nodeList; /* the current node list */
|
||||||
/* xmlNodePtr current; the node */
|
/* xmlNodePtr current; the node */
|
||||||
@@ -1623,6 +1680,7 @@ struct _xsltTransformContext {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* handling of temporary Result Value Tree
|
* handling of temporary Result Value Tree
|
||||||
|
* (XSLT 1.0 term: "Result Tree Fragment")
|
||||||
*/
|
*/
|
||||||
xmlDocPtr tmpRVT; /* list of RVT without persistance */
|
xmlDocPtr tmpRVT; /* list of RVT without persistance */
|
||||||
xmlDocPtr persistRVT; /* list of persistant RVTs */
|
xmlDocPtr persistRVT; /* list of persistant RVTs */
|
||||||
@@ -1647,8 +1705,8 @@ struct _xsltTransformContext {
|
|||||||
*/
|
*/
|
||||||
xmlDictPtr dict;
|
xmlDictPtr dict;
|
||||||
/*
|
/*
|
||||||
* temporary storage for doc ptr, currently only used for
|
* The current source doc; one of: the initial source doc, a RTF
|
||||||
* global var evaluation
|
* or a source doc aquired via the document() function.
|
||||||
*/
|
*/
|
||||||
xmlDocPtr tmpDoc;
|
xmlDocPtr tmpDoc;
|
||||||
/*
|
/*
|
||||||
@@ -1657,6 +1715,15 @@ struct _xsltTransformContext {
|
|||||||
int internalized;
|
int internalized;
|
||||||
int nbKeys;
|
int nbKeys;
|
||||||
int hasTemplKeyPatterns;
|
int hasTemplKeyPatterns;
|
||||||
|
xsltTemplatePtr currentTemplateRule; /* the Current Template Rule */
|
||||||
|
xmlNodePtr initialContextNode;
|
||||||
|
xmlDocPtr initialContextDoc;
|
||||||
|
xsltTransformCachePtr cache;
|
||||||
|
void *contextVariable; /* the current variable item */
|
||||||
|
xmlDocPtr localRVT; /* list of local tree fragments; will be freed when
|
||||||
|
the instruction which created the fragment
|
||||||
|
exits */
|
||||||
|
xmlDocPtr localRVTBase;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1762,11 +1829,31 @@ XSLTPUBFUN xmlDocPtr XSLTCALL
|
|||||||
XSLTPUBFUN int XSLTCALL
|
XSLTPUBFUN int XSLTCALL
|
||||||
xsltRegisterTmpRVT (xsltTransformContextPtr ctxt,
|
xsltRegisterTmpRVT (xsltTransformContextPtr ctxt,
|
||||||
xmlDocPtr RVT);
|
xmlDocPtr RVT);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRegisterLocalRVT (xsltTransformContextPtr ctxt,
|
||||||
|
xmlDocPtr RVT);
|
||||||
XSLTPUBFUN int XSLTCALL
|
XSLTPUBFUN int XSLTCALL
|
||||||
xsltRegisterPersistRVT (xsltTransformContextPtr ctxt,
|
xsltRegisterPersistRVT (xsltTransformContextPtr ctxt,
|
||||||
xmlDocPtr RVT);
|
xmlDocPtr RVT);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltExtensionInstructionResultRegister(
|
||||||
|
xsltTransformContextPtr ctxt,
|
||||||
|
xmlXPathObjectPtr obj);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltExtensionInstructionResultFinalize(
|
||||||
|
xsltTransformContextPtr ctxt);
|
||||||
XSLTPUBFUN void XSLTCALL
|
XSLTPUBFUN void XSLTCALL
|
||||||
xsltFreeRVTs (xsltTransformContextPtr ctxt);
|
xsltFreeRVTs (xsltTransformContextPtr ctxt);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltReleaseRVT (xsltTransformContextPtr ctxt,
|
||||||
|
xmlDocPtr RVT);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltTransStorageAdd (xsltTransformContextPtr ctxt,
|
||||||
|
void *id,
|
||||||
|
void *data);
|
||||||
|
XSLTPUBFUN void * XSLTCALL
|
||||||
|
xsltTransStorageRemove (xsltTransformContextPtr ctxt,
|
||||||
|
void *id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extra functions for Attribute Value Templates
|
* Extra functions for Attribute Value Templates
|
||||||
|
@@ -876,9 +876,16 @@ xsltGetQNameURI2(xsltStylesheetPtr style, xmlNodePtr node,
|
|||||||
qname = xmlStrndup(*name, len);
|
qname = xmlStrndup(*name, len);
|
||||||
ns = xmlSearchNs(node->doc, node, qname);
|
ns = xmlSearchNs(node->doc, node, qname);
|
||||||
if (ns == NULL) {
|
if (ns == NULL) {
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
if (style) {
|
||||||
|
xsltTransformError(NULL, style, node,
|
||||||
|
"No namespace bound to prefix '%s'.\n",
|
||||||
|
qname);
|
||||||
|
style->errors++;
|
||||||
|
} else {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"%s : no namespace bound to prefix %s\n",
|
"%s : no namespace bound to prefix %s\n",
|
||||||
*name, qname);
|
*name, qname);
|
||||||
|
}
|
||||||
*name = NULL;
|
*name = NULL;
|
||||||
xmlFree(qname);
|
xmlFree(qname);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
@@ -72,9 +72,11 @@ extern "C" {
|
|||||||
(((n) != NULL) && \
|
(((n) != NULL) && \
|
||||||
(((n)->type == XML_ELEMENT_NODE) || \
|
(((n)->type == XML_ELEMENT_NODE) || \
|
||||||
((n)->type == XML_TEXT_NODE) || \
|
((n)->type == XML_TEXT_NODE) || \
|
||||||
|
((n)->type == XML_CDATA_SECTION_NODE) || \
|
||||||
((n)->type == XML_ATTRIBUTE_NODE) || \
|
((n)->type == XML_ATTRIBUTE_NODE) || \
|
||||||
((n)->type == XML_DOCUMENT_NODE) || \
|
((n)->type == XML_DOCUMENT_NODE) || \
|
||||||
((n)->type == XML_HTML_DOCUMENT_NODE) || \
|
((n)->type == XML_HTML_DOCUMENT_NODE) || \
|
||||||
|
((n)->type == XML_COMMENT_NODE) || \
|
||||||
((n)->type == XML_PI_NODE)))
|
((n)->type == XML_PI_NODE)))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user