Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Unified Diff: third_party/libxslt/libxslt/attributes.c

Issue 2411263002: Roll libxslt to 8345634c5482ca04293ae1862d52fa9dd764aeca (Closed)
Patch Set: config.log Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/libxslt/libxslt.spec.in ('k') | third_party/libxslt/libxslt/numbers.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/libxslt/libxslt/attributes.c
diff --git a/third_party/libxslt/libxslt/attributes.c b/third_party/libxslt/libxslt/attributes.c
index 8440b1031592ab61ddbf2bda003a4e2428ae41fb..9165ab13781948ac3dadd066ccfd2a0343021dca 100644
--- a/third_party/libxslt/libxslt/attributes.c
+++ b/third_party/libxslt/libxslt/attributes.c
@@ -55,14 +55,6 @@
#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
*/
#ifdef IS_BLANK
@@ -75,6 +67,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
@@ -87,10 +83,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 *
@@ -148,11 +170,6 @@ xsltFreeAttrElemList(xsltAttrElemPtr list) {
}
}
-#ifdef XSLT_REFACTORED
- /*
- * This was moved to xsltParseStylesheetAttributeSet().
- */
-#else
/**
* xsltAddAttrElemList:
* @list: an XSLT AttrElem list
@@ -173,9 +190,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);
}
@@ -183,92 +198,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);
}
/************************************************************************
@@ -289,9 +386,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;
@@ -305,9 +403,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
@@ -319,7 +437,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.
@@ -345,71 +469,36 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
"xsl:attribute-set : unexpected child xsl:%s\n",
child->name);
} else {
-#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);
+ xsltStylePreCompute(style, child);
+ if (child->children != NULL) {
+#ifdef XSLT_REFACTORED
+ 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;
@@ -423,21 +512,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;
}
@@ -445,15 +551,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);
@@ -461,143 +558,141 @@ next_child:
}
/**
- * xsltGetSAS:
- * @style: the XSLT stylesheet
- * @name: the attribute list name
- * @ns: the attribute list namespace
- *
- * lookup an attribute set based on the style cascade
+ * xsltResolveUseAttrSets:
+ * @set: the attribute set
+ * @asctx: the context for attribute set resolution
+ * @depth: recursion depth
*
- * Returns the attribute set or NULL
+ * Process "use-attribute-sets".
*/
-static xsltAttrElemPtr
-xsltGetSAS(xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns) {
- xsltAttrElemPtr values;
-
- while (style != NULL) {
- values = xmlHashLookup2(style->attributeSets, name, ns);
- if (values != NULL)
- return(values);
- style = xsltNextImport(style);
+static void
+xsltResolveUseAttrSets(xsltAttrSetPtr set, xsltStylesheetPtr topStyle,
+ int depth) {
+ xsltStylesheetPtr cur;
+ xsltAttrSetPtr other;
+ xsltUseAttrSetPtr use = set->useAttrSets;
+ xsltUseAttrSetPtr next;
+
+ 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 {
+
+ 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,
- "Importing attribute list %s\n", tmp->set);
+ 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);
+ }
+ }
- 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;
+ 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);
+ }
}
}
@@ -610,15 +705,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) {
@@ -628,43 +722,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
* @inst: the xsl:attribute element
* @comp: precomputed information
- * @fromAttributeSet: the attribute comes from an attribute-set
*
* 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 =
@@ -704,7 +792,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;
}
@@ -869,19 +957,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.
*/
@@ -1032,21 +1107,6 @@ error:
}
/**
- * 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
* @node: the node in the source tree.
@@ -1066,7 +1126,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) {
@@ -1103,15 +1163,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;
@@ -1120,27 +1197,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;
@@ -1157,6 +1235,6 @@ void
xsltFreeAttributeSetsHashes(xsltStylesheetPtr style) {
if (style->attributeSets != NULL)
xmlHashFree((xmlHashTablePtr) style->attributeSets,
- (xmlHashDeallocator) xsltFreeAttrElemList);
+ (xmlHashDeallocator) xsltFreeAttrSet);
style->attributeSets = NULL;
}
« no previous file with comments | « third_party/libxslt/libxslt.spec.in ('k') | third_party/libxslt/libxslt/numbers.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698