added new code to handle attribute value templates also a lot of work to
authorDaniel Veillard <veillard@src.gnome.org>
Fri, 13 Feb 2004 16:07:08 +0000 (16:07 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Fri, 13 Feb 2004 16:07:08 +0000 (16:07 +0000)
* libxslt/attrvt.c libxslt/Makefile.am: added new code to handle
  attribute value templates
* libxslt/*.c libxslt/*.h: also a lot of work to reuse the
  dictionaries at the stylesheet and transformation level.
* configure.in: this relies on a recent version of libxml2
  with the sub dictionnary catalog.
Daniel

20 files changed:
ChangeLog
configure.in
libxslt/Makefile.am
libxslt/attributes.c
libxslt/attributes.h
libxslt/attrvt.c [new file with mode: 0644]
libxslt/documents.c
libxslt/keys.c
libxslt/numbers.c
libxslt/numbersInternals.h
libxslt/pattern.c
libxslt/preproc.c
libxslt/templates.c
libxslt/templates.h
libxslt/transform.c
libxslt/variables.c
libxslt/xslt.c
libxslt/xsltInternals.h
libxslt/xsltutils.c
libxslt/xsltutils.h

index f91f3c4..b98c126 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Fri Feb 13 16:59:46 CET 2004 Daniel Veillard <daniel@veillard.com>
+
+       * libxslt/attrvt.c libxslt/Makefile.am: added new code to handle
+         attribute value templates
+       * libxslt/*.c libxslt/*.h: also a lot of work to reuse the 
+         dictionaries at the stylesheet and transformation level.
+       * configure.in: this relies on a recent version of libxml2 
+         with the sub dictionnary catalog.
+
 Sun Feb  8 16:53:14 HKT 2004 William Brack <wbrack@mmm.com.hk>
 
        * libxslt/transform.c: added check for "?>" in PI content
index bae6457..23cfda2 100644 (file)
@@ -11,7 +11,7 @@ PACKAGE=libxslt
 LIBEXSLT_MAJOR_VERSION=0
 LIBEXSLT_MINOR_VERSION=8
 LIBEXSLT_MICRO_VERSION=2
-LIBXML_REQUIRED_VERSION=2.6.3
+LIBXML_REQUIRED_VERSION=2.6.5
 
 
 LIBXSLT_VERSION=$LIBXSLT_MAJOR_VERSION.$LIBXSLT_MINOR_VERSION.$LIBXSLT_MICRO_VERSION
index dff2e53..c0dc1a3 100644 (file)
@@ -27,6 +27,7 @@ xsltinc_HEADERS =                     \
        xsltexports.h
 
 libxslt_la_SOURCES =                   \
+       attrvt.c                        \
        xslt.c                          \
        xsltutils.c                     \
        pattern.c                       \
index 6931130..c3b2cce 100644 (file)
@@ -123,10 +123,6 @@ xsltNewAttrElem(xmlNodePtr attr) {
  */
 static void
 xsltFreeAttrElem(xsltAttrElemPtr attr) {
-    if (attr->set != NULL)
-       xmlFree((char *)attr->set);
-    if (attr->ns != NULL)
-       xmlFree((char *)attr->ns);
     xmlFree(attr);
 }
 
@@ -275,11 +271,11 @@ xsltMergeAttrElemList(xsltAttrElemPtr list, xsltAttrElemPtr old) {
 
 void
 xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
-    xmlChar *prop = NULL;
-    xmlChar *ncname = NULL;
-    xmlChar *prefix = NULL;
+    const xmlChar *ncname;
+    const xmlChar *prefix;
+    const xmlChar *attrib, *endattr;
+    xmlChar *prop;
     xmlChar *attributes;
-    xmlChar *attrib, *endattr;
     xmlNodePtr list;
     xsltAttrElemPtr values;
 
@@ -290,15 +286,11 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
     if (prop == NULL) {
        xsltGenericError(xsltGenericErrorContext,
             "xsl:attribute-set : name is missing\n");
-       goto error;
+       return;
     }
 
-    ncname = xmlSplitQName2(prop, &prefix);
-    if (ncname == NULL) {
-       ncname = prop;
-       prop = NULL;
-       prefix = NULL;
-    }
+    ncname = xsltSplitQName(style->dict, prop, &prefix);
+    xmlFree(prop);
 
     if (style->attributeSets == NULL) {
 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
@@ -308,7 +300,7 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
        style->attributeSets = xmlHashCreate(10);
     }
     if (style->attributeSets == NULL)
-       goto error;
+       return;
 
     values = xmlHashLookup2(style->attributeSets, ncname, prefix);
 
@@ -354,36 +346,24 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
            break;
         endattr = attrib;
        while ((*endattr != 0) && (!IS_BLANK(*endattr))) endattr++;
-       attrib = xmlStrndup(attrib, endattr - attrib);
+       attrib = xmlDictLookup(style->dict, attrib, endattr - attrib);
        if (attrib) {
-           xmlChar *ncname2 = NULL;
-           xmlChar *prefix2 = NULL;
+           const xmlChar *ncname2 = NULL;
+           const xmlChar *prefix2 = NULL;
            xsltAttrElemPtr values2;
+
 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
            xsltGenericDebug(xsltGenericDebugContext,
                "xsl:attribute-set : %s adds use %s\n", ncname, attrib);
 #endif
-           ncname2 = xmlSplitQName2(attrib, &prefix2);
-           if (ncname2 == NULL) {
-               ncname2 = attrib;
-               attrib = NULL;
-               prefix = NULL;
-           }
+           ncname2 = xsltSplitQName(style->dict, attrib, &prefix2);
            values2 = xsltNewAttrElem(NULL);
            if (values2 != NULL) {
                values2->set = ncname2;
                values2->ns = prefix2;
                values = xsltMergeAttrElemList(values, values2);
                xsltFreeAttrElem(values2);
-           } else {
-               if (ncname2 != NULL)
-                   xmlFree(ncname2);
-               if (prefix2 != NULL)
-                   xmlFree(prefix2);
            }
-
-           if (attrib != NULL)
-               xmlFree(attrib);
        }
        attrib = endattr;
     }
@@ -400,14 +380,6 @@ done:
     xsltGenericDebug(xsltGenericDebugContext,
        "updated attribute list %s\n", ncname);
 #endif
-
-error:
-    if (prop != NULL)
-        xmlFree(prop);
-    if (ncname != NULL)
-        xmlFree(ncname);
-    if (prefix != NULL)
-        xmlFree(prefix);
 }
 
 /**
@@ -597,8 +569,9 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt, xmlNodePtr node,
                       int fromset)
 {
     xmlChar *prop = NULL;
-    xmlChar *ncname = NULL, *name, *namespace;
-    xmlChar *prefix = NULL;
+    xmlChar *namespace;
+    const xmlChar *name = NULL;
+    const xmlChar *prefix = NULL;
     xmlChar *value = NULL;
     xmlNsPtr ns = NULL;
     xmlAttrPtr attr;
@@ -639,22 +612,17 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt, xmlNodePtr node,
                              "xsl:attribute : name is missing\n");
             goto error;
         }
-        name = prop;
+       if (xmlValidateQName(prop, 0)) {
+           xsltTransformError(ctxt, NULL, inst,
+                           "xsl:attribute : invalid QName\n");
+           /* we fall through to catch any further errors, if possible */
+       }
+       name = xsltSplitQName(ctxt->dict, prop, &prefix);
+       xmlFree(prop);
     } else {
-        name = comp->name;
+       name = xsltSplitQName(ctxt->dict, comp->name, &prefix);
     }
 
-    if (xmlValidateQName(name, 0)) {
-        xsltTransformError(ctxt, NULL, inst,
-                       "xsl:attribute : invalid QName\n");
-       /* we fall through to catch any further errors, if possible */
-    }
-    ncname = xmlSplitQName2(name, &prefix);
-    if (ncname == NULL) {
-        prefix = NULL;
-    } else {
-        name = ncname;
-    }
     if (!xmlStrncasecmp(prefix, (xmlChar *) "xmlns", 5)) {
 #ifdef WITH_XSLT_DEBUG_PARSING
         xsltGenericDebug(xsltGenericDebugContext,
@@ -721,13 +689,7 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt, xmlNodePtr node,
         }
     }
 
-  error:
-    if (prop != NULL)
-        xmlFree(prop);
-    if (ncname != NULL)
-        xmlFree(ncname);
-    if (prefix != NULL)
-        xmlFree(prefix);
+error:
     if (value != NULL)
         xmlFree(value);
 }
@@ -760,11 +722,11 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
 void
 xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
                       xmlNodePtr inst ATTRIBUTE_UNUSED,
-                      xmlChar * attributes)
+                      const xmlChar * attributes)
 {
-    xmlChar *ncname = NULL;
-    xmlChar *prefix = NULL;
-    xmlChar *attrib, *endattr;
+    const xmlChar *ncname = NULL;
+    const xmlChar *prefix = NULL;
+    const xmlChar *attrib, *endattr;
     xsltAttrElemPtr values;
     xsltStylesheetPtr style;
 
@@ -781,18 +743,13 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
         endattr = attrib;
         while ((*endattr != 0) && (!IS_BLANK(*endattr)))
             endattr++;
-        attrib = xmlStrndup(attrib, endattr - attrib);
+        attrib = xmlDictLookup(ctxt->dict, attrib, endattr - attrib);
         if (attrib) {
 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
             xsltGenericDebug(xsltGenericDebugContext,
                              "apply attribute set %s\n", attrib);
 #endif
-            ncname = xmlSplitQName2(attrib, &prefix);
-            if (ncname == NULL) {
-                ncname = attrib;
-                attrib = NULL;
-                prefix = NULL;
-            }
+            ncname = xsltSplitQName(ctxt->dict, attrib, &prefix);
 
             style = ctxt->style;
 #ifdef WITH_DEBUGGER
@@ -817,12 +774,6 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
                 }
                 style = xsltNextImport(style);
             }
-            if (attrib != NULL)
-                xmlFree(attrib);
-            if (ncname != NULL)
-                xmlFree(ncname);
-            if (prefix != NULL)
-                xmlFree(prefix);
         }
         attrib = endattr;
     }
