xslt: Import upstream release 1.1.35.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2022-04-07 12:25:14 +02:00
parent a279c2783c
commit f3f7dd4dba
15 changed files with 304 additions and 426 deletions

View File

@ -1968,12 +1968,6 @@ xsltGetExtInfo(xsltStylesheetPtr style, const xmlChar * URI)
return NULL;
}
/************************************************************************
* *
* Test module http://xmlsoft.org/XSLT/ *
* *
************************************************************************/
/************************************************************************
* *
* Test of the extension module API *

View File

@ -246,7 +246,7 @@ XSLTPUBFUN xmlHashTablePtr XSLTCALL
const xmlChar *URI);
/**
* Test module http://xmlsoft.org/XSLT/
* Test of the extension module API
*/
XSLTPUBFUN void XSLTCALL
xsltRegisterTestModule (void);

View File

@ -178,10 +178,22 @@ xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)
goto out_fragment;
}
#if LIBXML_VERSION >= 20911 || \
defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
xptrctxt->opLimit = ctxt->context->opLimit;
xptrctxt->opCount = ctxt->context->opCount;
xptrctxt->depth = ctxt->context->depth;
resObj = xmlXPtrEval(fragment, xptrctxt);
ctxt->context->opCount = xptrctxt->opCount;
#else
resObj = xmlXPtrEval(fragment, xptrctxt);
xmlXPathFreeContext(xptrctxt);
#endif
xmlXPathFreeContext(xptrctxt);
#endif /* LIBXML_XPTR_ENABLED */
if (resObj == NULL)
goto out_fragment;

View File

