/** * xsltAddAttrElemList: * @list: an XSLT AttrElem list * @attr: the new xsl:attribute node * * Add the new attribute to the list. * * Returns the new list pointer */ static xsltAttrElemPtr xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) { xsltAttrElemPtr next, cur; if (attr == NULL) return(list); if (list == NULL) return(xsltNewAttrElem(attr)); cur = list; while (cur != NULL) { next = cur->next; if (next == NULL) { cur->next = xsltNewAttrElem(attr); return(list); } cur = next; } return(list); }
/** * 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) { /* * Check that the attribute is not yet in the list */ cur = set->attrs; add = 1; while (cur != NULL) { 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) { if (cur == NULL) { set->attrs = xsltNewAttrElem(old->attr); } else if (add) { cur->next = xsltNewAttrElem(old->attr); } } old = old->next; } }
void xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) { const xmlChar *ncname; const xmlChar *prefix; xmlChar *value; xmlNodePtr child; xsltAttrElemPtr attrItems; if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE)) return; value = xmlGetNsProp(cur, (const xmlChar *)"name", NULL); if ((value == NULL) || (*value == 0)) { xsltGenericError(xsltGenericErrorContext, "xsl:attribute-set : name is missing\n"); if (value) xmlFree(value); return; } ncname = xsltSplitQName(style->dict, value, &prefix); xmlFree(value); value = NULL; if (style->attributeSets == NULL) { #ifdef WITH_XSLT_DEBUG_ATTRIBUTES xsltGenericDebug(xsltGenericDebugContext, "creating attribute set table\n"); #endif style->attributeSets = xmlHashCreate(10); } if (style->attributeSets == NULL) return; attrItems = xmlHashLookup2(style->attributeSets, ncname, prefix); /* * Parse the content. Only xsl:attribute elements are allowed. */ child = cur->children; while (child != NULL) { /* * Report invalid nodes. */ if ((child->type != XML_ELEMENT_NODE) || (child->ns == NULL) || (! IS_XSLT_ELEM(child))) { if (child->type == XML_ELEMENT_NODE) xsltTransformError(NULL, style, child, "xsl:attribute-set : unexpected child %s\n", child->name); else xsltTransformError(NULL, style, child, "xsl:attribute-set : child of unexpected type\n"); } else if (!IS_XSLT_NAME(child, "attribute")) { xsltTransformError(NULL, style, child, "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); #else #ifdef WITH_XSLT_DEBUG_ATTRIBUTES xsltGenericDebug(xsltGenericDebugContext, "add attribute to list %s\n", ncname); #endif /* * OLD behaviour: */ attrItems = xsltAddAttrElemList(attrItems, child); #endif } #ifdef XSLT_REFACTORED next_child: #endif child = child->next; } /* * Process attribue "use-attribute-sets". */ /* TODO check recursion */ value = xmlGetNsProp(cur, (const xmlChar *)"use-attribute-sets", NULL); if (value != NULL) { const xmlChar *curval, *endval; curval = value; while (*curval != 0) { while (IS_BLANK(*curval)) curval++; if (*curval == 0) break; endval = curval; while ((*endval != 0) && (!IS_BLANK(*endval))) endval++; curval = xmlDictLookup(style->dict, curval, endval - curval); if (curval) { const xmlChar *ncname2 = NULL; const xmlChar *prefix2 = NULL; xsltAttrElemPtr refAttrItems; #ifdef WITH_XSLT_DEBUG_ATTRIBUTES xsltGenericDebug(xsltGenericDebugContext, "xsl:attribute-set : %s adds use %s\n", ncname, curval); #endif 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); } } curval = endval; } xmlFree(value); 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); #endif }
/** * xsltMergeAttrElemList: * @list: an XSLT AttrElem list * @old: another XSLT AttrElem list * * Add all the attributes from list @old to list @list, * but drop redefinition of existing values. * * Returns the new list pointer */ static xsltAttrElemPtr xsltMergeAttrElemList(xsltStylesheetPtr style, xsltAttrElemPtr list, xsltAttrElemPtr old) { xsltAttrElemPtr cur; 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; 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); } 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); } } 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); }