index 5e219b1..d61ebb0 100644 (file)
@@ -27,7 +27,7 @@ XSLTPUBFUN void XSLTCALL
        xsltApplyAttributeSet           (xsltTransformContextPtr ctxt,
                                         xmlNodePtr node,
                                         xmlNodePtr inst,
-                                        xmlChar *attributes);
+                                        const xmlChar *attributes);
 XSLTPUBFUN void XSLTCALL       
        xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style);
 #ifdef __cplusplus
diff --git a/libxslt/attrvt.c b/libxslt/attrvt.c
new file mode 100644 (file)
index 0000000..29d4337
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * attrvt.c: Implementation of the XSL Transformation 1.0 engine
+ *           attribute value template handling part.
+ *
+ * References:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ *   Michael Kay "XSLT Programmer's Reference" pp 637-643
+ *   Writing Multiple Output Files
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include "xslt.h"
+#include "xsltutils.h"
+#include "xsltInternals.h"
+#include "templates.h"
+
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_AVT
+#define WITH_XSLT_DEBUG_AVT
+#endif
+
+static struct xsltIsAttVTStruct {
+    int key;
+} xsltIsAttVTStruct = { 0xdeadbeef };
+
+void *xsltIsAttVT = (void *) &xsltIsAttVTStruct;
+
+#define MAX_AVT_SEG 10
+
+typedef struct _xsltAttrVT xsltAttrVT;
+typedef xsltAttrVT *xsltAttrVTPtr;
+struct _xsltAttrVT {
+    struct _xsltAttrVT *next; /* next xsltAttrVT */
+    int nb_seg;                /* Number of segments */
+    int strstart;      /* is the start a string */
+    /*
+     * the namespaces in scope
+     */
+    xmlNsPtr *nsList;
+    int nsNr;
+    /*
+     * the content is an alternate of string and xmlXPathCompExprPtr
+     */
+    void *segments[MAX_AVT_SEG];
+};
+
+/**
+ * xsltNewAttrVT:
+ * @style:  a XSLT process context
+ *
+ * Build a new xsltAttrVT structure
+ *
+ * Returns the structure or NULL in case of error
+ */
+static xsltAttrVTPtr
+xsltNewAttrVT(xsltStylesheetPtr style) {
+    xsltAttrVTPtr cur;
+
+    cur = (xsltAttrVTPtr) xmlMalloc(sizeof(xsltAttrVT));
+    if (cur == NULL) {
+       xsltTransformError(NULL, style, NULL,
+               "xsltNewAttrVTPtr : malloc failed\n");
+       if (style != NULL) style->errors++;
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltAttrVT));
+
+    cur->nb_seg = 0;
+    cur->strstart = 0;
+    cur->next = style->attVTs;
+    style->attVTs = (xsltAttrVTPtr) cur;
+
+    return(cur);
+}
+
+/**
+ * xsltFreeAttrVT:
+ * @avt: pointer to an xsltAttrVT structure
+ *
+ * Free up the memory associated to the attribute value template
+ */
+static void
+xsltFreeAttrVT(xsltAttrVTPtr avt) {
+    int i;
+
+    if (avt == NULL) return;
+
+    if (avt->strstart == 1) {
+       for (i = 0;i < avt->nb_seg; i += 2)
+           xmlFree((xmlChar *) avt->segments[i]);
+       for (i = 1;i < avt->nb_seg; i += 2)
+           xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]);
+    } else {
+       for (i = 0;i < avt->nb_seg; i += 2)
+           xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]);
+       for (i = 1;i < avt->nb_seg; i += 2)
+           xmlFree((xmlChar *) avt->segments[i]);
+    }
+    if (avt->nsList != NULL)
+        xmlFree(avt->nsList);
+    xmlFree(avt);
+}
+
+/**
+ * xsltFreeAVTList:
+ * @avt: pointer to an list of AVT structures
+ *
+ * Free up the memory associated to the attribute value templates
+ */
+void
+xsltFreeAVTList(void *avt) {
+    xsltAttrVTPtr cur = (xsltAttrVTPtr) avt, next;
+
+    while (cur != NULL) {
+        next = cur->next;
+       xsltFreeAttrVT(cur);
+       cur = next;
+    }
+}
+
+/**
+ * xsltCompileAttr:
+ * @style:  a XSLT process context
+ * @attr: the attribute coming from the stylesheet.
+ *
+ * Precompile an attribute in a stylesheet, basically it checks if it is
+ * an attrubute value template, and if yes establish some structures needed
+ * to process it at transformation time.
+ */
+void
+xsltCompileAttr(xsltStylesheetPtr style, xmlAttrPtr attr) {
+    const xmlChar *str;
+    const xmlChar *cur;
+    xmlChar *ret = NULL;
+    xmlChar *expr = NULL;
+    xsltAttrVTPtr avt;
+    int i = 0;
+
+    if ((style == NULL) || (attr == NULL) || (attr->children == NULL))
+        return;
+    if ((attr->children->type != XML_TEXT_NODE) || 
+        (attr->children->next != NULL)) {
+        xsltTransformError(NULL, style, attr->parent,
+               "Attribute %s content is not a text node\n", attr->name);
+       style->errors++;
+       return;
+    }
+    str = attr->children->content;
+    if (xmlStrchr(str, '{') == NULL) return;
+
+    avt = xsltNewAttrVT(style);
+    if (avt == NULL) return;
+    attr->_private = avt;
+
+    avt->nsList = xmlGetNsList(attr->doc, attr->parent);
+    if (avt->nsList != NULL) {
+       while (avt->nsList[i] != NULL)
+           i++;
+    }
+    avt->nsNr = i;
+
+    cur = str;
+    while (*cur != 0) {
+       if (*cur == '{') {
+           if (*(cur+1) == '{') {      /* escaped '{' */
+               cur++;
+               ret = xmlStrncat(ret, str, cur - str);
+               cur++;
+               str = cur;
+               continue;
+           }
+           if (*(cur+1) == '}') {      /* skip empty AVT */
+               ret = xmlStrncat(ret, str, cur - str);
+               cur+=2;
+               str = cur;
+               continue;
+           }
+           if ((ret != NULL) || (cur - str > 0)) {
+               ret = xmlStrncat(ret, str, cur - str);
+               str = cur;
+               if (avt->nb_seg == 0)
+                   avt->strstart = 1;
+               avt->segments[avt->nb_seg++] = (void *) ret;
+               ret = NULL;
+           }
+
+           cur++;
+           while ((*cur != 0) && (*cur != '}')) cur++;
+           if (*cur == 0) {
+               xsltTransformError(NULL, style, attr->parent,
+                    "Attribute template %s: unmatched '{'\n", attr->name);
+               style->errors++;
+               goto error;
+           }
+           str++;
+           expr = xmlStrndup(str, cur - str);
+           if (expr == NULL) {
+               XSLT_TODO
+               goto error;
+           } else {
+               xmlXPathCompExprPtr comp;
+
+               comp = xsltXPathCompile(style, expr);
+               if (comp == NULL) {
+                   xsltTransformError(NULL, style, attr->parent,
+                        "Attribute template %s: failed to compile %s\n",
+                                      attr->name, expr);
+                   style->errors++;
+                   goto error;
+               }
+               if (avt->nb_seg == 0)
+                   avt->strstart = 0;
+               avt->segments[avt->nb_seg++] = (void *) comp;
+               xmlFree(expr);
+               expr = NULL;
+           }
+           cur++;
+           str = cur;
+       } else if (*cur == '}') {
+           cur++;
+           if (*cur == '}') {  /* escaped '}' */
+               ret = xmlStrncat(ret, str, cur - str);
+               cur++;
+               str = cur;
+               continue;
+           } else {
+               xsltTransformError(NULL, style, attr->parent,
+                    "Attribute template %s: unmatched '}'\n", attr->name);
+               goto error;
+           }
+       } else
+           cur++;
+    }
+    if ((ret != NULL) || (cur - str > 0)) {
+       ret = xmlStrncat(ret, str, cur - str);
+       str = cur;
+       if (avt->nb_seg == 0)
+           avt->strstart = 1;
+       avt->segments[avt->nb_seg++] = (void *) ret;
+       ret = NULL;
+    }
+
+error:
+    if (ret != NULL)
+       xmlFree(ret);
+    if (expr != NULL)
+       xmlFree(expr);
+}
+
+
+/**
+ * xsltEvalAVT:
+ * @ctxt: the XSLT transformation context
+ * @avt: the prevompiled attribute value template info
+ * @node: the node hosting the attribute
+ *
+ * Process the given AVT, and return the new string value.
+ *
+ * Returns the computed string value or NULL, must be deallocated by the
+ *         caller.
+ */
+xmlChar *
+xsltEvalAVT(xsltTransformContextPtr ctxt, void *avt, xmlNodePtr node) {
+    xmlChar *ret = NULL, *tmp;
+    xmlXPathCompExprPtr comp;
+    xsltAttrVTPtr cur = (xsltAttrVTPtr) avt;
+    int i;
+    int str;
+
+    if ((ctxt == NULL) || (avt == NULL) || (node == NULL))
+        return(NULL);
+    str = cur->strstart;
+    for (i = 0;i < cur->nb_seg;i++) {
+        if (str) {
+           ret = xmlStrcat(ret, (const xmlChar *) cur->segments[i]);
+       } else {
+           comp = (xmlXPathCompExprPtr) cur->segments[i];
+           tmp = xsltEvalXPathStringNs(ctxt, comp, cur->nsNr, cur->nsList);
+           if (tmp != NULL) {
+               if (ret != NULL) {
+                   ret = xmlStrcat(ret, tmp);
+                   xmlFree(tmp);
+               } else {
+                   ret = tmp;
+               }
+           }
+       }
+       str = !str;
+    }
+    return(ret);
+}
index b38ed51..e7f7396 100644 (file)
@@ -14,6 +14,8 @@
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
 #include <libxml/hash.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
 #include "xslt.h"
 #include "xsltInternals.h"
 #include "xsltutils.h"
@@ -147,6 +149,55 @@ xsltFreeDocuments(xsltTransformContextPtr ctxt) {
     }
 }
 