@ -177,7 +177,7 @@ xsltNumberFormatDecimal(xmlBufferPtr buffer,
i = -1;
break;
}
*(--pointer) = val;
*(--pointer) = (xmlChar)val;
}
else {
/*
@ -960,7 +960,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
xmlChar *nprefix, *nsuffix = NULL;
int prefix_length, suffix_length = 0, nprefix_length, nsuffix_length;
double scale;
int j, len;
int j, len = 0;
int self_grouping_len;
xsltFormatNumberInfo format_info;
/*

View File

@ -452,14 +452,11 @@ xsltReverseCompMatch(xsltParserContextPtr ctxt, xsltCompMatchPtr comp) {
xsltCompMatchAdd(ctxt, comp, XSLT_OP_END, NULL, NULL, 0);
/*
* Detect consecutive XSLT_OP_PREDICATE and predicates on ops which
* haven't been optimized yet indicating a direct matching should be done.
* Detect consecutive XSLT_OP_PREDICATE indicating a direct matching
* should be done.
*/
for (i = 0;i < comp->nbStep - 1;i++) {
xsltOp op = comp->steps[i].op;
if ((op != XSLT_OP_ELEM) &&
(op != XSLT_OP_ALL) &&
if ((comp->steps[i].op == XSLT_OP_PREDICATE) &&
(comp->steps[i + 1].op == XSLT_OP_PREDICATE)) {
comp->direct = 1;
@ -629,6 +626,152 @@ xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
return(0);
}
/**
* xsltTestStepMatch:
* @ctxt: a XSLT process context
* @node: a node
* @step: the step
*
* Test whether the node matches the step.
*
* Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
*/
static int
xsltTestStepMatch(xsltTransformContextPtr ctxt, xmlNodePtr node,
xsltStepOpPtr step) {
switch (step->op) {
case XSLT_OP_ROOT:
if ((node->type == XML_DOCUMENT_NODE) ||
#ifdef LIBXML_DOCB_ENABLED
(node->type == XML_DOCB_DOCUMENT_NODE) ||
#endif
(node->type == XML_HTML_DOCUMENT_NODE))
return(1);
if ((node->type == XML_ELEMENT_NODE) && (node->name[0] == ' '))
return(1);
return(0);
case XSLT_OP_ELEM:
if (node->type != XML_ELEMENT_NODE)
return(0);
if (step->value == NULL)
return(1);
if (step->value[0] != node->name[0])
return(0);
if (!xmlStrEqual(step->value, node->name))
return(0);
/* Namespace test */
if (node->ns == NULL) {
if (step->value2 != NULL)
return(0);
} else if (node->ns->href != NULL) {
if (step->value2 == NULL)
return(0);
if (!xmlStrEqual(step->value2, node->ns->href))
return(0);
}
return(1);
case XSLT_OP_ATTR:
if (node->type != XML_ATTRIBUTE_NODE)
return(0);
if (step->value != NULL) {
if (step->value[0] != node->name[0])
return(0);
if (!xmlStrEqual(step->value, node->name))
return(0);
}
/* Namespace test */
if (node->ns == NULL) {
if (step->value2 != NULL)
return(0);
} else if (step->value2 != NULL) {
if (!xmlStrEqual(step->value2, node->ns->href))
return(0);
}
return(1);
case XSLT_OP_ID: {
/* TODO Handle IDs decently, must be done differently */
xmlAttrPtr id;
if (node->type != XML_ELEMENT_NODE)
return(0);
id = xmlGetID(node->doc, step->value);
if ((id == NULL) || (id->parent != node))
return(0);
break;
}
case XSLT_OP_KEY: {
xmlNodeSetPtr list;
int indx;
list = xsltGetKey(ctxt, step->value,
step->value3, step->value2);
if (list == NULL)
return(0);
for (indx = 0;indx < list->nodeNr;indx++)
if (list->nodeTab[indx] == node)
break;
if (indx >= list->nodeNr)
return(0);
break;
}
case XSLT_OP_NS:
if (node->type != XML_ELEMENT_NODE)
return(0);
if (node->ns == NULL) {
if (step->value != NULL)
return(0);
} else if (node->ns->href != NULL) {
if (step->value == NULL)
return(0);
if (!xmlStrEqual(step->value, node->ns->href))
return(0);
}
break;
case XSLT_OP_ALL:
if (node->type != XML_ELEMENT_NODE)
return(0);
break;
case XSLT_OP_PI:
if (node->type != XML_PI_NODE)
return(0);
if (step->value != NULL) {
if (!xmlStrEqual(step->value, node->name))
return(0);
}
break;
case XSLT_OP_COMMENT:
if (node->type != XML_COMMENT_NODE)
return(0);
break;
case XSLT_OP_TEXT:
if ((node->type != XML_TEXT_NODE) &&
(node->type != XML_CDATA_SECTION_NODE))
return(0);
break;
case XSLT_OP_NODE:
switch (node->type) {
case XML_ELEMENT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
case XML_TEXT_NODE:
break;
default:
return(0);
}
break;
default:
xsltTransformError(ctxt, NULL, node,
"xsltTestStepMatch: unexpected step op %d\n",
step->op);
return(-1);
}
return(1);
}
/**
* xsltTestPredicateMatch:
* @ctxt: a XSLT process context
@ -656,6 +799,8 @@ xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
return(0);
if (step->comp == NULL)
return(0);
if (sel == NULL)
return(0);
doc = node->doc;
if (XSLT_IS_RES_TREE_FRAG(doc))
@ -666,16 +811,16 @@ xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
/*
* Recompute contextSize and proximityPosition.
*
* TODO: Make this work for additional ops. Currently, only XSLT_OP_ELEM
* and XSLT_OP_ALL are supported.
* This could be improved in the following ways:
*
* - Skip recomputation if predicates don't use position() or last()
* - Keep data for multiple parents. This would require a hash table
* or an unused member in xmlNode.
* - Store node test results in a bitmap to avoid computing them twice.
*/
oldCS = ctxt->xpathCtxt->contextSize;
oldCP = ctxt->xpathCtxt->proximityPosition;
if ((sel != NULL) &&
(sel->op == XSLT_OP_ELEM) &&
(sel->value != NULL) &&
(node->type == XML_ELEMENT_NODE) &&
(node->parent != NULL)) {
{
xmlNodePtr previous;
int nocache = 0;
@ -692,17 +837,8 @@ xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
while (sibling != NULL) {
if (sibling == previous)
break;
if ((sibling->type == XML_ELEMENT_NODE) &&
(previous->name != NULL) &&
(sibling->name != NULL) &&
(previous->name[0] == sibling->name[0]) &&
(xmlStrEqual(previous->name, sibling->name)))
{
if ((sel->value2 == NULL) ||
((sibling->ns != NULL) &&
(xmlStrEqual(sel->value2, sibling->ns->href))))
indx++;
}
if (xsltTestStepMatch(ctxt, sibling, sel))
indx++;
sibling = sibling->prev;
}
if (sibling == NULL) {
@ -712,20 +848,8 @@ xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
while (sibling != NULL) {
if (sibling == previous)
break;
if ((sibling->type == XML_ELEMENT_NODE) &&
(previous->name != NULL) &&
(sibling->name != NULL) &&
(previous->name[0] == sibling->name[0]) &&
(xmlStrEqual(previous->name, sibling->name)))
{
if ((sel->value2 == NULL) ||
((sibling->ns != NULL) &&
(xmlStrEqual(sel->value2,
sibling->ns->href))))
{
indx--;
}
}
if (xsltTestStepMatch(ctxt, sibling, sel))
indx--;
sibling = sibling->next;
}
}
@ -756,19 +880,11 @@ xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
if (parent) siblings = parent->children;
while (siblings != NULL) {
if (siblings->type == XML_ELEMENT_NODE) {
if (siblings == node) {
len++;
pos = len;
} else if ((node->name != NULL) &&
(siblings->name != NULL) &&
(node->name[0] == siblings->name[0]) &&
(xmlStrEqual(node->name, siblings->name))) {
if ((sel->value2 == NULL) ||
((siblings->ns != NULL) &&
(xmlStrEqual(sel->value2, siblings->ns->href))))
len++;
}
if (siblings == node) {
len++;
pos = len;
} else if (xsltTestStepMatch(ctxt, siblings, sel)) {
len++;
}
siblings = siblings->next;
}
@ -797,96 +913,6 @@ xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len;
}
}
} else if ((sel != NULL) && (sel->op == XSLT_OP_ALL) &&
(node->type == XML_ELEMENT_NODE)) {
xmlNodePtr previous;
int nocache = 0;
previous = (xmlNodePtr)
XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
if ((previous != NULL) &&
(previous->parent == node->parent)) {
/*
* just walk back to adjust the index
*/
int indx = 0;
xmlNodePtr sibling = node;
while (sibling != NULL) {
if (sibling == previous)
break;
if (sibling->type == XML_ELEMENT_NODE)
indx++;
sibling = sibling->prev;
}
if (sibling == NULL) {
/* hum going backward in document order ... */
indx = 0;
sibling = node;
while (sibling != NULL) {
if (sibling == previous)
break;
if (sibling->type == XML_ELEMENT_NODE)
indx--;
sibling = sibling->next;
}
}
if (sibling != NULL) {
pos = XSLT_RUNTIME_EXTRA(ctxt,
sel->indexExtra, ival) + indx;
/*
* If the node is in a Value Tree we cannot
* cache it !
*/
if ((node->doc != NULL) && !isRVT) {
len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival);
XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
}
} else
pos = 0;
} else {
/*
* recompute the index
*/
xmlNodePtr parent = node->parent;
xmlNodePtr siblings = NULL;
if (parent) siblings = parent->children;
while (siblings != NULL) {
if (siblings->type == XML_ELEMENT_NODE) {
len++;
if (siblings == node) {
pos = len;
}
}
siblings = siblings->next;
}
if ((parent == NULL) || (node->doc == NULL))
nocache = 1;
else {
while (parent->parent != NULL)
parent = parent->parent;
if (((parent->type != XML_DOCUMENT_NODE) &&
(parent->type != XML_HTML_DOCUMENT_NODE)) ||
(parent != (xmlNodePtr) node->doc))
nocache = 1;
}
}
if (pos != 0) {
ctxt->xpathCtxt->contextSize = len;
ctxt->xpathCtxt->proximityPosition = pos;
/*
* If the node is in a Value Tree we cannot
* cache it !
*/
if ((node->doc != NULL) && (nocache == 0) && !isRVT) {
XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len;
}
}
}
oldNode = ctxt->node;
@ -969,55 +995,6 @@ restart:
switch (step->op) {
case XSLT_OP_END:
goto found;
case XSLT_OP_ROOT:
if ((node->type == XML_DOCUMENT_NODE) ||
#ifdef LIBXML_DOCB_ENABLED
(node->type == XML_DOCB_DOCUMENT_NODE) ||
#endif
(node->type == XML_HTML_DOCUMENT_NODE))
continue;
if ((node->type == XML_ELEMENT_NODE) && (node->name[0] == ' '))
continue;
goto rollback;
case XSLT_OP_ELEM:
if (node->type != XML_ELEMENT_NODE)
goto rollback;
if (step->value == NULL)
continue;
if (step->value[0] != node->name[0])
goto rollback;
if (!xmlStrEqual(step->value, node->name))
goto rollback;
/* Namespace test */
if (node->ns == NULL) {
if (step->value2 != NULL)
goto rollback;
} else if (node->ns->href != NULL) {
if (step->value2 == NULL)
goto rollback;
if (!xmlStrEqual(step->value2, node->ns->href))
goto rollback;
}
continue;
case XSLT_OP_ATTR:
if (node->type != XML_ATTRIBUTE_NODE)
goto rollback;
if (step->value != NULL) {
if (step->value[0] != node->name[0])
goto rollback;
if (!xmlStrEqual(step->value, node->name))
goto rollback;
}
/* Namespace test */
if (node->ns == NULL) {
if (step->value2 != NULL)
goto rollback;
} else if (step->value2 != NULL) {
if (!xmlStrEqual(step->value2, node->ns->href))
goto rollback;
}
continue;
case XSLT_OP_PARENT:
if ((node->type == XML_DOCUMENT_NODE) ||
(node->type == XML_HTML_DOCUMENT_NODE) ||
@ -1075,6 +1052,7 @@ restart:
continue;
}
i++;
sel = step;
if (step->value == NULL) {
xsltPatPushState(ctxt, &states, i - 1, node);
continue;
@ -1099,50 +1077,6 @@ restart:
goto rollback;
xsltPatPushState(ctxt, &states, i - 1, node);
continue;
case XSLT_OP_ID: {
/* TODO Handle IDs decently, must be done differently */
xmlAttrPtr id;
if (node->type != XML_ELEMENT_NODE)
goto rollback;
id = xmlGetID(node->doc, step->value);
if ((id == NULL) || (id->parent != node))
goto rollback;
break;
}
case XSLT_OP_KEY: {
xmlNodeSetPtr list;
int indx;
list = xsltGetKey(ctxt, step->value,
step->value3, step->value2);
if (list == NULL)
goto rollback;
for (indx = 0;indx < list->nodeNr;indx++)
if (list->nodeTab[indx] == node)
break;
if (indx >= list->nodeNr)
goto rollback;
break;
}
case XSLT_OP_NS:
if (node->type != XML_ELEMENT_NODE)
goto rollback;
if (node->ns == NULL) {
if (step->value != NULL)
goto rollback;
} else if (node->ns->href != NULL) {
if (step->value == NULL)
goto rollback;
if (!xmlStrEqual(step->value, node->ns->href))
goto rollback;
}
break;
case XSLT_OP_ALL:
if (node->type != XML_ELEMENT_NODE)
goto rollback;
break;
case XSLT_OP_PREDICATE: {
/*
* When there is cascading XSLT_OP_PREDICATE or a predicate
@ -1162,34 +1096,9 @@ restart:
break;
}
case XSLT_OP_PI:
if (node->type != XML_PI_NODE)
goto rollback;
if (step->value != NULL) {
if (!xmlStrEqual(step->value, node->name))
goto rollback;
}
break;
case XSLT_OP_COMMENT:
if (node->type != XML_COMMENT_NODE)
goto rollback;
break;
case XSLT_OP_TEXT:
if ((node->type != XML_TEXT_NODE) &&
(node->type != XML_CDATA_SECTION_NODE))
goto rollback;
break;
case XSLT_OP_NODE:
switch (node->type) {
case XML_ELEMENT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
case XML_TEXT_NODE:
break;
default:
goto rollback;
}
default:
if (xsltTestStepMatch(ctxt, node, step) != 1)
goto rollback;
break;
}
}
@ -1439,6 +1348,7 @@ xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name,
if (ctxt->error) {
xsltTransformError(NULL, NULL, NULL,
"xsltCompileIdKeyPattern : Literal expected\n");
xmlFree(lit);
return;
}
SKIP_BLANKS;
@ -1465,6 +1375,7 @@ xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name,
if (ctxt->error) {
xsltTransformError(NULL, NULL, NULL,
"xsltCompileIdKeyPattern : Literal expected\n");
xmlFree(lit);
return;
}
SKIP_BLANKS;
@ -1506,6 +1417,7 @@ xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name,
if (ctxt->error) {
xsltTransformError(NULL, NULL, NULL,
"xsltCompileIdKeyPattern : Literal expected\n");
xmlFree(lit);
return;
}
SKIP_BLANKS;
@ -2127,13 +2039,16 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur,
* 'top' will point to style->xxxMatch ptr - declaring as 'void'
* avoids gcc 'type-punned pointer' warning.
*/
void **top = NULL;
xsltCompMatchPtr *top = NULL;
const xmlChar *name = NULL;
float priority; /* the priority */
if ((style == NULL) || (cur == NULL))
return(-1);
if (cur->next != NULL)
cur->position = cur->next->position + 1;
/* Register named template */
if (cur->name != NULL) {
if (style->namedTemplates == NULL) {
@ -2495,7 +2410,10 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
break;
}
while ((list != NULL) &&
((ret == NULL) || (list->priority > priority))) {
((ret == NULL) ||
(list->priority > priority) ||
((list->priority == priority) &&
(list->template->position > ret->position)))) {
if (xsltTestCompMatch(ctxt, list, node,
ctxt->mode, ctxt->modeURI) == 1) {
ret = list->template;
@ -2512,7 +2430,10 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
(node->type == XML_TEXT_NODE)) {
list = curstyle->elemMatch;
while ((list != NULL) &&
((ret == NULL) || (list->priority > priority))) {
((ret == NULL) ||
(list->priority > priority) ||
((list->priority == priority) &&
(list->template->position > ret->position)))) {
if (xsltTestCompMatch(ctxt, list, node,
ctxt->mode, ctxt->modeURI) == 1) {
ret = list->template;
@ -2525,7 +2446,10 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
(node->type == XML_COMMENT_NODE)) {
list = curstyle->elemMatch;
while ((list != NULL) &&
((ret == NULL) || (list->priority > priority))) {
((ret == NULL) ||
(list->priority > priority) ||
((list->priority == priority) &&
(list->template->position > ret->position)))) {
if (xsltTestCompMatch(ctxt, list, node,
ctxt->mode, ctxt->modeURI) == 1) {
ret = list->template;
@ -2540,7 +2464,10 @@ keyed_match:
if (keyed) {
list = curstyle->keyMatch;
while ((list != NULL) &&
((ret == NULL) || (list->priority > priority))) {
((ret == NULL) ||
(list->priority > priority) ||
((list->priority == priority) &&
(list->template->position > ret->position)))) {
if (xsltTestCompMatch(ctxt, list, node,
ctxt->mode, ctxt->modeURI) == 1) {
ret = list->template;
@ -2618,8 +2545,7 @@ xsltCleanupTemplates(xsltStylesheetPtr style ATTRIBUTE_UNUSED) {
void
xsltFreeTemplateHashes(xsltStylesheetPtr style) {
if (style->templatesHash != NULL)
xmlHashFree((xmlHashTablePtr) style->templatesHash,
xsltFreeCompMatchListEntry);
xmlHashFree(style->templatesHash, xsltFreeCompMatchListEntry);
if (style->rootMatch != NULL)
xsltFreeCompMatchList(style->rootMatch);
if (style->keyMatch != NULL)

View File

@ -1494,6 +1494,8 @@ xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
comp->numdata.groupingCharacterLen = xmlStrlen(prop);
comp->numdata.groupingCharacter =
xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));
if (comp->numdata.groupingCharacter < 0)
comp->numdata.groupingCharacter = 0;
}
prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);

View File

@ -22,7 +22,7 @@ extern "C" {
/*
* Interfaces
*/
extern const xmlChar *xsltExtMarker;
XSLTPUBVAR const xmlChar *xsltExtMarker;
XSLTPUBFUN xsltElemPreCompPtr XSLTCALL
xsltDocumentComp (xsltStylesheetPtr style,

View File

@ -282,7 +282,7 @@ xsltCheckFilename (const char *path)
#if defined(_WIN32) && !defined(__CYGWIN__)
DWORD dwAttrs;
dwAttrs = GetFileAttributes(path);
dwAttrs = GetFileAttributesA(path);
if (dwAttrs != INVALID_FILE_ATTRIBUTES) {
if (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) {
return 2;

View File

@ -210,6 +210,8 @@ xsltEvalTemplateString(xsltTransformContextPtr ctxt,
{
xmlNodePtr oldInsert, insert = NULL;
xmlChar *ret;
const xmlChar *oldLastText;
int oldLastTextSize, oldLastTextUse;
if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL) ||
(inst->type != XML_ELEMENT_NODE))
@ -233,12 +235,18 @@ xsltEvalTemplateString(xsltTransformContextPtr ctxt,
}
oldInsert = ctxt->insert;
ctxt->insert = insert;
oldLastText = ctxt->lasttext;
oldLastTextSize = ctxt->lasttsize;
oldLastTextUse = ctxt->lasttuse;
/*
* OPTIMIZE TODO: if inst->children consists only of text-nodes.
*/
xsltApplyOneTemplate(ctxt, contextNode, inst->children, NULL, NULL);
ctxt->insert = oldInsert;
ctxt->lasttext = oldLastText;
ctxt->lasttsize = oldLastTextSize;
ctxt->lasttuse = oldLastTextUse;
ret = xmlNodeGetContent(insert);
if (insert != NULL)

View File

@ -1895,7 +1895,7 @@ static void
xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
xsltStackElemPtr params) {
xmlNodePtr copy;
xmlNodePtr delete = NULL, cur;
xmlNodePtr cur;
int nbchild = 0, oldSize;
int childno = 0, oldPos;
xsltTemplatePtr template;
@ -1968,54 +1968,13 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
return;
}
/*
* Handling of Elements: first pass, cleanup and counting
* Handling of Elements: first pass, counting
*/
cur = node->children;
while (cur != NULL) {
switch (cur->type) {
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
case XML_ELEMENT_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
nbchild++;
break;
case XML_DTD_NODE:
/* Unlink the DTD, it's still reachable using doc->intSubset */
if (cur->next != NULL)
cur->next->prev = cur->prev;
if (cur->prev != NULL)
cur->prev->next = cur->next;
break;
default:
#ifdef WITH_XSLT_DEBUG_PROCESS
XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
"xsltDefaultProcessOneNode: skipping node type %d\n",
cur->type));
#endif
delete = cur;
}
if (IS_XSLT_REAL_NODE(cur))
nbchild++;
cur = cur->next;
if (delete != NULL) {
#ifdef WITH_XSLT_DEBUG_PROCESS
XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
"xsltDefaultProcessOneNode: removing ignorable blank node\n"));
#endif
xmlUnlinkNode(delete);
xmlFreeNode(delete);
delete = NULL;
}
}
if (delete != NULL) {
#ifdef WITH_XSLT_DEBUG_PROCESS
XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
"xsltDefaultProcessOneNode: removing ignorable blank node\n"));
#endif
xmlUnlinkNode(delete);
xmlFreeNode(delete);
delete = NULL;
}
/*
@ -3672,8 +3631,10 @@ xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
if (elements != NULL) {
if (style->stripSpaces == NULL)
style->stripSpaces = xmlHashCreate(10);
if (style->stripSpaces == NULL)
if (style->stripSpaces == NULL) {
xmlFree(elements);
return;
}
element = elements;
while (*element != 0) {
@ -4864,7 +4825,7 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
#endif
int i;
xmlNodePtr cur, delNode = NULL, oldContextNode;
xmlNodePtr cur, oldContextNode;
xmlNodeSetPtr list = NULL, oldList;
xsltStackElemPtr withParams = NULL;
int oldXPProximityPosition, oldXPContextSize;
@ -4998,73 +4959,9 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
else
cur = NULL;
while (cur != NULL) {
switch (cur->type) {
case XML_TEXT_NODE:
if ((IS_BLANK_NODE(cur)) &&
(cur->parent != NULL) &&
(cur->parent->type == XML_ELEMENT_NODE) &&
(ctxt->style->stripSpaces != NULL)) {
const xmlChar *val;
if (cur->parent->ns != NULL) {
val = (const xmlChar *)
xmlHashLookup2(ctxt->style->stripSpaces,
cur->parent->name,
cur->parent->ns->href);
if (val == NULL) {
val = (const xmlChar *)
xmlHashLookup2(ctxt->style->stripSpaces,
BAD_CAST "*",
cur->parent->ns->href);
}
} else {
val = (const xmlChar *)
xmlHashLookup2(ctxt->style->stripSpaces,
cur->parent->name, NULL);
}
if ((val != NULL) &&
(xmlStrEqual(val, (xmlChar *) "strip"))) {
delNode = cur;
break;
}
}
/* Intentional fall-through */
case XML_ELEMENT_NODE:
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
xmlXPathNodeSetAddUnique(list, cur);
break;
case XML_DTD_NODE:
/* Unlink the DTD, it's still reachable
* using doc->intSubset */
if (cur->next != NULL)
cur->next->prev = cur->prev;
if (cur->prev != NULL)
cur->prev->next = cur->next;
break;
case XML_NAMESPACE_DECL:
break;
default:
#ifdef WITH_XSLT_DEBUG_PROCESS
XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
"xsltApplyTemplates: skipping cur type %d\n",
cur->type));
#endif
delNode = cur;
}
if (IS_XSLT_REAL_NODE(cur))
xmlXPathNodeSetAddUnique(list, cur);
cur = cur->next;
if (delNode != NULL) {
#ifdef WITH_XSLT_DEBUG_PROCESS
XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
"xsltApplyTemplates: removing ignorable blank cur\n"));
#endif
xmlUnlinkNode(delNode);
xmlFreeNode(delNode);
delNode = NULL;
}
}
}
@ -5121,6 +5018,7 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr sorts[XSLT_MAX_SORT];
sorts[nbsorts++] = cur;
cur = cur->next;
while (cur) {

View File

@ -3656,12 +3656,8 @@ xsltPreprocessStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
(!xsltCheckExtURI(style, cur->ns->href))) {
goto skip_children;
} else if (cur->children != NULL) {
if ((cur->children->type != XML_ENTITY_DECL) &&
(cur->children->type != XML_ENTITY_REF_NODE) &&
(cur->children->type != XML_ENTITY_NODE)) {
cur = cur->children;
continue;
}
cur = cur->children;
continue;
}
skip_children:

View File

@ -291,6 +291,9 @@ struct _xsltTemplate {
int templMax; /* Size of the templtes stack */
xsltTemplatePtr *templCalledTab; /* templates called */
int *templCountTab; /* .. and how often */
/* Conflict resolution */
int position;
};
/**
@ -1500,17 +1503,18 @@ struct _xsltStylesheet {
/*
* Template descriptions.
*/
xsltTemplatePtr templates; /* the ordered list of templates */
void *templatesHash; /* hash table or wherever compiled templates
information is stored */
void *rootMatch; /* template based on / */
void *keyMatch; /* template based on key() */
void *elemMatch; /* template based on * */
void *attrMatch; /* template based on @* */
void *parentMatch; /* template based on .. */
void *textMatch; /* template based on text() */
void *piMatch; /* template based on processing-instruction() */
void *commentMatch; /* template based on comment() */
xsltTemplatePtr templates; /* the ordered list of templates */
xmlHashTablePtr templatesHash; /* hash table or wherever compiled
templates information is stored */
struct _xsltCompMatch *rootMatch; /* template based on / */
struct _xsltCompMatch *keyMatch; /* template based on key() */
struct _xsltCompMatch *elemMatch; /* template based on * */
struct _xsltCompMatch *attrMatch; /* template based on @* */
struct _xsltCompMatch *parentMatch; /* template based on .. */
struct _xsltCompMatch *textMatch; /* template based on text() */
struct _xsltCompMatch *piMatch; /* template based on
processing-instruction() */
struct _xsltCompMatch *commentMatch; /* template based on comment() */
/*
* Namespace aliases.

View File

@ -20,21 +20,21 @@ extern "C" {
*
* the version string like "1.2.3"
*/
#define LIBXSLT_DOTTED_VERSION "1.1.34"
#define LIBXSLT_DOTTED_VERSION "1.1.35"
/**
* LIBXSLT_VERSION:
*
* the version number: 1.2.3 value is 10203
*/
#define LIBXSLT_VERSION 10134
#define LIBXSLT_VERSION 10135
/**
* LIBXSLT_VERSION_STRING:
*
* the version number string, 1.2.3 value is "10203"
*/
#define LIBXSLT_VERSION_STRING "10134"
#define LIBXSLT_VERSION_STRING "10135"
/**
* LIBXSLT_VERSION_EXTRA:

View File

@ -346,7 +346,8 @@ xsltDefaultRegion(const xmlChar *localeName) {
void
xsltFreeLocale(xsltLocale locale) {
#ifdef XSLT_LOCALE_POSIX
freelocale(locale);
if (locale != NULL)
freelocale(locale);
#endif
}

View File

@ -948,17 +948,19 @@ xsltDocumentSortFunction(xmlNodeSetPtr list) {
}
/**
* xsltComputeSortResult:
* xsltComputeSortResultiInternal:
* @ctxt: a XSLT process context
* @sort: node list
* @xfrm: Transform strings according to locale
*
* reorder the current node list accordingly to the set of sorting
* requirement provided by the array of nodes.
*
* Returns a ordered XPath nodeset or NULL in case of error.
*/
xmlXPathObjectPtr *
xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) {
static xmlXPathObjectPtr *
xsltComputeSortResultInternal(xsltTransformContextPtr ctxt, xmlNodePtr sort,
int xfrm) {
#ifdef XSLT_REFACTORED
xsltStyleItemSortPtr comp;
#else
@ -1045,7 +1047,7 @@ xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) {
}
} else {
if (res->type == XPATH_STRING) {
if (comp->locale != (xsltLocale)0) {
if ((xfrm) && (comp->locale != (xsltLocale)0)) {
xmlChar *str = res->stringval;
res->stringval = (xmlChar *) xsltStrxfrm(comp->locale, str);
xmlFree(str);
@ -1075,6 +1077,21 @@ xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) {
return(results);
}
/**
* xsltComputeSortResult:
* @ctxt: a XSLT process context
* @sort: node list
*
* reorder the current node list accordingly to the set of sorting
* requirement provided by the array of nodes.
*
* Returns a ordered XPath nodeset or NULL in case of error.
*/
xmlXPathObjectPtr *
xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) {
return xsltComputeSortResultInternal(ctxt, sort, /* xfrm */ 0);
}
/**
* xsltDefaultSortFunction:
* @ctxt: a XSLT process context
@ -1102,7 +1119,8 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
int depth;
xmlNodePtr node;
xmlXPathObjectPtr tmp;
int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT];
int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT],
templang[XSLT_MAX_SORT];
if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
(nbsorts >= XSLT_MAX_SORT))
@ -1124,7 +1142,7 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
comp->stype =
xsltEvalAttrValueTemplate(ctxt, sorts[j],
(const xmlChar *) "data-type",
XSLT_NAMESPACE);
NULL);
if (comp->stype != NULL) {
tempstype[j] = 1;
if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
@ -1143,7 +1161,7 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
if ((comp->order == NULL) && (comp->has_order != 0)) {
comp->order = xsltEvalAttrValueTemplate(ctxt, sorts[j],
(const xmlChar *) "order",
XSLT_NAMESPACE);
NULL);
if (comp->order != NULL) {
temporder[j] = 1;
if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
@ -1159,11 +1177,23 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
}
}
}
templang[j] = 0;
if ((comp->lang == NULL) && (comp->has_lang != 0)) {
xmlChar *lang = xsltEvalAttrValueTemplate(ctxt, sorts[j],
(xmlChar *) "lang",
NULL);
if (lang != NULL) {
templang[j] = 1;
comp->locale = xsltNewLocale(lang);
xmlFree(lang);
}
}
}
len = list->nodeNr;
resultsTab[0] = xsltComputeSortResult(ctxt, sorts[0]);
resultsTab[0] = xsltComputeSortResultInternal(ctxt, sorts[0],
/* xfrm */ 1);
for (i = 1;i < XSLT_MAX_SORT;i++)
resultsTab[i] = NULL;
@ -1173,7 +1203,7 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
descending = comp->descending;
number = comp->number;
if (results == NULL)
return;
goto cleanup;
/* Shell's sort of node-set */
for (incr = len / 2; incr > 0; incr /= 2) {
@ -1234,8 +1264,10 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
* full set, this might be optimized ... or not
*/
if (resultsTab[depth] == NULL)
resultsTab[depth] = xsltComputeSortResult(ctxt,
sorts[depth]);
resultsTab[depth] =
xsltComputeSortResultInternal(ctxt,
sorts[depth],
/* xfrm */ 1);
res = resultsTab[depth];
if (res == NULL)
break;
@ -1315,6 +1347,7 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
}
}
cleanup:
for (j = 0; j < nbsorts; j++) {
comp = sorts[j]->psvi;
if (tempstype[j] == 1) {
@ -1327,6 +1360,10 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
xmlFree((void *)(comp->order));
comp->order = NULL;
}
if (templang[j] == 1) {
xsltFreeLocale(comp->locale);
comp->locale = (xsltLocale)0;
}
if (resultsTab[j] != NULL) {
for (i = 0;i < len;i++)
xmlXPathFreeObject(resultsTab[j][i]);