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 }
/** * xsltNamespaceAlias: * @style: the XSLT stylesheet * @node: the xsl:namespace-alias node * * Read the stylesheet-prefix and result-prefix attributes, register * them as well as the corresponding namespace. */ void xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node) { xmlChar *resultPrefix = NULL; xmlChar *stylePrefix = NULL; xmlNsPtr literalNs = NULL; xmlNsPtr targetNs = NULL; #ifdef XSLT_REFACTORED xsltNsAliasPtr alias; if ((style == NULL) || (node == NULL)) return; /* * SPEC XSLT 1.0: * "If a namespace URI is declared to be an alias for multiple * different namespace URIs, then the declaration with the highest * import precedence is used. It is an error if there is more than * one such declaration. An XSLT processor may signal the error; * if it does not signal the error, it must recover by choosing, * from amongst the declarations with the highest import precedence, * the one that occurs last in the stylesheet." * * SPEC TODO: Check for the errors mentioned above. */ /* * NOTE that the XSLT 2.0 also *does* use the NULL namespace if * "#default" is used and there's no default namespace is scope. * I.e., this is *not* an error. * Most XSLT 1.0 implementations work this way. * The XSLT 1.0 spec has nothing to say on the subject. */ /* * Attribute "stylesheet-prefix". */ stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL); if (stylePrefix == NULL) { xsltTransformError(NULL, style, node, "The attribute 'stylesheet-prefix' is missing.\n"); return; } if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default")) literalNs = xmlSearchNs(node->doc, node, NULL); else { literalNs = xmlSearchNs(node->doc, node, stylePrefix); if (literalNs == NULL) { xsltTransformError(NULL, style, node, "Attribute 'stylesheet-prefix': There's no namespace " "declaration in scope for the prefix '%s'.\n", stylePrefix); goto error; } } /* * Attribute "result-prefix". */ resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL); if (resultPrefix == NULL) { xsltTransformError(NULL, style, node, "The attribute 'result-prefix' is missing.\n"); goto error; } if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default")) targetNs = xmlSearchNs(node->doc, node, NULL); else { targetNs = xmlSearchNs(node->doc, node, resultPrefix); if (targetNs == NULL) { xsltTransformError(NULL, style, node, "Attribute 'result-prefix': There's no namespace " "declaration in scope for the prefix '%s'.\n", stylePrefix); goto error; } } /* * * Same alias for multiple different target namespace URIs: * TODO: The one with the highest import precedence is used. * Example: * <xsl:namespace-alias stylesheet-prefix="foo" * result-prefix="bar"/> * * <xsl:namespace-alias stylesheet-prefix="foo" * result-prefix="zar"/> * * Same target namespace URI for multiple different aliases: * All alias-definitions will be used. * Example: * <xsl:namespace-alias stylesheet-prefix="bar" * result-prefix="foo"/> * * <xsl:namespace-alias stylesheet-prefix="zar" * result-prefix="foo"/> * Cases using #default: * <xsl:namespace-alias stylesheet-prefix="#default" * result-prefix="#default"/> * TODO: Has this an effect at all? * * <xsl:namespace-alias stylesheet-prefix="foo" * result-prefix="#default"/> * From namespace to no namespace. * * <xsl:namespace-alias stylesheet-prefix="#default" * result-prefix="foo"/> * From no namespace to namespace. */ /* * Store the ns-node in the alias-object. */ alias = xsltNewNsAlias(XSLT_CCTXT(style)); if (alias == NULL) return; alias->literalNs = literalNs; alias->targetNs = targetNs; XSLT_CCTXT(style)->hasNsAliases = 1; #else /* XSLT_REFACTORED */ const xmlChar *literalNsName; const xmlChar *targetNsName; if ((style == NULL) || (node == NULL)) return; stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL); if (stylePrefix == NULL) { xsltTransformError(NULL, style, node, "namespace-alias: stylesheet-prefix attribute missing\n"); return; } resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL); if (resultPrefix == NULL) { xsltTransformError(NULL, style, node, "namespace-alias: result-prefix attribute missing\n"); goto error; } if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default")) { literalNs = xmlSearchNs(node->doc, node, NULL); if (literalNs == NULL) { literalNsName = NULL; } else literalNsName = literalNs->href; /* Yes - set for nsAlias table */ } else { literalNs = xmlSearchNs(node->doc, node, stylePrefix); if ((literalNs == NULL) || (literalNs->href == NULL)) { xsltTransformError(NULL, style, node, "namespace-alias: prefix %s not bound to any namespace\n", stylePrefix); goto error; } else literalNsName = literalNs->href; } /* * When "#default" is used for result, if a default namespace has not * been explicitly declared the special value UNDEFINED_DEFAULT_NS is * put into the nsAliases table */ if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default")) { targetNs = xmlSearchNs(node->doc, node, NULL); if (targetNs == NULL) { targetNsName = UNDEFINED_DEFAULT_NS; } else targetNsName = targetNs->href; } else { targetNs = xmlSearchNs(node->doc, node, resultPrefix); if ((targetNs == NULL) || (targetNs->href == NULL)) { xsltTransformError(NULL, style, node, "namespace-alias: prefix %s not bound to any namespace\n", resultPrefix); goto error; } else targetNsName = targetNs->href; } /* * Special case: if #default is used for * the stylesheet-prefix (literal namespace) and there's no default * namespace in scope, we'll use style->defaultAlias for this. */ if (literalNsName == NULL) { if (targetNs != NULL) { /* * BUG TODO: Is it not sufficient to have only 1 field for * this, since subsequently alias declarations will * overwrite this. * Example: * <xsl:namespace-alias result-prefix="foo" * stylesheet-prefix="#default"/> * <xsl:namespace-alias result-prefix="bar" * stylesheet-prefix="#default"/> * The mapping for "foo" won't be visible anymore. */ style->defaultAlias = targetNs->href; } } else { if (style->nsAliases == NULL) style->nsAliases = xmlHashCreate(10); if (style->nsAliases == NULL) { xsltTransformError(NULL, style, node, "namespace-alias: cannot create hash table\n"); goto error; } xmlHashAddEntry((xmlHashTablePtr) style->nsAliases, literalNsName, (void *) targetNsName); } #endif /* else of XSLT_REFACTORED */ error: if (stylePrefix != NULL) xmlFree(stylePrefix); if (resultPrefix != NULL) xmlFree(resultPrefix); }
void xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) { const xmlChar *ncname; const xmlChar *prefix; const xmlChar *nsUri = NULL; xmlChar *value; xmlNodePtr child; xsltAttrSetPtr set; 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; } 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 xsltGenericDebug(xsltGenericDebugContext, "creating attribute set table\n"); #endif style->attributeSets = xmlHashCreate(10); } if (style->attributeSets == NULL) return; 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. */ 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 WITH_XSLT_DEBUG_ATTRIBUTES xsltGenericDebug(xsltGenericDebugContext, "add attribute to list %s\n", ncname); #endif xsltStylePreCompute(style, child); if (child->children != NULL) { #ifdef XSLT_REFACTORED xsltParseSequenceConstructor(XSLT_CCTXT(style), child->children); #else 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); } } child = child->next; } /* * Process attribute "use-attribute-sets". */ value = xmlGetNsProp(cur, BAD_CAST "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; 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); 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; } xmlFree(value); value = NULL; } #ifdef WITH_XSLT_DEBUG_ATTRIBUTES xsltGenericDebug(xsltGenericDebugContext, "updated attribute list %s\n", ncname); #endif }