+/**
+ * xsltParseDocument:
+ * @URI: the URI to load.
+ * @dict: the dictionnary to use
+ * @options: the options to use
+ *
+ * Specialized parsing function
+ *
+ * Returns NULL in case of error or the Document parsed.
+ */
+static xmlDocPtr
+xsltParseDocument(const xmlChar *URI, xmlDictPtr dict, int options) {
+    xmlParserCtxtPtr pctxt;
+    xmlParserInputPtr inputStream;
+    xmlDocPtr doc;
+
+    pctxt = xmlNewParserCtxt();
+    if (pctxt == NULL)
+        return(NULL);
+    if (pctxt->dict != NULL) {
+        xmlDictFree(pctxt->dict);
+       pctxt->dict = dict;
+       xmlDictReference(pctxt->dict);
+    }
+    xmlCtxtUseOptions(pctxt, options);
+    inputStream = xmlLoadExternalEntity((const char *) URI, NULL, pctxt);
+    if (inputStream == NULL) {
+        xmlFreeParserCtxt(pctxt);
+       return(NULL);
+    }
+    inputPush(pctxt, inputStream);
+    if (pctxt->directory == NULL)
+        pctxt->directory = xmlParserGetDirectory((const char *) URI);
+
+    xmlParseDocument(pctxt);
+
+    if (pctxt->wellFormed) {
+        doc = pctxt->myDoc;
+       xmlDictReference(pctxt->dict);
+    }
+    else {
+        doc = NULL;
+        xmlFreeDoc(pctxt->myDoc);
+        pctxt->myDoc = NULL;
+    }
+    xmlFreeParserCtxt(pctxt);
+
+    return(doc);
+}
 
 /**
  * xsltLoadDocument:
@@ -192,11 +243,8 @@ xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) {
        ret = ret->next;
     }
 
-#ifdef XSLT_PARSE_OPTIONS
-    doc = xmlReadFile((const char *) URI, NULL, ctxt->parserOptions);
-#else
-    doc = xmlParseFile((const char *) URI);
-#endif
+    doc = xsltParseDocument(URI, ctxt->dict, ctxt->parserOptions);
+
     if (doc == NULL)
        return(NULL);
 
@@ -270,11 +318,7 @@ xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {
        ret = ret->next;
     }
 
-#ifdef XSLT_PARSE_OPTIONS
-    doc = xmlReadFile((const char *) URI, NULL, XSLT_PARSE_OPTIONS);
-#else
-    doc = xmlParseFile((const char *) URI);
-#endif
+    doc = xsltParseDocument(URI, style->dict, XSLT_PARSE_OPTIONS);
     if (doc == NULL)
        return(NULL);
 
index 664175d..6d0e757 100644 (file)
@@ -369,14 +369,14 @@ xsltAddKey(xsltStylesheetPtr style, const xmlChar *name,
     xsltGenericDebug(xsltGenericDebugContext,
        "   resulting pattern %s\n", pattern);
 #endif
-    key->comp = xmlXPathCompile(pattern);
+    key->comp = xsltXPathCompile(style, pattern);
     if (key->comp == NULL) {
        xsltTransformError(NULL, style, inst,
                "xsl:key : XPath pattern compilation failed '%s'\n",
                         pattern);
        if (style != NULL) style->errors++;
     }
-    key->usecomp = xmlXPathCompile(use);
+    key->usecomp = xsltXPathCompile(style, use);
     if (key->usecomp == NULL) {
        xsltTransformError(NULL, style, inst,
                "xsl:key : XPath pattern compilation failed '%s'\n",
index 0068276..6382bcd 100644 (file)
@@ -315,7 +315,7 @@ xsltNumberFormatRoman(xmlBufferPtr buffer,
 }
 
 static void
-xsltNumberFormatTokenize(xmlChar *format,
+xsltNumberFormatTokenize(const xmlChar *format,
                         xsltFormatPtr tokens)
 {
     int index = 0;
@@ -534,8 +534,8 @@ xsltNumberFormatInsertNumbers(xsltNumberDataPtr data,
 static int
 xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
                            xmlNodePtr node,
-                           xmlChar *count,
-                           xmlChar *from,
+                           const xmlChar *count,
+                           const xmlChar *from,
                            double *array,
                            xmlDocPtr doc,
                            xmlNodePtr elem)
@@ -623,8 +623,8 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
 static int
 xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context,
                                 xmlNodePtr node,
-                                xmlChar *count,
-                                xmlChar *from,
+                                const xmlChar *count,
+                                const xmlChar *from,
                                 double *array,
                                 int max,
                                 xmlDocPtr doc,
@@ -698,7 +698,7 @@ xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context,
 static int
 xsltNumberFormatGetValue(xmlXPathContextPtr context,
                         xmlNodePtr node,
-                        xmlChar *value,
+                        const xmlChar *value,
                         double *number)
 {
     int amount = 0;
@@ -842,7 +842,6 @@ xsltNumberFormat(xsltTransformContextPtr ctxt,
 XSLT_NUMBER_FORMAT_END:
     if (tempformat == 1) {
        /* The format need to be recomputed each time */
-       xmlFree(data->format);
        data->format = NULL;
     }
     if (output != NULL)
index 6e1343b..7b3cb17 100644 (file)
@@ -26,11 +26,11 @@ typedef struct _xsltNumberData xsltNumberData;
 typedef xsltNumberData *xsltNumberDataPtr;
     
 struct _xsltNumberData {
-    xmlChar *level;
-    xmlChar *count;
-    xmlChar *from;
-    xmlChar *value;
-    xmlChar *format;
+    const xmlChar *level;
+    const xmlChar *count;
+    const xmlChar *from;
+    const xmlChar *value;
+    const xmlChar *format;
     int has_format;
     int digitsPerGroup;
     int groupingCharacter;
index 7e2ed99..dd82eb3 100644 (file)
@@ -289,7 +289,7 @@ xsltCompMatchAdd(xsltParserContextPtr ctxt, xsltCompMatchPtr comp,
            xsltAllocateExtra(ctxt->style);
     }
     if (op == XSLT_OP_PREDICATE) {
-       comp->steps[comp->nbStep].comp = xmlXPathCompile(value);
+       comp->steps[comp->nbStep].comp = xsltXPathCompile(ctxt->style, value);
     }
     comp->nbStep++;
     return (0);
index 1bcf913..d77faf4 100644 (file)
@@ -142,38 +142,7 @@ static void
 xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
     if (comp == NULL)
        return;
-    if (comp->stype != NULL)
-       xmlFree(comp->stype);
-    if (comp->order != NULL)
-       xmlFree(comp->order);
-    if (comp->use != NULL)
-       xmlFree(comp->use);
-    if (comp->name != NULL)
-       xmlFree(comp->name);
-    if (comp->ns != NULL)
-       xmlFree(comp->ns);
-    if (comp->mode != NULL)
-       xmlFree(comp->mode);
-    if (comp->modeURI != NULL)
-       xmlFree(comp->modeURI);
-    if (comp->test != NULL)
-       xmlFree(comp->test);
-    if (comp->select != NULL)
-       xmlFree(comp->select);
-
-    if (comp->filename != NULL)
-       xmlFree(comp->filename);
-
-    if (comp->numdata.level != NULL)
-       xmlFree(comp->numdata.level);
-    if (comp->numdata.count != NULL)
-       xmlFree(comp->numdata.count);
-    if (comp->numdata.from != NULL)
-       xmlFree(comp->numdata.from);
-    if (comp->numdata.value != NULL)
-       xmlFree(comp->numdata.value);
-    if (comp->numdata.format != NULL)
-       xmlFree(comp->numdata.format);
+
     if (comp->comp != NULL)
        xmlXPathFreeCompExpr(comp->comp);
     if (comp->nsList != NULL)
@@ -203,7 +172,7 @@ xsltElemPreCompPtr
 xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
                 xsltTransformFunction function ATTRIBUTE_UNUSED) {
     xsltStylePreCompPtr comp;
-    xmlChar *filename = NULL;
+    const xmlChar *filename = NULL;
 
     comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
     if (comp == NULL)
@@ -330,16 +299,16 @@ xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {
                                 (const xmlChar *)"lang",
                                 XSLT_NAMESPACE, &comp->has_lang);
 
-    comp->select = xsltGetNsProp(inst,(const xmlChar *)"select", XSLT_NAMESPACE);
+    comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE);
     if (comp->select == NULL) {
        /*
         * The default value of the select attribute is ., which will
         * cause the string-value of the current node to be used as
         * the sort key.
         */
-       comp->select = xmlStrdup((const xmlChar *)".");
+       comp->select = xmlDictLookup(style->dict, BAD_CAST ".", 1);
     }
-    comp->comp = xmlXPathCompile(comp->select);
+    comp->comp = xsltXPathCompile(style, comp->select);
     if (comp->comp == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsltSortComp: could not compile select expression '%s'\n",
@@ -374,7 +343,7 @@ xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     comp->inst = inst;
 
 
-    comp->use = xsltGetNsProp(inst, (const xmlChar *)"use-attribute-sets",
+    comp->use = xsltGetCNsProp(style, inst, (const xmlChar *)"use-attribute-sets",
                                    XSLT_NAMESPACE);
     if (comp->use == NULL)
        comp->has_use = 0;
@@ -384,7 +353,7 @@ xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltTextComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt text node
  *
  * Process the xslt text node on the source node
@@ -392,7 +361,7 @@ xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 static void
 xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     xsltStylePreCompPtr comp;
-    xmlChar *prop;
+    const xmlChar *prop;
 
     if ((style == NULL) || (inst == NULL))
        return;
@@ -403,7 +372,7 @@ xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     comp->inst = inst;
     comp->noescape = 0;
 
-    prop = xsltGetNsProp(inst,
+    prop = xsltGetCNsProp(style, inst,
            (const xmlChar *)"disable-output-escaping",
                        XSLT_NAMESPACE);
     if (prop != NULL) {
@@ -415,13 +384,12 @@ xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 "xsl:text: disable-output-escaping allows only yes or no\n");
            if (style != NULL) style->warnings++;
        }
-       xmlFree(prop);
     }
 }
 
 /**
  * xsltElementComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt element node
  *
  * Process the xslt element node on the source node
@@ -438,12 +406,16 @@ xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     inst->_private = comp;
     comp->inst = inst;
 
-    /*
-     * TODO: more computation can be done there, especially namespace lookup
-     */
     comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
                                 (const xmlChar *)"name",
                                 XSLT_NAMESPACE, &comp->has_name);
