[LIBXSLT] Update to version 1.1.32. CORE-14291

This commit is contained in:
Thomas Faber 2018-02-04 15:52:31 +01:00
parent 5c72e50fd0
commit 5c0faa58cf
No known key found for this signature in database
GPG key ID: 076E7C3D44720826
24 changed files with 945 additions and 911 deletions

View file

@ -62,7 +62,7 @@ else
LIBXSLT_VERSION_SCRIPT =
endif
libxslt_la_LIBADD = $(LIBXML_LIBS) $(EXTRA_LIBS)
libxslt_la_LIBADD = $(LIBXML_LIBS) $(EXTRA_LIBS) $(M_LIBS)
libxslt_la_LDFLAGS = \
$(WIN32_EXTRA_LDFLAGS) \
$(LIBXSLT_VERSION_SCRIPT) \

View file

@ -16,14 +16,6 @@
#define WITH_XSLT_DEBUG_ATTRIBUTES
#endif
/*
* TODO: merge attribute sets from different import precedence.
* all this should be precomputed just before the transformation
* starts or at first hit with a cache in the context.
* The simple way for now would be to not allow redefinition of
* attributes once generated in the output tree, possibly costlier.
*/
/*
* Useful macros
*/
@ -37,6 +29,10 @@
#define IS_BLANK_NODE(n) \
(((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
#define ATTRSET_UNRESOLVED 0
#define ATTRSET_RESOLVING 1
#define ATTRSET_RESOLVED 2
/*
* The in-memory structure corresponding to an XSLT Attribute in
@ -49,10 +45,36 @@ typedef xsltAttrElem *xsltAttrElemPtr;
struct _xsltAttrElem {
struct _xsltAttrElem *next;/* chained list */
xmlNodePtr attr; /* the xsl:attribute definition */
const xmlChar *set; /* or the attribute set */
const xmlChar *ns; /* and its namespace */
};
typedef struct _xsltUseAttrSet xsltUseAttrSet;
typedef xsltUseAttrSet *xsltUseAttrSetPtr;
struct _xsltUseAttrSet {
struct _xsltUseAttrSet *next; /* chained list */
const xmlChar *ncname;
const xmlChar *ns;
};
typedef struct _xsltAttrSet xsltAttrSet;
typedef xsltAttrSet *xsltAttrSetPtr;
struct _xsltAttrSet {
int state;
xsltAttrElemPtr attrs; /* list head */
xsltUseAttrSetPtr useAttrSets; /* list head */
};
typedef struct _xsltAttrSetContext xsltAttrSetContext;
typedef xsltAttrSetContext *xsltAttrSetContextPtr;
struct _xsltAttrSetContext {
xsltStylesheetPtr topStyle;
xsltStylesheetPtr style;
};
static void
xsltResolveAttrSet(xsltAttrSetPtr set, xsltStylesheetPtr topStyle,
xsltStylesheetPtr style, const xmlChar *name,
const xmlChar *ns, int depth);
/************************************************************************
* *
* XSLT Attribute handling *
@ -110,11 +132,6 @@ xsltFreeAttrElemList(xsltAttrElemPtr list) {
}
}
#ifdef XSLT_REFACTORED
/*
* This was moved to xsltParseStylesheetAttributeSet().
*/
#else
/**
* xsltAddAttrElemList:
* @list: an XSLT AttrElem list
@ -135,9 +152,7 @@ xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) {
cur = list;
while (cur != NULL) {
next = cur->next;
if (cur->attr == attr)
return(cur);
if (cur->next == NULL) {
if (next == NULL) {
cur->next = xsltNewAttrElem(attr);
return(list);
}
@ -145,92 +160,174 @@ xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) {
}
return(list);
}
#endif /* XSLT_REFACTORED */
/**
* xsltMergeAttrElemList:
* @list: an XSLT AttrElem list
* @old: another XSLT AttrElem list
* xsltNewUseAttrSet:
* @ncname: local name
* @ns: namespace URI
*
* Add all the attributes from list @old to list @list,
* but drop redefinition of existing values.
* Create a new XSLT UseAttrSet
*
* Returns the new list pointer
* Returns the newly allocated xsltUseAttrSetPtr or NULL in case of error.
*/
static xsltAttrElemPtr
xsltMergeAttrElemList(xsltStylesheetPtr style,
xsltAttrElemPtr list, xsltAttrElemPtr old) {
static xsltUseAttrSetPtr
xsltNewUseAttrSet(const xmlChar *ncname, const xmlChar *ns) {
xsltUseAttrSetPtr cur;
cur = (xsltUseAttrSetPtr) xmlMalloc(sizeof(xsltUseAttrSet));
if (cur == NULL) {
xsltGenericError(xsltGenericErrorContext,
"xsltNewUseAttrSet : malloc failed\n");
return(NULL);
}
memset(cur, 0, sizeof(xsltUseAttrSet));
cur->ncname = ncname;
cur->ns = ns;
return(cur);
}
/**
* xsltFreeUseAttrSet:
* @use: an XSLT UseAttrSet
*
* Free up the memory allocated by @use
*/
static void
xsltFreeUseAttrSet(xsltUseAttrSetPtr use) {
xmlFree(use);
}
/**
* xsltFreeUseAttrSetList:
* @list: an XSLT UseAttrSet list
*
* Free up the memory allocated by @list
*/
static void
xsltFreeUseAttrSetList(xsltUseAttrSetPtr list) {
xsltUseAttrSetPtr next;
while (list != NULL) {
next = list->next;
xsltFreeUseAttrSet(list);
list = next;
}
}
/**
* xsltAddUseAttrSetList:
* @list: a xsltUseAttrSet list
* @ncname: local name
* @ns: namespace URI
*
* Add the use-attribute-set name to the list.
*
* Returns the new list pointer.
*/
static xsltUseAttrSetPtr
xsltAddUseAttrSetList(xsltUseAttrSetPtr list, const xmlChar *ncname,
const xmlChar *ns) {
xsltUseAttrSetPtr next, cur;
if (ncname == NULL)
return(list);
if (list == NULL)
return(xsltNewUseAttrSet(ncname, ns));
cur = list;
while (cur != NULL) {
if ((cur->ncname == ncname) && (cur->ns == ns))
return(list);
next = cur->next;
if (next == NULL) {
cur->next = xsltNewUseAttrSet(ncname, ns);
return(list);
}
cur = next;
}
return(list);
}
/**
* xsltNewAttrSet:
*
* Create a new attribute set.
*
* Returns the newly allocated xsltAttrSetPtr or NULL in case of error.
*/
static xsltAttrSetPtr
xsltNewAttrSet() {
xsltAttrSetPtr cur;
cur = (xsltAttrSetPtr) xmlMalloc(sizeof(xsltAttrSet));
if (cur == NULL) {
xsltGenericError(xsltGenericErrorContext,
"xsltNewAttrSet : malloc failed\n");
return(NULL);
}
memset(cur, 0, sizeof(xsltAttrSet));
return(cur);
}
/**
* xsltFreeAttrSet:
* @set: an attribute set
*
* Free memory allocated by @set
*/
static void
xsltFreeAttrSet(xsltAttrSetPtr set) {
if (set == NULL)
return;
xsltFreeAttrElemList(set->attrs);
xsltFreeUseAttrSetList(set->useAttrSets);
xmlFree(set);
}
/**
* xsltMergeAttrSets:
* @set: an attribute set
* @other: another attribute set
*
* Add all the attributes from @other to @set,
* but drop redefinition of existing values.
*/
static void
xsltMergeAttrSets(xsltAttrSetPtr set, xsltAttrSetPtr other) {
xsltAttrElemPtr cur;
xsltAttrElemPtr old = other->attrs;
int add;
while (old != NULL) {
if ((old->attr == NULL) && (old->set == NULL)) {
old = old->next;
continue;
}
/*
* Check that the attribute is not yet in the list
*/
cur = list;
cur = set->attrs;
add = 1;
while (cur != NULL) {
if ((cur->attr == NULL) && (cur->set == NULL)) {
if (cur->next == NULL)
break;
cur = cur->next;
continue;
}
if ((cur->set != NULL) && (cur->set == old->set)) {
add = 0;
break;
}
if (cur->set != NULL) {
if (cur->next == NULL)
break;
cur = cur->next;
continue;
}
if (old->set != NULL) {
if (cur->next == NULL)
break;
cur = cur->next;
continue;
}
if (cur->attr == old->attr) {
xsltGenericError(xsltGenericErrorContext,
"xsl:attribute-set : use-attribute-sets recursion detected\n");
return(list);
}
xsltStylePreCompPtr curComp = cur->attr->psvi;
xsltStylePreCompPtr oldComp = old->attr->psvi;
if ((curComp->name == oldComp->name) &&
(curComp->ns == oldComp->ns)) {
add = 0;
break;
}
if (cur->next == NULL)
break;
cur = cur->next;
}
if (add == 1) {
/*
* Changed to use the string-dict, rather than duplicating
* @set and @ns; this fixes bug #340400.
*/
if (cur == NULL) {
list = xsltNewAttrElem(old->attr);
if (old->set != NULL) {
list->set = xmlDictLookup(style->dict, old->set, -1);
if (old->ns != NULL)
list->ns = xmlDictLookup(style->dict, old->ns, -1);
}
set->attrs = xsltNewAttrElem(old->attr);
} else if (add) {
cur->next = xsltNewAttrElem(old->attr);
if (old->set != NULL) {
cur->next->set = xmlDictLookup(style->dict, old->set, -1);
if (old->ns != NULL)
cur->next->ns = xmlDictLookup(style->dict, old->ns, -1);
}
}
}
old = old->next;
}
return(list);
}
/************************************************************************
@ -251,9 +348,10 @@ void
xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
const xmlChar *ncname;
const xmlChar *prefix;
const xmlChar *nsUri = NULL;
xmlChar *value;
xmlNodePtr child;
xsltAttrElemPtr attrItems;
xsltAttrSetPtr set;
if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
return;
@ -267,9 +365,29 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
return;
}
if (xmlValidateQName(value, 0)) {
xsltTransformError(NULL, style, cur,
"xsl:attribute-set : The name '%s' is not a valid QName.\n",
value);
style->errors++;
xmlFree(value);
return;
}
ncname = xsltSplitQName(style->dict, value, &prefix);
xmlFree(value);
value = NULL;
if (prefix != NULL) {
xmlNsPtr ns = xmlSearchNs(style->doc, cur, prefix);
if (ns == NULL) {
xsltTransformError(NULL, style, cur,
"xsl:attribute-set : No namespace found for QName '%s:%s'\n",
prefix, ncname);
style->errors++;
return;
}
nsUri = ns->href;
}
if (style->attributeSets == NULL) {
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
@ -281,7 +399,13 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
if (style->attributeSets == NULL)
return;
attrItems = xmlHashLookup2(style->attributeSets, ncname, prefix);
set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
if (set == NULL) {
set = xsltNewAttrSet();
if (set == NULL)
return;
xmlHashAddEntry2(style->attributeSets, ncname, nsUri, set);
}
/*
* Parse the content. Only xsl:attribute elements are allowed.
@ -307,71 +431,36 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
"xsl:attribute-set : unexpected child xsl:%s\n",
child->name);
} else {
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
xsltGenericDebug(xsltGenericDebugContext,
"add attribute to list %s\n", ncname);
#endif
xsltStylePreCompute(style, child);
if (child->children != NULL) {
#ifdef XSLT_REFACTORED
xsltAttrElemPtr nextAttr, curAttr;
/*
* Process xsl:attribute
* ---------------------
*/
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
xsltGenericDebug(xsltGenericDebugContext,
"add attribute to list %s\n", ncname);
#endif
/*
* The following was taken over from
* xsltAddAttrElemList().
*/
if (attrItems == NULL) {
attrItems = xsltNewAttrElem(child);
} else {
curAttr = attrItems;
while (curAttr != NULL) {
nextAttr = curAttr->next;
if (curAttr->attr == child) {
/*
* URGENT TODO: Can somebody explain
* why attrItems is set to curAttr
* here? Is this somehow related to
* avoidance of recursions?
*/
attrItems = curAttr;
goto next_child;
}
if (curAttr->next == NULL)
curAttr->next = xsltNewAttrElem(child);
curAttr = nextAttr;
}
}
/*
* Parse the xsl:attribute and its content.
*/
xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
xsltParseSequenceConstructor(XSLT_CCTXT(style),
child->children);
#else
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
xsltGenericDebug(xsltGenericDebugContext,
"add attribute to list %s\n", ncname);
#endif
/*
* OLD behaviour:
*/
attrItems = xsltAddAttrElemList(attrItems, child);
xsltParseTemplateContent(style, child);
#endif
}
if (child->psvi == NULL) {
xsltTransformError(NULL, style, child,
"xsl:attribute-set : internal error, attribute %s not "
"compiled\n", child->name);
}
else {
set->attrs = xsltAddAttrElemList(set->attrs, child);
}
}
#ifdef XSLT_REFACTORED
next_child:
#endif
child = child->next;
}
/*
* Process attribue "use-attribute-sets".
* Process attribute "use-attribute-sets".
*/
/* TODO check recursion */
value = xmlGetNsProp(cur, (const xmlChar *)"use-attribute-sets",
NULL);
value = xmlGetNsProp(cur, BAD_CAST "use-attribute-sets", NULL);
if (value != NULL) {
const xmlChar *curval, *endval;
curval = value;
@ -385,21 +474,38 @@ next_child:
if (curval) {
const xmlChar *ncname2 = NULL;
const xmlChar *prefix2 = NULL;
xsltAttrElemPtr refAttrItems;
const xmlChar *nsUri2 = NULL;
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
xsltGenericDebug(xsltGenericDebugContext,
"xsl:attribute-set : %s adds use %s\n", ncname, curval);
#endif
if (xmlValidateQName(curval, 0)) {
xsltTransformError(NULL, style, cur,
"xsl:attribute-set : The name '%s' in "
"use-attribute-sets is not a valid QName.\n", curval);
style->errors++;
xmlFree(value);
return;
}
ncname2 = xsltSplitQName(style->dict, curval, &prefix2);
refAttrItems = xsltNewAttrElem(NULL);
if (refAttrItems != NULL) {
refAttrItems->set = ncname2;
refAttrItems->ns = prefix2;
attrItems = xsltMergeAttrElemList(style,
attrItems, refAttrItems);
xsltFreeAttrElem(refAttrItems);
}
if (prefix2 != NULL) {
xmlNsPtr ns2 = xmlSearchNs(style->doc, cur, prefix2);
if (ns2 == NULL) {
xsltTransformError(NULL, style, cur,
"xsl:attribute-set : No namespace found for QName "
"'%s:%s' in use-attribute-sets\n",
prefix2, ncname2);
style->errors++;
xmlFree(value);
return;
}
nsUri2 = ns2->href;
}
set->useAttrSets = xsltAddUseAttrSetList(set->useAttrSets,
ncname2, nsUri2);
}
curval = endval;
}
@ -407,15 +513,6 @@ next_child:
value = NULL;
}
/*
* Update the value
*/
/*
* TODO: Why is this dummy entry needed.?
*/
if (attrItems == NULL)
attrItems = xsltNewAttrElem(NULL);
xmlHashUpdateEntry2(style->attributeSets, ncname, prefix, attrItems, NULL);
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
xsltGenericDebug(xsltGenericDebugContext,
"updated attribute list %s\n", ncname);
@ -423,143 +520,141 @@ next_child:
}
/**
* xsltGetSAS:
* @style: the XSLT stylesheet
* @name: the attribute list name
* @ns: the attribute list namespace
* xsltResolveUseAttrSets:
* @set: the attribute set
* @asctx: the context for attribute set resolution
* @depth: recursion depth
*
* lookup an attribute set based on the style cascade
*
* Returns the attribute set or NULL
* Process "use-attribute-sets".
*/
static xsltAttrElemPtr
xsltGetSAS(xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns) {
xsltAttrElemPtr values;
static void
xsltResolveUseAttrSets(xsltAttrSetPtr set, xsltStylesheetPtr topStyle,
int depth) {
xsltStylesheetPtr cur;
xsltAttrSetPtr other;
xsltUseAttrSetPtr use = set->useAttrSets;
xsltUseAttrSetPtr next;
while (style != NULL) {
values = xmlHashLookup2(style->attributeSets, name, ns);
if (values != NULL)
return(values);
style = xsltNextImport(style);
while (use != NULL) {
/*
* Iterate top stylesheet and all imports.
*/
cur = topStyle;
while (cur != NULL) {
if (cur->attributeSets) {
other = xmlHashLookup2(cur->attributeSets, use->ncname,
use->ns);
if (other != NULL) {
xsltResolveAttrSet(other, topStyle, cur, use->ncname,
use->ns, depth + 1);
xsltMergeAttrSets(set, other);
break;
}
}
cur = xsltNextImport(cur);
}
next = use->next;
/* Free useAttrSets early. */
xsltFreeUseAttrSet(use);
use = next;
}
return(NULL);
set->useAttrSets = NULL;
}
/**
* xsltResolveSASCallbackInt:
* @style: the XSLT stylesheet
* xsltResolveAttrSet:
* @set: the attribute set
* @asctx: the context for attribute set resolution
* @name: the local name of the attirbute set
* @ns: the namespace of the attribute set
* @depth: recursion depth
*
* resolve the references in an attribute set.
*/
static void
xsltResolveSASCallbackInt(xsltAttrElemPtr values, xsltStylesheetPtr style,
const xmlChar *name, const xmlChar *ns,
int depth) {
xsltAttrElemPtr tmp;
xsltAttrElemPtr refs;
xsltResolveAttrSet(xsltAttrSetPtr set, xsltStylesheetPtr topStyle,
xsltStylesheetPtr style, const xmlChar *name,
const xmlChar *ns, int depth) {
xsltStylesheetPtr cur;
xsltAttrSetPtr other;
tmp = values;
if ((name == NULL) || (name[0] == 0))
if (set->state == ATTRSET_RESOLVED)
return;
if (set->state == ATTRSET_RESOLVING) {
xsltTransformError(NULL, topStyle, NULL,
"xsl:attribute-set : use-attribute-sets recursion detected"
" on %s\n", name);
topStyle->errors++;
set->state = ATTRSET_RESOLVED;
return;
}
if (depth > 100) {
xsltGenericError(xsltGenericErrorContext,
"xsl:attribute-set : use-attribute-sets recursion detected on %s\n",
name);
xsltTransformError(NULL, topStyle, NULL,
"xsl:attribute-set : use-attribute-sets maximum recursion "
"depth exceeded on %s\n", name);
topStyle->errors++;
return;
}
while (tmp != NULL) {
if (tmp->set != NULL) {
/*
* Check against cycles !
*/
if ((xmlStrEqual(name, tmp->set)) && (xmlStrEqual(ns, tmp->ns))) {
xsltGenericError(xsltGenericErrorContext,
"xsl:attribute-set : use-attribute-sets recursion detected on %s\n",
name);
} else {
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
xsltGenericDebug(xsltGenericDebugContext,
"Importing attribute list %s\n", tmp->set);
#endif
refs = xsltGetSAS(style, tmp->set, tmp->ns);
if (refs == NULL) {
xsltGenericError(xsltGenericErrorContext,
"xsl:attribute-set : use-attribute-sets %s reference missing %s\n",
name, tmp->set);
} else {
/*
* recurse first for cleanup
*/
xsltResolveSASCallbackInt(refs, style, name, ns, depth + 1);
/*
* Then merge
*/
xsltMergeAttrElemList(style, values, refs);
/*
* Then suppress the reference
*/
tmp->set = NULL;
tmp->ns = NULL;
}
}
}
tmp = tmp->next;
set->state = ATTRSET_RESOLVING;
xsltResolveUseAttrSets(set, topStyle, depth);
/* Merge imported sets. */
cur = xsltNextImport(style);
while (cur != NULL) {
if (cur->attributeSets != NULL) {
other = xmlHashLookup2(cur->attributeSets, name, ns);
if (other != NULL) {
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
xsltGenericDebug(xsltGenericDebugContext,
"xsl:attribute-set : merging import for %s\n", name);
#endif
xsltResolveUseAttrSets(other, topStyle, depth);
xsltMergeAttrSets(set, other);
xmlHashRemoveEntry2(cur->attributeSets, name, ns, NULL);
xsltFreeAttrSet(other);
}
}
cur = xsltNextImport(cur);
}
set->state = ATTRSET_RESOLVED;
}
/**
* xsltResolveSASCallback,:
* @style: the XSLT stylesheet
* xsltResolveSASCallback:
* @set: the attribute set
* @asctx: the context for attribute set resolution
* @name: the local name of the attirbute set
* @ns: the namespace of the attribute set
*
* resolve the references in an attribute set.
*/
static void
xsltResolveSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
xsltResolveSASCallback(xsltAttrSetPtr set, xsltAttrSetContextPtr asctx,
const xmlChar *name, const xmlChar *ns,
ATTRIBUTE_UNUSED const xmlChar *ignored) {
xsltResolveSASCallbackInt(values, style, name, ns, 1);
}
xsltStylesheetPtr topStyle = asctx->topStyle;
xsltStylesheetPtr style = asctx->style;
/**
* xsltMergeSASCallback,:
* @style: the XSLT stylesheet
*
* Merge an attribute set from an imported stylesheet.
*/
static void
xsltMergeSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
const xmlChar *name, const xmlChar *ns,
ATTRIBUTE_UNUSED const xmlChar *ignored) {
int ret;
xsltAttrElemPtr topSet;
xsltResolveAttrSet(set, topStyle, style, name, ns, 1);
ret = xmlHashAddEntry2(style->attributeSets, name, ns, values);
if (ret < 0) {
/*
* Add failed, this attribute set can be removed.
*/
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
xsltGenericDebug(xsltGenericDebugContext,
"attribute set %s present already in top stylesheet"
" - merging\n", name);
#endif
topSet = xmlHashLookup2(style->attributeSets, name, ns);
if (topSet==NULL) {
/* Move attribute sets to top stylesheet. */
if (style != topStyle) {
/*
* This imported stylesheet won't be visited anymore. Don't bother
* removing the hash entry.
*/
if (xmlHashAddEntry2(topStyle->attributeSets, name, ns, set) < 0) {
xsltGenericError(xsltGenericErrorContext,
"xsl:attribute-set : logic error merging from imports for"
" attribute-set %s\n", name);
} else {
topSet = xsltMergeAttrElemList(style, topSet, values);
xmlHashUpdateEntry2(style->attributeSets, name, ns, topSet, NULL);
}
xsltFreeAttrElemList(values);
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
} else {
xsltGenericDebug(xsltGenericDebugContext,
"attribute set %s moved to top stylesheet\n",
name);
#endif
"xsl:attribute-set : internal error, can't move imported "
" attribute set %s\n", name);
}
}
}
@ -572,15 +667,14 @@ xsltMergeSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
void
xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style) {
xsltStylesheetPtr cur;
xsltAttrSetContext asctx;
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
xsltGenericDebug(xsltGenericDebugContext,
"Resolving attribute sets references\n");
#endif
/*
* First aggregate all the attribute sets definitions from the imports
*/
cur = xsltNextImport(style);
asctx.topStyle = style;
cur = style;
while (cur != NULL) {
if (cur->attributeSets != NULL) {
if (style->attributeSets == NULL) {
@ -590,43 +684,37 @@ xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style) {
#endif
style->attributeSets = xmlHashCreate(10);
}
asctx.style = cur;
xmlHashScanFull(cur->attributeSets,
(xmlHashScannerFull) xsltMergeSASCallback, style);
/*
* the attribute lists have either been migrated to style
* or freed directly in xsltMergeSASCallback()
*/
xmlHashFree(cur->attributeSets, NULL);
cur->attributeSets = NULL;
(xmlHashScannerFull) xsltResolveSASCallback, &asctx);
if (cur != style) {
/*
* the attribute lists have either been migrated to style
* or freed directly in xsltResolveSASCallback()
*/
xmlHashFree(cur->attributeSets, NULL);
cur->attributeSets = NULL;
}
}
cur = xsltNextImport(cur);
}
/*
* Then resolve all the references and computes the resulting sets
*/
if (style->attributeSets != NULL) {
xmlHashScanFull(style->attributeSets,
(xmlHashScannerFull) xsltResolveSASCallback, style);
}
}
/**
* xsltAttributeInternal:
* xsltAttribute:
* @ctxt: a XSLT process context
* @node: the current node in the source tree
* @contextNode: the current node in the source tree
* @inst: the xsl:attribute element
* @comp: precomputed information
* @fromAttributeSet: the attribute comes from an attribute-set
* @castedComp: precomputed information
*
* Process the xslt attribute node on the source node
*/
static void
xsltAttributeInternal(xsltTransformContextPtr ctxt,
xmlNodePtr contextNode,
xmlNodePtr inst,
xsltStylePreCompPtr castedComp,
int fromAttributeSet)
void
xsltAttribute(xsltTransformContextPtr ctxt,
xmlNodePtr contextNode,
xmlNodePtr inst,
xsltStylePreCompPtr castedComp)
{
#ifdef XSLT_REFACTORED
xsltStyleItemAttributePtr comp =
@ -666,7 +754,7 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt,
if (comp == NULL) {
xsltTransformError(ctxt, NULL, inst,
"Internal error in xsltAttributeInternal(): "
"Internal error in xsltAttribute(): "
"The XSLT 'attribute' instruction was not compiled.\n");
return;
}
@ -831,19 +919,6 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt,
nsName = ns->href;
}
if (fromAttributeSet) {
/*
* This tries to ensure that xsl:attribute(s) coming
* from an xsl:attribute-set won't override attribute of
* literal result elements or of explicit xsl:attribute(s).
* URGENT TODO: This might be buggy, since it will miss to
* overwrite two equal attributes both from attribute sets.
*/
attr = xmlHasNsProp(targetElem, name, nsName);
if (attr != NULL)
return;
}
/*
* Find/create a matching ns-decl in the result tree.
*/
@ -993,21 +1068,6 @@ error:
return;
}
/**
* xsltAttribute:
* @ctxt: a XSLT process context
* @node: the node in the source tree.
* @inst: the xslt attribute node
* @comp: precomputed information
*
* Process the xslt attribute node on the source node
*/
void
xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr inst, xsltStylePreCompPtr comp) {
xsltAttributeInternal(ctxt, node, inst, comp, 0);
}
/**
* xsltApplyAttributeSet:
* @ctxt: the XSLT stylesheet
@ -1028,7 +1088,7 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
const xmlChar *ncname = NULL;
const xmlChar *prefix = NULL;
const xmlChar *curstr, *endstr;
xsltAttrElemPtr attrs;
xsltAttrSetPtr set;
xsltStylesheetPtr style;
if (attrSets == NULL) {
@ -1065,15 +1125,32 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
endstr++;
curstr = xmlDictLookup(ctxt->dict, curstr, endstr - curstr);
if (curstr) {
/*
* TODO: Validate the QName.
*/
xmlNsPtr ns;
const xmlChar *nsUri = NULL;
#ifdef WITH_XSLT_DEBUG_curstrUTES
#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
xsltGenericDebug(xsltGenericDebugContext,
"apply curstrute set %s\n", curstr);
"apply attribute set %s\n", curstr);
#endif
if (xmlValidateQName(curstr, 0)) {
xsltTransformError(ctxt, NULL, inst,
"The name '%s' in use-attribute-sets is not a valid "
"QName.\n", curstr);
return;
}
ncname = xsltSplitQName(ctxt->dict, curstr, &prefix);
if (prefix != NULL) {
ns = xmlSearchNs(inst->doc, inst, prefix);
if (ns == NULL) {
xsltTransformError(ctxt, NULL, inst,
"use-attribute-set : No namespace found for QName "
"'%s:%s'\n", prefix, ncname);
return;
}
nsUri = ns->href;
}
style = ctxt->style;
@ -1082,27 +1159,28 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
(style->attributeSets != NULL) &&
(ctxt->debugStatus != XSLT_DEBUG_NONE))
{
attrs =
xmlHashLookup2(style->attributeSets, ncname, prefix);
if ((attrs != NULL) && (attrs->attr != NULL))
xslHandleDebugger(attrs->attr->parent, node, NULL,
set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
if ((set != NULL) && (set->attrs != NULL) &&
(set->attrs->attr != NULL))
xslHandleDebugger(set->attrs->attr->parent, node, NULL,
ctxt);
}
#endif
/*
* Lookup the referenced curstrute-set.
* Lookup the referenced attribute-set. All attribute sets were
* moved to the top stylesheet so there's no need to iterate
* imported stylesheets
*/
while (style != NULL) {
attrs =
xmlHashLookup2(style->attributeSets, ncname, prefix);
while (attrs != NULL) {
if (attrs->attr != NULL) {
xsltAttributeInternal(ctxt, node, attrs->attr,
attrs->attr->psvi, 1);
set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
if (set != NULL) {
xsltAttrElemPtr cur = set->attrs;
while (cur != NULL) {
if (cur->attr != NULL) {
xsltAttribute(ctxt, node, cur->attr,
cur->attr->psvi);
}
attrs = attrs->next;
cur = cur->next;
}
style = xsltNextImport(style);
}
}
curstr = endstr;
@ -1119,6 +1197,6 @@ void
xsltFreeAttributeSetsHashes(xsltStylesheetPtr style) {
if (style->attributeSets != NULL)
xmlHashFree((xmlHashTablePtr) style->attributeSets,
(xmlHashDeallocator) xsltFreeAttrElemList);
(xmlHashDeallocator) xsltFreeAttrSet);
style->attributeSets = NULL;
}

View file

@ -372,8 +372,7 @@ xsltExtModuleRegisterDynamic(const xmlChar * URI)
/* build the module filename, and confirm the module exists */
xmlStrPrintf((xmlChar *) module_filename, sizeof(module_filename),
BAD_CAST "%s/%s%s",
ext_directory, ext_name, LIBXML_MODULE_EXTENSION);
"%s/%s%s", ext_directory, ext_name, LIBXML_MODULE_EXTENSION);
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
xsltGenericDebug(xsltGenericDebugContext,

View file

@ -76,7 +76,10 @@ xsltDebug(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED,
xsltGenericError(xsltGenericErrorContext, "noname !!!!");
#ifdef LIBXML_DEBUG_ENABLED
if (cur->value != NULL) {
xmlXPathDebugDumpObject(stdout, cur->value, 1);
if ((xsltGenericDebugContext == stdout) ||
(xsltGenericDebugContext == stderr))
xmlXPathDebugDumpObject((FILE*)xsltGenericDebugContext,
cur->value, 1);
} else {
xsltGenericError(xsltGenericErrorContext, "NULL !!!!");
}
@ -125,134 +128,6 @@ xsltFunctionNodeSet(xmlXPathParserContextPtr ctxt, int nargs){
}
}
/*
* Okay the following really seems unportable and since it's not
* part of any standard I'm not too ashamed to do this
*/
#if defined(linux) || defined(__sun)
#if defined(HAVE_MKTIME) && defined(HAVE_LOCALTIME) && defined(HAVE_ASCTIME)
#define WITH_LOCALTIME
/**
* xsltFunctionLocalTime:
* @ctxt: the XPath Parser context
* @nargs: the number of arguments
*
* Implement the localTime XSLT function used by NORM
* string localTime(???)
*
* This function is available in Norm's extension namespace
* Code (and comments) contributed by Norm
*/
static void
xsltFunctionLocalTime(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr obj;
char *str;
char digits[5];
char result[29];
long int field;
time_t gmt, lmt;
struct tm gmt_tm;
struct tm *local_tm;
if (nargs != 1) {
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
"localTime() : invalid number of args %d\n", nargs);
ctxt->error = XPATH_INVALID_ARITY;
return;
}
obj = valuePop(ctxt);
if (obj->type != XPATH_STRING) {
obj = xmlXPathConvertString(obj);
}
if (obj == NULL) {
valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
return;
}
str = (char *) obj->stringval;
/* str = "$Date$" */
memset(digits, 0, sizeof(digits));
strncpy(digits, str+7, 4);
field = strtol(digits, NULL, 10);
gmt_tm.tm_year = field - 1900;
memset(digits, 0, sizeof(digits));
strncpy(digits, str+12, 2);
field = strtol(digits, NULL, 10);
gmt_tm.tm_mon = field - 1;
memset(digits, 0, sizeof(digits));
strncpy(digits, str+15, 2);
field = strtol(digits, NULL, 10);
gmt_tm.tm_mday = field;
memset(digits, 0, sizeof(digits));
strncpy(digits, str+18, 2);
field = strtol(digits, NULL, 10);
gmt_tm.tm_hour = field;
memset(digits, 0, sizeof(digits));
strncpy(digits, str+21, 2);
field = strtol(digits, NULL, 10);
gmt_tm.tm_min = field;
memset(digits, 0, sizeof(digits));
strncpy(digits, str+24, 2);
field = strtol(digits, NULL, 10);
gmt_tm.tm_sec = field;
/* Now turn gmt_tm into a time. */
gmt = mktime(&gmt_tm);
/*
* FIXME: it's been too long since I did manual memory management.
* (I swore never to do it again.) Does this introduce a memory leak?
*/
local_tm = localtime(&gmt);
/*
* Calling localtime() has the side-effect of setting timezone.
* After we know the timezone, we can adjust for it
*/
#if !defined(__FreeBSD__)
lmt = gmt - timezone;
#else /* FreeBSD DOESN'T have such side-ffect */
lmt = gmt - local_tm->tm_gmtoff;
#endif
/*
* FIXME: it's been too long since I did manual memory management.
* (I swore never to do it again.) Does this introduce a memory leak?
*/
local_tm = localtime(&lmt);
/*
* Now convert local_tm back into a string. This doesn't introduce
* a memory leak, so says asctime(3).
*/
str = asctime(local_tm); /* "Tue Jun 26 05:02:16 2001" */
/* 0123456789 123456789 123 */
memset(result, 0, sizeof(result)); /* "Thu, 26 Jun 2001" */
/* 0123456789 12345 */
strncpy(result, str, 20);
strcpy(result+20, "???"); /* tzname doesn't work, fake it */
strncpy(result+23, str+19, 5);
/* Ok, now result contains the string I want to send back. */
valuePush(ctxt, xmlXPathNewString((xmlChar *)result));
}
#endif
#endif /* linux or sun */
/**
* xsltRegisterExtras:
* @ctxt: a XSLT process context
@ -281,11 +156,6 @@ xsltRegisterAllExtras (void) {
xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
XSLT_XT_NAMESPACE,
xsltFunctionNodeSet);
#ifdef WITH_LOCALTIME
xsltRegisterExtModuleFunction((const xmlChar *) "localTime",
XSLT_NORM_SAXON_NAMESPACE,
xsltFunctionLocalTime);
#endif
xsltRegisterExtModuleElement((const xmlChar *) "debug",
XSLT_LIBXSLT_NAMESPACE,
NULL,

View file

@ -48,14 +48,6 @@ extern "C" {
#define XSLT_XALAN_NAMESPACE ((xmlChar *) \
"org.apache.xalan.xslt.extensions.Redirect")
/**
* XSLT_NORM_SAXON_NAMESPACE:
*
* This is Norm's namespace for SAXON extensions.
*/
#define XSLT_NORM_SAXON_NAMESPACE ((xmlChar *) \
"http://nwalsh.com/xslt/ext/com.nwalsh.saxon.CVS")
XSLTPUBFUN void XSLTCALL
xsltFunctionNodeSet (xmlXPathParserContextPtr ctxt,

View file

@ -575,12 +575,15 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
xmlXPathObjectPtr formatObj = NULL;
xmlXPathObjectPtr decimalObj = NULL;
xsltStylesheetPtr sheet;
xsltDecimalFormatPtr formatValues;
xsltDecimalFormatPtr formatValues = NULL;
xmlChar *result;
const xmlChar *ncname;
const xmlChar *prefix = NULL;
const xmlChar *nsUri = NULL;
xsltTransformContextPtr tctxt;
tctxt = xsltXPathGetTransformContext(ctxt);
if (tctxt == NULL)
if ((tctxt == NULL) || (tctxt->inst == NULL))
return;
sheet = tctxt->style;
if (sheet == NULL)
@ -591,7 +594,23 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
case 3:
CAST_TO_STRING;
decimalObj = valuePop(ctxt);
formatValues = xsltDecimalFormatGetByName(sheet, decimalObj->stringval);
ncname = xsltSplitQName(sheet->dict, decimalObj->stringval, &prefix);
if (prefix != NULL) {
xmlNsPtr ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, prefix);
if (ns == NULL) {
xsltTransformError(tctxt, NULL, NULL,
"format-number : No namespace found for QName '%s:%s'\n",
prefix, ncname);
sheet->errors++;
ncname = NULL;
}
else {
nsUri = ns->href;
}
}
if (ncname != NULL) {
formatValues = xsltDecimalFormatGetByQName(sheet, nsUri, ncname);
}
if (formatValues == NULL) {
xsltTransformError(tctxt, NULL, NULL,
"format-number() : undeclared decimal format '%s'\n",
@ -807,7 +826,7 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
}
obj = valuePop(ctxt);
tctxt = xsltXPathGetTransformContext(ctxt);
if (tctxt == NULL) {
if ((tctxt == NULL) || (tctxt->inst == NULL)) {
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
"element-available() : internal error tctxt == NULL\n");
xmlXPathFreeObject(obj);
@ -822,7 +841,7 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
name = xmlStrdup(obj->stringval);
ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL);
if (ns != NULL) nsURI = xmlStrdup(ns->href);
if (ns != NULL) nsURI = ns->href;
} else {
nsURI = xmlXPathNsLookup(ctxt->context, prefix);
if (nsURI == NULL) {

View file

@ -384,10 +384,13 @@ xsltAddKey(xsltStylesheetPtr style, const xmlChar *name,
prev->next = key;
}
key->next = NULL;
key = NULL;
error:
if (pattern != NULL)
xmlFree(pattern);
if (key != NULL)
xsltFreeKeyDef(key);
return(0);
}

View file

@ -48,39 +48,11 @@ static xsltFormatToken default_token;
/*
* **** Start temp insert ****
*
* The following two routines (xsltUTF8Size and xsltUTF8Charcmp)
* will be replaced with calls to the corresponding libxml routines
* at a later date (when other inter-library dependencies require it)
* The following routine xsltUTF8Charcmp will be replaced with calls to
* the corresponding libxml routine at a later date (when other
* inter-library dependencies require it).
*/
/**
* xsltUTF8Size:
* @utf: pointer to the UTF8 character
*
* returns the numbers of bytes in the character, -1 on format error
*/
static int
xsltUTF8Size(xmlChar *utf) {
xmlChar mask;
int len;
if (utf == NULL)
return -1;
if (*utf < 0x80)
return 1;
/* check valid UTF8 character */
if (!(*utf & 0x40))
return -1;
/* determine number of bytes in char */
len = 2;
for (mask=0x20; mask != 0; mask>>=1) {
if (!(*utf & mask))
return len;
len++;
}
return -1;
}
/**
* xsltUTF8Charcmp
* @utf1: pointer to first UTF8 char
@ -91,13 +63,16 @@ xsltUTF8Size(xmlChar *utf) {
*/
static int
xsltUTF8Charcmp(xmlChar *utf1, xmlChar *utf2) {
int len = xmlUTF8Strsize(utf1, 1);
if (len < 1)
return -1;
if (utf1 == NULL ) {
if (utf2 == NULL)
return 0;
return -1;
}
return xmlStrncmp(utf1, utf2, xsltUTF8Size(utf1));
return xmlStrncmp(utf1, utf2, len);
}
/***** Stop temp insert *****/
@ -205,7 +180,7 @@ xsltNumberFormatDecimal(xmlBufferPtr buffer,
}
if (i < 0)
xsltGenericError(xsltGenericErrorContext,
"xsltNumberFormatDecimal: Internal buffer size exceeded");
"xsltNumberFormatDecimal: Internal buffer size exceeded\n");
xmlBufferCat(buffer, pointer);
}
@ -599,25 +574,7 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
{
int amount = 0;
int cnt = 0;
xmlNodePtr cur;
/* select the starting node */
switch (node->type) {
case XML_ELEMENT_NODE:
cur = node;
break;
case XML_ATTRIBUTE_NODE:
cur = ((xmlAttrPtr) node)->parent;
break;
case XML_TEXT_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
cur = node->parent;
break;
default:
cur = NULL;
break;
}
xmlNodePtr cur = node;
while (cur != NULL) {
/* process current node */
@ -636,16 +593,25 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
(cur->type == XML_HTML_DOCUMENT_NODE))
break; /* while */
while ((cur->prev != NULL) && ((cur->prev->type == XML_DTD_NODE) ||
(cur->prev->type == XML_XINCLUDE_START) ||
(cur->prev->type == XML_XINCLUDE_END)))
cur = cur->prev;
if (cur->prev != NULL) {
for (cur = cur->prev; cur->last != NULL; cur = cur->last);
} else {
cur = cur->parent;
}
if (cur->type == XML_NAMESPACE_DECL) {
/*
* The XPath module stores the parent of a namespace node in
* the ns->next field.
*/
cur = (xmlNodePtr) ((xmlNsPtr) cur)->next;
} else if (cur->type == XML_ATTRIBUTE_NODE) {
cur = cur->parent;
} else {
while ((cur->prev != NULL) && ((cur->prev->type == XML_DTD_NODE) ||
(cur->prev->type == XML_XINCLUDE_START) ||
(cur->prev->type == XML_XINCLUDE_END)))
cur = cur->prev;
if (cur->prev != NULL) {
for (cur = cur->prev; cur->last != NULL; cur = cur->last);
} else {
cur = cur->parent;
}
}
}
array[amount++] = (double) cnt;
@ -891,7 +857,7 @@ xsltFormatNumberPreSuffix(xsltDecimalFormatPtr self, xmlChar **format, xsltForma
}
}
if ((len=xsltUTF8Size(*format)) < 1)
if ((len=xmlUTF8Strsize(*format, 1)) < 1)
return -1;
count += len;
*format += len;
@ -1073,7 +1039,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
} else
break; /* while */
if ((len=xsltUTF8Size(the_format)) < 1) {
if ((len=xmlUTF8Strsize(the_format, 1)) < 1) {
found_error = 1;
goto OUTPUT_NUMBER;
}
@ -1082,9 +1048,14 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
}
/* We have finished the integer part, now work on fraction */
if (xsltUTF8Charcmp(the_format, self->decimalPoint) == 0) {
if ( (*the_format != 0) &&
(xsltUTF8Charcmp(the_format, self->decimalPoint) == 0) ) {
format_info.add_decimal = TRUE;
the_format += xsltUTF8Size(the_format); /* Skip over the decimal */
if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
found_error = 1;
goto OUTPUT_NUMBER;
}
the_format += len; /* Skip over the decimal */
}
while (*the_format != 0) {
@ -1103,7 +1074,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
goto OUTPUT_NUMBER;
}
delayed_multiplier = 100;
if ((len = xsltUTF8Size(the_format)) < 1) {
if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
found_error = 1;
goto OUTPUT_NUMBER;
}
@ -1115,7 +1086,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
goto OUTPUT_NUMBER;
}
delayed_multiplier = 1000;
if ((len = xsltUTF8Size(the_format)) < 1) {
if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
found_error = 1;
goto OUTPUT_NUMBER;
}
@ -1124,7 +1095,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
} else if (xsltUTF8Charcmp(the_format, self->grouping) != 0) {
break; /* while */
}
if ((len = xsltUTF8Size(the_format)) < 1) {
if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
found_error = 1;
goto OUTPUT_NUMBER;
}
@ -1201,7 +1172,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
delayed_multiplier = 0;
else
break; /* while */
if ((len = xsltUTF8Size(the_format)) < 1) {
if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
found_error = 1;
goto OUTPUT_NUMBER;
}
@ -1267,12 +1238,12 @@ OUTPUT_NUMBER:
/* Ready to output our number. First see if "default sign" is required */
if (default_sign != 0)
xmlBufferAdd(buffer, self->minusSign, xsltUTF8Size(self->minusSign));
xmlBufferAdd(buffer, self->minusSign, xmlUTF8Strsize(self->minusSign, 1));
/* Put the prefix into the buffer */
for (j = 0; j < prefix_length; j++) {
if ((pchar = *prefix++) == SYMBOL_QUOTE) {
len = xsltUTF8Size(prefix);
len = xmlUTF8Strsize(prefix, 1);
xmlBufferAdd(buffer, prefix, len);
prefix += len;
j += len - 1; /* length of symbol less length of quote */
@ -1309,20 +1280,20 @@ OUTPUT_NUMBER:
/* Add leading zero, if required */
if ((floor(number) == 0) &&
(format_info.integer_digits + format_info.frac_digits == 0)) {
xmlBufferAdd(buffer, self->zeroDigit, xsltUTF8Size(self->zeroDigit));
xmlBufferAdd(buffer, self->zeroDigit, xmlUTF8Strsize(self->zeroDigit, 1));
}
/* Next the fractional part, if required */
if (format_info.frac_digits + format_info.frac_hash == 0) {
if (format_info.add_decimal)
xmlBufferAdd(buffer, self->decimalPoint,
xsltUTF8Size(self->decimalPoint));
xmlUTF8Strsize(self->decimalPoint, 1));
}
else {
number -= floor(number);
if ((number != 0) || (format_info.frac_digits != 0)) {
xmlBufferAdd(buffer, self->decimalPoint,
xsltUTF8Size(self->decimalPoint));
xmlUTF8Strsize(self->decimalPoint, 1));
number = floor(scale * number + 0.5);
for (j = format_info.frac_hash; j > 0; j--) {
if (fmod(number, 10.0) >= 1.0)
@ -1337,7 +1308,7 @@ OUTPUT_NUMBER:
/* Put the suffix into the buffer */
for (j = 0; j < suffix_length; j++) {
if ((pchar = *suffix++) == SYMBOL_QUOTE) {
len = xsltUTF8Size(suffix);
len = xmlUTF8Strsize(suffix, 1);
xmlBufferAdd(buffer, suffix, len);
suffix += len;
j += len - 1; /* length of symbol less length of escape */

View file

@ -85,6 +85,7 @@ struct _xsltCompMatch {
const xmlChar *mode; /* the mode */
const xmlChar *modeURI; /* the mode URI */
xsltTemplatePtr template; /* the associated template */
xmlNodePtr node; /* the containing element */
int direct;
/* TODO fix the statically allocated size steps[] */
@ -895,7 +896,9 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
xmlNodePtr matchNode, const xmlChar *mode,
const xmlChar *modeURI) {
int i;
int found = 0;
xmlNodePtr node = matchNode;
xmlNodePtr oldInst;
xsltStepOpPtr step, sel = NULL;
xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */
@ -929,6 +932,10 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
return(0);
}
/* Some XPath functions rely on inst being set correctly. */
oldInst = ctxt->inst;
ctxt->inst = comp->node;
i = 0;
restart:
for (;i < comp->nbStep;i++) {
@ -1121,12 +1128,9 @@ restart:
* as possible this costly computation.
*/
if (comp->direct) {
if (states.states != NULL) {
/* Free the rollback states */
xmlFree(states.states);
}
return(xsltTestCompMatchDirect(ctxt, comp, matchNode,
comp->nsList, comp->nsNr));
found = xsltTestCompMatchDirect(ctxt, comp, matchNode,
comp->nsList, comp->nsNr);
goto exit;
}
if (!xsltTestPredicateMatch(ctxt, comp, node, step, sel))
@ -1166,18 +1170,19 @@ restart:
}
}
found:
found = 1;
exit:
ctxt->inst = oldInst;
if (states.states != NULL) {
/* Free the rollback states */
xmlFree(states.states);
}
return(1);
return found;
rollback:
/* got an error try to rollback */
if (states.states == NULL)
return(0);
if (states.nbstates <= 0) {
xmlFree(states.states);
return(0);
if (states.states == NULL || states.nbstates <= 0) {
found = 0;
goto exit;
}
states.nbstates--;
i = states.states[states.nbstates].step;
@ -1456,6 +1461,7 @@ xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name,
xsltTransformError(NULL, NULL, NULL,
"xsltCompileIdKeyPattern : ) expected\n");
ctxt->error = 1;
xmlFree(lit);
return;
}
}
@ -1618,6 +1624,7 @@ parse_node_test:
xsltTransformError(NULL, NULL, NULL,
"xsltCompileStepPattern : Name expected\n");
ctxt->error = 1;
xmlFree(URL);
goto error;
}
} else {
@ -1925,6 +1932,7 @@ xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc,
goto error;
ctxt->cur = &(ctxt->base)[current - start];
element->pattern = ctxt->base;
element->node = node;
element->nsList = xmlGetNsList(doc, node);
j = 0;
if (element->nsList != NULL) {

View file

@ -1394,9 +1394,6 @@ xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
return;
cur->psvi = comp;
if ((style == NULL) || (cur == NULL))
return;
comp->numdata.doc = cur->doc;
comp->numdata.node = cur;
comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",
@ -2319,7 +2316,7 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
xsltCheckInstructionElement(style, inst);
inst->psvi = (void *) xsltDocumentComp(style, inst,
(xsltTransformFunction) xsltDocumentElem);
} else {
} else if ((style == NULL) || (style->forwards_compatible == 0)) {
xsltTransformError(NULL, style, inst,
"xsltStylePreCompute: unknown xsl:%s\n", inst->name);
if (style != NULL) style->warnings++;

View file

@ -246,7 +246,7 @@ xsltCheckFilename (const char *path)
{
#ifdef HAVE_STAT
struct stat stat_buffer;
#if defined(WIN32) && !defined(__CYGWIN__)
#if defined(_WIN32) && !defined(__CYGWIN__)
DWORD dwAttrs;
dwAttrs = GetFileAttributes(path);
@ -351,7 +351,7 @@ xsltCheckWrite(xsltSecurityPrefsPtr sec,
if ((uri->scheme == NULL) ||
(xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
#if defined(WIN32) && !defined(__CYGWIN__)
#if defined(_WIN32) && !defined(__CYGWIN__)
if ((uri->path)&&(uri->path[0]=='/')&&
(uri->path[1]!='\0')&&(uri->path[2]==':'))
ret = xsltCheckWritePath(sec, ctxt, uri->path+1);

View file

@ -45,6 +45,12 @@ xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
xmlNodePtr oldInst;
int oldProximityPosition, oldContextSize;
if ((ctxt == NULL) || (ctxt->inst == NULL)) {
xsltTransformError(ctxt, NULL, NULL,
"xsltEvalXPathPredicate: No context or instruction\n");
return(0);
}
oldContextSize = ctxt->xpathCtxt->contextSize;
oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
oldNsNr = ctxt->xpathCtxt->nsNr;
@ -106,6 +112,12 @@ xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
int oldNsNr;
xmlNsPtr *oldNamespaces;
if ((ctxt == NULL) || (ctxt->inst == NULL)) {
xsltTransformError(ctxt, NULL, NULL,
"xsltEvalXPathStringNs: No context or instruction\n");
return(0);
}
oldInst = ctxt->inst;
oldNode = ctxt->node;
oldPos = ctxt->xpathCtxt->proximityPosition;
@ -278,12 +290,12 @@ xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,
xsltTransformError(ctxt, NULL, inst,
"xsltAttrTemplateValueProcessNode: unmatched '{'\n");
ret = xmlStrncat(ret, str, cur - str);
return(ret);
goto exit;
}
str++;
expr = xmlStrndup(str, cur - str);
if (expr == NULL)
return(ret);
goto exit;
else if (*expr == '{') {
ret = xmlStrcat(ret, expr);
xmlFree(expr);
@ -331,6 +343,7 @@ xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,
ret = xmlStrncat(ret, str, cur - str);
}
exit:
if (nsList != NULL)
xmlFree(nsList);

View file

@ -23,6 +23,7 @@
#ifdef WITH_XSLT_DEBUG
#define WITH_XSLT_DEBUG_EXTRA
#define WITH_XSLT_DEBUG_PROCESS
#define WITH_XSLT_DEBUG_VARIABLE
#endif
#define XSLT_GENERATE_HTML_DOCTYPE
@ -55,10 +56,9 @@ static xmlNsPtr
xsltCopyNamespaceListInternal(xmlNodePtr node, xmlNsPtr cur);
static xmlNodePtr
xsltCopyTreeInternal(xsltTransformContextPtr ctxt,
xmlNodePtr invocNode,
xmlNodePtr node,
xmlNodePtr insert, int isLRE, int topElemVisited);
xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
xmlNodePtr node, xmlNodePtr insert, int isLRE,
int topElemVisited);
static void
xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
@ -434,7 +434,7 @@ xsltGetXIncludeDefault(void) {
return(xsltDoXIncludeDefault);
}
unsigned long xsltDefaultTrace = (unsigned long) XSLT_TRACE_ALL;
static unsigned long xsltDefaultTrace = (unsigned long) XSLT_TRACE_ALL;
/**
* xsltDebugSetDefaultTrace:
@ -733,9 +733,6 @@ xsltFreeTransformContext(xsltTransformContextPtr ctxt) {
* *
************************************************************************/
xmlNodePtr xsltCopyTree(xsltTransformContextPtr ctxt,
xmlNodePtr node, xmlNodePtr insert, int literal);
/**
* xsltAddChild:
* @parent: the parent node
@ -751,7 +748,7 @@ static xmlNodePtr
xsltAddChild(xmlNodePtr parent, xmlNodePtr cur) {
xmlNodePtr ret;
if ((cur == NULL) || (parent == NULL))
if (cur == NULL)
return(NULL);
if (parent == NULL) {
xmlFreeNode(cur);
@ -783,13 +780,32 @@ xsltAddTextString(xsltTransformContextPtr ctxt, xmlNodePtr target,
return(target);
if (ctxt->lasttext == target->content) {
int minSize;
if (ctxt->lasttuse + len >= ctxt->lasttsize) {
/* Check for integer overflow accounting for NUL terminator. */
if (len >= INT_MAX - ctxt->lasttuse) {
xsltTransformError(ctxt, NULL, target,
"xsltCopyText: text allocation failed\n");
return(NULL);
}
minSize = ctxt->lasttuse + len + 1;
if (ctxt->lasttsize < minSize) {
xmlChar *newbuf;
int size;
int extra;
/* Double buffer size but increase by at least 100 bytes. */
extra = minSize < 100 ? 100 : minSize;
/* Check for integer overflow. */
if (extra > INT_MAX - ctxt->lasttsize) {
size = INT_MAX;
}
else {
size = ctxt->lasttsize + extra;
}
size = ctxt->lasttsize + len + 100;
size *= 2;
newbuf = (xmlChar *) xmlRealloc(target->content,size);
if (newbuf == NULL) {
xsltTransformError(ctxt, NULL, target,
@ -1090,7 +1106,7 @@ exit:
*
* Do a copy of an attribute.
* Called by:
* - xsltCopyTreeInternal()
* - xsltCopyTree()
* - xsltCopyOf()
* - xsltCopy()
*
@ -1191,7 +1207,7 @@ xsltShallowCopyAttr(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
* @target element node.
*
* Called by:
* - xsltCopyTreeInternal()
* - xsltCopyTree()
*
* Returns 0 on success and -1 on errors and internal errors.
*/
@ -1313,7 +1329,7 @@ xsltShallowCopyElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
* copy over all namespace nodes in scope.
* The damn thing about this is, that we would need to
* use the xmlGetNsList(), for every single node; this is
* also done in xsltCopyTreeInternal(), but only for the top node.
* also done in xsltCopyTree(), but only for the top node.
*/
if (node->ns != NULL) {
if (isLRE) {
@ -1371,7 +1387,7 @@ xsltCopyTreeList(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
xmlNodePtr copy, ret = NULL;
while (list != NULL) {
copy = xsltCopyTreeInternal(ctxt, invocNode,
copy = xsltCopyTree(ctxt, invocNode,
list, insert, isLRE, topElemVisited);
if (copy != NULL) {
if (ret == NULL) {
@ -1391,7 +1407,7 @@ xsltCopyTreeList(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
* Do a copy of a namespace list. If @node is non-NULL the
* new namespaces are added automatically.
* Called by:
* xsltCopyTreeInternal()
* xsltCopyTree()
*
* QUESTION: What is the exact difference between this function
* and xsltCopyNamespaceList() in "namespaces.c"?
@ -1549,7 +1565,7 @@ occupied:
}
/**
* xsltCopyTreeInternal:
* xsltCopyTree:
* @ctxt: the XSLT transformation context
* @invocNode: responsible node in the stylesheet; used for error reports
* @node: the element node in the source tree
@ -1568,10 +1584,9 @@ occupied:
* Returns a pointer to the new tree, or NULL in case of error
*/
static xmlNodePtr
xsltCopyTreeInternal(xsltTransformContextPtr ctxt,
xmlNodePtr invocNode,
xmlNodePtr node,
xmlNodePtr insert, int isLRE, int topElemVisited)
xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
xmlNodePtr node, xmlNodePtr insert, int isLRE,
int topElemVisited)
{
xmlNodePtr copy;
@ -1627,7 +1642,7 @@ xsltCopyTreeInternal(xsltTransformContextPtr ctxt,
copy = xsltAddChild(insert, copy);
if (copy == NULL) {
xsltTransformError(ctxt, NULL, invocNode,
"xsltCopyTreeInternal: Copying of '%s' failed.\n", node->name);
"xsltCopyTree: Copying of '%s' failed.\n", node->name);
return (copy);
}
/*
@ -1758,34 +1773,11 @@ xsltCopyTreeInternal(xsltTransformContextPtr ctxt,
}
} else {
xsltTransformError(ctxt, NULL, invocNode,
"xsltCopyTreeInternal: Copying of '%s' failed.\n", node->name);
"xsltCopyTree: Copying of '%s' failed.\n", node->name);
}
return(copy);
}
/**
* xsltCopyTree:
* @ctxt: the XSLT transformation context
* @node: the element node in the source tree
* @insert: the parent in the result tree
* @literal: indicates if @node is a Literal Result Element
*
* Make a copy of the full tree under the element node @node
* and insert it as last child of @insert
* For literal result element, some of the namespaces may not be copied
* over according to section 7.1.
* TODO: Why is this a public function?
*
* Returns a pointer to the new tree, or NULL in case of error
*/
xmlNodePtr
xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr insert, int literal)
{
return(xsltCopyTreeInternal(ctxt, node, node, insert, literal, 0));
}
/************************************************************************
* *
* Error/fallback processing *
@ -1987,6 +1979,9 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
/*
* Handling of Elements: second pass, actual processing
*
* Note that params are passed to the next template. This matches
* XSLT 2.0 behavior but doesn't conform to XSLT 1.0.
*/
oldSize = ctxt->xpathCtxt->contextSize;
oldPos = ctxt->xpathCtxt->proximityPosition;
@ -2266,30 +2261,28 @@ xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
{
xmlDocPtr cur = ctxt->localRVT, tmp;
while ((cur != NULL) && (cur != base)) {
if (cur->psvi == (void *) ((long) 1)) {
cur = (xmlDocPtr) cur->next;
} else {
tmp = cur;
cur = (xmlDocPtr) cur->next;
if (cur == base)
return;
if (cur->prev != NULL)
xsltTransformError(ctxt, NULL, NULL, "localRVT not head of list\n");
if (tmp == ctxt->localRVT)
ctxt->localRVT = cur;
do {
tmp = cur;
cur = (xmlDocPtr) cur->next;
if (tmp->psvi == XSLT_RVT_LOCAL) {
xsltReleaseRVT(ctxt, tmp);
} else if (tmp->psvi == XSLT_RVT_GLOBAL) {
xsltRegisterPersistRVT(ctxt, tmp);
} else if (tmp->psvi != XSLT_RVT_FUNC_RESULT) {
xmlGenericError(xmlGenericErrorContext,
"xsltReleaseLocalRVTs: Unexpected RVT flag %p\n",
tmp->psvi);
}
} while (cur != base);
/*
* We need ctxt->localRVTBase for extension instructions
* which return values (like EXSLT's function).
*/
if (tmp == ctxt->localRVTBase)
ctxt->localRVTBase = cur;
if (tmp->prev)
tmp->prev->next = (xmlNodePtr) cur;
if (cur)
cur->prev = tmp->prev;
xsltReleaseRVT(ctxt, tmp);
}
}
if (base != NULL)
base->prev = NULL;
ctxt->localRVT = base;
}
/**
@ -2315,7 +2308,7 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
xmlNodePtr oldInsert, oldInst, oldCurInst, oldContextNode;
xmlNodePtr cur, insert, copy = NULL;
int level = 0, oldVarsNr;
xmlDocPtr oldLocalFragmentTop, oldLocalFragmentBase;
xmlDocPtr oldLocalFragmentTop;
#ifdef XSLT_REFACTORED
xsltStylePreCompPtr info;
@ -2343,6 +2336,24 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
return;
CHECK_STOPPED;
/*
* Check for infinite recursion: stop if the maximum of nested templates
* is excceeded. Adjust xsltMaxDepth if you need more.
*/
if (ctxt->depth >= ctxt->maxTemplateDepth) {
xsltTransformError(ctxt, NULL, list,
"xsltApplySequenceConstructor: A potential infinite template "
"recursion was detected.\n"
"You can adjust xsltMaxDepth (--maxdepth) in order to "
"raise the maximum number of nested template calls and "
"variables/params (currently set to %d).\n",
ctxt->maxTemplateDepth);
xsltDebug(ctxt, contextNode, list, NULL);
ctxt->state = XSLT_STATE_STOPPED;
return;
}
ctxt->depth++;
oldLocalFragmentTop = ctxt->localRVT;
oldInsert = insert = ctxt->insert;
oldInst = oldCurInst = ctxt->inst;
@ -2642,17 +2653,22 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
"xsltApplySequenceConstructor: extension construct %s\n",
cur->name));
#endif
/*
* Disable the xsltCopyTextString optimization for
* extension elements. Extensions could append text using
* xmlAddChild which will free the buffer pointed to by
* 'lasttext'. This buffer could later be reallocated with
* a different size than recorded in 'lasttsize'. See bug
* #777432.
*/
if (cur->psvi == xsltExtMarker) {
ctxt->lasttext = NULL;
}
ctxt->insert = insert;
/*
* We need the fragment base for extension instructions
* which return values (like EXSLT's function).
*/
oldLocalFragmentBase = ctxt->localRVTBase;
ctxt->localRVTBase = NULL;
func(ctxt, contextNode, cur, cur->psvi);
ctxt->localRVTBase = oldLocalFragmentBase;
/*
* Cleanup temporary tree fragments.
*/
@ -2716,12 +2732,9 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
oldCurInst = ctxt->inst;
ctxt->inst = cur;
ctxt->insert = insert;
oldLocalFragmentBase = ctxt->localRVTBase;
ctxt->localRVTBase = NULL;
info->func(ctxt, contextNode, cur, (xsltElemPreCompPtr) info);
ctxt->localRVTBase = oldLocalFragmentBase;
/*
* Cleanup temporary tree fragments.
*/
@ -2835,13 +2848,19 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
cur->name));
#endif
/*
* Disable the xsltCopyTextString optimization for
* extension elements. Extensions could append text using
* xmlAddChild which will free the buffer pointed to by
* 'lasttext'. This buffer could later be reallocated with
* a different size than recorded in 'lasttsize'. See bug
* #777432.
*/
if (cur->psvi == xsltExtMarker) {
ctxt->lasttext = NULL;
}
ctxt->insert = insert;
/*
* We need the fragment base for extension instructions
* which return values (like EXSLT's function).
*/
oldLocalFragmentBase = ctxt->localRVTBase;
ctxt->localRVTBase = NULL;
function(ctxt, contextNode, cur, cur->psvi);
/*
@ -2850,7 +2869,6 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
if (oldLocalFragmentTop != ctxt->localRVT)
xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
ctxt->localRVTBase = oldLocalFragmentBase;
ctxt->insert = oldInsert;
}
@ -2992,6 +3010,8 @@ error:
ctxt->inst = oldInst;
ctxt->insert = oldInsert;
ctxt->depth--;
#ifdef WITH_DEBUGGER
if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (addCallResult)) {
xslDropCall();
@ -3026,7 +3046,7 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
long start = 0;
xmlNodePtr cur;
xsltStackElemPtr tmpParam = NULL;
xmlDocPtr oldUserFragmentTop, oldLocalFragmentTop;
xmlDocPtr oldUserFragmentTop;
#ifdef XSLT_REFACTORED
xsltStyleItemParamPtr iparam;
@ -3058,23 +3078,6 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
return;
CHECK_STOPPED;
/*
* Check for infinite recursion: stop if the maximum of nested templates
* is excceeded. Adjust xsltMaxDepth if you need more.
*/
if (ctxt->templNr >= ctxt->maxTemplateDepth)
{
xsltTransformError(ctxt, NULL, list,
"xsltApplyXSLTTemplate: A potential infinite template recursion "
"was detected.\n"
"You can adjust xsltMaxDepth (--maxdepth) in order to "
"raise the maximum number of nested template calls and "
"variables/params (currently set to %d).\n",
ctxt->maxTemplateDepth);
xsltDebug(ctxt, contextNode, list, NULL);
return;
}
if (ctxt->varsNr >= ctxt->maxTemplateVars)
{
xsltTransformError(ctxt, NULL, list,
@ -3084,12 +3087,12 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
"raise the maximum number of variables/params (currently set to %d).\n",
ctxt->maxTemplateVars);
xsltDebug(ctxt, contextNode, list, NULL);
ctxt->state = XSLT_STATE_STOPPED;
return;
}
oldUserFragmentTop = ctxt->tmpRVT;
ctxt->tmpRVT = NULL;
oldLocalFragmentTop = ctxt->localRVT;
/*
* Initiate a distinct scope of local params/variables.
@ -3190,31 +3193,6 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
xsltTemplateParamsCleanup(ctxt);
ctxt->varsBase = oldVarsBase;
/*
* Clean up remaining local tree fragments.
* This also frees fragments which are the result of
* extension instructions. Should normally not be hit; but
* just for the case xsltExtensionInstructionResultFinalize()
* was not called by the extension author.
*/
if (oldLocalFragmentTop != ctxt->localRVT) {
xmlDocPtr curdoc = ctxt->localRVT, tmp;
do {
tmp = curdoc;
curdoc = (xmlDocPtr) curdoc->next;
/* Need to housekeep localRVTBase */
if (tmp == ctxt->localRVTBase)
ctxt->localRVTBase = curdoc;
if (tmp->prev)
tmp->prev->next = (xmlNodePtr) curdoc;
if (curdoc)
curdoc->prev = tmp->prev;
xsltReleaseRVT(ctxt, tmp);
} while (curdoc != oldLocalFragmentTop);
}
ctxt->localRVT = oldLocalFragmentTop;
/*
* Release user-created fragments stored in the scope
* of xsl:template. Note that this mechanism is deprecated:
@ -3820,7 +3798,6 @@ xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
xsltTransformError(ctxt, NULL, inst,
"xsltDocumentElem: unable to save to %s\n",
filename);
ctxt->state = XSLT_STATE_ERROR;
#ifdef WITH_XSLT_DEBUG_EXTRA
} else {
xsltGenericDebug(xsltGenericDebugContext,
@ -4433,8 +4410,7 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
xsltShallowCopyAttr(ctxt, inst,
ctxt->insert, (xmlAttrPtr) cur);
} else {
xsltCopyTreeInternal(ctxt, inst,
cur, ctxt->insert, 0, 0);
xsltCopyTree(ctxt, inst, cur, ctxt->insert, 0, 0);
}
}
}
@ -4685,6 +4661,10 @@ xsltApplyImports(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
ctxt->currentTemplateRule = oldCurTemplRule;
}
else {
/* Use built-in templates. */
xsltDefaultProcessOneNode(ctxt, contextNode, NULL);
}
}
/**
@ -5632,6 +5612,7 @@ typedef struct xsltHTMLVersion {
} xsltHTMLVersion;
static xsltHTMLVersion xsltHTMLVersions[] = {
{ "5", NULL, "about:legacy-compat" },
{ "4.01frame", "-//W3C//DTD HTML 4.01 Frameset//EN",
"http://www.w3.org/TR/1999/REC-html401-19991224/frameset.dtd"},
{ "4.01strict", "-//W3C//DTD HTML 4.01//EN",
@ -5857,7 +5838,8 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
*/
root = xmlDocGetRootElement(doc);
if (root != NULL) {
if (((long) root->content) >= 0 && (xslDebugStatus == XSLT_DEBUG_NONE))
if (((ptrdiff_t) root->content >= 0) &&
(xslDebugStatus == XSLT_DEBUG_NONE))
xmlXPathOrderDocElems(doc);
}
@ -6007,6 +5989,9 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
xsltEvalGlobalVariables(ctxt);
/* Clean up any unused RVTs. */
xsltReleaseLocalRVTs(ctxt, NULL);
ctxt->node = (xmlNodePtr) doc;
ctxt->output = res;
ctxt->insert = (xmlNodePtr) res;
@ -6151,7 +6136,7 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
/*
* Be pedantic.
*/
if ((ctxt != NULL) && (ctxt->state == XSLT_STATE_ERROR)) {
if ((ctxt != NULL) && (ctxt->state != XSLT_STATE_OK)) {
xmlFreeDoc(res);
res = NULL;
}

View file

@ -19,11 +19,11 @@
const xmlChar *xsltDocFragFake = (const xmlChar *) " fake node libxslt";
#endif
const xmlChar *xsltComputingGlobalVarMarker =
static const xmlChar *xsltComputingGlobalVarMarker =
(const xmlChar *) " var/param being computed";
#define XSLT_VAR_GLOBAL 1<<0
#define XSLT_VAR_IN_SELECT 1<<1
#define XSLT_VAR_GLOBAL (1<<0)
#define XSLT_VAR_IN_SELECT (1<<1)
#define XSLT_TCTXT_VARIABLE(c) ((xsltStackElemPtr) (c)->contextVariable)
/************************************************************************
@ -101,6 +101,9 @@ xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
if ((ctxt == NULL) || (RVT == NULL))
return(-1);
RVT->prev = NULL;
RVT->psvi = XSLT_RVT_VARIABLE;
/*
* We'll restrict the lifetime of user-created fragments
* insinde an xsl:variable and xsl:param to the lifetime of the
@ -138,15 +141,18 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
if ((ctxt == NULL) || (RVT == NULL))
return(-1);
RVT->prev = NULL;
/*
* When evaluating "select" expressions of xsl:variable
* and xsl:param, we need to bind newly created tree fragments
* to the variable itself; otherwise the tragment will be
* to the variable itself; otherwise the fragment will be
* freed before we leave the scope of a var.
*/
if ((ctxt->contextVariable != NULL) &&
(XSLT_TCTXT_VARIABLE(ctxt)->flags & XSLT_VAR_IN_SELECT))
{
RVT->psvi = XSLT_RVT_VARIABLE;
RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
return(0);
@ -156,19 +162,11 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
* If not reference by a returning instruction (like EXSLT's function),
* then this fragment will be freed, when the instruction exits.
*/
RVT->psvi = XSLT_RVT_LOCAL;
RVT->next = (xmlNodePtr) ctxt->localRVT;
if (ctxt->localRVT != NULL)
ctxt->localRVT->prev = (xmlNodePtr) RVT;
ctxt->localRVT = RVT;
/*
* We need to keep track of the first registered fragment
* for extension instructions which return fragments
* (e.g. EXSLT'S function), in order to let
* xsltExtensionInstructionResultFinalize() clear the
* preserving flag on the fragments.
*/
if (ctxt->localRVTBase == NULL)
ctxt->localRVTBase = RVT;
return(0);
}
@ -183,26 +181,16 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
* collector will free them after the function-calling process exits.
*
* Returns 0 in case of success and -1 in case of API or internal errors.
*
* This function is unsupported in newer releases of libxslt.
*/
int
xsltExtensionInstructionResultFinalize(xsltTransformContextPtr ctxt)
{
xmlDocPtr cur;
if (ctxt == NULL)
return(-1);
if (ctxt->localRVTBase == NULL)
return(0);
/*
* Enable remaining local tree fragments to be freed
* by the fragment garbage collector.
*/
cur = ctxt->localRVTBase;
do {
cur->psvi = NULL;
cur = (xmlDocPtr) cur->next;
} while (cur != NULL);
return(0);
xmlGenericError(xmlGenericErrorContext,
"xsltExtensionInstructionResultFinalize is unsupported "
"in this release of libxslt.\n");
return(-1);
}
/**
@ -217,11 +205,35 @@ xsltExtensionInstructionResultFinalize(xsltTransformContextPtr ctxt)
* tree fragments (via xsltCreateRVT()) with xsltRegisterLocalRVT().
*
* Returns 0 in case of success and -1 in case of error.
*
* It isn't necessary to call this function in newer releases of
* libxslt.
*/
int
xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt,
xmlXPathObjectPtr obj)
{
return(0);
}
/**
* xsltFlagRVTs:
* @ctxt: an XSLT transformation context
* @obj: an XPath object to be inspected for result tree fragments
* @val: the flag value
*
* Updates ownership information of RVTs in @obj according to @val.
*
* @val = XSLT_RVT_FUNC_RESULT for the result of an extension function, so its
* RVTs won't be destroyed after leaving the returning scope.
* @val = XSLT_RVT_LOCAL for the result of an extension function to reset
* the state of its RVTs after it was returned to a new scope.
* @val = XSLT_RVT_GLOBAL for parts of global variables.
*
* Returns 0 in case of success and -1 in case of error.
*/
int
xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val) {
int i;
xmlNodePtr cur;
xmlDocPtr doc;
@ -254,36 +266,59 @@ xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt,
doc = cur->doc;
} else {
xsltTransformError(ctxt, NULL, ctxt->inst,
"Internal error in "
"xsltExtensionInstructionResultRegister(): "
"Internal error in xsltFlagRVTs(): "
"Cannot retrieve the doc of a namespace node.\n");
goto error;
return(-1);
}
} else {
doc = cur->doc;
}
if (doc == NULL) {
xsltTransformError(ctxt, NULL, ctxt->inst,
"Internal error in "
"xsltExtensionInstructionResultRegister(): "
"Internal error in xsltFlagRVTs(): "
"Cannot retrieve the doc of a node.\n");
goto error;
return(-1);
}
if (doc->name && (doc->name[0] == ' ')) {
if (doc->name && (doc->name[0] == ' ') &&
doc->psvi != XSLT_RVT_GLOBAL) {
/*
* This is a result tree fragment.
* We'll use the @psvi field for reference counting.
* TODO: How do we know if this is a value of a
* global variable or a doc acquired via the
* We store ownership information in the @psvi field.
* TODO: How do we know if this is a doc acquired via the
* document() function?
*/
doc->psvi = (void *) ((long) 1);
#ifdef WITH_XSLT_DEBUG_VARIABLE
XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
"Flagging RVT %p: %p -> %p\n", doc, doc->psvi, val));
#endif
if (val == XSLT_RVT_LOCAL) {
if (doc->psvi != XSLT_RVT_FUNC_RESULT) {
xmlGenericError(xmlGenericErrorContext,
"xsltFlagRVTs: Invalid transition %p => LOCAL\n",
doc->psvi);
return(-1);
}
xsltRegisterLocalRVT(ctxt, doc);
} else if (val == XSLT_RVT_GLOBAL) {
if (doc->psvi != XSLT_RVT_LOCAL) {
xmlGenericError(xmlGenericErrorContext,
"xsltFlagRVTs: Invalid transition %p => GLOBAL\n",
doc->psvi);
doc->psvi = XSLT_RVT_GLOBAL;
return(-1);
}
/* Will be registered as persistant in xsltReleaseLocalRVTs. */
doc->psvi = XSLT_RVT_GLOBAL;
} else if (val == XSLT_RVT_FUNC_RESULT) {
doc->psvi = val;
}
}
}
return(0);
error:
return(-1);
}
/**
@ -329,9 +364,9 @@ xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
}
/*
* Reset the reference counter.
* Reset the ownership information.
*/
RVT->psvi = 0;
RVT->psvi = NULL;
RVT->next = (xmlNodePtr) ctxt->cache->RVT;
ctxt->cache->RVT = RVT;
@ -370,6 +405,8 @@ xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
{
if ((ctxt == NULL) || (RVT == NULL)) return(-1);
RVT->psvi = XSLT_RVT_GLOBAL;
RVT->prev = NULL;
RVT->next = (xmlNodePtr) ctxt->persistRVT;
if (ctxt->persistRVT != NULL)
ctxt->persistRVT->prev = (xmlNodePtr) RVT;
@ -520,35 +557,21 @@ xsltFreeStackElem(xsltStackElemPtr elem) {
/*
* Release the list of temporary Result Tree Fragments.
*/
if (elem->fragment) {
if (elem->context) {
xmlDocPtr cur;
while (elem->fragment != NULL) {
cur = elem->fragment;
elem->fragment = (xmlDocPtr) cur->next;
if (elem->context &&
(cur->psvi == (void *) ((long) 1)))
{
/*
* This fragment is a result of an extension instruction
* (e.g. XSLT's function) and needs to be preserved until
* the instruction exits.
* Example: The fragment of the variable must not be freed
* since it is returned by the EXSLT function:
* <f:function name="foo">
* <xsl:variable name="bar">
* <bar/>
* </xsl:variable>
* <f:result select="$bar"/>
* </f:function>
*
*/
xsltRegisterLocalRVT(elem->context, cur);
} else {
if (cur->psvi == XSLT_RVT_VARIABLE) {
xsltReleaseRVT((xsltTransformContextPtr) elem->context,
cur);
}
} else if (cur->psvi != XSLT_RVT_FUNC_RESULT) {
xmlGenericError(xmlGenericErrorContext,
"xsltFreeStackElem: Unexpected RVT flag %p\n",
cur->psvi);
}
}
}
/*
@ -942,6 +965,7 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable,
* the Result Tree Fragment.
*/
variable->fragment = container;
container->psvi = XSLT_RVT_VARIABLE;
oldOutput = ctxt->output;
oldInsert = ctxt->insert;
@ -1128,16 +1152,23 @@ xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt)
xsltTransformError(ctxt, NULL, comp->inst,
"Evaluating global variable %s failed\n", elem->name);
ctxt->state = XSLT_STATE_STOPPED;
goto error;
}
/*
* Mark all RVTs that are referenced from result as part
* of this variable so they won't be freed too early.
*/
xsltFlagRVTs(ctxt, result, XSLT_RVT_GLOBAL);
#ifdef WITH_XSLT_DEBUG_VARIABLE
#ifdef LIBXML_DEBUG_ENABLED
} else {
if ((xsltGenericDebugContext == stdout) ||
(xsltGenericDebugContext == stderr))
xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
result, 0);
if ((xsltGenericDebugContext == stdout) ||
(xsltGenericDebugContext == stderr))
xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
result, 0);
#endif
#endif
}
} else {
if (elem->tree == NULL) {
result = xmlXPathNewCString("");
@ -1751,8 +1782,7 @@ xsltBuildVariable(xsltTransformContextPtr ctxt,
elem->tree = tree;
elem->value = xsltEvalVariable(ctxt, elem,
(xsltStylePreCompPtr) comp);
if (elem->value != NULL)
elem->computed = 1;
elem->computed = 1;
return(elem);
}

View file

@ -247,7 +247,7 @@ xsltIsBlank(xmlChar *str) {
* *
************************************************************************/
static xsltDecimalFormatPtr
xsltNewDecimalFormat(xmlChar *name)
xsltNewDecimalFormat(const xmlChar *nsUri, xmlChar *name)
{
xsltDecimalFormatPtr self;
/* UTF-8 for 0x2030 */
@ -256,6 +256,7 @@ xsltNewDecimalFormat(xmlChar *name)
self = xmlMalloc(sizeof(xsltDecimalFormat));
if (self != NULL) {
self->next = NULL;
self->nsUri = nsUri;
self->name = name;
/* Default values */
@ -341,7 +342,39 @@ xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name)
for (result = style->decimalFormat->next;
result != NULL;
result = result->next) {
if (xmlStrEqual(name, result->name))
if ((result->nsUri == NULL) && xmlStrEqual(name, result->name))
return result;
}
style = xsltNextImport(style);
}
return result;
}
/**
* xsltDecimalFormatGetByQName:
* @style: the XSLT stylesheet
* @nsUri: the namespace URI of the QName
* @name: the local part of the QName
*
* Find decimal-format by QName
*
* Returns the xsltDecimalFormatPtr
*/
xsltDecimalFormatPtr
xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri,
const xmlChar *name)
{
xsltDecimalFormatPtr result = NULL;
if (name == NULL)
return style->decimalFormat;
while (style != NULL) {
for (result = style->decimalFormat->next;
result != NULL;
result = result->next) {
if (xmlStrEqual(nsUri, result->nsUri) &&
xmlStrEqual(name, result->name))
return result;
}
style = xsltNextImport(style);
@ -719,7 +752,7 @@ xsltNewStylesheet(void) {
ret->omitXmlDeclaration = -1;
ret->standalone = -1;
ret->decimalFormat = xsltNewDecimalFormat(NULL);
ret->decimalFormat = xsltNewDecimalFormat(NULL, NULL);
ret->indent = -1;
ret->errors = 0;
ret->warnings = 0;
@ -782,9 +815,8 @@ xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
ctxt->extras = (xsltRuntimeExtraPtr)
xmlMalloc(ctxt->extrasMax * sizeof(xsltRuntimeExtra));
if (ctxt->extras == NULL) {
xmlGenericError(xmlGenericErrorContext,
xsltTransformError(ctxt, NULL, NULL,
"xsltAllocateExtraCtxt: out of memory\n");
ctxt->state = XSLT_STATE_ERROR;
return(0);
}
for (i = 0;i < ctxt->extrasMax;i++) {
@ -800,9 +832,8 @@ xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
tmp = (xsltRuntimeExtraPtr) xmlRealloc(ctxt->extras,
ctxt->extrasMax * sizeof(xsltRuntimeExtra));
if (tmp == NULL) {
xmlGenericError(xmlGenericErrorContext,
xsltTransformError(ctxt, NULL, NULL,
"xsltAllocateExtraCtxt: out of memory\n");
ctxt->state = XSLT_STATE_ERROR;
return(0);
}
ctxt->extras = tmp;
@ -1181,6 +1212,7 @@ xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
xsltTransformError(NULL, style, cur,
"invalid value for method: %s\n", prop);
if (style != NULL) style->warnings++;
xmlFree(prop);
}
} else {
style->method = prop;
@ -1358,18 +1390,37 @@ xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur)
prop = xmlGetNsProp(cur, BAD_CAST("name"), NULL);
if (prop != NULL) {
format = xsltDecimalFormatGetByName(style, prop);
const xmlChar *nsUri;
if (xmlValidateQName(prop, 0) != 0) {
xsltTransformError(NULL, style, cur,
"xsl:decimal-format: Invalid QName '%s'.\n", prop);
style->warnings++;
xmlFree(prop);
return;
}
/*
* TODO: Don't use xsltGetQNameURI().
*/
nsUri = xsltGetQNameURI(cur, &prop);
if (prop == NULL) {
style->warnings++;
return;
}
format = xsltDecimalFormatGetByQName(style, nsUri, prop);
if (format != NULL) {
xsltTransformError(NULL, style, cur,
"xsltParseStylestyleDecimalFormat: %s already exists\n", prop);
if (style != NULL) style->warnings++;
style->warnings++;
xmlFree(prop);
return;
}
format = xsltNewDecimalFormat(prop);
format = xsltNewDecimalFormat(nsUri, prop);
if (format == NULL) {
xsltTransformError(NULL, style, cur,
"xsltParseStylestyleDecimalFormat: failed creating new decimal-format\n");
if (style != NULL) style->errors++;
style->errors++;
xmlFree(prop);
return;
}
/* Append new decimal-format structure */
@ -3396,7 +3447,7 @@ internal_err:
#ifdef XSLT_REFACTORED
#else
static void
xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
xsltPreprocessStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
{
xmlNodePtr deleteNode, styleelem;
int internalize = 0;
@ -3427,7 +3478,7 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
if (deleteNode != NULL) {
#ifdef WITH_XSLT_DEBUG_BLANKS
xsltGenericDebug(xsltGenericDebugContext,
"xsltPrecomputeStylesheet: removing ignorable blank node\n");
"xsltPreprocessStylesheet: removing ignorable blank node\n");
#endif
xmlUnlinkNode(deleteNode);
xmlFreeNode(deleteNode);
@ -3467,7 +3518,6 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
}
if (IS_XSLT_ELEM(cur)) {
exclPrefixes = 0;
xsltStylePreCompute(style, cur);
if (IS_XSLT_NAME(cur, "text")) {
for (;exclPrefixes > 0;exclPrefixes--)
exclPrefixPop(style);
@ -3518,7 +3568,7 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
* going back
*/
if (exclPrefixes > 0) {
xsltPrecomputeStylesheet(style, cur->children);
xsltPreprocessStylesheet(style, cur->children);
for (;exclPrefixes > 0;exclPrefixes--)
exclPrefixPop(style);
goto skip_children;
@ -3589,7 +3639,7 @@ skip_children:
if (deleteNode != NULL) {
#ifdef WITH_XSLT_DEBUG_PARSING
xsltGenericDebug(xsltGenericDebugContext,
"xsltPrecomputeStylesheet: removing ignorable blank node\n");
"xsltPreprocessStylesheet: removing ignorable blank node\n");
#endif
xmlUnlinkNode(deleteNode);
xmlFreeNode(deleteNode);
@ -4834,10 +4884,12 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
delete = NULL;
}
if (IS_XSLT_ELEM(cur)) {
xsltStylePreCompute(style, cur);
if (IS_XSLT_NAME(cur, "text")) {
/*
* TODO: Processing of xsl:text should be moved to
* xsltPrecomputeStylesheet(), since otherwise this
* xsltPreprocessStylesheet(), since otherwise this
* will be performed for every multiply included
* stylesheet; i.e. this here is not skipped with
* the use of the style->nopreproc flag.
@ -5367,6 +5419,7 @@ xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
xsltTransformError(NULL, style, template,
"xsl:template : error invalid name '%s'\n", prop);
if (style != NULL) style->errors++;
xmlFree(prop);
goto error;
}
ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1);
@ -6026,7 +6079,7 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
(!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
xsltTransformError(NULL, style, top,
"xsl:version: only 1.0 features are supported\n");
"xsl:version: only 1.1 features are supported\n");
if (style != NULL) {
style->forwards_compatible = 1;
style->warnings++;
@ -6097,31 +6150,31 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
xsltTransformError(NULL, style, cur,
"xsltParseStylesheetTop: ignoring misplaced import element\n");
if (style != NULL) style->errors++;
} else if (IS_XSLT_NAME(cur, "include")) {
} else if (IS_XSLT_NAME(cur, "include")) {
if (xsltParseStylesheetInclude(style, cur) != 0)
if (style != NULL) style->errors++;
} else if (IS_XSLT_NAME(cur, "strip-space")) {
} else if (IS_XSLT_NAME(cur, "strip-space")) {
xsltParseStylesheetStripSpace(style, cur);
} else if (IS_XSLT_NAME(cur, "preserve-space")) {
} else if (IS_XSLT_NAME(cur, "preserve-space")) {
xsltParseStylesheetPreserveSpace(style, cur);
} else if (IS_XSLT_NAME(cur, "output")) {
} else if (IS_XSLT_NAME(cur, "output")) {
xsltParseStylesheetOutput(style, cur);
} else if (IS_XSLT_NAME(cur, "key")) {
} else if (IS_XSLT_NAME(cur, "key")) {
xsltParseStylesheetKey(style, cur);
} else if (IS_XSLT_NAME(cur, "decimal-format")) {
} else if (IS_XSLT_NAME(cur, "decimal-format")) {
xsltParseStylesheetDecimalFormat(style, cur);
} else if (IS_XSLT_NAME(cur, "attribute-set")) {
} else if (IS_XSLT_NAME(cur, "attribute-set")) {
xsltParseStylesheetAttributeSet(style, cur);
} else if (IS_XSLT_NAME(cur, "variable")) {
} else if (IS_XSLT_NAME(cur, "variable")) {
xsltParseGlobalVariable(style, cur);
} else if (IS_XSLT_NAME(cur, "param")) {
} else if (IS_XSLT_NAME(cur, "param")) {
xsltParseGlobalParam(style, cur);
} else if (IS_XSLT_NAME(cur, "template")) {
} else if (IS_XSLT_NAME(cur, "template")) {
#ifdef WITH_XSLT_DEBUG_PARSING
templates++;
#endif
xsltParseStylesheetTemplate(style, cur);
} else if (IS_XSLT_NAME(cur, "namespace-alias")) {
} else if (IS_XSLT_NAME(cur, "namespace-alias")) {
xsltNamespaceAlias(style, cur);
} else {
if ((style != NULL) && (style->forwards_compatible == 0)) {
@ -6130,13 +6183,6 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
cur->name);
if (style != NULL) style->errors++;
}
else {
/* do Forwards-Compatible Processing */
xsltTransformError(NULL, style, cur,
"xsltParseStylesheetTop: ignoring unknown %s element\n",
cur->name);
if (style != NULL) style->warnings++;
}
}
cur = cur->next;
}
@ -6380,7 +6426,7 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
ret->literal_result = 1;
}
if (!ret->nopreproc) {
xsltPrecomputeStylesheet(ret, cur);
xsltPreprocessStylesheet(ret, cur);
}
if (ret->literal_result == 0) {
xsltParseStylesheetTop(ret, cur);
@ -6403,10 +6449,11 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
"xsltParseStylesheetProcess : document is stylesheet\n");
#endif
if (!xmlStrEqual(prop, (const xmlChar *)"1.0")) {
if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
(!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
xsltTransformError(NULL, ret, cur,
"xsl:version: only 1.0 features are supported\n");
/* TODO set up compatibility when not XSLT 1.0 */
"xsl:version: only 1.1 features are supported\n");
ret->forwards_compatible = 1;
ret->warnings++;
}
xmlFree(prop);

View file

@ -123,19 +123,6 @@ extern "C" {
#define LIBXSLT_DEFAULT_PLUGINS_PATH() "@LIBXSLT_DEFAULT_PLUGINS_PATH@"
#endif
/**
* Locale support
*/
#if @XSLT_LOCALE_XLOCALE@
#ifndef XSLT_LOCALE_XLOCALE
#define XSLT_LOCALE_XLOCALE
#endif
#elif @XSLT_LOCALE_WINAPI@
#ifndef XSLT_LOCALE_WINAPI
#define XSLT_LOCALE_WINAPI
#endif
#endif
/**
* ATTRIBUTE_UNUSED:
*

View file

@ -14,13 +14,6 @@
#include "xsltlocale.h"
#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2
#define newlocale __newlocale
#define freelocale __freelocale
#define strxfrm_l __strxfrm_l
#define LC_COLLATE_MASK (1 << LC_COLLATE)
#endif
#define TOUPPER(c) (c & ~0x20)
#define TOLOWER(c) (c | 0x20)
#define ISALPHA(c) ((unsigned)(TOUPPER(c) - 'A') < 26)
@ -87,7 +80,7 @@ xsltFreeLocales(void) {
*/
xsltLocale
xsltNewLocale(const xmlChar *languageTag) {
#ifdef XSLT_LOCALE_XLOCALE
#ifdef XSLT_LOCALE_POSIX
xsltLocale locale;
char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */
const xmlChar *p = languageTag;
@ -189,7 +182,7 @@ xsltNewLocale(const xmlChar *languageTag) {
region = xsltDefaultRegion(localeName);
if (region == NULL) goto end;
strcpy(localeName + llen + 1, region);
strcpy((char *) localeName + llen + 1, (char *) region);
locale = xslt_locale_WINAPI(localeName);
end:
return(locale);
@ -347,7 +340,7 @@ xsltDefaultRegion(const xmlChar *localeName) {
*/
void
xsltFreeLocale(xsltLocale locale) {
#ifdef XSLT_LOCALE_XLOCALE
#ifdef XSLT_LOCALE_POSIX
freelocale(locale);
#endif
}
@ -371,7 +364,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string)
size_t xstrlen, r;
xsltLocaleChar *xstr;
#ifdef XSLT_LOCALE_XLOCALE
#ifdef XSLT_LOCALE_POSIX
xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1;
xstr = (xsltLocaleChar *) xmlMalloc(xstrlen);
if (xstr == NULL) {
@ -384,7 +377,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string)
#endif
#ifdef XSLT_LOCALE_WINAPI
xstrlen = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
xstrlen = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, NULL, 0);
if (xstrlen == 0) {
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
return(NULL);
@ -394,7 +387,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string)
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
return(NULL);
}
r = MultiByteToWideChar(CP_UTF8, 0, string, -1, xstr, xstrlen);
r = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, xstr, xstrlen);
if (r == 0) {
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
xmlFree(xstr);
@ -481,9 +474,11 @@ xsltIterateSupportedLocales(LPSTR lcid) {
k = sscanf(lcid, "%lx", (long*)&p->lcid);
if (k < 1) goto end;
/*don't count terminating null character*/
k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME , iso639lang , sizeof(iso639lang ));
k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME,
(char *) iso639lang, sizeof(iso639lang));
if (--k < 1) goto end;
l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME, iso3136ctry, sizeof(iso3136ctry));
l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME,
(char *) iso3136ctry, sizeof(iso3136ctry));
if (--l < 1) goto end;
{ /*fill results*/

View file

@ -18,16 +18,9 @@
#include <unistd.h>
#endif
/* gettimeofday on Windows ??? */
#if defined(WIN32) && !defined(__CYGWIN__)
#ifdef _MSC_VER
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define gettimeofday(p1,p2)
#define HAVE_GETTIMEOFDAY
#if defined(_WIN32) && !defined(__CYGWIN__)
#define XSLT_WIN32_PERFORMANCE_COUNTER
#endif /* _MS_VER */
#endif /* WIN32 */
#endif
/************************************************************************
* *
@ -433,9 +426,8 @@ xsltMessage(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst) {
} else if (xmlStrEqual(prop, (const xmlChar *)"no")) {
terminate = 0;
} else {
error(errctx,
xsltTransformError(ctxt, NULL, inst,
"xsl:message : terminate expecting 'yes' or 'no'\n");
ctxt->state = XSLT_STATE_ERROR;
}
xmlFree(prop);
}
@ -598,7 +590,8 @@ xsltPrintErrorContext(xsltTransformContextPtr ctxt,
void *errctx = xsltGenericErrorContext;
if (ctxt != NULL) {
ctxt->state = XSLT_STATE_ERROR;
if (ctxt->state == XSLT_STATE_OK)
ctxt->state = XSLT_STATE_ERROR;
if (ctxt->error != NULL) {
error = ctxt->error;
errctx = ctxt->errctx;
@ -691,7 +684,8 @@ xsltTransformError(xsltTransformContextPtr ctxt,
char * str;
if (ctxt != NULL) {
ctxt->state = XSLT_STATE_ERROR;
if (ctxt->state == XSLT_STATE_OK)
ctxt->state = XSLT_STATE_ERROR;
if (ctxt->error != NULL) {
error = ctxt->error;
errctx = ctxt->errctx;
@ -1224,6 +1218,8 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
if (res[j] == NULL) {
if (res[j+incr] != NULL)
tst = 1;
} else if (res[j+incr] == NULL) {
tst = -1;
} else {
if (numb) {
/* We make NaN smaller than number in
@ -1784,6 +1780,8 @@ static long calibration = -1;
*
* Returns the number of milliseconds used by xsltTimestamp()
*/
#if !defined(XSLT_WIN32_PERFORMANCE_COUNTER) && \
(defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETTIMEOFDAY))
static long
xsltCalibrateTimestamps(void) {
register int i;
@ -1792,6 +1790,7 @@ xsltCalibrateTimestamps(void) {
xsltTimestamp();
return(xsltTimestamp() / 1000);
}
#endif
/**
* xsltCalibrateAdjust:

View file

@ -23,21 +23,21 @@ extern "C" {
*
* the version string like "1.2.3"
*/
#define LIBXSLT_DOTTED_VERSION "1.1.28"
#define LIBXSLT_DOTTED_VERSION "1.1.32"
/**
* LIBXSLT_VERSION:
*
* the version number: 1.2.3 value is 1002003
*/
#define LIBXSLT_VERSION 10128
#define LIBXSLT_VERSION 10132
/**
* LIBXSLT_VERSION_STRING:
*
* the version number string, 1.2.3 value is "1002003"
*/
#define LIBXSLT_VERSION_STRING "10128"
#define LIBXSLT_VERSION_STRING "10132"
/**
* LIBXSLT_VERSION_EXTRA:
@ -53,7 +53,7 @@ extern "C" {
* is insignifiant and being able to run xsltpoc -v is useful. On
* by default
*/
#if 0
#if 1
#define WITH_XSLT_DEBUG
#endif
@ -62,7 +62,7 @@ extern "C" {
*
* Whether module support is configured into libxslt
*/
#if 0
#if 1
#ifndef WITH_MODULES
#define WITH_MODULES
#endif

View file

@ -10,7 +10,7 @@
#ifndef __XSLT_LIBXSLT_H__
#define __XSLT_LIBXSLT_H__
#if defined(WIN32) && !defined (__CYGWIN__) && !defined (__MINGW32__)
#if defined(_WIN32) && !defined (__CYGWIN__) && !defined (__MINGW32__)
#include <win32config.h>
#else
#include "config.h"

View file

@ -34,6 +34,41 @@ extern "C" {
xsltRegisterAllElement(ctxt); \
(ctxt)->xpathCtxt->extra = ctxt
/*
* Flags for memory management of RVTs
*/
/**
* XSLT_RVT_LOCAL:
*
* RVT is destroyed after the current instructions ends.
*/
#define XSLT_RVT_LOCAL ((void *)1)
/**
* XSLT_RVT_VARIABLE:
*
* RVT is part of a local variable and destroyed after the variable goes out
* of scope.
*/
#define XSLT_RVT_VARIABLE ((void *)2)
/**
* XSLT_RVT_FUNC_RESULT:
*
* RVT is part of results returned with func:result. The RVT won't be
* destroyed after exiting a template and will be reset to XSLT_RVT_LOCAL or
* XSLT_RVT_VARIABLE in the template that receives the return value.
*/
#define XSLT_RVT_FUNC_RESULT ((void *)3)
/**
* XSLT_RVT_GLOBAL:
*
* RVT is part of a global variable.
*/
#define XSLT_RVT_GLOBAL ((void *)4)
/*
* Interfaces for the variable module.
*/

View file

@ -324,6 +324,7 @@ struct _xsltDecimalFormat {
xmlChar *percent;
xmlChar *permille;
xmlChar *zeroDigit;
const xmlChar *nsUri;
};
/**
@ -1754,8 +1755,8 @@ struct _xsltTransformContext {
* Speed optimization when coalescing text nodes
*/
const xmlChar *lasttext; /* last text node content */
unsigned int lasttsize; /* last text node size */
unsigned int lasttuse; /* last text node use */
int lasttsize; /* last text node size */
int lasttuse; /* last text node use */
/*
* Per Context Debugging
*/
@ -1783,9 +1784,9 @@ struct _xsltTransformContext {
xmlDocPtr localRVT; /* list of local tree fragments; will be freed when
the instruction which created the fragment
exits */
xmlDocPtr localRVTBase;
xmlDocPtr localRVTBase; /* Obsolete */
int keyInitLevel; /* Needed to catch recursive keys issues */
int funcLevel; /* Needed to catch recursive functions issues */
int depth; /* Needed to catch recursions */
int maxTemplateDepth;
int maxTemplateVars;
};
@ -1854,6 +1855,10 @@ XSLTPUBFUN void XSLTCALL
XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL
xsltDecimalFormatGetByName(xsltStylesheetPtr style,
xmlChar *name);
XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL
xsltDecimalFormatGetByQName(xsltStylesheetPtr style,
const xmlChar *nsUri,
const xmlChar *name);
XSLTPUBFUN xsltStylesheetPtr XSLTCALL
xsltParseStylesheetProcess(xsltStylesheetPtr ret,
@ -1906,6 +1911,11 @@ XSLTPUBFUN int XSLTCALL
XSLTPUBFUN int XSLTCALL
xsltExtensionInstructionResultFinalize(
xsltTransformContextPtr ctxt);
XSLTPUBFUN int XSLTCALL
xsltFlagRVTs(
xsltTransformContextPtr ctxt,
xmlXPathObjectPtr obj,
void *val);
XSLTPUBFUN void XSLTCALL
xsltFreeRVTs (xsltTransformContextPtr ctxt);
XSLTPUBFUN void XSLTCALL

View file

@ -20,21 +20,21 @@ extern "C" {
*
* the version string like "1.2.3"
*/
#define LIBXSLT_DOTTED_VERSION "1.1.29"
#define LIBXSLT_DOTTED_VERSION "1.1.32"
/**
* LIBXSLT_VERSION:
*
* the version number: 1.2.3 value is 10203
*/
#define LIBXSLT_VERSION 10129
#define LIBXSLT_VERSION 10132
/**
* LIBXSLT_VERSION_STRING:
*
* the version number string, 1.2.3 value is "10203"
*/
#define LIBXSLT_VERSION_STRING "10129"
#define LIBXSLT_VERSION_STRING "10132"
/**
* LIBXSLT_VERSION_EXTRA:
@ -123,19 +123,6 @@ extern "C" {
#define LIBXSLT_DEFAULT_PLUGINS_PATH() "/usr/lib/libxslt-plugins"
#endif
/**
* Locale support
*/
#if 0
#ifndef XSLT_LOCALE_XLOCALE
#define XSLT_LOCALE_XLOCALE
#endif
#elif 1
#ifndef XSLT_LOCALE_WINAPI
#define XSLT_LOCALE_WINAPI
#endif
#endif
/**
* ATTRIBUTE_UNUSED:
*

View file

@ -14,20 +14,31 @@
#include <libxml/xmlstring.h>
#include "xsltexports.h"
#ifdef XSLT_LOCALE_XLOCALE
#ifdef HAVE_STRXFRM_L
/*
* XSLT_LOCALE_POSIX:
* Macro indicating to use POSIX locale extensions
*/
#define XSLT_LOCALE_POSIX
#ifdef HAVE_LOCALE_H
#include <locale.h>
#include <xlocale.h>
#ifdef __GLIBC__
/*locale_t is defined only if _GNU_SOURCE is defined*/
typedef __locale_t xsltLocale;
#else
typedef locale_t xsltLocale;
#endif
#ifdef HAVE_XLOCALE_H
#include <xlocale.h>
#endif
typedef locale_t xsltLocale;
typedef xmlChar xsltLocaleChar;
#elif defined(XSLT_LOCALE_WINAPI)
#elif defined(_WIN32) && !defined(__CYGWIN__)
/*
* XSLT_LOCALE_WINAPI:
* Macro indicating to use WinAPI for extended locale support
*/
#define XSLT_LOCALE_WINAPI
#ifdef __REACTOS__
#define WIN32_NO_STATUS
@ -45,11 +56,9 @@ typedef wchar_t xsltLocaleChar;
/*
* XSLT_LOCALE_NONE:
* Macro indicating that locale are not supported
* Macro indicating that there's no extended locale support
*/
#ifndef XSLT_LOCALE_NONE
#define XSLT_LOCALE_NONE
#endif
typedef void *xsltLocale;
typedef xmlChar xsltLocaleChar;