15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * attributes.c: Implementation of the XSLT attributes handling
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Reference:
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   http://www.w3.org/TR/1999/REC-xslt-19991116
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See Copyright for the status of this software.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * daniel@veillard.com
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IN_LIBXSLT
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "libxslt.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_TYPES_H
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_MATH_H
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_FLOAT_H
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <float.h>
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_IEEEFP_H
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ieeefp.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_NAN_H
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nan.h>
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_CTYPE_H
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h>
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xmlmemory.h>
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/tree.h>
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/hash.h>
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xmlerror.h>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/uri.h>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/parserInternals.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xslt.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xsltInternals.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xsltutils.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "attributes.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "namespaces.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "templates.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "imports.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "transform.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "preproc.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WITH_XSLT_DEBUG_ATTRIBUTES
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WITH_XSLT_DEBUG_ATTRIBUTES
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * TODO: merge attribute sets from different import precedence.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *       all this should be precomputed just before the transformation
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *       starts or at first hit with a cache in the context.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *       The simple way for now would be to not allow redefinition of
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *       attributes once generated in the output tree, possibly costlier.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Useful macros
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef IS_BLANK
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef IS_BLANK
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) ||	\
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     ((c) == 0x0D))
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IS_BLANK_NODE(n)						\
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The in-memory structure corresponding to an XSLT Attribute in
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * an attribute set
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct _xsltAttrElem xsltAttrElem;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef xsltAttrElem *xsltAttrElemPtr;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct _xsltAttrElem {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct _xsltAttrElem *next;/* chained list */
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlNodePtr attr;	/* the xsl:attribute definition */
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *set; /* or the attribute set */
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ns;  /* and its namespace */
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/************************************************************************
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *									*
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *			XSLT Attribute handling				*
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *									*
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ************************************************************************/
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltNewAttrElem:
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @attr:  the new xsl:attribute node
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create a new XSLT AttrElem
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the newly allocated xsltAttrElemPtr or NULL in case of error
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xsltAttrElemPtr
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltNewAttrElem(xmlNodePtr attr) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttrElemPtr cur;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur = (xsltAttrElemPtr) xmlMalloc(sizeof(xsltAttrElem));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cur == NULL) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltGenericError(xsltGenericErrorContext,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"xsltNewAttrElem : malloc failed\n");
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(cur, 0, sizeof(xsltAttrElem));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur->attr = attr;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(cur);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltFreeAttrElem:
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @attr:  an XSLT AttrElem
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Free up the memory allocated by @attr
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltFreeAttrElem(xsltAttrElemPtr attr) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(attr);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltFreeAttrElemList:
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @list:  an XSLT AttrElem list
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Free up the memory allocated by @list
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltFreeAttrElemList(xsltAttrElemPtr list) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttrElemPtr next;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (list != NULL) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	next = list->next;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltFreeAttrElem(list);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	list = next;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_REFACTORED
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * This was moved to xsltParseStylesheetAttributeSet().
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltAddAttrElemList:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @list:  an XSLT AttrElem list
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @attr:  the new xsl:attribute node
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add the new attribute to the list.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the new list pointer
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xsltAttrElemPtr
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttrElemPtr next, cur;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (attr == NULL)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(list);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (list == NULL)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(xsltNewAttrElem(attr));
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur = list;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (cur != NULL) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	next = cur->next;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (cur->attr == attr)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(cur);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (cur->next == NULL) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur->next = xsltNewAttrElem(attr);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(list);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur = next;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(list);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* XSLT_REFACTORED */
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltMergeAttrElemList:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @list:  an XSLT AttrElem list
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @old:  another XSLT AttrElem list
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add all the attributes from list @old to list @list,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * but drop redefinition of existing values.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the new list pointer
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xsltAttrElemPtr
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltMergeAttrElemList(xsltStylesheetPtr style,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      xsltAttrElemPtr list, xsltAttrElemPtr old) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttrElemPtr cur;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int add;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (old != NULL) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((old->attr == NULL) && (old->set == NULL)) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    old = old->next;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    continue;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * Check that the attribute is not yet in the list
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur = list;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	add = 1;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (cur != NULL) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((cur->attr == NULL) && (cur->set == NULL)) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (cur->next == NULL)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    break;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		cur = cur->next;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		continue;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((cur->set != NULL) && (cur->set == old->set)) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		add = 0;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (cur->set != NULL) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (cur->next == NULL)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    break;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		cur = cur->next;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		continue;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (old->set != NULL) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (cur->next == NULL)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    break;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		cur = cur->next;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		continue;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (cur->attr == old->attr) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltGenericError(xsltGenericErrorContext,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     "xsl:attribute-set : use-attribute-sets recursion detected\n");
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return(list);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (cur->next == NULL)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            cur = cur->next;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (add == 1) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * Changed to use the string-dict, rather than duplicating
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * @set and @ns; this fixes bug #340400.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (cur == NULL) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		list = xsltNewAttrElem(old->attr);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (old->set != NULL) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    list->set = xmlDictLookup(style->dict, old->set, -1);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (old->ns != NULL)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			list->ns = xmlDictLookup(style->dict, old->ns, -1);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else if (add) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		cur->next = xsltNewAttrElem(old->attr);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (old->set != NULL) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    cur->next->set = xmlDictLookup(style->dict, old->set, -1);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (old->ns != NULL)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			cur->next->ns = xmlDictLookup(style->dict, old->ns, -1);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	old = old->next;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(list);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/************************************************************************
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *									*
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *			Module interfaces				*
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *									*
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ************************************************************************/
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltParseStylesheetAttributeSet:
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @style:  the XSLT stylesheet
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur:  the "attribute-set" element
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * parse an XSLT stylesheet attribute-set element
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ncname;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *prefix;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *value;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlNodePtr child;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttrElemPtr attrItems;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((cur == NULL) || (style == NULL))
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value = xmlGetNsProp(cur, (const xmlChar *)"name", NULL);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value == NULL) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltGenericError(xsltGenericErrorContext,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     "xsl:attribute-set : name is missing\n");
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ncname = xsltSplitQName(style->dict, value, &prefix);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(value);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value = NULL;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (style->attributeSets == NULL) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltGenericDebug(xsltGenericDebugContext,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "creating attribute set table\n");
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	style->attributeSets = xmlHashCreate(10);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (style->attributeSets == NULL)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    attrItems = xmlHashLookup2(style->attributeSets, ncname, prefix);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Parse the content. Only xsl:attribute elements are allowed.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    child = cur->children;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (child != NULL) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* Report invalid nodes.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((child->type != XML_ELEMENT_NODE) ||
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (child->ns == NULL) ||
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (! IS_XSLT_ELEM(child)))
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (child->type == XML_ELEMENT_NODE)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltTransformError(NULL, style, child,
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			"xsl:attribute-set : unexpected child %s\n",
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		                 child->name);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    else
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltTransformError(NULL, style, child,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			"xsl:attribute-set : child of unexpected type\n");
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else if (!IS_XSLT_NAME(child, "attribute")) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(NULL, style, child,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"xsl:attribute-set : unexpected child xsl:%s\n",
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		child->name);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_REFACTORED
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltAttrElemPtr nextAttr, curAttr;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * Process xsl:attribute
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * ---------------------
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltGenericDebug(xsltGenericDebugContext,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"add attribute to list %s\n", ncname);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * The following was taken over from
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * xsltAddAttrElemList().
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (attrItems == NULL) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		attrItems = xsltNewAttrElem(child);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		curAttr = attrItems;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		while (curAttr != NULL) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    nextAttr = curAttr->next;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (curAttr->attr == child) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			/*
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			* URGENT TODO: Can somebody explain
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			*  why attrItems is set to curAttr
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			*  here? Is this somehow related to
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			*  avoidance of recursions?
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			*/
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			attrItems = curAttr;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			goto next_child;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (curAttr->next == NULL)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			curAttr->next = xsltNewAttrElem(child);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    curAttr = nextAttr;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * Parse the xsl:attribute and its content.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltGenericDebug(xsltGenericDebugContext,
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"add attribute to list %s\n", ncname);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * OLD behaviour:
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    attrItems = xsltAddAttrElemList(attrItems, child);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_REFACTORED
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)next_child:
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	child = child->next;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Process attribue "use-attribute-sets".
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO check recursion */
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value = xmlGetNsProp(cur, (const xmlChar *)"use-attribute-sets",
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	NULL);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value != NULL) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const xmlChar *curval, *endval;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	curval = value;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (*curval != 0) {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    while (IS_BLANK(*curval)) curval++;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (*curval == 0)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    endval = curval;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    while ((*endval != 0) && (!IS_BLANK(*endval))) endval++;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    curval = xmlDictLookup(style->dict, curval, endval - curval);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (curval) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		const xmlChar *ncname2 = NULL;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		const xmlChar *prefix2 = NULL;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltAttrElemPtr refAttrItems;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltGenericDebug(xsltGenericDebugContext,
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    "xsl:attribute-set : %s adds use %s\n", ncname, curval);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ncname2 = xsltSplitQName(style->dict, curval, &prefix2);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		refAttrItems = xsltNewAttrElem(NULL);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (refAttrItems != NULL) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    refAttrItems->set = ncname2;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    refAttrItems->ns = prefix2;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    attrItems = xsltMergeAttrElemList(style,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			attrItems, refAttrItems);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    xsltFreeAttrElem(refAttrItems);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    curval = endval;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(value);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	value = NULL;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Update the value
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * TODO: Why is this dummy entry needed.?
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (attrItems == NULL)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	attrItems = xsltNewAttrElem(NULL);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlHashUpdateEntry2(style->attributeSets, ncname, prefix, attrItems, NULL);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltGenericDebug(xsltGenericDebugContext,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"updated attribute list %s\n", ncname);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltGetSAS:
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @style:  the XSLT stylesheet
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @name:  the attribute list name
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ns:  the attribute list namespace
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * lookup an attribute set based on the style cascade
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the attribute set or NULL
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xsltAttrElemPtr
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltGetSAS(xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttrElemPtr values;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (style != NULL) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	values = xmlHashLookup2(style->attributeSets, name, ns);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (values != NULL)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(values);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	style = xsltNextImport(style);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(NULL);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltResolveSASCallback,:
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @style:  the XSLT stylesheet
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * resolve the references in an attribute set.
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltResolveSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	               const xmlChar *name, const xmlChar *ns,
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       ATTRIBUTE_UNUSED const xmlChar *ignored) {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttrElemPtr tmp;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttrElemPtr refs;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp = values;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (tmp != NULL) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tmp->set != NULL) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * Check against cycles !
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     */
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((xmlStrEqual(name, tmp->set)) && (xmlStrEqual(ns, tmp->ns))) {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltGenericError(xsltGenericErrorContext,
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     "xsl:attribute-set : use-attribute-sets recursion detected on %s\n",
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 name);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltGenericDebug(xsltGenericDebugContext,
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			"Importing attribute list %s\n", tmp->set);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		refs = xsltGetSAS(style, tmp->set, tmp->ns);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (refs == NULL) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    xsltGenericError(xsltGenericErrorContext,
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     "xsl:attribute-set : use-attribute-sets %s reference missing %s\n",
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     name, tmp->set);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /*
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * recurse first for cleanup
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     */
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    xsltResolveSASCallback(refs, style, name, ns, NULL);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /*
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * Then merge
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     */
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    xsltMergeAttrElemList(style, values, refs);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /*
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * Then suppress the reference
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     */
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    tmp->set = NULL;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    tmp->ns = NULL;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tmp = tmp->next;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltMergeSASCallback,:
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @style:  the XSLT stylesheet
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Merge an attribute set from an imported stylesheet.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltMergeSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	               const xmlChar *name, const xmlChar *ns,
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       ATTRIBUTE_UNUSED const xmlChar *ignored) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttrElemPtr topSet;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = xmlHashAddEntry2(style->attributeSets, name, ns, values);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret < 0) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * Add failed, this attribute set can be removed.
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltGenericDebug(xsltGenericDebugContext,
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"attribute set %s present already in top stylesheet"
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		" - merging\n", name);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	topSet = xmlHashLookup2(style->attributeSets, name, ns);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (topSet==NULL) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltGenericError(xsltGenericErrorContext,
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        "xsl:attribute-set : logic error merging from imports for"
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		" attribute-set %s\n", name);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    topSet = xsltMergeAttrElemList(style, topSet, values);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlHashUpdateEntry2(style->attributeSets, name, ns, topSet, NULL);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltFreeAttrElemList(values);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltGenericDebug(xsltGenericDebugContext,
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"attribute set %s moved to top stylesheet\n",
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		         name);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltResolveStylesheetAttributeSet:
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @style:  the XSLT stylesheet
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * resolve the references between attribute sets.
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltStylesheetPtr cur;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltGenericDebug(xsltGenericDebugContext,
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "Resolving attribute sets references\n");
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * First aggregate all the attribute sets definitions from the imports
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur = xsltNextImport(style);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (cur != NULL) {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (cur->attributeSets != NULL) {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (style->attributeSets == NULL) {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltGenericDebug(xsltGenericDebugContext,
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    "creating attribute set table\n");
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		style->attributeSets = xmlHashCreate(10);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlHashScanFull(cur->attributeSets,
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(xmlHashScannerFull) xsltMergeSASCallback, style);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * the attribute lists have either been migrated to style
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * or freed directly in xsltMergeSASCallback()
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     */
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlHashFree(cur->attributeSets, NULL);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur->attributeSets = NULL;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur = xsltNextImport(cur);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Then resolve all the references and computes the resulting sets
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (style->attributeSets != NULL) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlHashScanFull(style->attributeSets,
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(xmlHashScannerFull) xsltResolveSASCallback, style);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltAttributeInternal:
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  a XSLT process context
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @node:  the current node in the source tree
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @inst:  the xsl:attribute element
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @comp:  precomputed information
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fromAttributeSet:  the attribute comes from an attribute-set
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Process the xslt attribute node on the source node
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltAttributeInternal(xsltTransformContextPtr ctxt,
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      xmlNodePtr contextNode,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      xmlNodePtr inst,
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      xsltStylePreCompPtr castedComp,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int fromAttributeSet)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_REFACTORED
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltStyleItemAttributePtr comp =
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(xsltStyleItemAttributePtr) castedComp;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltStylePreCompPtr comp = castedComp;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlNodePtr targetElem;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *prop = NULL;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *name = NULL, *prefix = NULL, *nsName = NULL;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *value = NULL;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlNsPtr ns = NULL;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlAttrPtr attr;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * A comp->has_name == 0 indicates that we need to skip this instruction,
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * since it was evaluated to be invalid already during compilation.
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!comp->has_name)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * BIG NOTE: This previously used xsltGetSpecialNamespace() and
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *  xsltGetNamespace(), but since both are not appropriate, we
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *  will process namespace lookup here to avoid adding yet another
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *  ns-lookup function to namespaces.c.
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * SPEC XSLT 1.0: Error cases:
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * - Creating nodes other than text nodes during the instantiation of
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *   the content of the xsl:attribute element; implementations may
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *   either signal the error or ignore the offending nodes."
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (comp == NULL) {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltTransformError(ctxt, NULL, inst,
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "Internal error in xsltAttributeInternal(): "
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "The XSLT 'attribute' instruction was not compiled.\n");
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * TODO: Shouldn't ctxt->insert == NULL be treated as an internal error?
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *   So report an internal error?
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ctxt->insert == NULL)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * SPEC XSLT 1.0:
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *  "Adding an attribute to a node that is not an element;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *  implementations may either signal the error or ignore the attribute."
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * TODO: I think we should signal such errors in the future, and maybe
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *  provide an option to ignore such errors.
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    targetElem = ctxt->insert;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (targetElem->type != XML_ELEMENT_NODE)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * SPEC XSLT 1.0:
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * "Adding an attribute to an element after children have been added
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *  to it; implementations may either signal the error or ignore the
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *  attribute."
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * TODO: We should decide whether not to report such errors or
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *  to ignore them; note that we *ignore* if the parent is not an
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *  element, but here we report an error.
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (targetElem->children != NULL) {
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* NOTE: Ah! This seems to be intended to support streamed
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  result generation!.
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltTransformError(ctxt, NULL, inst,
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "xsl:attribute: Cannot add attributes to an "
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "element if children have been already added "
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "to the element.\n");
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Process the name
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * ----------------
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_DEBUGGER
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ctxt->debugStatus != XSLT_DEBUG_NONE)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xslHandleDebugger(inst, contextNode, NULL, ctxt);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (comp->name == NULL) {
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* TODO: fix attr acquisition wrt to the XSLT namespace */
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prop = xsltEvalAttrValueTemplate(ctxt, inst,
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (const xmlChar *) "name", XSLT_NAMESPACE);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (prop == NULL) {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xsltTransformError(ctxt, NULL, inst,
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"xsl:attribute: The attribute 'name' is missing.\n");
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto error;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlValidateQName(prop, 0)) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(ctxt, NULL, inst,
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"xsl:attribute: The effective name '%s' is not a "
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"valid QName.\n", prop);
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* we fall through to catch any further errors, if possible */
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	name = xsltSplitQName(ctxt->dict, prop, &prefix);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(prop);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* Reject a prefix of "xmlns".
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((prefix != NULL) &&
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (!xmlStrncasecmp(prefix, (xmlChar *) "xmlns", 5)))
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_PARSING
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltGenericDebug(xsltGenericDebugContext,
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"xsltAttribute: xmlns prefix forbidden\n");
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * SPEC XSLT 1.0:
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *  "It is an error if the string that results from instantiating
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *  the attribute value template is not a QName or is the string
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *  xmlns. An XSLT processor may signal the error; if it does not
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *  signal the error, it must recover by not adding the attribute
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *  to the result tree."
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * TODO: Decide which way to go here.
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* The "name" value was static.
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_REFACTORED
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	prefix = comp->nsPrefix;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	name = comp->name;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	name = xsltSplitQName(ctxt->dict, comp->name, &prefix);
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Process namespace semantics
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * ---------------------------
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Evaluate the namespace name.
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (comp->has_ns) {
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* The "namespace" attribute was existent.
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (comp->ns != NULL) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * No AVT; just plain text for the namespace name.
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (comp->ns[0] != 0)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		nsName = comp->ns;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlChar *tmpNsName;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * Eval the AVT.
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* TODO: check attr acquisition wrt to the XSLT namespace */
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    tmpNsName = xsltEvalAttrValueTemplate(ctxt, inst,
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(const xmlChar *) "namespace", XSLT_NAMESPACE);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * This fixes bug #302020: The AVT might also evaluate to the
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * empty string; this means that the empty string also indicates
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * "no namespace".
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * SPEC XSLT 1.0:
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *  "If the string is empty, then the expanded-name of the
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *  attribute has a null namespace URI."
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((tmpNsName != NULL) && (tmpNsName[0] != 0))
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFree(tmpNsName);
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	};
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (prefix != NULL) {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* SPEC XSLT 1.0:
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  "If the namespace attribute is not present, then the QName is
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  expanded into an expanded-name using the namespace declarations
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  in effect for the xsl:attribute element, *not* including any
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  default namespace declaration."
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ns = xmlSearchNs(inst->doc, inst, prefix);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ns == NULL) {
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * Note that this is treated as an error now (checked with
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *  Saxon, Xalan-J and MSXML).
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(ctxt, NULL, inst,
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"xsl:attribute: The QName '%s:%s' has no "
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"namespace binding in scope in the stylesheet; "
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"this is an error, since the namespace was not "
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"specified by the instruction itself.\n", prefix, name);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    nsName = ns->href;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fromAttributeSet) {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* This tries to ensure that xsl:attribute(s) coming
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* from an xsl:attribute-set won't override attribute of
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* literal result elements or of explicit xsl:attribute(s).
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* URGENT TODO: This might be buggy, since it will miss to
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  overwrite two equal attributes both from attribute sets.
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	attr = xmlHasNsProp(targetElem, name, nsName);
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (attr != NULL)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Find/create a matching ns-decl in the result tree.
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ns = NULL;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (0) {
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* OPTIMIZE TODO: How do we know if we are adding to a
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  fragment or to the result tree?
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* If we are adding to a result tree fragment (i.e., not to the
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* actual result tree), we'll don't bother searching for the
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* ns-decl, but just store it in the dummy-doc of the result
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* tree fragment.
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (nsName != NULL) {
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * TODO: Get the doc of @targetElem.
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ns = xsltTreeAcquireStoredNs(some doc, nsName, prefix);
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nsName != NULL) {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* Something about ns-prefixes:
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* SPEC XSLT 1.0:
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  "XSLT processors may make use of the prefix of the QName specified
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  in the name attribute when selecting the prefix used for outputting
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  the created attribute as XML; however, they are not required to do
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  so and, if the prefix is xmlns, they must not do so"
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* xsl:attribute can produce a scenario where the prefix is NULL,
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* so generate a prefix.
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (prefix == NULL) {
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlChar *pref = xmlStrdup(BAD_CAST "ns_1");
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ns = xsltGetSpecialNamespace(ctxt, inst, nsName, BAD_CAST pref,
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		targetElem);
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFree(pref);
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix,
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		targetElem);
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ns == NULL) {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(ctxt, NULL, inst,
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"Namespace fixup error: Failed to acquire an in-scope "
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"namespace binding for the generated attribute '{%s}%s'.\n",
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		nsName, name);
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Construction of the value
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * -------------------------
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (inst->children == NULL) {
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* No content.
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* TODO: Do we need to put the empty string in ?
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	attr = xmlSetNsProp(ctxt->insert, ns, name, (const xmlChar *) "");
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if ((inst->children->next == NULL) &&
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ((inst->children->type == XML_TEXT_NODE) ||
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     (inst->children->type == XML_CDATA_SECTION_NODE)))
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlNodePtr copyTxt;
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* xmlSetNsProp() will take care of duplicates.
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	attr = xmlSetNsProp(ctxt->insert, ns, name, NULL);
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (attr == NULL) /* TODO: report error ? */
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* This was taken over from xsltCopyText() (transform.c).
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ctxt->internalized &&
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (ctxt->insert->doc != NULL) &&
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (ctxt->insert->doc->dict == ctxt->dict))
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    copyTxt = xmlNewText(NULL);
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (copyTxt == NULL) /* TODO: report error */
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto error;
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * This is a safe scenario where we don't need to lookup
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * the dict.
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    copyTxt->content = inst->children->content;
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * Copy "disable-output-escaping" information.
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * TODO: Does this have any effect for attribute values
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *  anyway?
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (inst->children->name == xmlStringTextNoenc)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		copyTxt->name = xmlStringTextNoenc;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * Copy the value.
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    copyTxt = xmlNewText(inst->children->content);
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (copyTxt == NULL) /* TODO: report error */
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto error;
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	attr->children = attr->last = copyTxt;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	copyTxt->parent = (xmlNodePtr) attr;
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	copyTxt->doc = attr->doc;
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* Copy "disable-output-escaping" information.
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* TODO: Does this have any effect for attribute values
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*  anyway?
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (inst->children->name == xmlStringTextNoenc)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    copyTxt->name = xmlStringTextNoenc;
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /*
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * since we create the attribute without content IDness must be
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * asserted as a second step
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         */
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((copyTxt->content != NULL) &&
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (xmlIsID(attr->doc, attr->parent, attr)))
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xmlAddID(NULL, attr->doc, copyTxt->content, attr);
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* The sequence constructor might be complex, so instantiate it.
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	value = xsltEvalTemplateString(ctxt, contextNode, inst);
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (value != NULL) {
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    attr = xmlSetNsProp(ctxt->insert, ns, name, value);
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFree(value);
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * TODO: Do we have to add the empty string to the attr?
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * TODO: Does a  value of NULL indicate an
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *  error in xsltEvalTemplateString() ?
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    attr = xmlSetNsProp(ctxt->insert, ns, name,
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(const xmlChar *) "");
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error:
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltAttribute:
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  a XSLT process context
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @node:  the node in the source tree.
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @inst:  the xslt attribute node
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @comp:  precomputed information
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Process the xslt attribute node on the source node
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	      xmlNodePtr inst, xsltStylePreCompPtr comp) {
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttributeInternal(ctxt, node, inst, comp, 0);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltApplyAttributeSet:
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XSLT stylesheet
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @node:  the node in the source tree.
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @inst:  the attribute node "xsl:use-attribute-sets"
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @attrSets:  the list of QNames of the attribute-sets to be applied
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Apply the xsl:use-attribute-sets.
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If @attrSets is NULL, then @inst will be used to exctract this
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * value.
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If both, @attrSets and @inst, are NULL, then this will do nothing.
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      xmlNodePtr inst,
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const xmlChar *attrSets)
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ncname = NULL;
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *prefix = NULL;
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *curstr, *endstr;
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltAttrElemPtr attrs;
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltStylesheetPtr style;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (attrSets == NULL) {
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (inst == NULL)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else {
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * Extract the value from @inst.
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (inst->type == XML_ATTRIBUTE_NODE) {
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ( ((xmlAttrPtr) inst)->children != NULL)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    attrSets = ((xmlAttrPtr) inst)->children->content;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (attrSets == NULL) {
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/*
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		* TODO: Return an error?
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*/
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Parse/apply the list of QNames.
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    curstr = attrSets;
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (*curstr != 0) {
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (IS_BLANK(*curstr))
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            curstr++;
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (*curstr == 0)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        endstr = curstr;
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while ((*endstr != 0) && (!IS_BLANK(*endstr)))
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            endstr++;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curstr = xmlDictLookup(ctxt->dict, curstr, endstr - curstr);
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (curstr) {
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * TODO: Validate the QName.
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_curstrUTES
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xsltGenericDebug(xsltGenericDebugContext,
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "apply curstrute set %s\n", curstr);
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ncname = xsltSplitQName(ctxt->dict, curstr, &prefix);
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            style = ctxt->style;
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_DEBUGGER
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((style != NULL) &&
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(style->attributeSets != NULL) &&
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(ctxt->debugStatus != XSLT_DEBUG_NONE))
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    {
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                attrs =
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    xmlHashLookup2(style->attributeSets, ncname, prefix);
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if ((attrs != NULL) && (attrs->attr != NULL))
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    xslHandleDebugger(attrs->attr->parent, node, NULL,
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			ctxt);
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * Lookup the referenced curstrute-set.
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            while (style != NULL) {
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                attrs =
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    xmlHashLookup2(style->attributeSets, ncname, prefix);
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                while (attrs != NULL) {
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if (attrs->attr != NULL) {
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        xsltAttributeInternal(ctxt, node, attrs->attr,
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    attrs->attr->psvi, 1);
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    }
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    attrs = attrs->next;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                style = xsltNextImport(style);
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curstr = endstr;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltFreeAttributeSetsHashes:
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @style: an XSLT stylesheet
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Free up the memory used by attribute sets
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltFreeAttributeSetsHashes(xsltStylesheetPtr style) {
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (style->attributeSets != NULL)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlHashFree((xmlHashTablePtr) style->attributeSets,
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (xmlHashDeallocator) xsltFreeAttrElemList);
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    style->attributeSets = NULL;
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1140