+    if (comp->name != NULL) {
+       if (xmlValidateQName(comp->name, 0)) {
+           xsltTransformError(NULL, style, inst,
+                   "xsl:element : invalid name\n");
+           if (style != NULL) style->errors++;
+       }
+    }
     comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
                         (const xmlChar *)"namespace",
                         XSLT_NAMESPACE, &comp->has_ns);
@@ -452,7 +424,7 @@ xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
        defaultNs = xmlSearchNs(inst->doc, inst, NULL);
        if (defaultNs != NULL) {
-           comp->ns = xmlStrdup(defaultNs->href);
+           comp->ns = xmlDictLookup(style->dict, defaultNs->href, -1);
            comp->has_ns = 1;
        }
     }
@@ -463,7 +435,7 @@ xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltAttributeComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt attribute node
  *
  * Process the xslt attribute node on the source node
@@ -486,6 +458,13 @@ xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
                                 (const xmlChar *)"name",
                                 XSLT_NAMESPACE, &comp->has_name);
+    if (comp->name != NULL) {
+       if (xmlValidateQName(comp->name, 0)) {
+           xsltTransformError(NULL, style, inst,
+                           "xsl:attribute : invalid QName\n");
+           if (style != NULL) style->errors++;
+       }
+    }
     comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
                         (const xmlChar *)"namespace",
                         XSLT_NAMESPACE, &comp->has_ns);
@@ -494,7 +473,7 @@ xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltCommentComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt comment node
  *
  * Process the xslt comment node on the source node
@@ -514,7 +493,7 @@ xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltProcessingInstructionComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt processing-instruction node
  *
  * Process the xslt processing-instruction node on the source node
@@ -538,7 +517,7 @@ xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltCopyOfComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt copy-of node
  *
  * Process the xslt copy-of node on the source node
@@ -555,7 +534,7 @@ xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     inst->_private = comp;
     comp->inst = inst;
 
-    comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
                                XSLT_NAMESPACE);
     if (comp->select == NULL) {
        xsltTransformError(NULL, style, inst,
@@ -563,7 +542,7 @@ xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
        if (style != NULL) style->errors++;
        return;
     }
-    comp->comp = xmlXPathCompile(comp->select);
+    comp->comp = xsltXPathCompile(style, comp->select);
     if (comp->comp == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsl:copy-of : could not compile select expression '%s'\n",
@@ -574,7 +553,7 @@ xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltValueOfComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt value-of node
  *
  * Process the xslt value-of node on the source node
@@ -582,7 +561,7 @@ xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 static void
 xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     xsltStylePreCompPtr comp;
-    xmlChar *prop;
+    const xmlChar *prop;
 
     if ((style == NULL) || (inst == NULL))
        return;
@@ -592,7 +571,7 @@ xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     inst->_private = comp;
     comp->inst = inst;
 
-    prop = xsltGetNsProp(inst,
+    prop = xsltGetCNsProp(style, inst,
            (const xmlChar *)"disable-output-escaping",
                        XSLT_NAMESPACE);
     if (prop != NULL) {
@@ -604,9 +583,8 @@ xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 "xsl:value-of : disable-output-escaping allows only yes or no\n");
            if (style != NULL) style->warnings++;
        }
-       xmlFree(prop);
     }
-    comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
                                XSLT_NAMESPACE);
     if (comp->select == NULL) {
        xsltTransformError(NULL, style, inst,
@@ -614,7 +592,7 @@ xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
        if (style != NULL) style->errors++;
        return;
     }
-    comp->comp = xmlXPathCompile(comp->select);
+    comp->comp = xsltXPathCompile(style, comp->select);
     if (comp->comp == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsl:value-of : could not compile select expression '%s'\n",
@@ -625,7 +603,7 @@ xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltWithParamComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt with-param node
  *
  * Process the xslt with-param node on the source node
@@ -633,7 +611,7 @@ xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 static void
 xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     xsltStylePreCompPtr comp;
-    xmlChar *prop;
+    const xmlChar *prop;
 
     if ((style == NULL) || (inst == NULL))
        return;
@@ -646,7 +624,7 @@ xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     /*
      * The full namespace resolution can be done statically
      */
-    prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
+    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
     if (prop == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsl:with-param : name is missing\n");
@@ -669,10 +647,10 @@ xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
        }
     }
 
-    comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
                                XSLT_NAMESPACE);
     if (comp->select != NULL) {
-       comp->comp = xmlXPathCompile(comp->select);
+       comp->comp = xsltXPathCompile(style, comp->select);
        if (comp->comp == NULL) {
            xsltTransformError(NULL, style, inst,
                 "xsl:param : could not compile select expression '%s'\n",
@@ -689,7 +667,7 @@ xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltNumberComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @cur:   the xslt number node
  *
  * Process the xslt number node on the source node
@@ -697,7 +675,7 @@ xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 static void
 xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
     xsltStylePreCompPtr comp;
-    xmlChar *prop;
+    const xmlChar *prop;
 
     if ((style == NULL) || (cur == NULL))
        return;
@@ -711,24 +689,24 @@ xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
 
     comp->numdata.doc = cur->doc;
     comp->numdata.node = cur;
-    comp->numdata.value = xsltGetNsProp(cur, (const xmlChar *)"value",
+    comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",
                                        XSLT_NAMESPACE);
     
     prop = xsltEvalStaticAttrValueTemplate(style, cur,
                         (const xmlChar *)"format",
                         XSLT_NAMESPACE, &comp->numdata.has_format);
     if (comp->numdata.has_format == 0) {
-       comp->numdata.format = xmlStrdup(BAD_CAST(""));
+       comp->numdata.format = xmlDictLookup(style->dict, BAD_CAST "" , 0);
     } else {
        comp->numdata.format = prop;
     }
 
-    comp->numdata.count = xsltGetNsProp(cur, (const xmlChar *)"count",
+    comp->numdata.count = xsltGetCNsProp(style, cur, (const xmlChar *)"count",
                                        XSLT_NAMESPACE);
-    comp->numdata.from = xsltGetNsProp(cur, (const xmlChar *)"from",
+    comp->numdata.from = xsltGetCNsProp(style, cur, (const xmlChar *)"from",
                                        XSLT_NAMESPACE);
     
-    prop = xsltGetNsProp(cur, (const xmlChar *)"level", XSLT_NAMESPACE);
+    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"level", XSLT_NAMESPACE);
     if (prop != NULL) {
        if (xmlStrEqual(prop, BAD_CAST("single")) ||
            xmlStrEqual(prop, BAD_CAST("multiple")) ||
@@ -742,13 +720,13 @@ xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
        }
     }
     
-    prop = xsltGetNsProp(cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
+    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
     if (prop != NULL) {
        XSLT_TODO; /* xsl:number lang attribute */
        xmlFree(prop);
     }
     
-    prop = xsltGetNsProp(cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
+    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
     if (prop != NULL) {
        if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {
            xsltTransformError(NULL, style, cur,
@@ -765,22 +743,19 @@ xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
                     "xsl:number : invalid value %s for letter-value\n", prop);
            if (style != NULL) style->warnings++;
        }
-       xmlFree(prop);
     }
     
-    prop = xsltGetNsProp(cur, (const xmlChar *)"grouping-separator",
+    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-separator",
                        XSLT_NAMESPACE);
     if (prop != NULL) {
         comp->numdata.groupingCharacterLen = xmlStrlen(prop);
        comp->numdata.groupingCharacter =
            xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));
-       xmlFree(prop);
     }
     
-    prop = xsltGetNsProp(cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);
+    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);
     if (prop != NULL) {
        sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup);
-       xmlFree(prop);
     } else {
        comp->numdata.groupingCharacter = 0;
     }
@@ -788,7 +763,8 @@ xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
     /* Set default values */
     if (comp->numdata.value == NULL) {
        if (comp->numdata.level == NULL) {
-           comp->numdata.level = xmlStrdup(BAD_CAST("single"));
+           comp->numdata.level = xmlDictLookup(style->dict,
+                                               BAD_CAST"single", 6);
        }
     }
     
@@ -796,7 +772,7 @@ xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
 
 /**
  * xsltApplyImportsComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt apply-imports node
  *
  * Process the xslt apply-imports node on the source node
@@ -816,7 +792,7 @@ xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltCallTemplateComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt call-template node
  *
  * Process the xslt call-template node on the source node
@@ -824,7 +800,7 @@ xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 static void
 xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     xsltStylePreCompPtr comp;
-    xmlChar *prop;
+    const xmlChar *prop;
 
     if ((style == NULL) || (inst == NULL))
        return;
@@ -837,7 +813,7 @@ xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     /*
      * The full template resolution can be done statically
      */
-    prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
+    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
     if (prop == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsl:call-template : name is missing\n");
@@ -864,7 +840,7 @@ xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltApplyTemplatesComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the apply-templates node
  *
  * Process the apply-templates node on the source node
@@ -872,7 +848,7 @@ xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 static void
 xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     xsltStylePreCompPtr comp;
-    xmlChar *prop;
+    const xmlChar *prop;
 
     if ((style == NULL) || (inst == NULL))
        return;
@@ -885,7 +861,7 @@ xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     /*
      * Get mode if any
      */
-    prop = xsltGetNsProp(inst, (const xmlChar *)"mode", XSLT_NAMESPACE);
+    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"mode", XSLT_NAMESPACE);
     if (prop != NULL) {
         const xmlChar *URI;
 
@@ -901,10 +877,10 @@ xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
            }
        }
     }
