mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 07:13:23 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
825
dll/3rdparty/libxslt/templates.c
vendored
Normal file
825
dll/3rdparty/libxslt/templates.c
vendored
Normal file
|
@ -0,0 +1,825 @@
|
|||
/*
|
||||
* templates.c: Implementation of the template processing
|
||||
*
|
||||
* Reference:
|
||||
* http://www.w3.org/TR/1999/REC-xslt-19991116
|
||||
*
|
||||
* See Copyright for the status of this software.
|
||||
*
|
||||
* daniel@veillard.com
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#include <libxml/globals.h>
|
||||
|
||||
#ifdef WITH_XSLT_DEBUG
|
||||
#define WITH_XSLT_DEBUG_TEMPLATES
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Module interfaces *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* xsltEvalXPathPredicate:
|
||||
* @ctxt: the XSLT transformation context
|
||||
* @comp: the XPath compiled expression
|
||||
* @nsList: the namespaces in scope
|
||||
* @nsNr: the number of namespaces in scope
|
||||
*
|
||||
* Process the expression using XPath and evaluate the result as
|
||||
* an XPath predicate
|
||||
*
|
||||
* Returns 1 is the predicate was true, 0 otherwise
|
||||
*/
|
||||
int
|
||||
xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
|
||||
xmlNsPtr *nsList, int nsNr) {
|
||||
int ret;
|
||||
xmlXPathObjectPtr res;
|
||||
int oldNsNr;
|
||||
xmlNsPtr *oldNamespaces;
|
||||
xmlNodePtr oldInst;
|
||||
int oldProximityPosition, oldContextSize;
|
||||
|
||||
oldContextSize = ctxt->xpathCtxt->contextSize;
|
||||
oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
|
||||
oldNsNr = ctxt->xpathCtxt->nsNr;
|
||||
oldNamespaces = ctxt->xpathCtxt->namespaces;
|
||||
oldInst = ctxt->inst;
|
||||
|
||||
ctxt->xpathCtxt->node = ctxt->node;
|
||||
ctxt->xpathCtxt->namespaces = nsList;
|
||||
ctxt->xpathCtxt->nsNr = nsNr;
|
||||
|
||||
res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
|
||||
|
||||
if (res != NULL) {
|
||||
ret = xmlXPathEvalPredicate(ctxt->xpathCtxt, res);
|
||||
xmlXPathFreeObject(res);
|
||||
#ifdef WITH_XSLT_DEBUG_TEMPLATES
|
||||
XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
|
||||
"xsltEvalXPathPredicate: returns %d\n", ret));
|
||||
#endif
|
||||
} else {
|
||||
#ifdef WITH_XSLT_DEBUG_TEMPLATES
|
||||
XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
|
||||
"xsltEvalXPathPredicate: failed\n"));
|
||||
#endif
|
||||
ctxt->state = XSLT_STATE_STOPPED;
|
||||
ret = 0;
|
||||
}
|
||||
ctxt->xpathCtxt->nsNr = oldNsNr;
|
||||
|
||||
ctxt->xpathCtxt->namespaces = oldNamespaces;
|
||||
ctxt->inst = oldInst;
|
||||
ctxt->xpathCtxt->contextSize = oldContextSize;
|
||||
ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltEvalXPathStringNs:
|
||||
* @ctxt: the XSLT transformation context
|
||||
* @comp: the compiled XPath expression
|
||||
* @nsNr: the number of namespaces in the list
|
||||
* @nsList: the list of in-scope namespaces to use
|
||||
*
|
||||
* Process the expression using XPath, allowing to pass a namespace mapping
|
||||
* context and get a string
|
||||
*
|
||||
* Returns the computed string value or NULL, must be deallocated by the
|
||||
* caller.
|
||||
*/
|
||||
xmlChar *
|
||||
xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
|
||||
int nsNr, xmlNsPtr *nsList) {
|
||||
xmlChar *ret = NULL;
|
||||
xmlXPathObjectPtr res;
|
||||
xmlNodePtr oldInst;
|
||||
xmlNodePtr oldNode;
|
||||
int oldPos, oldSize;
|
||||
int oldNsNr;
|
||||
xmlNsPtr *oldNamespaces;
|
||||
|
||||
oldInst = ctxt->inst;
|
||||
oldNode = ctxt->node;
|
||||
oldPos = ctxt->xpathCtxt->proximityPosition;
|
||||
oldSize = ctxt->xpathCtxt->contextSize;
|
||||
oldNsNr = ctxt->xpathCtxt->nsNr;
|
||||
oldNamespaces = ctxt->xpathCtxt->namespaces;
|
||||
|
||||
ctxt->xpathCtxt->node = ctxt->node;
|
||||
/* TODO: do we need to propagate the namespaces here ? */
|
||||
ctxt->xpathCtxt->namespaces = nsList;
|
||||
ctxt->xpathCtxt->nsNr = nsNr;
|
||||
res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
|
||||
if (res != NULL) {
|
||||
if (res->type != XPATH_STRING)
|
||||
res = xmlXPathConvertString(res);
|
||||
if (res->type == XPATH_STRING) {
|
||||
ret = res->stringval;
|
||||
res->stringval = NULL;
|
||||
} else {
|
||||
xsltTransformError(ctxt, NULL, NULL,
|
||||
"xpath : string() function didn't return a String\n");
|
||||
}
|
||||
xmlXPathFreeObject(res);
|
||||
} else {
|
||||
ctxt->state = XSLT_STATE_STOPPED;
|
||||
}
|
||||
#ifdef WITH_XSLT_DEBUG_TEMPLATES
|
||||
XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
|
||||
"xsltEvalXPathString: returns %s\n", ret));
|
||||
#endif
|
||||
ctxt->inst = oldInst;
|
||||
ctxt->node = oldNode;
|
||||
ctxt->xpathCtxt->contextSize = oldSize;
|
||||
ctxt->xpathCtxt->proximityPosition = oldPos;
|
||||
ctxt->xpathCtxt->nsNr = oldNsNr;
|
||||
ctxt->xpathCtxt->namespaces = oldNamespaces;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltEvalXPathString:
|
||||
* @ctxt: the XSLT transformation context
|
||||
* @comp: the compiled XPath expression
|
||||
*
|
||||
* Process the expression using XPath and get a string
|
||||
*
|
||||
* Returns the computed string value or NULL, must be deallocated by the
|
||||
* caller.
|
||||
*/
|
||||
xmlChar *
|
||||
xsltEvalXPathString(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp) {
|
||||
return(xsltEvalXPathStringNs(ctxt, comp, 0, NULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltEvalTemplateString:
|
||||
* @ctxt: the XSLT transformation context
|
||||
* @contextNode: the current node in the source tree
|
||||
* @inst: the XSLT instruction (xsl:comment, xsl:processing-instruction)
|
||||
*
|
||||
* Processes the sequence constructor of the given instruction on
|
||||
* @contextNode and converts the resulting tree to a string.
|
||||
* This is needed by e.g. xsl:comment and xsl:processing-instruction.
|
||||
*
|
||||
* Returns the computed string value or NULL; it's up to the caller to
|
||||
* free the result.
|
||||
*/
|
||||
xmlChar *
|
||||
xsltEvalTemplateString(xsltTransformContextPtr ctxt,
|
||||
xmlNodePtr contextNode,
|
||||
xmlNodePtr inst)
|
||||
{
|
||||
xmlNodePtr oldInsert, insert = NULL;
|
||||
xmlChar *ret;
|
||||
|
||||
if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL) ||
|
||||
(inst->type != XML_ELEMENT_NODE))
|
||||
return(NULL);
|
||||
|
||||
if (inst->children == NULL)
|
||||
return(NULL);
|
||||
|
||||
/*
|
||||
* This creates a temporary element-node to add the resulting
|
||||
* text content to.
|
||||
* OPTIMIZE TODO: Keep such an element-node in the transformation
|
||||
* context to avoid creating it every time.
|
||||
*/
|
||||
insert = xmlNewDocNode(ctxt->output, NULL,
|
||||
(const xmlChar *)"fake", NULL);
|
||||
if (insert == NULL) {
|
||||
xsltTransformError(ctxt, NULL, contextNode,
|
||||
"Failed to create temporary node\n");
|
||||
return(NULL);
|
||||
}
|
||||
oldInsert = ctxt->insert;
|
||||
ctxt->insert = insert;
|
||||
/*
|
||||
* OPTIMIZE TODO: if inst->children consists only of text-nodes.
|
||||
*/
|
||||
xsltApplyOneTemplate(ctxt, contextNode, inst->children, NULL, NULL);
|
||||
|
||||
ctxt->insert = oldInsert;
|
||||
|
||||
ret = xmlNodeGetContent(insert);
|
||||
if (insert != NULL)
|
||||
xmlFreeNode(insert);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltAttrTemplateValueProcessNode:
|
||||
* @ctxt: the XSLT transformation context
|
||||
* @str: the attribute template node value
|
||||
* @inst: the instruction (or LRE) in the stylesheet holding the
|
||||
* attribute with an AVT
|
||||
*
|
||||
* Process the given string, allowing to pass a namespace mapping
|
||||
* context and return the new string value.
|
||||
*
|
||||
* Called by:
|
||||
* - xsltAttrTemplateValueProcess() (templates.c)
|
||||
* - xsltEvalAttrValueTemplate() (templates.c)
|
||||
*
|
||||
* QUESTION: Why is this function public? It is not used outside
|
||||
* of templates.c.
|
||||
*
|
||||
* Returns the computed string value or NULL, must be deallocated by the
|
||||
* caller.
|
||||
*/
|
||||
xmlChar *
|
||||
xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,
|
||||
const xmlChar *str, xmlNodePtr inst)
|
||||
{
|
||||
xmlChar *ret = NULL;
|
||||
const xmlChar *cur;
|
||||
xmlChar *expr, *val;
|
||||
xmlNsPtr *nsList = NULL;
|
||||
int nsNr = 0;
|
||||
|
||||
if (str == NULL) return(NULL);
|
||||
if (*str == 0)
|
||||
return(xmlStrndup((xmlChar *)"", 0));
|
||||
|
||||
cur = str;
|
||||
while (*cur != 0) {
|
||||
if (*cur == '{') {
|
||||
if (*(cur+1) == '{') { /* escaped '{' */
|
||||
cur++;
|
||||
ret = xmlStrncat(ret, str, cur - str);
|
||||
cur++;
|
||||
str = cur;
|
||||
continue;
|
||||
}
|
||||
ret = xmlStrncat(ret, str, cur - str);
|
||||
str = cur;
|
||||
cur++;
|
||||
while ((*cur != 0) && (*cur != '}')) {
|
||||
/* Need to check for literal (bug539741) */
|
||||
if ((*cur == '\'') || (*cur == '"')) {
|
||||
char delim = *(cur++);
|
||||
while ((*cur != 0) && (*cur != delim))
|
||||
cur++;
|
||||
if (*cur != 0)
|
||||
cur++; /* skip the ending delimiter */
|
||||
} else
|
||||
cur++;
|
||||
}
|
||||
if (*cur == 0) {
|
||||
xsltTransformError(ctxt, NULL, inst,
|
||||
"xsltAttrTemplateValueProcessNode: unmatched '{'\n");
|
||||
ret = xmlStrncat(ret, str, cur - str);
|
||||
return(ret);
|
||||
}
|
||||
str++;
|
||||
expr = xmlStrndup(str, cur - str);
|
||||
if (expr == NULL)
|
||||
return(ret);
|
||||
else if (*expr == '{') {
|
||||
ret = xmlStrcat(ret, expr);
|
||||
xmlFree(expr);
|
||||
} else {
|
||||
xmlXPathCompExprPtr comp;
|
||||
/*
|
||||
* TODO: keep precompiled form around
|
||||
*/
|
||||
if ((nsList == NULL) && (inst != NULL)) {
|
||||
int i = 0;
|
||||
|
||||
nsList = xmlGetNsList(inst->doc, inst);
|
||||
if (nsList != NULL) {
|
||||
while (nsList[i] != NULL)
|
||||
i++;
|
||||
nsNr = i;
|
||||
}
|
||||
}
|
||||
comp = xmlXPathCompile(expr);
|
||||
val = xsltEvalXPathStringNs(ctxt, comp, nsNr, nsList);
|
||||
xmlXPathFreeCompExpr(comp);
|
||||
xmlFree(expr);
|
||||
if (val != NULL) {
|
||||
ret = xmlStrcat(ret, val);
|
||||
xmlFree(val);
|
||||
}
|
||||
}
|
||||
cur++;
|
||||
str = cur;
|
||||
} else if (*cur == '}') {
|
||||
cur++;
|
||||
if (*cur == '}') { /* escaped '}' */
|
||||
ret = xmlStrncat(ret, str, cur - str);
|
||||
cur++;
|
||||
str = cur;
|
||||
continue;
|
||||
} else {
|
||||
xsltTransformError(ctxt, NULL, inst,
|
||||
"xsltAttrTemplateValueProcessNode: unmatched '}'\n");
|
||||
}
|
||||
} else
|
||||
cur++;
|
||||
}
|
||||
if (cur != str) {
|
||||
ret = xmlStrncat(ret, str, cur - str);
|
||||
}
|
||||
|
||||
if (nsList != NULL)
|
||||
xmlFree(nsList);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltAttrTemplateValueProcess:
|
||||
* @ctxt: the XSLT transformation context
|
||||
* @str: the attribute template node value
|
||||
*
|
||||
* Process the given node and return the new string value.
|
||||
*
|
||||
* Returns the computed string value or NULL, must be deallocated by the
|
||||
* caller.
|
||||
*/
|
||||
xmlChar *
|
||||
xsltAttrTemplateValueProcess(xsltTransformContextPtr ctxt, const xmlChar *str) {
|
||||
return(xsltAttrTemplateValueProcessNode(ctxt, str, NULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltEvalAttrValueTemplate:
|
||||
* @ctxt: the XSLT transformation context
|
||||
* @inst: the instruction (or LRE) in the stylesheet holding the
|
||||
* attribute with an AVT
|
||||
* @name: the attribute QName
|
||||
* @ns: the attribute namespace URI
|
||||
*
|
||||
* Evaluate a attribute value template, i.e. the attribute value can
|
||||
* contain expressions contained in curly braces ({}) and those are
|
||||
* substituted by they computed value.
|
||||
*
|
||||
* Returns the computed string value or NULL, must be deallocated by the
|
||||
* caller.
|
||||
*/
|
||||
xmlChar *
|
||||
xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst,
|
||||
const xmlChar *name, const xmlChar *ns)
|
||||
{
|
||||
xmlChar *ret;
|
||||
xmlChar *expr;
|
||||
|
||||
if ((ctxt == NULL) || (inst == NULL) || (name == NULL) ||
|
||||
(inst->type != XML_ELEMENT_NODE))
|
||||
return(NULL);
|
||||
|
||||
expr = xsltGetNsProp(inst, name, ns);
|
||||
if (expr == NULL)
|
||||
return(NULL);
|
||||
|
||||
/*
|
||||
* TODO: though now {} is detected ahead, it would still be good to
|
||||
* optimize both functions to keep the splitted value if the
|
||||
* attribute content and the XPath precompiled expressions around
|
||||
*/
|
||||
|
||||
ret = xsltAttrTemplateValueProcessNode(ctxt, expr, inst);
|
||||
#ifdef WITH_XSLT_DEBUG_TEMPLATES
|
||||
XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
|
||||
"xsltEvalAttrValueTemplate: %s returns %s\n", expr, ret));
|
||||
#endif
|
||||
if (expr != NULL)
|
||||
xmlFree(expr);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltEvalStaticAttrValueTemplate:
|
||||
* @style: the XSLT stylesheet
|
||||
* @inst: the instruction (or LRE) in the stylesheet holding the
|
||||
* attribute with an AVT
|
||||
* @name: the attribute Name
|
||||
* @ns: the attribute namespace URI
|
||||
* @found: indicator whether the attribute is present
|
||||
*
|
||||
* Check if an attribute value template has a static value, i.e. the
|
||||
* attribute value does not contain expressions contained in curly braces ({})
|
||||
*
|
||||
* Returns the static string value or NULL, must be deallocated by the
|
||||
* caller.
|
||||
*/
|
||||
const xmlChar *
|
||||
xsltEvalStaticAttrValueTemplate(xsltStylesheetPtr style, xmlNodePtr inst,
|
||||
const xmlChar *name, const xmlChar *ns, int *found) {
|
||||
const xmlChar *ret;
|
||||
xmlChar *expr;
|
||||
|
||||
if ((style == NULL) || (inst == NULL) || (name == NULL) ||
|
||||
(inst->type != XML_ELEMENT_NODE))
|
||||
return(NULL);
|
||||
|
||||
expr = xsltGetNsProp(inst, name, ns);
|
||||
if (expr == NULL) {
|
||||
*found = 0;
|
||||
return(NULL);
|
||||
}
|
||||
*found = 1;
|
||||
|
||||
ret = xmlStrchr(expr, '{');
|
||||
if (ret != NULL) {
|
||||
xmlFree(expr);
|
||||
return(NULL);
|
||||
}
|
||||
ret = xmlDictLookup(style->dict, expr, -1);
|
||||
xmlFree(expr);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xsltAttrTemplateProcess:
|
||||
* @ctxt: the XSLT transformation context
|
||||
* @target: the element where the attribute will be grafted
|
||||
* @attr: the attribute node of a literal result element
|
||||
*
|
||||
* Process one attribute of a Literal Result Element (in the stylesheet).
|
||||
* Evaluates Attribute Value Templates and copies the attribute over to
|
||||
* the result element.
|
||||
* This does *not* process attribute sets (xsl:use-attribute-set).
|
||||
*
|
||||
*
|
||||
* Returns the generated attribute node.
|
||||
*/
|
||||
xmlAttrPtr
|
||||
xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
|
||||
xmlAttrPtr attr)
|
||||
{
|
||||
const xmlChar *value;
|
||||
xmlAttrPtr ret;
|
||||
|
||||
if ((ctxt == NULL) || (attr == NULL) || (target == NULL) ||
|
||||
(target->type != XML_ELEMENT_NODE))
|
||||
return(NULL);
|
||||
|
||||
if (attr->type != XML_ATTRIBUTE_NODE)
|
||||
return(NULL);
|
||||
|
||||
/*
|
||||
* Skip all XSLT attributes.
|
||||
*/
|
||||
#ifdef XSLT_REFACTORED
|
||||
if (attr->psvi == xsltXSLTAttrMarker)
|
||||
return(NULL);
|
||||
#else
|
||||
if ((attr->ns != NULL) && xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
|
||||
return(NULL);
|
||||
#endif
|
||||
/*
|
||||
* Get the value.
|
||||
*/
|
||||
if (attr->children != NULL) {
|
||||
if ((attr->children->type != XML_TEXT_NODE) ||
|
||||
(attr->children->next != NULL))
|
||||
{
|
||||
xsltTransformError(ctxt, NULL, attr->parent,
|
||||
"Internal error: The children of an attribute node of a "
|
||||
"literal result element are not in the expected form.\n");
|
||||
return(NULL);
|
||||
}
|
||||
value = attr->children->content;
|
||||
if (value == NULL)
|
||||
value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
|
||||
} else
|
||||
value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
|
||||
/*
|
||||
* Overwrite duplicates.
|
||||
*/
|
||||
ret = target->properties;
|
||||
while (ret != NULL) {
|
||||
if (((attr->ns != NULL) == (ret->ns != NULL)) &&
|
||||
xmlStrEqual(ret->name, attr->name) &&
|
||||
((attr->ns == NULL) || xmlStrEqual(ret->ns->href, attr->ns->href)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
ret = ret->next;
|
||||
}
|
||||
if (ret != NULL) {
|
||||
/* free the existing value */
|
||||
xmlFreeNodeList(ret->children);
|
||||
ret->children = ret->last = NULL;
|
||||
/*
|
||||
* Adjust ns-prefix if needed.
|
||||
*/
|
||||
if ((ret->ns != NULL) &&
|
||||
(! xmlStrEqual(ret->ns->prefix, attr->ns->prefix)))
|
||||
{
|
||||
ret->ns = xsltGetNamespace(ctxt, attr->parent, attr->ns, target);
|
||||
}
|
||||
} else {
|
||||
/* create a new attribute */
|
||||
if (attr->ns != NULL)
|
||||
ret = xmlNewNsProp(target,
|
||||
xsltGetNamespace(ctxt, attr->parent, attr->ns, target),
|
||||
attr->name, NULL);
|
||||
else
|
||||
ret = xmlNewNsProp(target, NULL, attr->name, NULL);
|
||||
}
|
||||
/*
|
||||
* Set the value.
|
||||
*/
|
||||
if (ret != NULL) {
|
||||
xmlNodePtr text;
|
||||
|
||||
text = xmlNewText(NULL);
|
||||
if (text != NULL) {
|
||||
ret->last = ret->children = text;
|
||||
text->parent = (xmlNodePtr) ret;
|
||||
text->doc = ret->doc;
|
||||
|
||||
if (attr->psvi != NULL) {
|
||||
/*
|
||||
* Evaluate the Attribute Value Template.
|
||||
*/
|
||||
xmlChar *val;
|
||||
val = xsltEvalAVT(ctxt, attr->psvi, attr->parent);
|
||||
if (val == NULL) {
|
||||
/*
|
||||
* TODO: Damn, we need an easy mechanism to report
|
||||
* qualified names!
|
||||
*/
|
||||
if (attr->ns) {
|
||||
xsltTransformError(ctxt, NULL, attr->parent,
|
||||
"Internal error: Failed to evaluate the AVT "
|
||||
"of attribute '{%s}%s'.\n",
|
||||
attr->ns->href, attr->name);
|
||||
} else {
|
||||
xsltTransformError(ctxt, NULL, attr->parent,
|
||||
"Internal error: Failed to evaluate the AVT "
|
||||
"of attribute '%s'.\n",
|
||||
attr->name);
|
||||
}
|
||||
text->content = xmlStrdup(BAD_CAST "");
|
||||
} else {
|
||||
text->content = val;
|
||||
}
|
||||
} else if ((ctxt->internalized) && (target != NULL) &&
|
||||
(target->doc != NULL) &&
|
||||
(target->doc->dict == ctxt->dict) &&
|
||||
xmlDictOwns(ctxt->dict, value)) {
|
||||
text->content = (xmlChar *) value;
|
||||
} else {
|
||||
text->content = xmlStrdup(value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (attr->ns) {
|
||||
xsltTransformError(ctxt, NULL, attr->parent,
|
||||
"Internal error: Failed to create attribute '{%s}%s'.\n",
|
||||
attr->ns->href, attr->name);
|
||||
} else {
|
||||
xsltTransformError(ctxt, NULL, attr->parent,
|
||||
"Internal error: Failed to create attribute '%s'.\n",
|
||||
attr->name);
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xsltAttrListTemplateProcess:
|
||||
* @ctxt: the XSLT transformation context
|
||||
* @target: the element where the attributes will be grafted
|
||||
* @attrs: the first attribute
|
||||
*
|
||||
* Processes all attributes of a Literal Result Element.
|
||||
* Attribute references are applied via xsl:use-attribute-set
|
||||
* attributes.
|
||||
* Copies all non XSLT-attributes over to the @target element
|
||||
* and evaluates Attribute Value Templates.
|
||||
*
|
||||
* Called by xsltApplySequenceConstructor() (transform.c).
|
||||
*
|
||||
* Returns a new list of attribute nodes, or NULL in case of error.
|
||||
* (Don't assign the result to @target->properties; if
|
||||
* the result is NULL, you'll get memory leaks, since the
|
||||
* attributes will be disattached.)
|
||||
*/
|
||||
xmlAttrPtr
|
||||
xsltAttrListTemplateProcess(xsltTransformContextPtr ctxt,
|
||||
xmlNodePtr target, xmlAttrPtr attrs)
|
||||
{
|
||||
xmlAttrPtr attr, copy, last;
|
||||
xmlNodePtr oldInsert, text;
|
||||
xmlNsPtr origNs = NULL, copyNs = NULL;
|
||||
const xmlChar *value;
|
||||
xmlChar *valueAVT;
|
||||
|
||||
if ((ctxt == NULL) || (target == NULL) || (attrs == NULL) ||
|
||||
(target->type != XML_ELEMENT_NODE))
|
||||
return(NULL);
|
||||
|
||||
oldInsert = ctxt->insert;
|
||||
ctxt->insert = target;
|
||||
|
||||
/*
|
||||
* Instantiate LRE-attributes.
|
||||
*/
|
||||
if (target->properties) {
|
||||
last = target->properties;
|
||||
while (last->next != NULL)
|
||||
last = last->next;
|
||||
} else {
|
||||
last = NULL;
|
||||
}
|
||||
attr = attrs;
|
||||
do {
|
||||
/*
|
||||
* Skip XSLT attributes.
|
||||
*/
|
||||
#ifdef XSLT_REFACTORED
|
||||
if (attr->psvi == xsltXSLTAttrMarker) {
|
||||
goto next_attribute;
|
||||
}
|
||||
#else
|
||||
if ((attr->ns != NULL) &&
|
||||
xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
|
||||
{
|
||||
goto next_attribute;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Get the value.
|
||||
*/
|
||||
if (attr->children != NULL) {
|
||||
if ((attr->children->type != XML_TEXT_NODE) ||
|
||||
(attr->children->next != NULL))
|
||||
{
|
||||
xsltTransformError(ctxt, NULL, attr->parent,
|
||||
"Internal error: The children of an attribute node of a "
|
||||
"literal result element are not in the expected form.\n");
|
||||
goto error;
|
||||
}
|
||||
value = attr->children->content;
|
||||
if (value == NULL)
|
||||
value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
|
||||
} else
|
||||
value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
|
||||
|
||||
/*
|
||||
* Create a new attribute.
|
||||
*/
|
||||
copy = xmlNewDocProp(target->doc, attr->name, NULL);
|
||||
if (copy == NULL) {
|
||||
if (attr->ns) {
|
||||
xsltTransformError(ctxt, NULL, attr->parent,
|
||||
"Internal error: Failed to create attribute '{%s}%s'.\n",
|
||||
attr->ns->href, attr->name);
|
||||
} else {
|
||||
xsltTransformError(ctxt, NULL, attr->parent,
|
||||
"Internal error: Failed to create attribute '%s'.\n",
|
||||
attr->name);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
* Attach it to the target element.
|
||||
*/
|
||||
copy->parent = target;
|
||||
if (last == NULL) {
|
||||
target->properties = copy;
|
||||
last = copy;
|
||||
} else {
|
||||
last->next = copy;
|
||||
copy->prev = last;
|
||||
last = copy;
|
||||
}
|
||||
/*
|
||||
* Set the namespace. Avoid lookups of same namespaces.
|
||||
*/
|
||||
if (attr->ns != origNs) {
|
||||
origNs = attr->ns;
|
||||
if (attr->ns != NULL) {
|
||||
#ifdef XSLT_REFACTORED
|
||||
copyNs = xsltGetSpecialNamespace(ctxt, attr->parent,
|
||||
attr->ns->href, attr->ns->prefix, target);
|
||||
#else
|
||||
copyNs = xsltGetNamespace(ctxt, attr->parent,
|
||||
attr->ns, target);
|
||||
#endif
|
||||
if (copyNs == NULL)
|
||||
goto error;
|
||||
} else
|
||||
copyNs = NULL;
|
||||
}
|
||||
copy->ns = copyNs;
|
||||
|
||||
/*
|
||||
* Set the value.
|
||||
*/
|
||||
text = xmlNewText(NULL);
|
||||
if (text != NULL) {
|
||||
copy->last = copy->children = text;
|
||||
text->parent = (xmlNodePtr) copy;
|
||||
text->doc = copy->doc;
|
||||
|
||||
if (attr->psvi != NULL) {
|
||||
/*
|
||||
* Evaluate the Attribute Value Template.
|
||||
*/
|
||||
valueAVT = xsltEvalAVT(ctxt, attr->psvi, attr->parent);
|
||||
if (valueAVT == NULL) {
|
||||
/*
|
||||
* TODO: Damn, we need an easy mechanism to report
|
||||
* qualified names!
|
||||
*/
|
||||
if (attr->ns) {
|
||||
xsltTransformError(ctxt, NULL, attr->parent,
|
||||
"Internal error: Failed to evaluate the AVT "
|
||||
"of attribute '{%s}%s'.\n",
|
||||
attr->ns->href, attr->name);
|
||||
} else {
|
||||
xsltTransformError(ctxt, NULL, attr->parent,
|
||||
"Internal error: Failed to evaluate the AVT "
|
||||
"of attribute '%s'.\n",
|
||||
attr->name);
|
||||
}
|
||||
text->content = xmlStrdup(BAD_CAST "");
|
||||
goto error;
|
||||
} else {
|
||||
text->content = valueAVT;
|
||||
}
|
||||
} else if ((ctxt->internalized) &&
|
||||
(target->doc != NULL) &&
|
||||
(target->doc->dict == ctxt->dict) &&
|
||||
xmlDictOwns(ctxt->dict, value))
|
||||
{
|
||||
text->content = (xmlChar *) value;
|
||||
} else {
|
||||
text->content = xmlStrdup(value);
|
||||
}
|
||||
if ((copy != NULL) && (text != NULL) &&
|
||||
(xmlIsID(copy->doc, copy->parent, copy)))
|
||||
xmlAddID(NULL, copy->doc, text->content, copy);
|
||||
}
|
||||
|
||||
next_attribute:
|
||||
attr = attr->next;
|
||||
} while (attr != NULL);
|
||||
|
||||
/*
|
||||
* Apply attribute-sets.
|
||||
* The creation of such attributes will not overwrite any existing
|
||||
* attribute.
|
||||
*/
|
||||
attr = attrs;
|
||||
do {
|
||||
#ifdef XSLT_REFACTORED
|
||||
if ((attr->psvi == xsltXSLTAttrMarker) &&
|
||||
xmlStrEqual(attr->name, (const xmlChar *)"use-attribute-sets"))
|
||||
{
|
||||
xsltApplyAttributeSet(ctxt, ctxt->node, (xmlNodePtr) attr, NULL);
|
||||
}
|
||||
#else
|
||||
if ((attr->ns != NULL) &&
|
||||
xmlStrEqual(attr->name, (const xmlChar *)"use-attribute-sets") &&
|
||||
xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
|
||||
{
|
||||
xsltApplyAttributeSet(ctxt, ctxt->node, (xmlNodePtr) attr, NULL);
|
||||
}
|
||||
#endif
|
||||
attr = attr->next;
|
||||
} while (attr != NULL);
|
||||
|
||||
ctxt->insert = oldInsert;
|
||||
return(target->properties);
|
||||
|
||||
error:
|
||||
ctxt->insert = oldInsert;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xsltTemplateProcess:
|
||||
* @ctxt: the XSLT transformation context
|
||||
* @node: the attribute template node
|
||||
*
|
||||
* Obsolete. Don't use it.
|
||||
*
|
||||
* Returns NULL.
|
||||
*/
|
||||
xmlNodePtr *
|
||||
xsltTemplateProcess(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, xmlNodePtr node) {
|
||||
if (node == NULL)
|
||||
return(NULL);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue