+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
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
xsltexports.h
libxslt_la_SOURCES = \
+ attrvt.c \
xslt.c \
xsltutils.c \
pattern.c \
*/
static void
xsltFreeAttrElem(xsltAttrElemPtr attr) {
- if (attr->set != NULL)
- xmlFree((char *)attr->set);
- if (attr->ns != NULL)
- xmlFree((char *)attr->ns);
xmlFree(attr);
}
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;
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
style->attributeSets = xmlHashCreate(10);
}
if (style->attributeSets == NULL)
- goto error;
+ return;
values = xmlHashLookup2(style->attributeSets, ncname, prefix);
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;
}
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);
}
/**
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;
"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,
}
}
- error:
- if (prop != NULL)
- xmlFree(prop);
- if (ncname != NULL)
- xmlFree(ncname);
- if (prefix != NULL)
- xmlFree(prefix);
+error:
if (value != NULL)
xmlFree(value);
}
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;
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
}
style = xsltNextImport(style);
}
- if (attrib != NULL)
- xmlFree(attrib);
- if (ncname != NULL)
- xmlFree(ncname);
- if (prefix != NULL)
- xmlFree(prefix);
}
attrib = endattr;
}
xsltApplyAttributeSet (xsltTransformContextPtr ctxt,
xmlNodePtr node,
xmlNodePtr inst,
- xmlChar *attributes);
+ const xmlChar *attributes);
XSLTPUBFUN void XSLTCALL
xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style);
#ifdef __cplusplus
--- /dev/null
+/*
+ * 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);
+}
#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"
}
}
+/**
+ * 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:
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);
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);
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",
}
static void
-xsltNumberFormatTokenize(xmlChar *format,
+xsltNumberFormatTokenize(const xmlChar *format,
xsltFormatPtr tokens)
{
int index = 0;
static int
xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
xmlNodePtr node,
- xmlChar *count,
- xmlChar *from,
+ const xmlChar *count,
+ const xmlChar *from,
double *array,
xmlDocPtr doc,
xmlNodePtr elem)
static int
xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context,
xmlNodePtr node,
- xmlChar *count,
- xmlChar *from,
+ const xmlChar *count,
+ const xmlChar *from,
double *array,
int max,
xmlDocPtr doc,
static int
xsltNumberFormatGetValue(xmlXPathContextPtr context,
xmlNodePtr node,
- xmlChar *value,
+ const xmlChar *value,
double *number)
{
int amount = 0;
XSLT_NUMBER_FORMAT_END:
if (tempformat == 1) {
/* The format need to be recomputed each time */
- xmlFree(data->format);
data->format = NULL;
}
if (output != NULL)
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;
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);
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)
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)
(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",
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;
/**
* 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
static void
xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
xsltStylePreCompPtr comp;
- xmlChar *prop;
+ const xmlChar *prop;
if ((style == NULL) || (inst == NULL))
return;
comp->inst = inst;
comp->noescape = 0;
- prop = xsltGetNsProp(inst,
+ prop = xsltGetCNsProp(style, inst,
(const xmlChar *)"disable-output-escaping",
XSLT_NAMESPACE);
if (prop != NULL) {
"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
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);
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;
}
}
/**
* 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
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);
/**
* 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
/**
* 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
/**
* 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
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,
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",
/**
* 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
static void
xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
xsltStylePreCompPtr comp;
- xmlChar *prop;
+ const xmlChar *prop;
if ((style == NULL) || (inst == NULL))
return;
inst->_private = comp;
comp->inst = inst;
- prop = xsltGetNsProp(inst,
+ prop = xsltGetCNsProp(style, inst,
(const xmlChar *)"disable-output-escaping",
XSLT_NAMESPACE);
if (prop != NULL) {
"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,
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",
/**
* 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
static void
xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
xsltStylePreCompPtr comp;
- xmlChar *prop;
+ const xmlChar *prop;
if ((style == NULL) || (inst == NULL))
return;
/*
* 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");
}
}
- 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",
/**
* 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
static void
xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
xsltStylePreCompPtr comp;
- xmlChar *prop;
+ const xmlChar *prop;
if ((style == NULL) || (cur == NULL))
return;
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")) ||
}
}
- 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,
"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;
}
/* 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);
}
}
/**
* 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
/**
* 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
static void
xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
xsltStylePreCompPtr comp;
- xmlChar *prop;
+ const xmlChar *prop;
if ((style == NULL) || (inst == NULL))
return;
/*
* 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");
/**
* 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
static void
xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
xsltStylePreCompPtr comp;
- xmlChar *prop;
+ const xmlChar *prop;
if ((style == NULL) || (inst == NULL))
return;
/*
* 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;
}
}
}
- 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",
/**
* 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
/**
* 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
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",
/**
* 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
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",
/**
* 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
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",
/**
* 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
static void
xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
xsltStylePreCompPtr comp;
- xmlChar *prop;
+ const xmlChar *prop;
if ((style == NULL) || (inst == NULL))
return;
/*
* 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");
}
}
- 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",
/**
* 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
static void
xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
xsltStylePreCompPtr comp;
- xmlChar *prop;
+ const xmlChar *prop;
if ((style == NULL) || (inst == NULL))
return;
/*
* 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");
}
}
- 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",
* 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;
xmlFree(expr);
return(NULL);
}
- return(expr);
+ ret = xmlDictLookup(style->dict, expr, -1);
+ xmlFree(expr);
+ return(ret);
}
/**
xmlAttrPtr
xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
xmlAttrPtr cur) {
+ const xmlChar *value;
xmlNsPtr ns;
xmlAttrPtr ret;
if ((ctxt == NULL) || (cur == NULL))
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);
}
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);
}
xmlNodePtr node,
const xmlChar *name,
const xmlChar *ns);
-XSLTPUBFUN xmlChar * XSLTCALL
+XSLTPUBFUN const xmlChar * XSLTCALL
xsltEvalStaticAttrValueTemplate (xsltStylesheetPtr style,
xmlNodePtr node,
const xmlChar *name,
int xsltMaxDepth = 5000;
+xmlDictPtr xmlDictCreateSub(xmlDictPtr sub);
+
/*
* Useful macros
*/
cur->traceCode = (unsigned long*) &xsltDefaultTrace;
cur->parserOptions = XSLT_PARSE_OPTIONS;
+ cur->dict = xmlDictCreateSub(style->dict);
+
return(cur);
}
xsltFreeDocuments(ctxt);
xsltFreeCtxtExts(ctxt);
xsltFreeRVTs(ctxt);
+ xmlDictFree(ctxt->dict);
memset(ctxt, -1, sizeof(xsltTransformContext));
xmlFree(ctxt);
}
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",
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)
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;
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;
xsltGenericDebug(xsltGenericDebugContext,
"xsltElement: xml prefix forbidden\n");
#endif
- goto error;
+ return;
}
oldns = xmlSearchNs(inst->doc, inst, prefix);
if (oldns == NULL) {
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);
}
void
xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr inst, xsltStylePreCompPtr comp) {
- xmlChar *ncname = NULL, *name;
+ const xmlChar *name;
xmlChar *value = NULL;
xmlNodePtr pi;
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;
}
#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
xmlAddChild(ctxt->insert, pi);
error:
- if (ncname != NULL)
- xmlFree(ncname);
+ if ((name != NULL) && (name != comp->name))
+ xmlFree((xmlChar *) name);
if (value != NULL)
xmlFree(value);
}
}
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",
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",
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)
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;
"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;
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);
* 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) {
xmlNodePtr oldInst;
int oldNsNr;
xmlNsPtr *oldNamespaces;
- xmlChar *name;
+ const xmlChar *name;
if ((ctxt == NULL) || (elem == NULL))
return(NULL);
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;
int eval) {
xsltStylesheetPtr style;
- xmlChar *ncname;
- xmlChar *prefix;
+ const xmlChar *prefix;
const xmlChar *href;
xmlXPathCompExprPtr comp;
xmlXPathObjectPtr result;
* 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);
}
/*
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;
xsltTransformError(ctxt, style, NULL,
"Evaluating user parameter %s failed\n", name);
ctxt->state = XSLT_STATE_STOPPED;
- xmlFree(ncname);
return(-1);
}
}
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) {
* 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);
}
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);
cur->exclPrefixTab = NULL;
cur->extInfos = NULL;
cur->extrasNr = 0;
+ cur->dict = xmlDictCreate();
xsltInit();
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);
}
goto skip_children;
}
}
+
/*
* Remove excluded prefixes
*/
exclPrefixPop(style);
goto skip_children;
}
+
} else if (cur->type == XML_TEXT_NODE) {
if (IS_BLANK_NODE(cur)) {
if (xmlNodeGetSpacePreserve(cur) != 1) {
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;
+ }
}
}
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 */
}
}
-#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);
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);
#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"
* 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 */
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 */
};
/*
* 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;
};
/*
unsigned long* traceCode; /* pointer to the variable holding the mask */
int parserOptions; /* parser options xmlParserOption */
+
+ /*
+ * dictionnary: shared between stylesheet, context and documents.
+ */
+ xmlDictPtr dict;
};
/**
#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);
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
************************************************************************/
/**
+ * 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
************************************************************************/
/**
+ * 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
/************************************************************************
* *
+ * 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 *
* *
************************************************************************/
#include <stdarg.h>
#endif
#include <libxml/xpath.h>
+#include <libxml/dict.h>
#include <libxml/xmlerror.h>
#include "xsltexports.h"
#include "xsltInternals.h"
/*
* 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
* QNames handling.
*/
+XSLTPUBFUN const xmlChar * XSLTCALL
+ xsltSplitQName (xmlDictPtr dict,
+ const xmlChar *name,
+ const xmlChar **prefix);
XSLTPUBFUN const xmlChar * XSLTCALL
xsltGetQNameURI (xmlNodePtr node,
xmlChar **name);
xsltStylesheetPtr style);
/*
+ * XPath interface
+ */
+XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
+ xsltXPathCompile (xsltStylesheetPtr style,
+ const xmlChar *str);
+
+/*
* Profiling.
*/
XSLTPUBFUN void XSLTCALL