-    comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
                                XSLT_NAMESPACE);
     if (comp->select != NULL) {
-       comp->comp = xmlXPathCompile(comp->select);
+       comp->comp = xsltXPathCompile(style, comp->select);
        if (comp->comp == NULL) {
            xsltTransformError(NULL, style, inst,
      "xsl:apply-templates : could not compile select expression '%s'\n",
@@ -918,7 +894,7 @@ xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltChooseComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt choose node
  *
  * Process the xslt choose node on the source node
@@ -938,7 +914,7 @@ xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltIfComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt if node
  *
  * Process the xslt if node on the source node
@@ -955,14 +931,14 @@ xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     inst->_private = comp;
     comp->inst = inst;
 
-    comp->test = xsltGetNsProp(inst, (const xmlChar *)"test", XSLT_NAMESPACE);
+    comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
     if (comp->test == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsl:if : test is not defined\n");
        if (style != NULL) style->errors++;
        return;
     }
-    comp->comp = xmlXPathCompile(comp->test);
+    comp->comp = xsltXPathCompile(style, comp->test);
     if (comp->comp == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsl:if : could not compile test expression '%s'\n",
@@ -973,7 +949,7 @@ xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltWhenComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt if node
  *
  * Process the xslt if node on the source node
@@ -990,14 +966,14 @@ xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     inst->_private = comp;
     comp->inst = inst;
 
-    comp->test = xsltGetNsProp(inst, (const xmlChar *)"test", XSLT_NAMESPACE);
+    comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
     if (comp->test == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsl:when : test is not defined\n");
        if (style != NULL) style->errors++;
        return;
     }
-    comp->comp = xmlXPathCompile(comp->test);
+    comp->comp = xsltXPathCompile(style, comp->test);
     if (comp->comp == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsl:when : could not compile test expression '%s'\n",
@@ -1008,7 +984,7 @@ xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltForEachComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt for-each node
  *
  * Process the xslt for-each node on the source node
@@ -1025,14 +1001,14 @@ xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     inst->_private = comp;
     comp->inst = inst;
 
-    comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
                                XSLT_NAMESPACE);
     if (comp->select == NULL) {
        xsltTransformError(NULL, style, inst,
                "xsl:for-each : select is missing\n");
        if (style != NULL) style->errors++;
     } else {
-       comp->comp = xmlXPathCompile(comp->select);
+       comp->comp = xsltXPathCompile(style, comp->select);
        if (comp->comp == NULL) {
            xsltTransformError(NULL, style, inst,
      "xsl:for-each : could not compile select expression '%s'\n",
@@ -1045,7 +1021,7 @@ xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltVariableComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt variable node
  *
  * Process the xslt variable node on the source node
@@ -1053,7 +1029,7 @@ xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 static void
 xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     xsltStylePreCompPtr comp;
-    xmlChar *prop;
+    const xmlChar *prop;
 
     if ((style == NULL) || (inst == NULL))
        return;
@@ -1066,7 +1042,7 @@ xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     /*
      * The full template resolution can be done statically
      */
-    prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
+    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
     if (prop == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsl:variable : name is missing\n");
@@ -1089,10 +1065,10 @@ xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
        }
     }
 
-    comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
                                XSLT_NAMESPACE);
     if (comp->select != NULL) {
-       comp->comp = xmlXPathCompile(comp->select);
+       comp->comp = xsltXPathCompile(style, comp->select);
        if (comp->comp == NULL) {
            xsltTransformError(NULL, style, inst,
                 "xsl:variable : could not compile select expression '%s'\n",
@@ -1109,7 +1085,7 @@ xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 
 /**
  * xsltParamComp:
- * @style:  a XSLT process context
+ * @style: an XSLT compiled stylesheet
  * @inst:  the xslt param node
  *
  * Process the xslt param node on the source node
@@ -1117,7 +1093,7 @@ xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
 static void
 xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     xsltStylePreCompPtr comp;
-    xmlChar *prop;
+    const xmlChar *prop;
 
     if ((style == NULL) || (inst == NULL))
        return;
@@ -1130,7 +1106,7 @@ xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     /*
      * The full template resolution can be done statically
      */
-    prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
+    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
     if (prop == NULL) {
        xsltTransformError(NULL, style, inst,
             "xsl:param : name is missing\n");
@@ -1153,10 +1129,10 @@ xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
        }
     }
 
-    comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
                                XSLT_NAMESPACE);
     if (comp->select != NULL) {
-       comp->comp = xmlXPathCompile(comp->select);
+       comp->comp = xsltXPathCompile(style, comp->select);
        if (comp->comp == NULL) {
            xsltTransformError(NULL, style, inst,
                 "xsl:param : could not compile select expression '%s'\n",
index 1af31c9..f120a5d 100644 (file)
@@ -393,7 +393,7 @@ xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
  * Returns the static string value or NULL, must be deallocated by the
  *    caller.
  */
-xmlChar *
+const xmlChar *
 xsltEvalStaticAttrValueTemplate(xsltStylesheetPtr style, xmlNodePtr node,
                        const xmlChar *name, const xmlChar *ns, int *found) {
     const xmlChar *ret;
@@ -414,7 +414,9 @@ xsltEvalStaticAttrValueTemplate(xsltStylesheetPtr style, xmlNodePtr node,
        xmlFree(expr);
        return(NULL);
     }
-    return(expr);
+    ret = xmlDictLookup(style->dict, expr, -1);
+    xmlFree(expr);
+    return(ret);
 }
 
 /**
@@ -430,6 +432,7 @@ xsltEvalStaticAttrValueTemplate(xsltStylesheetPtr style, xmlNodePtr node,
 xmlAttrPtr
 xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
                        xmlAttrPtr cur) {
+    const xmlChar *value;
     xmlNsPtr ns;
     xmlAttrPtr ret;
     if ((ctxt == NULL) || (cur == NULL))
@@ -438,20 +441,18 @@ xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
     if (cur->type != XML_ATTRIBUTE_NODE)
        return(NULL);
 
+    if ((cur->children == NULL) || (cur->children->type != XML_TEXT_NODE) ||
+        (cur->children->next != NULL)) {
+       xsltTransformError(ctxt, NULL, cur->parent,
+               "attribute %s content problem\n", cur->name);
+        return(NULL);
+    }
+    value = cur->children->content;
+    if (value == NULL) value = BAD_CAST "";
     if ((cur->ns != NULL) &&
        (xmlStrEqual(cur->ns->href, XSLT_NAMESPACE))) {
        if (xmlStrEqual(cur->name, (const xmlChar *)"use-attribute-sets")) {
-           xmlChar *in;
-
-           if (ctxt->document != NULL)
-               in = xmlNodeListGetString(ctxt->document->doc,
-                                         cur->children, 1);
-           else
-               in = xmlNodeListGetString(NULL, cur->children, 1);
-           if (in != NULL) {
-               xsltApplyAttributeSet(ctxt, ctxt->node, NULL, in);
-               xmlFree(in);
-           }
+           xsltApplyAttributeSet(ctxt, ctxt->node, NULL, value);
        }
        return(NULL);
     }
@@ -460,27 +461,28 @@ xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
     else
        ns = NULL;
 
-    if (cur->children != NULL) {
-       xmlChar *in;
-       xmlChar *out;
-       
-       if (ctxt->document != NULL)
-           in = xmlNodeListGetString(ctxt->document->doc, cur->children, 1);
-       else
-           in = xmlNodeListGetString(NULL, cur->children, 1);
-
-       /* TODO: optimize if no template value was detected */
-       if (in != NULL) {
-            out = xsltAttrTemplateValueProcessNode(ctxt, in, cur->parent);
-           ret = xmlSetNsProp(target, ns, cur->name, out);
-           if (out != NULL)
-               xmlFree(out);
-           xmlFree(in);
-       } else
-           ret = xmlSetNsProp(target, ns, cur->name, (const xmlChar *)"");
-       
-    } else 
-       ret = xmlSetNsProp(target, ns, cur->name, (const xmlChar *)"");
+    /* TODO output doc->dict, use xmlNewNsPropEatName() instead */
+    ret = xmlNewNsProp(target, ns, cur->name, NULL);
+    if (ret != NULL) {
+        xmlNodePtr text;
+
+        text = xmlNewText(NULL);
+       if (text != NULL) {
+           ret->last = ret->children = text;
+           text->parent = (xmlNodePtr) ret;
+           if (cur->_private != NULL) {
+               xmlChar *val;
+               val = xsltEvalAVT(ctxt, cur->_private, cur->parent);
+               if (val == NULL) {
+                   text->content = xmlStrdup("runtime error");
+               } else {
+                   text->content = val;
+               }
+           } else {
+               text->content = xmlStrdup(value);
+           }
+       }
+    }
     return(ret);
 }
 
index f54948e..b9a6e8f 100644 (file)
@@ -34,7 +34,7 @@ XSLTPUBFUN xmlChar * XSLTCALL
                                                 xmlNodePtr node,
                                                 const xmlChar *name,
                                                 const xmlChar *ns);
-XSLTPUBFUN xmlChar * XSLTCALL  
+XSLTPUBFUN const xmlChar * XSLTCALL    
                xsltEvalStaticAttrValueTemplate (xsltStylesheetPtr style,
                                                 xmlNodePtr node,
                                                 const xmlChar *name,
index 1a69100..c83d154 100644 (file)
@@ -65,6 +65,8 @@ static int xsltGetHTMLIDs(const xmlChar *version, const xmlChar **publicID,
 
 int xsltMaxDepth = 5000;
 
+xmlDictPtr xmlDictCreateSub(xmlDictPtr sub);
+
 /*
  * Useful macros
  */
@@ -450,6 +452,8 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
     cur->traceCode = (unsigned long*) &xsltDefaultTrace;
     cur->parserOptions = XSLT_PARSE_OPTIONS;
 
+    cur->dict = xmlDictCreateSub(style->dict);
+
     return(cur);
 }
 
@@ -494,6 +498,7 @@ xsltFreeTransformContext(xsltTransformContextPtr ctxt) {
     xsltFreeDocuments(ctxt);
     xsltFreeCtxtExts(ctxt);
     xsltFreeRVTs(ctxt);
+    xmlDictFree(ctxt->dict);
     memset(ctxt, -1, sizeof(xsltTransformContext));
     xmlFree(ctxt);
 }
@@ -2161,6 +2166,8 @@ xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
            res = xmlNewDoc(style->version);
            if (res == NULL)
                goto error;
+           res->dict = ctxt->dict;
+           xmlDictReference(res->dict);
        } else {
            xsltTransformError(ctxt, NULL, inst,
                             "xsltDocumentElem: unsupported method %s\n",
@@ -2172,6 +2179,8 @@ xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
        res = xmlNewDoc(style->version);
        if (res == NULL)
            goto error;
+       res->dict = ctxt->dict;
+       xmlDictReference(res->dict);
     }
     res->charset = XML_CHAR_ENCODING_UTF8;
     if (style->encoding != NULL)
@@ -2499,10 +2508,9 @@ xsltText(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED,
 void
 xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
            xmlNodePtr inst, xsltStylePreCompPtr comp) {
-    xmlChar *prop = NULL, *attributes = NULL;
-    xmlChar *ncname = NULL, *name, *namespace;
-    xmlChar *prefix = NULL;
-    xmlChar *value = NULL;
+    xmlChar *prop = NULL, *attributes = NULL, *namespace;
+    const xmlChar *name;
+    const xmlChar *prefix;
     xmlNsPtr ns = NULL, oldns = NULL;
     xmlNodePtr copy;
     xmlNodePtr oldInsert;
@@ -2526,33 +2534,27 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
        if (prop == NULL) {
            xsltTransformError(ctxt, NULL, inst,
                 "xsl:element : name is missing\n");
-           goto error;
+           return;
        }
-       name = prop;
-    } else {
-       name = comp->name;
-    }
-
-    if (xmlValidateQName(name, 0)) {
-       xsltTransformError(ctxt, NULL, inst,
-               "xsl:element : invalid name\n");
-       /* we fall through to catch any other errors if possible */
-    }
-    ncname = xmlSplitQName2(name, &prefix);
-    if (ncname == NULL) {
-       prefix = NULL;
+       if (xmlValidateQName(prop, 0)) {
+           xsltTransformError(ctxt, NULL, inst,
+                   "xsl:element : invalid name\n");
+           /* we fall through to catch any other errors if possible */
+       }
+       name = xsltSplitQName(ctxt->dict, prop, &prefix);
+       xmlFree(prop);
     } else {
-       name = ncname;
+       name = xsltSplitQName(ctxt->dict, comp->name, &prefix);
     }
 
     /*
      * Create the new element
      */
-    copy = xmlNewDocNode(ctxt->output, NULL, name, NULL);
+    copy = xmlNewDocNodeEatName(ctxt->output, NULL, (xmlChar *)name, NULL);
     if (copy == NULL) {
        xsltTransformError(ctxt, NULL, inst,
            "xsl:element : creation of %s failed\n", name);
-       goto error;
+       return;
     }
     xmlAddChild(ctxt->insert, copy);
     ctxt->insert = copy;
@@ -2577,7 +2579,7 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
            xsltGenericDebug(xsltGenericDebugContext,
                 "xsltElement: xml prefix forbidden\n");
 #endif
-           goto error;
+           return;
        }
        oldns = xmlSearchNs(inst->doc, inst, prefix);
        if (oldns == NULL) {
@@ -2623,16 +2625,6 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
     xsltApplyOneTemplate(ctxt, ctxt->node, inst->children, NULL, NULL);
 
     ctxt->insert = oldInsert;
-
-error:
-    if (prop != NULL)
-        xmlFree(prop);
-    if (ncname != NULL)
-        xmlFree(ncname);
-    if (prefix != NULL)
-        xmlFree(prefix);
-    if (value != NULL)
-        xmlFree(value);
 }
 
 
@@ -2692,7 +2684,7 @@ xsltComment(xsltTransformContextPtr ctxt, xmlNodePtr node,
 void
 xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node,
                   xmlNodePtr inst, xsltStylePreCompPtr comp) {
-    xmlChar *ncname = NULL, *name;
+    const xmlChar *name;
     xmlChar *value = NULL;
     xmlNodePtr pi;
 
@@ -2702,14 +2694,13 @@ xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node,
     if (comp->has_name == 0)
        return;
     if (comp->name == NULL) {
-       ncname = xsltEvalAttrValueTemplate(ctxt, inst,
+       name = xsltEvalAttrValueTemplate(ctxt, inst,
                            (const xmlChar *)"name", XSLT_NAMESPACE);
-       if (ncname == NULL) {
+       if (name == NULL) {
            xsltTransformError(ctxt, NULL, inst,
                 "xsl:processing-instruction : name is missing\n");
            goto error;
        }
-       name = ncname;
     } else {
        name = comp->name;
     }
@@ -2725,10 +2716,10 @@ xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node,
 #ifdef WITH_XSLT_DEBUG_PROCESS
     if (value == NULL) {
        XSLT_TRACE(ctxt,XSLT_TRACE_PI,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltProcessingInstruction: %s empty\n", ncname));
+            "xsltProcessingInstruction: %s empty\n", name));
     } else {
        XSLT_TRACE(ctxt,XSLT_TRACE_PI,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltProcessingInstruction: %s content %s\n", ncname, value));
+            "xsltProcessingInstruction: %s content %s\n", name, value));
     }
 #endif
 
@@ -2736,8 +2727,8 @@ xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node,
     xmlAddChild(ctxt->insert, pi);
 
 error:
-    if (ncname != NULL)
-        xmlFree(ncname);
+    if ((name != NULL) && (name != comp->name))
+        xmlFree((xmlChar *) name);
     if (value != NULL)
        xmlFree(value);
 }
@@ -3963,6 +3954,8 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
             }
             if (res == NULL)
                 goto error;
+           res->dict = ctxt->dict;
+           xmlDictReference(res->dict);
         } else if (xmlStrEqual(method, (const xmlChar *) "xhtml")) {
            xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
      "xsltApplyStylesheetInternal: unsupported method xhtml, using html\n",
@@ -3971,11 +3964,15 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
             res = htmlNewDoc(doctypeSystem, doctypePublic);
             if (res == NULL)
                 goto error;
+           res->dict = ctxt->dict;
+           xmlDictReference(res->dict);
         } else if (xmlStrEqual(method, (const xmlChar *) "text")) {
             ctxt->type = XSLT_OUTPUT_TEXT;
             res = xmlNewDoc(style->version);
             if (res == NULL)
                 goto error;
+           res->dict = ctxt->dict;
+           xmlDictReference(res->dict);
         } else {
            xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
                     "xsltApplyStylesheetInternal: unsupported method %s\n",
@@ -3987,6 +3984,8 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
         res = xmlNewDoc(style->version);
         if (res == NULL)
             goto error;
+       res->dict = ctxt->dict;
+       xmlDictReference(ctxt->dict);
     }
     res->charset = XML_CHAR_ENCODING_UTF8;
     if (style->encoding != NULL)
index 323487f..9e7a491 100644 (file)
@@ -57,6 +57,8 @@ xsltCreateRVT(xsltTransformContextPtr ctxt)
     container = xmlNewDoc(NULL);
     if (container == NULL)
        return(NULL);
+    container->dict = ctxt->dict;
+    xmlDictReference(container->dict);
 
     container->name = (char *) xmlStrdup(BAD_CAST " fake node libxslt");
     container->doc = container;
@@ -184,9 +186,9 @@ xsltCopyStackElem(xsltStackElemPtr elem) {
                "xsltCopyStackElem : malloc failed\n");
        return(NULL);
     }
-    cur->name = xmlStrdup(elem->name);
-    cur->nameURI = xmlStrdup(elem->nameURI);
-    cur->select = xmlStrdup(elem->select);
+    cur->name = elem->name;
+    cur->nameURI = elem->nameURI;
+    cur->select = elem->select;
     cur->tree = elem->tree;
     cur->comp = elem->comp;
     cur->computed = 0;
@@ -204,12 +206,6 @@ static void
 xsltFreeStackElem(xsltStackElemPtr elem) {
     if (elem == NULL)
        return;
-    if (elem->name != NULL)
-       xmlFree(elem->name);
-    if (elem->nameURI != NULL)
-       xmlFree(elem->nameURI);
-    if (elem->select != NULL)
-       xmlFree(elem->select);
     if (elem->value != NULL)
        xmlXPathFreeObject(elem->value);
 
@@ -255,8 +251,6 @@ xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
      * Do the lookup from the top of the stack, but
      * don't use params being computed in a call-param
      */
-    ;
-
     for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
        cur = ctxt->varsTab[i-1];
        while (cur != NULL) {
@@ -507,7 +501,7 @@ xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt) {
     xmlNodePtr oldInst;
     int oldNsNr;
     xmlNsPtr *oldNamespaces;
-    xmlChar *name;
+    const xmlChar *name;
 
     if ((ctxt == NULL) || (elem == NULL))
        return(NULL);
@@ -761,8 +755,8 @@ xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,
     if (elem == NULL)
        return(-1);
     elem->comp = comp;
-    elem->name = xmlStrdup(name);
-    elem->select = xmlStrdup(select);
+    elem->name = xmlDictLookup(style->dict, name, -1);
+    elem->select = xmlDictLookup(style->dict, select, -1);
     if (ns_uri)
        elem->nameURI = xmlStrdup(ns_uri);
     elem->tree = tree;
@@ -834,8 +828,7 @@ xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
                             int eval) {
 
     xsltStylesheetPtr style;
-    xmlChar *ncname;
-    xmlChar *prefix;
+    const xmlChar *prefix;
     const xmlChar *href;
     xmlXPathCompExprPtr comp;
     xmlXPathObjectPtr result;
@@ -865,40 +858,29 @@ xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
      * Name lookup
      */
 
-    ncname = xmlSplitQName2(name, &prefix);
+    name = xsltSplitQName(ctxt->dict, name, &prefix);
     href = NULL;
-    if (ncname != NULL) {
-       if (prefix != NULL) {
-           xmlNsPtr ns;
-
-           ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),
-                            prefix);
-           if (ns == NULL) {
-               xsltTransformError(ctxt, style, NULL,
-               "user param : no namespace bound to prefix %s\n", prefix);
-               href = NULL;
-           } else {
-               href = ns->href;
-           }
-           xmlFree(prefix);
-           prefix = NULL;
-       } else {
+    if (prefix != NULL) {
+       xmlNsPtr ns;
+
+       ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),
+                        prefix);
+       if (ns == NULL) {
+           xsltTransformError(ctxt, style, NULL,
+           "user param : no namespace bound to prefix %s\n", prefix);
            href = NULL;
+       } else {
+           href = ns->href;
        }
-       xmlFree(ncname);
-       ncname = NULL;
-    } else {
-       href = NULL;
-       ncname = xmlStrdup(name);
     }
 
-    if (ncname == NULL)
+    if (name == NULL)
        return (-1);
 
-    res_ptr = xmlHashLookup2(ctxt->globalVars, ncname, href);
+    res_ptr = xmlHashLookup2(ctxt->globalVars, name, href);
     if (res_ptr != 0) {
        xsltTransformError(ctxt, style, NULL,
-           "Global parameter %s already defined\n", ncname);
+           "Global parameter %s already defined\n", name);
     }
 
     /*
@@ -909,9 +891,8 @@ xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
        while (elem != NULL) {
            if ((elem->comp != NULL) &&
                (elem->comp->type == XSLT_FUNC_VARIABLE) &&
-               (xmlStrEqual(elem->name, ncname)) &&
+               (xmlStrEqual(elem->name, name)) &&
                (xmlStrEqual(elem->nameURI, href))) {
-               xmlFree(ncname);
                return(0);
            }
             elem = elem->next;
@@ -953,7 +934,6 @@ xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
            xsltTransformError(ctxt, style, NULL,
                "Evaluating user parameter %s failed\n", name);
            ctxt->state = XSLT_STATE_STOPPED;
-           xmlFree(ncname);
            return(-1);
        }
     }
@@ -980,13 +960,13 @@ xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
 
     elem = xsltNewStackElem();
     if (elem != NULL) {
-       elem->name = xmlStrdup(ncname);
+       elem->name = name;
        if (value != NULL)
-           elem->select = xmlStrdup(value);
+           elem->select = xmlDictLookup(ctxt->dict, value, -1);
        else
            elem->select = NULL;
        if (href)
-           elem->nameURI = xmlStrdup(href);
+           elem->nameURI = xmlDictLookup(ctxt->dict, href, -1);
        elem->tree = NULL;
        elem->computed = 1;
        if (eval == 0) {
@@ -1001,13 +981,12 @@ xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
      * Global parameters are stored in the XPath context variables pool.
      */
 
-    res = xmlHashAddEntry2(ctxt->globalVars, ncname, href, elem);
+    res = xmlHashAddEntry2(ctxt->globalVars, name, href, elem);
     if (res != 0) {
        xsltFreeStackElem(elem);
        xsltTransformError(ctxt, style, NULL,
-           "Global parameter %s already defined\n", ncname);
+           "Global parameter %s already defined\n", name);
     }
-    xmlFree(ncname);
     return(0);
 }
 
@@ -1148,13 +1127,13 @@ xsltBuildVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
     if (elem == NULL)
        return(NULL);
     elem->comp = comp;
-    elem->name = xmlStrdup(comp->name);
+    elem->name = comp->name;
     if (comp->select != NULL)
-       elem->select = xmlStrdup(comp->select);
+       elem->select = comp->select;
     else
        elem->select = NULL;
     if (comp->ns)
-       elem->nameURI = xmlStrdup(comp->ns);
+       elem->nameURI = comp->ns;
     elem->tree = tree;
     if (elem->computed == 0) {
        elem->value = xsltEvalVariable(ctxt, elem, comp);
index 8e3fdf7..dfe191d 100644 (file)
@@ -372,6 +372,7 @@ xsltNewStylesheet(void) {
     cur->exclPrefixTab = NULL;
     cur->extInfos = NULL;
     cur->extrasNr = 0;
+    cur->dict = xmlDictCreate();
 
     xsltInit();
 
@@ -513,10 +514,14 @@ xsltFreeStylesheet(xsltStylesheetPtr sheet)
         xmlFree(sheet->doctypeSystem);
     if (sheet->mediaType != NULL)
         xmlFree(sheet->mediaType);
+    if (sheet->attVTs)
+        xsltFreeAVTList(sheet->attVTs);
 
     if (sheet->imports != NULL)
         xsltFreeStylesheetList(sheet->imports);
 
+    xmlDictFree(sheet->dict);
+
     memset(sheet, -1, sizeof(xsltStylesheet));
     xmlFree(sheet);
 }
@@ -1194,6 +1199,7 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur) {
                    goto skip_children;
                }
            }
+
            /*
             * Remove excluded prefixes
             */
@@ -1243,6 +1249,7 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur) {
                    exclPrefixPop(style);
                goto skip_children;
            }
+
        } else if (cur->type == XML_TEXT_NODE) {
            if (IS_BLANK_NODE(cur)) {
                if (xmlNodeGetSpacePreserve(cur) != 1) {
@@ -1469,12 +1476,24 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
                delete = cur;
                goto skip_children;
            }
-       } else if ((cur->ns != NULL) && (style->nsDefs != NULL)) {
-           if (xsltCheckExtPrefix(style, cur->ns->prefix)) {
-               /*
-                * okay this is an extension element compile it too
-                */
-               xsltStylePreCompute(style, cur);
+       } else if ((cur->ns != NULL) && (style->nsDefs != NULL) &&
+                  (xsltCheckExtPrefix(style, cur->ns->prefix))) {
+           /*
+            * okay this is an extension element compile it too
+            */
+           xsltStylePreCompute(style, cur);
+       } else {
+           /*
+            * This is an element which will be output as part of the
+            * template exectution, precompile AVT if found.
+            */
+           if (cur->properties != NULL) {
+               xmlAttrPtr attr = cur->properties;
+
+               while (attr != NULL) {
+                   xsltCompileAttr(style, attr);
+                   attr = attr->next;
+               }
            }
        }
 
@@ -2007,6 +2026,11 @@ xsltParseStylesheetImportedDoc(xmlDocPtr doc, xsltStylesheetPtr style) {
     ret = xsltNewStylesheet();
     if (ret == NULL)
        return(NULL);
+    if (doc->dict != NULL) {
+        xmlDictFree(ret->dict);
+       ret->dict = doc->dict;
+       xmlDictReference(ret->dict);
+    }
     
     ret->doc = doc;
     ret->parent = style;       /* needed to prevent loops */
@@ -2089,11 +2113,7 @@ xsltParseStylesheetFile(const xmlChar* filename) {
        }
     }
 
-#ifdef XSLT_PARSE_OPTIONS
     doc = xmlReadFile((const char *) filename, NULL, XSLT_PARSE_OPTIONS);
-#else
-    doc = xmlParseFile((const char *) filename);
-#endif
     if (doc == NULL) {
        xsltTransformError(NULL, NULL, NULL,
                "xsltParseStylesheetFile : cannot parse %s\n", filename);
@@ -2288,14 +2308,13 @@ xsltLoadStylesheetPI(xmlDocPtr doc) {
                subtree = ID->parent;
                fake = xmlNewDoc(NULL);
                if (fake != NULL) {
-#if LIBXML_VERSION >= 20600
                     /*
                     * the dictionnary should be shared since nodes are
                     * moved over.
                     */
                    fake->dict = doc->dict;
                    xmlDictReference(doc->dict);
-#endif
+
                    xmlUnlinkNode(subtree);
                    xmlAddChild((xmlNodePtr) fake, subtree);
                    ret = xsltParseStylesheetDoc(fake);
index bdc5076..64902a8 100644 (file)
@@ -17,6 +17,7 @@
 #include <libxml/hash.h>
 #include <libxml/xpath.h>
 #include <libxml/xmlerror.h>
+#include <libxml/dict.h>
 #include <libxslt/xslt.h>
 #include "xsltexports.h"
 #include "numbersInternals.h"
@@ -252,38 +253,38 @@ struct _xsltStylePreComp {
      * Pre computed values.
      */
 
-    xmlChar *stype;             /* sort */
+    const xmlChar *stype;       /* sort */
     int      has_stype;                /* sort */
     int      number;           /* sort */
-    xmlChar *order;             /* sort */
+    const xmlChar *order;      /* sort */
     int      has_order;                /* sort */
     int      descending;       /* sort */
-    xmlChar *lang;             /* sort */
+    const xmlChar *lang;       /* sort */
     int      has_lang;         /* sort */
-    xmlChar *case_order;       /* sort */
+    const xmlChar *case_order; /* sort */
     int      lower_first;      /* sort */
 
-    xmlChar *use;              /* copy, element */
+    const xmlChar *use;                /* copy, element */
     int      has_use;          /* copy, element */
 
     int      noescape;         /* text */
 
-    xmlChar *name;             /* element, attribute, pi */
+    const xmlChar *name;       /* element, attribute, pi */
     int      has_name;         /* element, attribute, pi */
-    xmlChar *ns;               /* element */
+    const xmlChar *ns;         /* element */
     int      has_ns;           /* element */
 
-    xmlChar *mode;             /* apply-templates */
-    xmlChar *modeURI;          /* apply-templates */
+    const xmlChar *mode;       /* apply-templates */
+    const xmlChar *modeURI;    /* apply-templates */
 
-    xmlChar *test;             /* if */
+    const xmlChar *test;       /* if */
 
     xsltTemplatePtr templ;     /* call-template */
 
-    xmlChar *select;           /* sort, copy-of, value-of, apply-templates */
+    const xmlChar *select;     /* sort, copy-of, value-of, apply-templates */
 
     int      ver11;            /* document */
-    xmlChar *filename;         /* document URL */
+    const xmlChar *filename;   /* document URL */
     int      has_filename;     /* document */
 
     xsltNumberData numdata;    /* number */
@@ -303,12 +304,12 @@ typedef xsltStackElem *xsltStackElemPtr;
 struct _xsltStackElem {
     struct _xsltStackElem *next;/* chained list */
     xsltStylePreCompPtr comp;   /* the compiled form */
-    int computed;      /* was the evaluation done */
-    xmlChar *name;     /* the local part of the name QName */
-    xmlChar *nameURI;  /* the URI part of the name QName */
-    xmlChar *select;   /* the eval string */
-    xmlNodePtr tree;   /* the tree if no eval string or the location */
-    xmlXPathObjectPtr value; /* The value if computed */
+    int computed;              /* was the evaluation done */
+    const xmlChar *name;       /* the local part of the name QName */
+    const xmlChar *nameURI;    /* the URI part of the name QName */
+    const xmlChar *select;     /* the eval string */
+    xmlNodePtr tree;           /* the tree if no eval string or the location */
+    xmlXPathObjectPtr value;   /* The value if computed */
 };
 
 /*
@@ -421,6 +422,15 @@ struct _xsltStylesheet {
      * For keeping track of nested includes
      */
     xsltDocumentPtr includes;  /* points to last nested include */
+
+    /*
+     * dictionnary: shared between stylesheet, context and documents.
+     */
+    xmlDictPtr dict;
+    /*
+     * precompiled attribute value templates.
+     */
+    void *attVTs;
 };
 
 /*
@@ -527,6 +537,11 @@ struct _xsltTransformContext {
     unsigned long* traceCode;          /* pointer to the variable holding the mask */
 
     int parserOptions;                 /* parser options xmlParserOption */
+
+    /*
+     * dictionnary: shared between stylesheet, context and documents.
+     */
+    xmlDictPtr dict;
 };
 
 /**
@@ -554,6 +569,12 @@ struct _xsltTransformContext {
 #define CHECK_STOPPED0 if (ctxt->state == XSLT_STATE_STOPPED) return(0);
 
 /*
+ * internal value used to indicate attribute value templates
+ */
+
+XSLTPUBVAR void *xsltIsAttVT;
+
+/*
  * Functions associated to the internal types
 xsltDecimalFormatPtr   xsltDecimalFormatGetByName(xsltStylesheetPtr sheet,
                                                   xmlChar *name);
@@ -616,6 +637,18 @@ XSLTPUBFUN int XSLTCALL
 XSLTPUBFUN void XSLTCALL                       
                        xsltFreeRVTs            (xsltTransformContextPtr ctxt);
                        
+/*
+ * Extra functions for Attribute Value Templates
+ */
+XSLTPUBFUN void XSLTCALL
+                       xsltCompileAttr         (xsltStylesheetPtr style,
+                                                xmlAttrPtr attr);
+XSLTPUBFUN xmlChar * XSLTCALL
+                       xsltEvalAVT             (xsltTransformContextPtr ctxt,
+                                                void *avt,
+                                                xmlNodePtr node);
+XSLTPUBFUN void XSLTCALL
+                       xsltFreeAVTList         (void *avt);
 #ifdef __cplusplus
 }
 #endif
index bc6f6a3..b984e46 100644 (file)
  ************************************************************************/
 
 /**
+ * xsltGetCNsProp:
+ * @style: the stylesheet
+ * @node:  the node
+ * @name:  the attribute name
+ * @nameSpace:  the URI of the namespace
+ *
+ * Similar to xmlGetNsProp() but with a slightly different semantic
+ *
+ * Search and get the value of an attribute associated to a node
+ * This attribute has to be anchored in the namespace specified,
+ * or has no namespace and the element is in that namespace.
+ *
+ * This does the entity substitution.
+ * This function looks in DTD attribute declaration for #FIXED or
+ * default declaration values unless DTD use has been turned off.
+ *
+ * Returns the attribute value or NULL if not found. The string is allocated
+ *         in the stylesheet dictionnary.
+ */
+const xmlChar *
+xsltGetCNsProp(xsltStylesheetPtr style, xmlNodePtr node,
+              const xmlChar *name, const xmlChar *nameSpace) {
+    xmlAttrPtr prop;
+    xmlDocPtr doc;
+    xmlNsPtr ns;
+    xmlChar *tmp;
+    const xmlChar *ret;
+
+    if ((node == NULL) || (style == NULL) || (style->dict == NULL))
+       return(NULL);
+
+    prop = node->properties;
+    if (nameSpace == NULL) {
+        tmp = xmlGetProp(node, name);
+       goto found;
+    }
+    while (prop != NULL) {
+       /*
+        * One need to have
+        *   - same attribute names
+        *   - and the attribute carrying that namespace
+        */
+        if ((xmlStrEqual(prop->name, name)) &&
+           (((prop->ns == NULL) && (node->ns != NULL) &&
+             (xmlStrEqual(node->ns->href, nameSpace))) ||
+            ((prop->ns != NULL) &&
+             (xmlStrEqual(prop->ns->href, nameSpace))))) {
+
+           tmp = xmlNodeListGetString(node->doc, prop->children, 1);
+           goto found;
+        }
+       prop = prop->next;
+    }
+
+    /*
+     * Check if there is a default declaration in the internal
+     * or external subsets
+     */
+    doc =  node->doc;
+    if (doc != NULL) {
+        if (doc->intSubset != NULL) {
+           xmlAttributePtr attrDecl;
+
+           attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
+           if ((attrDecl == NULL) && (doc->extSubset != NULL))
+               attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
+               
+           if ((attrDecl != NULL) && (attrDecl->prefix != NULL)) {
+               /*
+                * The DTD declaration only allows a prefix search
+                */
+               ns = xmlSearchNs(doc, node, attrDecl->prefix);
+               if ((ns != NULL) && (xmlStrEqual(ns->href, nameSpace)))
+                   return(xmlDictLookup(style->dict,
+                                        attrDecl->defaultValue, -1));
+           }
+       }
+    }
+    return(NULL);
+found:
+    if (tmp == NULL)
+        ret = xmlDictLookup(style->dict, BAD_CAST "", 0);
+    else {
+       ret = xmlDictLookup(style->dict, tmp, -1);
+       xmlFree(tmp);
+    }
+    return(ret);
+}
+/**
  * xsltGetNsProp:
  * @node:  the node
  * @name:  the attribute name
@@ -506,6 +595,32 @@ xsltTransformError(xsltTransformContextPtr ctxt,
  ************************************************************************/
 
 /**
+ * xsltSplitQName:
+ * @dict: a dictionnary
+ * @name:  the full QName
+ * @prefix: the return value
+ *
+ * Split QNames into prefix and local names, both allocated from a dictionnary.
+ *
+ * Returns: the localname or NULL in case of error.
+ */
+const xmlChar *
+xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix) {
+    int len = 0;
+    const xmlChar *ret = NULL;
+
+    *prefix = NULL;
+    if ((name == NULL) || (dict == NULL)) return(NULL);
+    if (name[0] == ':')
+        return(xmlDictLookup(dict, name, -1));
+    while ((name[len] != 0) && (name[len] != ':')) len++;
+    if (name[len] == 0) return(xmlDictLookup(dict, name, -1));
+    *prefix = xmlDictLookup(dict, name, len);
+    ret = xmlDictLookup(dict, &name[len + 1], -1);
+    return(ret);
+}
+
+/**
  * xsltGetQNameURI:
  * @node:  the node holding the QName
  * @name:  pointer to the initial QName value
@@ -1723,6 +1838,38 @@ xsltGetProfileInformation(xsltTransformContextPtr ctxt)
 
 /************************************************************************
  *                                                                     *
+ *             Hooks for libxml2 XPath                                 *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltXPathCompile:
+ * @style: the stylesheet
+ * @str:  the XPath expression
+ *
+ * Compile an XPath expression
+ *
+ * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
+ *         the caller has to free the object.
+ */
+xmlXPathCompExprPtr
+xsltXPathCompile(xsltStylesheetPtr style, const xmlChar *str) {
+    xmlXPathContext xctxt;
+    xmlXPathCompExprPtr ret;
+
+    memset(&xctxt, 0, sizeof(xctxt));
+    if (style != NULL)
+       xctxt.dict = style->dict;
+    ret = xmlXPathCtxtCompile(&xctxt, str);
+    /*
+     * TODO: there is a lot of optimizations which should be possible
+     *       like variable slot precomputations, function precomputations, etc.
+     */
+     
+    return(ret);
+}
+/************************************************************************
+ *                                                                     *
  *             Hooks for the debugger                                  *
  *                                                                     *
  ************************************************************************/
index 547c82b..d1f0cfe 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdarg.h>
 #endif
 #include <libxml/xpath.h>
+#include <libxml/dict.h>
 #include <libxml/xmlerror.h>
 #include "xsltexports.h"
 #include "xsltInternals.h"
@@ -83,11 +84,18 @@ extern "C" {
 /*
  * Our own version of namespaced atributes lookup.
  */
-XSLTPUBFUN xmlChar * XSLTCALL  xsltGetNsProp   (xmlNodePtr node,
-                                                const xmlChar *name,
-                                                const xmlChar *nameSpace);
-XSLTPUBFUN int XSLTCALL                xsltGetUTF8Char (const unsigned char *utf,
-                                                int *len);
+XSLTPUBFUN xmlChar * XSLTCALL
+               xsltGetNsProp   (xmlNodePtr node,
+                                const xmlChar *name,
+                                const xmlChar *nameSpace);
+XSLTPUBFUN const xmlChar * XSLTCALL
+               xsltGetCNsProp  (xsltStylesheetPtr style,
+                                xmlNodePtr node,
+                                const xmlChar *name,
+                                const xmlChar *nameSpace);
+XSLTPUBFUN int XSLTCALL
+               xsltGetUTF8Char (const unsigned char *utf,
+                                int *len);
 
 /*
  * XSLT Debug Tracing Tracing Types
@@ -191,6 +199,10 @@ XSLTPUBFUN xmlXPathObjectPtr * XSLTCALL
  * QNames handling.
  */
 
+XSLTPUBFUN const xmlChar * XSLTCALL
+               xsltSplitQName                  (xmlDictPtr dict,
+                                                const xmlChar *name,
+                                                const xmlChar **prefix);
 XSLTPUBFUN const xmlChar * XSLTCALL 
                xsltGetQNameURI                 (xmlNodePtr node,
                                                 xmlChar **name);
@@ -222,6 +234,13 @@ XSLTPUBFUN int XSLTCALL
                                                  xsltStylesheetPtr style);
 
 /*
+ * XPath interface
+ */
+XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
+               xsltXPathCompile                (xsltStylesheetPtr style,
+                                                const xmlChar *str);
+
+/*
  * Profiling.
  */
 XSLTPUBFUN void XSLTCALL