Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Unified Diff: third_party/libxslt/libxslt/xslt.c

Issue 2865973002: Check in the libxslt roll script. (Closed)
Patch Set: Consistent quotes. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/libxslt/libxslt/xslt.h ('k') | third_party/libxslt/libxslt/xsltInternals.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/libxslt/libxslt/xslt.c
diff --git a/third_party/libxslt/libxslt/xslt.c b/third_party/libxslt/libxslt/xslt.c
deleted file mode 100644
index b367f9e9405c09389ffe584ec887dab1d94814f5..0000000000000000000000000000000000000000
--- a/third_party/libxslt/libxslt/xslt.c
+++ /dev/null
@@ -1,7042 +0,0 @@
-/*
- * xslt.c: Implemetation of an XSL Transformation 1.0 engine
- *
- * Reference:
- * XSLT specification
- * http://www.w3.org/TR/1999/REC-xslt-19991116
- *
- * Associating Style Sheets with XML documents
- * http://www.w3.org/1999/06/REC-xml-stylesheet-19990629
- *
- * 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/parser.h>
-#include <libxml/tree.h>
-#include <libxml/valid.h>
-#include <libxml/hash.h>
-#include <libxml/uri.h>
-#include <libxml/xmlerror.h>
-#include <libxml/parserInternals.h>
-#include <libxml/xpathInternals.h>
-#include <libxml/xpath.h>
-#include "xslt.h"
-#include "xsltInternals.h"
-#include "pattern.h"
-#include "variables.h"
-#include "namespaces.h"
-#include "attributes.h"
-#include "xsltutils.h"
-#include "imports.h"
-#include "keys.h"
-#include "documents.h"
-#include "extensions.h"
-#include "preproc.h"
-#include "extra.h"
-#include "security.h"
-
-#ifdef WITH_XSLT_DEBUG
-#define WITH_XSLT_DEBUG_PARSING
-/* #define WITH_XSLT_DEBUG_BLANKS */
-#endif
-
-const char *xsltEngineVersion = LIBXSLT_VERSION_STRING LIBXSLT_VERSION_EXTRA;
-const int xsltLibxsltVersion = LIBXSLT_VERSION;
-const int xsltLibxmlVersion = LIBXML_VERSION;
-
-#ifdef XSLT_REFACTORED
-
-const xmlChar *xsltConstNamespaceNameXSLT = (const xmlChar *) XSLT_NAMESPACE;
-
-#define XSLT_ELEMENT_CATEGORY_XSLT 0
-#define XSLT_ELEMENT_CATEGORY_EXTENSION 1
-#define XSLT_ELEMENT_CATEGORY_LRE 2
-
-/*
-* xsltLiteralResultMarker:
-* Marker for Literal result elements, in order to avoid multiple attempts
-* to recognize such elements in the stylesheet's tree.
-* This marker is set on node->psvi during the initial traversal
-* of a stylesheet's node tree.
-*
-const xmlChar *xsltLiteralResultMarker =
- (const xmlChar *) "Literal Result Element";
-*/
-
-/*
-* xsltXSLTTextMarker:
-* Marker for xsl:text elements. Used to recognize xsl:text elements
-* for post-processing of the stylesheet's tree, where those
-* elements are removed from the tree.
-*/
-const xmlChar *xsltXSLTTextMarker = (const xmlChar *) "XSLT Text Element";
-
-/*
-* xsltXSLTAttrMarker:
-* Marker for XSLT attribute on Literal Result Elements.
-*/
-const xmlChar *xsltXSLTAttrMarker = (const xmlChar *) "LRE XSLT Attr";
-
-#endif
-
-#ifdef XSLT_LOCALE_WINAPI
-extern xmlRMutexPtr xsltLocaleMutex;
-#endif
-/*
- * Harmless but avoiding a problem when compiling against a
- * libxml <= 2.3.11 without LIBXML_DEBUG_ENABLED
- */
-#ifndef LIBXML_DEBUG_ENABLED
-double xmlXPathStringEvalNumber(const xmlChar *str);
-#endif
-/*
- * Useful macros
- */
-
-#ifdef IS_BLANK
-#undef IS_BLANK
-#endif
-#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \
- ((c) == 0x0D))
-
-#ifdef IS_BLANK_NODE
-#undef IS_BLANK_NODE
-#endif
-#define IS_BLANK_NODE(n) \
- (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
-
-/**
- * xsltParseContentError:
- *
- * @style: the stylesheet
- * @node: the node where the error occured
- *
- * Compile-time error function.
- */
-static void
-xsltParseContentError(xsltStylesheetPtr style,
- xmlNodePtr node)
-{
- if ((style == NULL) || (node == NULL))
- return;
-
- if (IS_XSLT_ELEM(node))
- xsltTransformError(NULL, style, node,
- "The XSLT-element '%s' is not allowed at this position.\n",
- node->name);
- else
- xsltTransformError(NULL, style, node,
- "The element '%s' is not allowed at this position.\n",
- node->name);
- style->errors++;
-}
-
-#ifdef XSLT_REFACTORED
-#else
-/**
- * exclPrefixPush:
- * @style: the transformation stylesheet
- * @value: the excluded namespace name to push on the stack
- *
- * Push an excluded namespace name on the stack
- *
- * Returns the new index in the stack or -1 if already present or
- * in case of error
- */
-static int
-exclPrefixPush(xsltStylesheetPtr style, xmlChar * value)
-{
- int i;
-
- if (style->exclPrefixMax == 0) {
- style->exclPrefixMax = 4;
- style->exclPrefixTab =
- (xmlChar * *)xmlMalloc(style->exclPrefixMax *
- sizeof(style->exclPrefixTab[0]));
- if (style->exclPrefixTab == NULL) {
- xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
- return (-1);
- }
- }
- /* do not push duplicates */
- for (i = 0;i < style->exclPrefixNr;i++) {
- if (xmlStrEqual(style->exclPrefixTab[i], value))
- return(-1);
- }
- if (style->exclPrefixNr >= style->exclPrefixMax) {
- style->exclPrefixMax *= 2;
- style->exclPrefixTab =
- (xmlChar * *)xmlRealloc(style->exclPrefixTab,
- style->exclPrefixMax *
- sizeof(style->exclPrefixTab[0]));
- if (style->exclPrefixTab == NULL) {
- xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
- return (-1);
- }
- }
- style->exclPrefixTab[style->exclPrefixNr] = value;
- style->exclPrefix = value;
- return (style->exclPrefixNr++);
-}
-/**
- * exclPrefixPop:
- * @style: the transformation stylesheet
- *
- * Pop an excluded prefix value from the stack
- *
- * Returns the stored excluded prefix value
- */
-static xmlChar *
-exclPrefixPop(xsltStylesheetPtr style)
-{
- xmlChar *ret;
-
- if (style->exclPrefixNr <= 0)
- return (0);
- style->exclPrefixNr--;
- if (style->exclPrefixNr > 0)
- style->exclPrefix = style->exclPrefixTab[style->exclPrefixNr - 1];
- else
- style->exclPrefix = NULL;
- ret = style->exclPrefixTab[style->exclPrefixNr];
- style->exclPrefixTab[style->exclPrefixNr] = 0;
- return (ret);
-}
-#endif
-
-/************************************************************************
- * *
- * Helper functions *
- * *
- ************************************************************************/
-
-static int initialized = 0;
-/**
- * xsltInit:
- *
- * Initializes the processor (e.g. registers built-in extensions,
- * etc.)
- */
-void
-xsltInit (void) {
- if (initialized == 0) {
- initialized = 1;
-#ifdef XSLT_LOCALE_WINAPI
- xsltLocaleMutex = xmlNewRMutex();
-#endif
- xsltRegisterAllExtras();
- }
-}
-
-/**
- * xsltUninit:
- *
- * Uninitializes the processor.
- */
-void
-xsltUninit (void) {
-#ifdef XSLT_LOCALE_WINAPI
- xmlFreeRMutex(xsltLocaleMutex);
- xsltLocaleMutex = NULL;
-#endif
- initialized = 0;
-}
-
-/**
- * xsltIsBlank:
- * @str: a string
- *
- * Check if a string is ignorable
- *
- * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
- */
-int
-xsltIsBlank(xmlChar *str) {
- if (str == NULL)
- return(1);
- while (*str != 0) {
- if (!(IS_BLANK(*str))) return(0);
- str++;
- }
- return(1);
-}
-
-/************************************************************************
- * *
- * Routines to handle XSLT data structures *
- * *
- ************************************************************************/
-static xsltDecimalFormatPtr
-xsltNewDecimalFormat(const xmlChar *nsUri, xmlChar *name)
-{
- xsltDecimalFormatPtr self;
- /* UTF-8 for 0x2030 */
- static const xmlChar permille[4] = {0xe2, 0x80, 0xb0, 0};
-
- self = xmlMalloc(sizeof(xsltDecimalFormat));
- if (self != NULL) {
- self->next = NULL;
- self->nsUri = nsUri;
- self->name = name;
-
- /* Default values */
- self->digit = xmlStrdup(BAD_CAST("#"));
- self->patternSeparator = xmlStrdup(BAD_CAST(";"));
- self->decimalPoint = xmlStrdup(BAD_CAST("."));
- self->grouping = xmlStrdup(BAD_CAST(","));
- self->percent = xmlStrdup(BAD_CAST("%"));
- self->permille = xmlStrdup(BAD_CAST(permille));
- self->zeroDigit = xmlStrdup(BAD_CAST("0"));
- self->minusSign = xmlStrdup(BAD_CAST("-"));
- self->infinity = xmlStrdup(BAD_CAST("Infinity"));
- self->noNumber = xmlStrdup(BAD_CAST("NaN"));
- }
- return self;
-}
-
-static void
-xsltFreeDecimalFormat(xsltDecimalFormatPtr self)
-{
- if (self != NULL) {
- if (self->digit)
- xmlFree(self->digit);
- if (self->patternSeparator)
- xmlFree(self->patternSeparator);
- if (self->decimalPoint)
- xmlFree(self->decimalPoint);
- if (self->grouping)
- xmlFree(self->grouping);
- if (self->percent)
- xmlFree(self->percent);
- if (self->permille)
- xmlFree(self->permille);
- if (self->zeroDigit)
- xmlFree(self->zeroDigit);
- if (self->minusSign)
- xmlFree(self->minusSign);
- if (self->infinity)
- xmlFree(self->infinity);
- if (self->noNumber)
- xmlFree(self->noNumber);
- if (self->name)
- xmlFree(self->name);
- xmlFree(self);
- }
-}
-
-static void
-xsltFreeDecimalFormatList(xsltStylesheetPtr self)
-{
- xsltDecimalFormatPtr iter;
- xsltDecimalFormatPtr tmp;
-
- if (self == NULL)
- return;
-
- iter = self->decimalFormat;
- while (iter != NULL) {
- tmp = iter->next;
- xsltFreeDecimalFormat(iter);
- iter = tmp;
- }
-}
-
-/**
- * xsltDecimalFormatGetByName:
- * @style: the XSLT stylesheet
- * @name: the decimal-format name to find
- *
- * Find decimal-format by name
- *
- * Returns the xsltDecimalFormatPtr
- */
-xsltDecimalFormatPtr
-xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name)
-{
- xsltDecimalFormatPtr result = NULL;
-
- if (name == NULL)
- return style->decimalFormat;
-
- while (style != NULL) {
- for (result = style->decimalFormat->next;
- result != NULL;
- result = result->next) {
- if ((result->nsUri == NULL) && xmlStrEqual(name, result->name))
- return result;
- }
- style = xsltNextImport(style);
- }
- return result;
-}
-
-/**
- * xsltDecimalFormatGetByQName:
- * @style: the XSLT stylesheet
- * @nsUri: the namespace URI of the QName
- * @name: the local part of the QName
- *
- * Find decimal-format by QName
- *
- * Returns the xsltDecimalFormatPtr
- */
-xsltDecimalFormatPtr
-xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri,
- const xmlChar *name)
-{
- xsltDecimalFormatPtr result = NULL;
-
- if (name == NULL)
- return style->decimalFormat;
-
- while (style != NULL) {
- for (result = style->decimalFormat->next;
- result != NULL;
- result = result->next) {
- if (xmlStrEqual(nsUri, result->nsUri) &&
- xmlStrEqual(name, result->name))
- return result;
- }
- style = xsltNextImport(style);
- }
- return result;
-}
-
-
-/**
- * xsltNewTemplate:
- *
- * Create a new XSLT Template
- *
- * Returns the newly allocated xsltTemplatePtr or NULL in case of error
- */
-static xsltTemplatePtr
-xsltNewTemplate(void) {
- xsltTemplatePtr cur;
-
- cur = (xsltTemplatePtr) xmlMalloc(sizeof(xsltTemplate));
- if (cur == NULL) {
- xsltTransformError(NULL, NULL, NULL,
- "xsltNewTemplate : malloc failed\n");
- return(NULL);
- }
- memset(cur, 0, sizeof(xsltTemplate));
- cur->priority = XSLT_PAT_NO_PRIORITY;
- return(cur);
-}
-
-/**
- * xsltFreeTemplate:
- * @template: an XSLT template
- *
- * Free up the memory allocated by @template
- */
-static void
-xsltFreeTemplate(xsltTemplatePtr template) {
- if (template == NULL)
- return;
- if (template->match) xmlFree(template->match);
-/*
-* NOTE: @name and @nameURI are put into the string dict now.
-* if (template->name) xmlFree(template->name);
-* if (template->nameURI) xmlFree(template->nameURI);
-*/
-/*
- if (template->mode) xmlFree(template->mode);
- if (template->modeURI) xmlFree(template->modeURI);
- */
- if (template->inheritedNs) xmlFree(template->inheritedNs);
-
- /* free profiling data */
- if (template->templCalledTab) xmlFree(template->templCalledTab);
- if (template->templCountTab) xmlFree(template->templCountTab);
-
- memset(template, -1, sizeof(xsltTemplate));
- xmlFree(template);
-}
-
-/**
- * xsltFreeTemplateList:
- * @template: an XSLT template list
- *
- * Free up the memory allocated by all the elements of @template
- */
-static void
-xsltFreeTemplateList(xsltTemplatePtr template) {
- xsltTemplatePtr cur;
-
- while (template != NULL) {
- cur = template;
- template = template->next;
- xsltFreeTemplate(cur);
- }
-}
-
-#ifdef XSLT_REFACTORED
-
-static void
-xsltFreeNsAliasList(xsltNsAliasPtr item)
-{
- xsltNsAliasPtr tmp;
-
- while (item) {
- tmp = item;
- item = item->next;
- xmlFree(tmp);
- }
- return;
-}
-
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP
-static void
-xsltFreeNamespaceMap(xsltNsMapPtr item)
-{
- xsltNsMapPtr tmp;
-
- while (item) {
- tmp = item;
- item = item->next;
- xmlFree(tmp);
- }
- return;
-}
-
-static xsltNsMapPtr
-xsltNewNamespaceMapItem(xsltCompilerCtxtPtr cctxt,
- xmlDocPtr doc,
- xmlNsPtr ns,
- xmlNodePtr elem)
-{
- xsltNsMapPtr ret;
-
- if ((cctxt == NULL) || (doc == NULL) || (ns == NULL))
- return(NULL);
-
- ret = (xsltNsMapPtr) xmlMalloc(sizeof(xsltNsMap));
- if (ret == NULL) {
- xsltTransformError(NULL, cctxt->style, elem,
- "Internal error: (xsltNewNamespaceMapItem) "
- "memory allocation failed.\n");
- return(NULL);
- }
- memset(ret, 0, sizeof(xsltNsMap));
- ret->doc = doc;
- ret->ns = ns;
- ret->origNsName = ns->href;
- /*
- * Store the item at current stylesheet-level.
- */
- if (cctxt->psData->nsMap != NULL)
- ret->next = cctxt->psData->nsMap;
- cctxt->psData->nsMap = ret;
-
- return(ret);
-}
-#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
-
-/**
- * xsltCompilerVarInfoFree:
- * @cctxt: the compilation context
- *
- * Frees the list of information for vars/params.
- */
-static void
-xsltCompilerVarInfoFree(xsltCompilerCtxtPtr cctxt)
-{
- xsltVarInfoPtr ivar = cctxt->ivars, ivartmp;
-
- while (ivar) {
- ivartmp = ivar;
- ivar = ivar->next;
- xmlFree(ivartmp);
- }
-}
-
-/**
- * xsltCompilerCtxtFree:
- *
- * Free an XSLT compiler context.
- */
-static void
-xsltCompilationCtxtFree(xsltCompilerCtxtPtr cctxt)
-{
- if (cctxt == NULL)
- return;
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "Freeing compilation context\n");
- xsltGenericDebug(xsltGenericDebugContext,
- "### Max inodes: %d\n", cctxt->maxNodeInfos);
- xsltGenericDebug(xsltGenericDebugContext,
- "### Max LREs : %d\n", cctxt->maxLREs);
-#endif
- /*
- * Free node-infos.
- */
- if (cctxt->inodeList != NULL) {
- xsltCompilerNodeInfoPtr tmp, cur = cctxt->inodeList;
- while (cur != NULL) {
- tmp = cur;
- cur = cur->next;
- xmlFree(tmp);
- }
- }
- if (cctxt->tmpList != NULL)
- xsltPointerListFree(cctxt->tmpList);
-#ifdef XSLT_REFACTORED_XPATHCOMP
- if (cctxt->xpathCtxt != NULL)
- xmlXPathFreeContext(cctxt->xpathCtxt);
-#endif
- if (cctxt->nsAliases != NULL)
- xsltFreeNsAliasList(cctxt->nsAliases);
-
- if (cctxt->ivars)
- xsltCompilerVarInfoFree(cctxt);
-
- xmlFree(cctxt);
-}
-
-/**
- * xsltCompilerCreate:
- *
- * Creates an XSLT compiler context.
- *
- * Returns the pointer to the created xsltCompilerCtxt or
- * NULL in case of an internal error.
- */
-static xsltCompilerCtxtPtr
-xsltCompilationCtxtCreate(xsltStylesheetPtr style) {
- xsltCompilerCtxtPtr ret;
-
- ret = (xsltCompilerCtxtPtr) xmlMalloc(sizeof(xsltCompilerCtxt));
- if (ret == NULL) {
- xsltTransformError(NULL, style, NULL,
- "xsltCompilerCreate: allocation of compiler "
- "context failed.\n");
- return(NULL);
- }
- memset(ret, 0, sizeof(xsltCompilerCtxt));
-
- ret->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
- ret->tmpList = xsltPointerListCreate(20);
- if (ret->tmpList == NULL) {
- goto internal_err;
- }
-#ifdef XSLT_REFACTORED_XPATHCOMP
- /*
- * Create the XPath compilation context in order
- * to speed up precompilation of XPath expressions.
- */
- ret->xpathCtxt = xmlXPathNewContext(NULL);
- if (ret->xpathCtxt == NULL)
- goto internal_err;
-#endif
-
- return(ret);
-
-internal_err:
- xsltCompilationCtxtFree(ret);
- return(NULL);
-}
-
-static void
-xsltLREEffectiveNsNodesFree(xsltEffectiveNsPtr first)
-{
- xsltEffectiveNsPtr tmp;
-
- while (first != NULL) {
- tmp = first;
- first = first->nextInStore;
- xmlFree(tmp);
- }
-}
-
-static void
-xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)
-{
- if (data == NULL)
- return;
-
- if (data->inScopeNamespaces != NULL) {
- int i;
- xsltNsListContainerPtr nsi;
- xsltPointerListPtr list =
- (xsltPointerListPtr) data->inScopeNamespaces;
-
- for (i = 0; i < list->number; i++) {
- /*
- * REVISIT TODO: Free info of in-scope namespaces.
- */
- nsi = (xsltNsListContainerPtr) list->items[i];
- if (nsi->list != NULL)
- xmlFree(nsi->list);
- xmlFree(nsi);
- }
- xsltPointerListFree(list);
- data->inScopeNamespaces = NULL;
- }
-
- if (data->exclResultNamespaces != NULL) {
- int i;
- xsltPointerListPtr list = (xsltPointerListPtr)
- data->exclResultNamespaces;
-
- for (i = 0; i < list->number; i++)
- xsltPointerListFree((xsltPointerListPtr) list->items[i]);
-
- xsltPointerListFree(list);
- data->exclResultNamespaces = NULL;
- }
-
- if (data->extElemNamespaces != NULL) {
- xsltPointerListPtr list = (xsltPointerListPtr)
- data->extElemNamespaces;
- int i;
-
- for (i = 0; i < list->number; i++)
- xsltPointerListFree((xsltPointerListPtr) list->items[i]);
-
- xsltPointerListFree(list);
- data->extElemNamespaces = NULL;
- }
- if (data->effectiveNs) {
- xsltLREEffectiveNsNodesFree(data->effectiveNs);
- data->effectiveNs = NULL;
- }
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP
- xsltFreeNamespaceMap(data->nsMap);
-#endif
- xmlFree(data);
-}
-
-static xsltPrincipalStylesheetDataPtr
-xsltNewPrincipalStylesheetData(void)
-{
- xsltPrincipalStylesheetDataPtr ret;
-
- ret = (xsltPrincipalStylesheetDataPtr)
- xmlMalloc(sizeof(xsltPrincipalStylesheetData));
- if (ret == NULL) {
- xsltTransformError(NULL, NULL, NULL,
- "xsltNewPrincipalStylesheetData: memory allocation failed.\n");
- return(NULL);
- }
- memset(ret, 0, sizeof(xsltPrincipalStylesheetData));
-
- /*
- * Global list of in-scope namespaces.
- */
- ret->inScopeNamespaces = xsltPointerListCreate(-1);
- if (ret->inScopeNamespaces == NULL)
- goto internal_err;
- /*
- * Global list of excluded result ns-decls.
- */
- ret->exclResultNamespaces = xsltPointerListCreate(-1);
- if (ret->exclResultNamespaces == NULL)
- goto internal_err;
- /*
- * Global list of extension instruction namespace names.
- */
- ret->extElemNamespaces = xsltPointerListCreate(-1);
- if (ret->extElemNamespaces == NULL)
- goto internal_err;
-
- return(ret);
-
-internal_err:
-
- return(NULL);
-}
-
-#endif
-
-/**
- * xsltNewStylesheet:
- *
- * Create a new XSLT Stylesheet
- *
- * Returns the newly allocated xsltStylesheetPtr or NULL in case of error
- */
-xsltStylesheetPtr
-xsltNewStylesheet(void) {
- xsltStylesheetPtr ret = NULL;
-
- ret = (xsltStylesheetPtr) xmlMalloc(sizeof(xsltStylesheet));
- if (ret == NULL) {
- xsltTransformError(NULL, NULL, NULL,
- "xsltNewStylesheet : malloc failed\n");
- goto internal_err;
- }
- memset(ret, 0, sizeof(xsltStylesheet));
-
- ret->omitXmlDeclaration = -1;
- ret->standalone = -1;
- ret->decimalFormat = xsltNewDecimalFormat(NULL, NULL);
- ret->indent = -1;
- ret->errors = 0;
- ret->warnings = 0;
- ret->exclPrefixNr = 0;
- ret->exclPrefixMax = 0;
- ret->exclPrefixTab = NULL;
- ret->extInfos = NULL;
- ret->extrasNr = 0;
- ret->internalized = 1;
- ret->literal_result = 0;
- ret->forwards_compatible = 0;
- ret->dict = xmlDictCreate();
-#ifdef WITH_XSLT_DEBUG
- xsltGenericDebug(xsltGenericDebugContext,
- "creating dictionary for stylesheet\n");
-#endif
-
- xsltInit();
-
- return(ret);
-
-internal_err:
- if (ret != NULL)
- xsltFreeStylesheet(ret);
- return(NULL);
-}
-
-/**
- * xsltAllocateExtra:
- * @style: an XSLT stylesheet
- *
- * Allocate an extra runtime information slot statically while compiling
- * the stylesheet and return its number
- *
- * Returns the number of the slot
- */
-int
-xsltAllocateExtra(xsltStylesheetPtr style)
-{
- return(style->extrasNr++);
-}
-
-/**
- * xsltAllocateExtraCtxt:
- * @ctxt: an XSLT transformation context
- *
- * Allocate an extra runtime information slot at run-time
- * and return its number
- * This make sure there is a slot ready in the transformation context
- *
- * Returns the number of the slot
- */
-int
-xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
-{
- if (ctxt->extrasNr >= ctxt->extrasMax) {
- int i;
- if (ctxt->extrasNr == 0) {
- ctxt->extrasMax = 20;
- ctxt->extras = (xsltRuntimeExtraPtr)
- xmlMalloc(ctxt->extrasMax * sizeof(xsltRuntimeExtra));
- if (ctxt->extras == NULL) {
- xsltTransformError(ctxt, NULL, NULL,
- "xsltAllocateExtraCtxt: out of memory\n");
- return(0);
- }
- for (i = 0;i < ctxt->extrasMax;i++) {
- ctxt->extras[i].info = NULL;
- ctxt->extras[i].deallocate = NULL;
- ctxt->extras[i].val.ptr = NULL;
- }
-
- } else {
- xsltRuntimeExtraPtr tmp;
-
- ctxt->extrasMax += 100;
- tmp = (xsltRuntimeExtraPtr) xmlRealloc(ctxt->extras,
- ctxt->extrasMax * sizeof(xsltRuntimeExtra));
- if (tmp == NULL) {
- xsltTransformError(ctxt, NULL, NULL,
- "xsltAllocateExtraCtxt: out of memory\n");
- return(0);
- }
- ctxt->extras = tmp;
- for (i = ctxt->extrasNr;i < ctxt->extrasMax;i++) {
- ctxt->extras[i].info = NULL;
- ctxt->extras[i].deallocate = NULL;
- ctxt->extras[i].val.ptr = NULL;
- }
- }
- }
- return(ctxt->extrasNr++);
-}
-
-/**
- * xsltFreeStylesheetList:
- * @style: an XSLT stylesheet list
- *
- * Free up the memory allocated by the list @style
- */
-static void
-xsltFreeStylesheetList(xsltStylesheetPtr style) {
- xsltStylesheetPtr next;
-
- while (style != NULL) {
- next = style->next;
- xsltFreeStylesheet(style);
- style = next;
- }
-}
-
-/**
- * xsltCleanupStylesheetTree:
- *
- * @doc: the document-node
- * @node: the element where the stylesheet is rooted at
- *
- * Actually @node need not be the document-element, but
- * currently Libxslt does not support embedded stylesheets.
- *
- * Returns 0 if OK, -1 on API or internal errors.
- */
-static int
-xsltCleanupStylesheetTree(xmlDocPtr doc ATTRIBUTE_UNUSED,
- xmlNodePtr rootElem ATTRIBUTE_UNUSED)
-{
-#if 0 /* TODO: Currently disabled, since probably not needed. */
- xmlNodePtr cur;
-
- if ((doc == NULL) || (rootElem == NULL) ||
- (rootElem->type != XML_ELEMENT_NODE) ||
- (doc != rootElem->doc))
- return(-1);
-
- /*
- * Cleanup was suggested by Aleksey Sanin:
- * Clear the PSVI field to avoid problems if the
- * node-tree of the stylesheet is intended to be used for
- * further processing by the user (e.g. for compiling it
- * once again - although not recommended).
- */
-
- cur = rootElem;
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE) {
- /*
- * Clear the PSVI field.
- */
- cur->psvi = NULL;
- if (cur->children) {
- cur = cur->children;
- continue;
- }
- }
-
-leave_node:
- if (cur == rootElem)
- break;
- if (cur->next != NULL)
- cur = cur->next;
- else {
- cur = cur->parent;
- if (cur == NULL)
- break;
- goto leave_node;
- }
- }
-#endif /* #if 0 */
- return(0);
-}
-
-/**
- * xsltFreeStylesheet:
- * @style: an XSLT stylesheet
- *
- * Free up the memory allocated by @style
- */
-void
-xsltFreeStylesheet(xsltStylesheetPtr style)
-{
- if (style == NULL)
- return;
-
-#ifdef XSLT_REFACTORED
- /*
- * Start with a cleanup of the main stylesheet's doc.
- */
- if ((style->principal == style) && (style->doc))
- xsltCleanupStylesheetTree(style->doc,
- xmlDocGetRootElement(style->doc));
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP
- /*
- * Restore changed ns-decls before freeing the document.
- */
- if ((style->doc != NULL) &&
- XSLT_HAS_INTERNAL_NSMAP(style))
- {
- xsltRestoreDocumentNamespaces(XSLT_GET_INTERNAL_NSMAP(style),
- style->doc);
- }
-#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
-#else
- /*
- * Start with a cleanup of the main stylesheet's doc.
- */
- if ((style->parent == NULL) && (style->doc))
- xsltCleanupStylesheetTree(style->doc,
- xmlDocGetRootElement(style->doc));
-#endif /* XSLT_REFACTORED */
-
- xsltFreeKeys(style);
- xsltFreeExts(style);
- xsltFreeTemplateHashes(style);
- xsltFreeDecimalFormatList(style);
- xsltFreeTemplateList(style->templates);
- xsltFreeAttributeSetsHashes(style);
- xsltFreeNamespaceAliasHashes(style);
- xsltFreeStylePreComps(style);
- /*
- * Free documents of all included stylsheet modules of this
- * stylesheet level.
- */
- xsltFreeStyleDocuments(style);
- /*
- * TODO: Best time to shutdown extension stuff?
- */
- xsltShutdownExts(style);
-
- if (style->variables != NULL)
- xsltFreeStackElemList(style->variables);
- if (style->cdataSection != NULL)
- xmlHashFree(style->cdataSection, NULL);
- if (style->stripSpaces != NULL)
- xmlHashFree(style->stripSpaces, NULL);
- if (style->nsHash != NULL)
- xmlHashFree(style->nsHash, NULL);
- if (style->exclPrefixTab != NULL)
- xmlFree(style->exclPrefixTab);
- if (style->method != NULL)
- xmlFree(style->method);
- if (style->methodURI != NULL)
- xmlFree(style->methodURI);
- if (style->version != NULL)
- xmlFree(style->version);
- if (style->encoding != NULL)
- xmlFree(style->encoding);
- if (style->doctypePublic != NULL)
- xmlFree(style->doctypePublic);
- if (style->doctypeSystem != NULL)
- xmlFree(style->doctypeSystem);
- if (style->mediaType != NULL)
- xmlFree(style->mediaType);
- if (style->attVTs)
- xsltFreeAVTList(style->attVTs);
- if (style->imports != NULL)
- xsltFreeStylesheetList(style->imports);
-
-#ifdef XSLT_REFACTORED
- /*
- * If this is the principal stylesheet, then
- * free its internal data.
- */
- if (style->principal == style) {
- if (style->principalData) {
- xsltFreePrincipalStylesheetData(style->principalData);
- style->principalData = NULL;
- }
- }
-#endif
- /*
- * Better to free the main document of this stylesheet level
- * at the end - so here.
- */
- if (style->doc != NULL) {
- xmlFreeDoc(style->doc);
- }
-
-#ifdef WITH_XSLT_DEBUG
- xsltGenericDebug(xsltGenericDebugContext,
- "freeing dictionary from stylesheet\n");
-#endif
- xmlDictFree(style->dict);
-
- memset(style, -1, sizeof(xsltStylesheet));
- xmlFree(style);
-}
-
-/************************************************************************
- * *
- * Parsing of an XSLT Stylesheet *
- * *
- ************************************************************************/
-
-#ifdef XSLT_REFACTORED
- /*
- * This is now performed in an optimized way in xsltParseXSLTTemplate.
- */
-#else
-/**
- * xsltGetInheritedNsList:
- * @style: the stylesheet
- * @template: the template
- * @node: the current node
- *
- * Search all the namespace applying to a given element except the ones
- * from excluded output prefixes currently in scope. Initialize the
- * template inheritedNs list with it.
- *
- * Returns the number of entries found
- */
-static int
-xsltGetInheritedNsList(xsltStylesheetPtr style,
- xsltTemplatePtr template,
- xmlNodePtr node)
-{
- xmlNsPtr cur;
- xmlNsPtr *ret = NULL;
- int nbns = 0;
- int maxns = 10;
- int i;
-
- if ((style == NULL) || (template == NULL) || (node == NULL) ||
- (template->inheritedNsNr != 0) || (template->inheritedNs != NULL))
- return(0);
- while (node != NULL) {
- if (node->type == XML_ELEMENT_NODE) {
- cur = node->nsDef;
- while (cur != NULL) {
- if (xmlStrEqual(cur->href, XSLT_NAMESPACE))
- goto skip_ns;
-
- if ((cur->prefix != NULL) &&
- (xsltCheckExtPrefix(style, cur->prefix)))
- goto skip_ns;
- /*
- * Check if this namespace was excluded.
- * Note that at this point only the exclusions defined
- * on the topmost stylesheet element are in the exclusion-list.
- */
- for (i = 0;i < style->exclPrefixNr;i++) {
- if (xmlStrEqual(cur->href, style->exclPrefixTab[i]))
- goto skip_ns;
- }
- if (ret == NULL) {
- ret =
- (xmlNsPtr *) xmlMalloc((maxns + 1) *
- sizeof(xmlNsPtr));
- if (ret == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "xsltGetInheritedNsList : out of memory!\n");
- return(0);
- }
- ret[nbns] = NULL;
- }
- /*
- * Skip shadowed namespace bindings.
- */
- for (i = 0; i < nbns; i++) {
- if ((cur->prefix == ret[i]->prefix) ||
- (xmlStrEqual(cur->prefix, ret[i]->prefix)))
- break;
- }
- if (i >= nbns) {
- if (nbns >= maxns) {
- maxns *= 2;
- ret = (xmlNsPtr *) xmlRealloc(ret,
- (maxns +
- 1) *
- sizeof(xmlNsPtr));
- if (ret == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "xsltGetInheritedNsList : realloc failed!\n");
- return(0);
- }
- }
- ret[nbns++] = cur;
- ret[nbns] = NULL;
- }
-skip_ns:
- cur = cur->next;
- }
- }
- node = node->parent;
- }
- if (nbns != 0) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "template has %d inherited namespaces\n", nbns);
-#endif
- template->inheritedNsNr = nbns;
- template->inheritedNs = ret;
- }
- return (nbns);
-}
-#endif /* else of XSLT_REFACTORED */
-
-/**
- * xsltParseStylesheetOutput:
- * @style: the XSLT stylesheet
- * @cur: the "output" element
- *
- * parse an XSLT stylesheet output element and record
- * information related to the stylesheet output
- */
-
-void
-xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
-{
- xmlChar *elements,
- *prop;
- xmlChar *element,
- *end;
-
- if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
- return;
-
- prop = xmlGetNsProp(cur, (const xmlChar *) "version", NULL);
- if (prop != NULL) {
- if (style->version != NULL)
- xmlFree(style->version);
- style->version = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *) "encoding", NULL);
- if (prop != NULL) {
- if (style->encoding != NULL)
- xmlFree(style->encoding);
- style->encoding = prop;
- }
-
- /* relaxed to support xt:document
- * TODO KB: What does "relaxed to support xt:document" mean?
- */
- prop = xmlGetNsProp(cur, (const xmlChar *) "method", NULL);
- if (prop != NULL) {
- const xmlChar *URI;
-
- if (style->method != NULL)
- xmlFree(style->method);
- style->method = NULL;
- if (style->methodURI != NULL)
- xmlFree(style->methodURI);
- style->methodURI = NULL;
-
- /*
- * TODO: Don't use xsltGetQNameURI().
- */
- URI = xsltGetQNameURI(cur, &prop);
- if (prop == NULL) {
- if (style != NULL) style->errors++;
- } else if (URI == NULL) {
- if ((xmlStrEqual(prop, (const xmlChar *) "xml")) ||
- (xmlStrEqual(prop, (const xmlChar *) "html")) ||
- (xmlStrEqual(prop, (const xmlChar *) "text"))) {
- style->method = prop;
- } else {
- xsltTransformError(NULL, style, cur,
- "invalid value for method: %s\n", prop);
- if (style != NULL) style->warnings++;
- }
- } else {
- style->method = prop;
- style->methodURI = xmlStrdup(URI);
- }
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-system", NULL);
- if (prop != NULL) {
- if (style->doctypeSystem != NULL)
- xmlFree(style->doctypeSystem);
- style->doctypeSystem = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-public", NULL);
- if (prop != NULL) {
- if (style->doctypePublic != NULL)
- xmlFree(style->doctypePublic);
- style->doctypePublic = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *) "standalone", NULL);
- if (prop != NULL) {
- if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
- style->standalone = 1;
- } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
- style->standalone = 0;
- } else {
- xsltTransformError(NULL, style, cur,
- "invalid value for standalone: %s\n", prop);
- style->errors++;
- }
- xmlFree(prop);
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *) "indent", NULL);
- if (prop != NULL) {
- if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
- style->indent = 1;
- } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
- style->indent = 0;
- } else {
- xsltTransformError(NULL, style, cur,
- "invalid value for indent: %s\n", prop);
- style->errors++;
- }
- xmlFree(prop);
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *) "omit-xml-declaration", NULL);
- if (prop != NULL) {
- if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
- style->omitXmlDeclaration = 1;
- } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
- style->omitXmlDeclaration = 0;
- } else {
- xsltTransformError(NULL, style, cur,
- "invalid value for omit-xml-declaration: %s\n",
- prop);
- style->errors++;
- }
- xmlFree(prop);
- }
-
- elements = xmlGetNsProp(cur, (const xmlChar *) "cdata-section-elements",
- NULL);
- if (elements != NULL) {
- if (style->cdataSection == NULL)
- style->cdataSection = xmlHashCreate(10);
- if (style->cdataSection == NULL)
- return;
-
- element = elements;
- while (*element != 0) {
- while (IS_BLANK(*element))
- element++;
- if (*element == 0)
- break;
- end = element;
- while ((*end != 0) && (!IS_BLANK(*end)))
- end++;
- element = xmlStrndup(element, end - element);
- if (element) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "add cdata section output element %s\n",
- element);
-#endif
- if (xmlValidateQName(BAD_CAST element, 0) != 0) {
- xsltTransformError(NULL, style, cur,
- "Attribute 'cdata-section-elements': The value "
- "'%s' is not a valid QName.\n", element);
- xmlFree(element);
- style->errors++;
- } else {
- const xmlChar *URI;
-
- /*
- * TODO: Don't use xsltGetQNameURI().
- */
- URI = xsltGetQNameURI(cur, &element);
- if (element == NULL) {
- /*
- * TODO: We'll report additionally an error
- * via the stylesheet's error handling.
- */
- xsltTransformError(NULL, style, cur,
- "Attribute 'cdata-section-elements': The value "
- "'%s' is not a valid QName.\n", element);
- style->errors++;
- } else {
- xmlNsPtr ns;
-
- /*
- * XSLT-1.0 "Each QName is expanded into an
- * expanded-name using the namespace declarations in
- * effect on the xsl:output element in which the QName
- * occurs; if there is a default namespace, it is used
- * for QNames that do not have a prefix"
- * NOTE: Fix of bug #339570.
- */
- if (URI == NULL) {
- ns = xmlSearchNs(style->doc, cur, NULL);
- if (ns != NULL)
- URI = ns->href;
- }
- xmlHashAddEntry2(style->cdataSection, element, URI,
- (void *) "cdata");
- xmlFree(element);
- }
- }
- }
- element = end;
- }
- xmlFree(elements);
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *) "media-type", NULL);
- if (prop != NULL) {
- if (style->mediaType)
- xmlFree(style->mediaType);
- style->mediaType = prop;
- }
- if (cur->children != NULL) {
- xsltParseContentError(style, cur->children);
- }
-}
-
-/**
- * xsltParseStylesheetDecimalFormat:
- * @style: the XSLT stylesheet
- * @cur: the "decimal-format" element
- *
- * <!-- Category: top-level-element -->
- * <xsl:decimal-format
- * name = qname, decimal-separator = char, grouping-separator = char,
- * infinity = string, minus-sign = char, NaN = string, percent = char
- * per-mille = char, zero-digit = char, digit = char,
- * pattern-separator = char />
- *
- * parse an XSLT stylesheet decimal-format element and
- * and record the formatting characteristics
- */
-static void
-xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur)
-{
- xmlChar *prop;
- xsltDecimalFormatPtr format;
- xsltDecimalFormatPtr iter;
-
- if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
- return;
-
- format = style->decimalFormat;
-
- prop = xmlGetNsProp(cur, BAD_CAST("name"), NULL);
- if (prop != NULL) {
- const xmlChar *nsUri;
-
- if (xmlValidateQName(prop, 0) != 0) {
- xsltTransformError(NULL, style, cur,
- "xsl:decimal-format: Invalid QName '%s'.\n", prop);
- style->warnings++;
- xmlFree(prop);
- return;
- }
- /*
- * TODO: Don't use xsltGetQNameURI().
- */
- nsUri = xsltGetQNameURI(cur, &prop);
- if (prop == NULL) {
- style->warnings++;
- return;
- }
- format = xsltDecimalFormatGetByQName(style, nsUri, prop);
- if (format != NULL) {
- xsltTransformError(NULL, style, cur,
- "xsltParseStylestyleDecimalFormat: %s already exists\n", prop);
- style->warnings++;
- xmlFree(prop);
- return;
- }
- format = xsltNewDecimalFormat(nsUri, prop);
- if (format == NULL) {
- xsltTransformError(NULL, style, cur,
- "xsltParseStylestyleDecimalFormat: failed creating new decimal-format\n");
- style->errors++;
- xmlFree(prop);
- return;
- }
- /* Append new decimal-format structure */
- for (iter = style->decimalFormat; iter->next; iter = iter->next)
- ;
- if (iter)
- iter->next = format;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *)"decimal-separator", NULL);
- if (prop != NULL) {
- if (format->decimalPoint != NULL) xmlFree(format->decimalPoint);
- format->decimalPoint = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *)"grouping-separator", NULL);
- if (prop != NULL) {
- if (format->grouping != NULL) xmlFree(format->grouping);
- format->grouping = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *)"infinity", NULL);
- if (prop != NULL) {
- if (format->infinity != NULL) xmlFree(format->infinity);
- format->infinity = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *)"minus-sign", NULL);
- if (prop != NULL) {
- if (format->minusSign != NULL) xmlFree(format->minusSign);
- format->minusSign = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *)"NaN", NULL);
- if (prop != NULL) {
- if (format->noNumber != NULL) xmlFree(format->noNumber);
- format->noNumber = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *)"percent", NULL);
- if (prop != NULL) {
- if (format->percent != NULL) xmlFree(format->percent);
- format->percent = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *)"per-mille", NULL);
- if (prop != NULL) {
- if (format->permille != NULL) xmlFree(format->permille);
- format->permille = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *)"zero-digit", NULL);
- if (prop != NULL) {
- if (format->zeroDigit != NULL) xmlFree(format->zeroDigit);
- format->zeroDigit = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *)"digit", NULL);
- if (prop != NULL) {
- if (format->digit != NULL) xmlFree(format->digit);
- format->digit = prop;
- }
-
- prop = xmlGetNsProp(cur, (const xmlChar *)"pattern-separator", NULL);
- if (prop != NULL) {
- if (format->patternSeparator != NULL) xmlFree(format->patternSeparator);
- format->patternSeparator = prop;
- }
- if (cur->children != NULL) {
- xsltParseContentError(style, cur->children);
- }
-}
-
-/**
- * xsltParseStylesheetPreserveSpace:
- * @style: the XSLT stylesheet
- * @cur: the "preserve-space" element
- *
- * parse an XSLT stylesheet preserve-space element and record
- * elements needing preserving
- */
-
-static void
-xsltParseStylesheetPreserveSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
- xmlChar *elements;
- xmlChar *element, *end;
-
- if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
- return;
-
- elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);
- if (elements == NULL) {
- xsltTransformError(NULL, style, cur,
- "xsltParseStylesheetPreserveSpace: missing elements attribute\n");
- if (style != NULL) style->warnings++;
- return;
- }
-
- if (style->stripSpaces == NULL)
- style->stripSpaces = xmlHashCreate(10);
- if (style->stripSpaces == NULL)
- return;
-
- element = elements;
- while (*element != 0) {
- while (IS_BLANK(*element)) element++;
- if (*element == 0)
- break;
- end = element;
- while ((*end != 0) && (!IS_BLANK(*end))) end++;
- element = xmlStrndup(element, end - element);
- if (element) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "add preserved space element %s\n", element);
-#endif
- if (xmlStrEqual(element, (const xmlChar *)"*")) {
- style->stripAll = -1;
- } else {
- const xmlChar *URI;
-
- /*
- * TODO: Don't use xsltGetQNameURI().
- */
- URI = xsltGetQNameURI(cur, &element);
-
- xmlHashAddEntry2(style->stripSpaces, element, URI,
- (xmlChar *) "preserve");
- }
- xmlFree(element);
- }
- element = end;
- }
- xmlFree(elements);
- if (cur->children != NULL) {
- xsltParseContentError(style, cur->children);
- }
-}
-
-#ifdef XSLT_REFACTORED
-#else
-/**
- * xsltParseStylesheetExtPrefix:
- * @style: the XSLT stylesheet
- * @template: the "extension-element-prefixes" prefix
- *
- * parse an XSLT stylesheet's "extension-element-prefix" attribute value
- * and register the namespaces of extension instruction.
- * SPEC "A namespace is designated as an extension namespace by using
- * an extension-element-prefixes attribute on:
- * 1) an xsl:stylesheet element
- * 2) an xsl:extension-element-prefixes attribute on a
- * literal result element
- * 3) an extension instruction."
- */
-static void
-xsltParseStylesheetExtPrefix(xsltStylesheetPtr style, xmlNodePtr cur,
- int isXsltElem) {
- xmlChar *prefixes;
- xmlChar *prefix, *end;
-
- if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
- return;
-
- if (isXsltElem) {
- /* For xsl:stylesheet/xsl:transform. */
- prefixes = xmlGetNsProp(cur,
- (const xmlChar *)"extension-element-prefixes", NULL);
- } else {
- /* For literal result elements and extension instructions. */
- prefixes = xmlGetNsProp(cur,
- (const xmlChar *)"extension-element-prefixes", XSLT_NAMESPACE);
- }
- if (prefixes == NULL) {
- return;
- }
-
- prefix = prefixes;
- while (*prefix != 0) {
- while (IS_BLANK(*prefix)) prefix++;
- if (*prefix == 0)
- break;
- end = prefix;
- while ((*end != 0) && (!IS_BLANK(*end))) end++;
- prefix = xmlStrndup(prefix, end - prefix);
- if (prefix) {
- xmlNsPtr ns;
-
- if (xmlStrEqual(prefix, (const xmlChar *)"#default"))
- ns = xmlSearchNs(style->doc, cur, NULL);
- else
- ns = xmlSearchNs(style->doc, cur, prefix);
- if (ns == NULL) {
- xsltTransformError(NULL, style, cur,
- "xsl:extension-element-prefix : undefined namespace %s\n",
- prefix);
- if (style != NULL) style->warnings++;
- } else {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "add extension prefix %s\n", prefix);
-#endif
- xsltRegisterExtPrefix(style, prefix, ns->href);
- }
- xmlFree(prefix);
- }
- prefix = end;
- }
- xmlFree(prefixes);
-}
-#endif /* else of XSLT_REFACTORED */
-
-/**
- * xsltParseStylesheetStripSpace:
- * @style: the XSLT stylesheet
- * @cur: the "strip-space" element
- *
- * parse an XSLT stylesheet's strip-space element and record
- * the elements needing stripping
- */
-
-static void
-xsltParseStylesheetStripSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
- xmlChar *elements;
- xmlChar *element, *end;
-
- if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
- return;
-
- elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);
- if (elements == NULL) {
- xsltTransformError(NULL, style, cur,
- "xsltParseStylesheetStripSpace: missing elements attribute\n");
- if (style != NULL) style->warnings++;
- return;
- }
-
- if (style->stripSpaces == NULL)
- style->stripSpaces = xmlHashCreate(10);
- if (style->stripSpaces == NULL)
- return;
-
- element = elements;
- while (*element != 0) {
- while (IS_BLANK(*element)) element++;
- if (*element == 0)
- break;
- end = element;
- while ((*end != 0) && (!IS_BLANK(*end))) end++;
- element = xmlStrndup(element, end - element);
- if (element) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "add stripped space element %s\n", element);
-#endif
- if (xmlStrEqual(element, (const xmlChar *)"*")) {
- style->stripAll = 1;
- } else {
- const xmlChar *URI;
-
- /*
- * TODO: Don't use xsltGetQNameURI().
- */
- URI = xsltGetQNameURI(cur, &element);
-
- xmlHashAddEntry2(style->stripSpaces, element, URI,
- (xmlChar *) "strip");
- }
- xmlFree(element);
- }
- element = end;
- }
- xmlFree(elements);
- if (cur->children != NULL) {
- xsltParseContentError(style, cur->children);
- }
-}
-
-#ifdef XSLT_REFACTORED
-#else
-/**
- * xsltParseStylesheetExcludePrefix:
- * @style: the XSLT stylesheet
- * @cur: the current point in the stylesheet
- *
- * parse an XSLT stylesheet exclude prefix and record
- * namespaces needing stripping
- *
- * Returns the number of Excluded prefixes added at that level
- */
-
-static int
-xsltParseStylesheetExcludePrefix(xsltStylesheetPtr style, xmlNodePtr cur,
- int isXsltElem)
-{
- int nb = 0;
- xmlChar *prefixes;
- xmlChar *prefix, *end;
-
- if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
- return(0);
-
- if (isXsltElem)
- prefixes = xmlGetNsProp(cur,
- (const xmlChar *)"exclude-result-prefixes", NULL);
- else
- prefixes = xmlGetNsProp(cur,
- (const xmlChar *)"exclude-result-prefixes", XSLT_NAMESPACE);
-
- if (prefixes == NULL) {
- return(0);
- }
-
- prefix = prefixes;
- while (*prefix != 0) {
- while (IS_BLANK(*prefix)) prefix++;
- if (*prefix == 0)
- break;
- end = prefix;
- while ((*end != 0) && (!IS_BLANK(*end))) end++;
- prefix = xmlStrndup(prefix, end - prefix);
- if (prefix) {
- xmlNsPtr ns;
-
- if (xmlStrEqual(prefix, (const xmlChar *)"#default"))
- ns = xmlSearchNs(style->doc, cur, NULL);
- else
- ns = xmlSearchNs(style->doc, cur, prefix);
- if (ns == NULL) {
- xsltTransformError(NULL, style, cur,
- "xsl:exclude-result-prefixes : undefined namespace %s\n",
- prefix);
- if (style != NULL) style->warnings++;
- } else {
- if (exclPrefixPush(style, (xmlChar *) ns->href) >= 0) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "exclude result prefix %s\n", prefix);
-#endif
- nb++;
- }
- }
- xmlFree(prefix);
- }
- prefix = end;
- }
- xmlFree(prefixes);
- return(nb);
-}
-#endif /* else of XSLT_REFACTORED */
-
-#ifdef XSLT_REFACTORED
-
-/*
-* xsltTreeEnsureXMLDecl:
-* @doc: the doc
-*
-* BIG NOTE:
-* This was copy&pasted from Libxml2's xmlTreeEnsureXMLDecl() in "tree.c".
-* Ensures that there is an XML namespace declaration on the doc.
-*
-* Returns the XML ns-struct or NULL on API and internal errors.
-*/
-static xmlNsPtr
-xsltTreeEnsureXMLDecl(xmlDocPtr doc)
-{
- if (doc == NULL)
- return (NULL);
- if (doc->oldNs != NULL)
- return (doc->oldNs);
- {
- xmlNsPtr ns;
- ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
- if (ns == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "xsltTreeEnsureXMLDecl: Failed to allocate "
- "the XML namespace.\n");
- return (NULL);
- }
- memset(ns, 0, sizeof(xmlNs));
- ns->type = XML_LOCAL_NAMESPACE;
- /*
- * URGENT TODO: revisit this.
- */
-#ifdef LIBXML_NAMESPACE_DICT
- if (doc->dict)
- ns->href = xmlDictLookup(doc->dict, XML_XML_NAMESPACE, -1);
- else
- ns->href = xmlStrdup(XML_XML_NAMESPACE);
-#else
- ns->href = xmlStrdup(XML_XML_NAMESPACE);
-#endif
- ns->prefix = xmlStrdup((const xmlChar *)"xml");
- doc->oldNs = ns;
- return (ns);
- }
-}
-
-/*
-* xsltTreeAcquireStoredNs:
-* @doc: the doc
-* @nsName: the namespace name
-* @prefix: the prefix
-*
-* BIG NOTE:
-* This was copy&pasted from Libxml2's xmlDOMWrapStoreNs() in "tree.c".
-* Creates or reuses an xmlNs struct on doc->oldNs with
-* the given prefix and namespace name.
-*
-* Returns the aquired ns struct or NULL in case of an API
-* or internal error.
-*/
-static xmlNsPtr
-xsltTreeAcquireStoredNs(xmlDocPtr doc,
- const xmlChar *nsName,
- const xmlChar *prefix)
-{
- xmlNsPtr ns;
-
- if (doc == NULL)
- return (NULL);
- if (doc->oldNs != NULL)
- ns = doc->oldNs;
- else
- ns = xsltTreeEnsureXMLDecl(doc);
- if (ns == NULL)
- return (NULL);
- if (ns->next != NULL) {
- /* Reuse. */
- ns = ns->next;
- while (ns != NULL) {
- if ((ns->prefix == NULL) != (prefix == NULL)) {
- /* NOP */
- } else if (prefix == NULL) {
- if (xmlStrEqual(ns->href, nsName))
- return (ns);
- } else {
- if ((ns->prefix[0] == prefix[0]) &&
- xmlStrEqual(ns->prefix, prefix) &&
- xmlStrEqual(ns->href, nsName))
- return (ns);
-
- }
- if (ns->next == NULL)
- break;
- ns = ns->next;
- }
- }
- /* Create. */
- ns->next = xmlNewNs(NULL, nsName, prefix);
- return (ns->next);
-}
-
-/**
- * xsltLREBuildEffectiveNs:
- *
- * Apply ns-aliasing on the namespace of the given @elem and
- * its attributes.
- */
-static int
-xsltLREBuildEffectiveNs(xsltCompilerCtxtPtr cctxt,
- xmlNodePtr elem)
-{
- xmlNsPtr ns;
- xsltNsAliasPtr alias;
-
- if ((cctxt == NULL) || (elem == NULL))
- return(-1);
- if ((cctxt->nsAliases == NULL) || (! cctxt->hasNsAliases))
- return(0);
-
- alias = cctxt->nsAliases;
- while (alias != NULL) {
- if ( /* If both namespaces are NULL... */
- ( (elem->ns == NULL) &&
- ((alias->literalNs == NULL) ||
- (alias->literalNs->href == NULL)) ) ||
- /* ... or both namespace are equal */
- ( (elem->ns != NULL) &&
- (alias->literalNs != NULL) &&
- xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )
- {
- if ((alias->targetNs != NULL) &&
- (alias->targetNs->href != NULL))
- {
- /*
- * Convert namespace.
- */
- if (elem->doc == alias->docOfTargetNs) {
- /*
- * This is the nice case: same docs.
- * This will eventually assign a ns-decl which
- * is shadowed, but this has no negative effect on
- * the generation of the result tree.
- */
- elem->ns = alias->targetNs;
- } else {
- /*
- * This target xmlNs originates from a different
- * stylesheet tree. Try to locate it in the
- * in-scope namespaces.
- * OPTIMIZE TODO: Use the compiler-node-info inScopeNs.
- */
- ns = xmlSearchNs(elem->doc, elem,
- alias->targetNs->prefix);
- /*
- * If no matching ns-decl found, then assign a
- * ns-decl stored in xmlDoc.
- */
- if ((ns == NULL) ||
- (! xmlStrEqual(ns->href, alias->targetNs->href)))
- {
- /*
- * BIG NOTE: The use of xsltTreeAcquireStoredNs()
- * is not very efficient, but currently I don't
- * see an other way of *safely* changing a node's
- * namespace, since the xmlNs struct in
- * alias->targetNs might come from an other
- * stylesheet tree. So we need to anchor it in the
- * current document, without adding it to the tree,
- * which would otherwise change the in-scope-ns
- * semantic of the tree.
- */
- ns = xsltTreeAcquireStoredNs(elem->doc,
- alias->targetNs->href,
- alias->targetNs->prefix);
-
- if (ns == NULL) {
- xsltTransformError(NULL, cctxt->style, elem,
- "Internal error in "
- "xsltLREBuildEffectiveNs(): "
- "failed to acquire a stored "
- "ns-declaration.\n");
- cctxt->style->errors++;
- return(-1);
-
- }
- }
- elem->ns = ns;
- }
- } else {
- /*
- * Move into or leave in the NULL namespace.
- */
- elem->ns = NULL;
- }
- break;
- }
- alias = alias->next;
- }
- /*
- * Same with attributes of literal result elements.
- */
- if (elem->properties != NULL) {
- xmlAttrPtr attr = elem->properties;
-
- while (attr != NULL) {
- if (attr->ns == NULL) {
- attr = attr->next;
- continue;
- }
- alias = cctxt->nsAliases;
- while (alias != NULL) {
- if ( /* If both namespaces are NULL... */
- ( (elem->ns == NULL) &&
- ((alias->literalNs == NULL) ||
- (alias->literalNs->href == NULL)) ) ||
- /* ... or both namespace are equal */
- ( (elem->ns != NULL) &&
- (alias->literalNs != NULL) &&
- xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )
- {
- if ((alias->targetNs != NULL) &&
- (alias->targetNs->href != NULL))
- {
- if (elem->doc == alias->docOfTargetNs) {
- elem->ns = alias->targetNs;
- } else {
- ns = xmlSearchNs(elem->doc, elem,
- alias->targetNs->prefix);
- if ((ns == NULL) ||
- (! xmlStrEqual(ns->href, alias->targetNs->href)))
- {
- ns = xsltTreeAcquireStoredNs(elem->doc,
- alias->targetNs->href,
- alias->targetNs->prefix);
-
- if (ns == NULL) {
- xsltTransformError(NULL, cctxt->style, elem,
- "Internal error in "
- "xsltLREBuildEffectiveNs(): "
- "failed to acquire a stored "
- "ns-declaration.\n");
- cctxt->style->errors++;
- return(-1);
-
- }
- }
- elem->ns = ns;
- }
- } else {
- /*
- * Move into or leave in the NULL namespace.
- */
- elem->ns = NULL;
- }
- break;
- }
- alias = alias->next;
- }
-
- attr = attr->next;
- }
- }
- return(0);
-}
-
-/**
- * xsltLREBuildEffectiveNsNodes:
- *
- * Computes the effective namespaces nodes for a literal result
- * element.
- * @effectiveNs is the set of effective ns-nodes
- * on the literal result element, which will be added to the result
- * element if not already existing in the result tree.
- * This means that excluded namespaces (via exclude-result-prefixes,
- * extension-element-prefixes and the XSLT namespace) not added
- * to the set.
- * Namespace-aliasing was applied on the @effectiveNs.
- */
-static int
-xsltLREBuildEffectiveNsNodes(xsltCompilerCtxtPtr cctxt,
- xsltStyleItemLRElementInfoPtr item,
- xmlNodePtr elem,
- int isLRE)
-{
- xmlNsPtr ns, tmpns;
- xsltEffectiveNsPtr effNs, lastEffNs = NULL;
- int i, j, holdByElem;
- xsltPointerListPtr extElemNs = cctxt->inode->extElemNs;
- xsltPointerListPtr exclResultNs = cctxt->inode->exclResultNs;
-
- if ((cctxt == NULL) || (cctxt->inode == NULL) || (elem == NULL) ||
- (item == NULL) || (item->effectiveNs != NULL))
- return(-1);
-
- if (item->inScopeNs == NULL)
- return(0);
-
- extElemNs = cctxt->inode->extElemNs;
- exclResultNs = cctxt->inode->exclResultNs;
-
- for (i = 0; i < item->inScopeNs->totalNumber; i++) {
- ns = item->inScopeNs->list[i];
- /*
- * Skip namespaces designated as excluded namespaces
- * -------------------------------------------------
- *
- * XSLT-20 TODO: In XSLT 2.0 we need to keep namespaces
- * which are target namespaces of namespace-aliases
- * regardless if designated as excluded.
- *
- * Exclude the XSLT namespace.
- */
- if (xmlStrEqual(ns->href, XSLT_NAMESPACE))
- goto skip_ns;
-
- /*
- * Apply namespace aliasing
- * ------------------------
- *
- * SPEC XSLT 2.0
- * "- A namespace node whose string value is a literal namespace
- * URI is not copied to the result tree.
- * - A namespace node whose string value is a target namespace URI
- * is copied to the result tree, whether or not the URI
- * identifies an excluded namespace."
- *
- * NOTE: The ns-aliasing machanism is non-cascading.
- * (checked with Saxon, Xalan and MSXML .NET).
- * URGENT TODO: is style->nsAliases the effective list of
- * ns-aliases, or do we need to lookup the whole
- * import-tree?
- * TODO: Get rid of import-tree lookup.
- */
- if (cctxt->hasNsAliases) {
- xsltNsAliasPtr alias;
- /*
- * First check for being a target namespace.
- */
- alias = cctxt->nsAliases;
- do {
- /*
- * TODO: Is xmlns="" handled already?
- */
- if ((alias->targetNs != NULL) &&
- (xmlStrEqual(alias->targetNs->href, ns->href)))
- {
- /*
- * Recognized as a target namespace; use it regardless
- * if excluded otherwise.
- */
- goto add_effective_ns;
- }
- alias = alias->next;
- } while (alias != NULL);
-
- alias = cctxt->nsAliases;
- do {
- /*
- * TODO: Is xmlns="" handled already?
- */
- if ((alias->literalNs != NULL) &&
- (xmlStrEqual(alias->literalNs->href, ns->href)))
- {
- /*
- * Recognized as an namespace alias; do not use it.
- */
- goto skip_ns;
- }
- alias = alias->next;
- } while (alias != NULL);
- }
-
- /*
- * Exclude excluded result namespaces.
- */
- if (exclResultNs) {
- for (j = 0; j < exclResultNs->number; j++)
- if (xmlStrEqual(ns->href, BAD_CAST exclResultNs->items[j]))
- goto skip_ns;
- }
- /*
- * Exclude extension-element namespaces.
- */
- if (extElemNs) {
- for (j = 0; j < extElemNs->number; j++)
- if (xmlStrEqual(ns->href, BAD_CAST extElemNs->items[j]))
- goto skip_ns;
- }
-
-add_effective_ns:
- /*
- * OPTIMIZE TODO: This information may not be needed.
- */
- if (isLRE && (elem->nsDef != NULL)) {
- holdByElem = 0;
- tmpns = elem->nsDef;
- do {
- if (tmpns == ns) {
- holdByElem = 1;
- break;
- }
- tmpns = tmpns->next;
- } while (tmpns != NULL);
- } else
- holdByElem = 0;
-
-
- /*
- * Add the effective namespace declaration.
- */
- effNs = (xsltEffectiveNsPtr) xmlMalloc(sizeof(xsltEffectiveNs));
- if (effNs == NULL) {
- xsltTransformError(NULL, cctxt->style, elem,
- "Internal error in xsltLREBuildEffectiveNs(): "
- "failed to allocate memory.\n");
- cctxt->style->errors++;
- return(-1);
- }
- if (cctxt->psData->effectiveNs == NULL) {
- cctxt->psData->effectiveNs = effNs;
- effNs->nextInStore = NULL;
- } else {
- effNs->nextInStore = cctxt->psData->effectiveNs;
- cctxt->psData->effectiveNs = effNs;
- }
-
- effNs->next = NULL;
- effNs->prefix = ns->prefix;
- effNs->nsName = ns->href;
- effNs->holdByElem = holdByElem;
-
- if (lastEffNs == NULL)
- item->effectiveNs = effNs;
- else
- lastEffNs->next = effNs;
- lastEffNs = effNs;
-
-skip_ns:
- {}
- }
- return(0);
-}
-
-
-/**
- * xsltLREInfoCreate:
- *
- * @isLRE: indicates if the given @elem is a literal result element
- *
- * Creates a new info for a literal result element.
- */
-static int
-xsltLREInfoCreate(xsltCompilerCtxtPtr cctxt,
- xmlNodePtr elem,
- int isLRE)
-{
- xsltStyleItemLRElementInfoPtr item;
-
- if ((cctxt == NULL) || (cctxt->inode == NULL))
- return(-1);
-
- item = (xsltStyleItemLRElementInfoPtr)
- xmlMalloc(sizeof(xsltStyleItemLRElementInfo));
- if (item == NULL) {
- xsltTransformError(NULL, cctxt->style, NULL,
- "Internal error in xsltLREInfoCreate(): "
- "memory allocation failed.\n");
- cctxt->style->errors++;
- return(-1);
- }
- memset(item, 0, sizeof(xsltStyleItemLRElementInfo));
- item->type = XSLT_FUNC_LITERAL_RESULT_ELEMENT;
- /*
- * Store it in the stylesheet.
- */
- item->next = cctxt->style->preComps;
- cctxt->style->preComps = (xsltElemPreCompPtr) item;
- /*
- * @inScopeNs are used for execution of XPath expressions
- * in AVTs.
- */
- item->inScopeNs = cctxt->inode->inScopeNs;
-
- if (elem)
- xsltLREBuildEffectiveNsNodes(cctxt, item, elem, isLRE);
-
- cctxt->inode->litResElemInfo = item;
- cctxt->inode->nsChanged = 0;
- cctxt->maxLREs++;
- return(0);
-}
-
-/**
- * xsltCompilerVarInfoPush:
- * @cctxt: the compilation context
- *
- * Pushes a new var/param info onto the stack.
- *
- * Returns the acquired variable info.
- */
-static xsltVarInfoPtr
-xsltCompilerVarInfoPush(xsltCompilerCtxtPtr cctxt,
- xmlNodePtr inst,
- const xmlChar *name,
- const xmlChar *nsName)
-{
- xsltVarInfoPtr ivar;
-
- if ((cctxt->ivar != NULL) && (cctxt->ivar->next != NULL)) {
- ivar = cctxt->ivar->next;
- } else if ((cctxt->ivar == NULL) && (cctxt->ivars != NULL)) {
- ivar = cctxt->ivars;
- } else {
- ivar = (xsltVarInfoPtr) xmlMalloc(sizeof(xsltVarInfo));
- if (ivar == NULL) {
- xsltTransformError(NULL, cctxt->style, inst,
- "xsltParseInScopeVarPush: xmlMalloc() failed!\n");
- cctxt->style->errors++;
- return(NULL);
- }
- /* memset(retVar, 0, sizeof(xsltInScopeVar)); */
- if (cctxt->ivars == NULL) {
- cctxt->ivars = ivar;
- ivar->prev = NULL;
- } else {
- cctxt->ivar->next = ivar;
- ivar->prev = cctxt->ivar;
- }
- cctxt->ivar = ivar;
- ivar->next = NULL;
- }
- ivar->depth = cctxt->depth;
- ivar->name = name;
- ivar->nsName = nsName;
- return(ivar);
-}
-
-/**
- * xsltCompilerVarInfoPop:
- * @cctxt: the compilation context
- *
- * Pops all var/param infos from the stack, which
- * have the current depth.
- */
-static void
-xsltCompilerVarInfoPop(xsltCompilerCtxtPtr cctxt)
-{
-
- while ((cctxt->ivar != NULL) &&
- (cctxt->ivar->depth > cctxt->depth))
- {
- cctxt->ivar = cctxt->ivar->prev;
- }
-}
-
-/*
-* xsltCompilerNodePush:
-*
-* @cctxt: the compilation context
-* @node: the node to be pushed (this can also be the doc-node)
-*
-*
-*
-* Returns the current node info structure or
-* NULL in case of an internal error.
-*/
-static xsltCompilerNodeInfoPtr
-xsltCompilerNodePush(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
-{
- xsltCompilerNodeInfoPtr inode, iprev;
-
- if ((cctxt->inode != NULL) && (cctxt->inode->next != NULL)) {
- inode = cctxt->inode->next;
- } else if ((cctxt->inode == NULL) && (cctxt->inodeList != NULL)) {
- inode = cctxt->inodeList;
- } else {
- /*
- * Create a new node-info.
- */
- inode = (xsltCompilerNodeInfoPtr)
- xmlMalloc(sizeof(xsltCompilerNodeInfo));
- if (inode == NULL) {
- xsltTransformError(NULL, cctxt->style, NULL,
- "xsltCompilerNodePush: malloc failed.\n");
- return(NULL);
- }
- memset(inode, 0, sizeof(xsltCompilerNodeInfo));
- if (cctxt->inodeList == NULL)
- cctxt->inodeList = inode;
- else {
- cctxt->inodeLast->next = inode;
- inode->prev = cctxt->inodeLast;
- }
- cctxt->inodeLast = inode;
- cctxt->maxNodeInfos++;
- if (cctxt->inode == NULL) {
- cctxt->inode = inode;
- /*
- * Create an initial literal result element info for
- * the root of the stylesheet.
- */
- xsltLREInfoCreate(cctxt, NULL, 0);
- }
- }
- cctxt->depth++;
- cctxt->inode = inode;
- /*
- * REVISIT TODO: Keep the reset always complete.
- * NOTE: Be carefull with the @node, since it might be
- * a doc-node.
- */
- inode->node = node;
- inode->depth = cctxt->depth;
- inode->templ = NULL;
- inode->category = XSLT_ELEMENT_CATEGORY_XSLT;
- inode->type = 0;
- inode->item = NULL;
- inode->curChildType = 0;
- inode->extContentHandled = 0;
- inode->isRoot = 0;
-
- if (inode->prev != NULL) {
- iprev = inode->prev;
- /*
- * Inherit the following information:
- * ---------------------------------
- *
- * In-scope namespaces
- */
- inode->inScopeNs = iprev->inScopeNs;
- /*
- * Info for literal result elements
- */
- inode->litResElemInfo = iprev->litResElemInfo;
- inode->nsChanged = iprev->nsChanged;
- /*
- * Excluded result namespaces
- */
- inode->exclResultNs = iprev->exclResultNs;
- /*
- * Extension instruction namespaces
- */
- inode->extElemNs = iprev->extElemNs;
- /*
- * Whitespace preservation
- */
- inode->preserveWhitespace = iprev->preserveWhitespace;
- /*
- * Forwards-compatible mode
- */
- inode->forwardsCompat = iprev->forwardsCompat;
- } else {
- inode->inScopeNs = NULL;
- inode->exclResultNs = NULL;
- inode->extElemNs = NULL;
- inode->preserveWhitespace = 0;
- inode->forwardsCompat = 0;
- }
-
- return(inode);
-}
-
-/*
-* xsltCompilerNodePop:
-*
-* @cctxt: the compilation context
-* @node: the node to be pushed (this can also be the doc-node)
-*
-* Pops the current node info.
-*/
-static void
-xsltCompilerNodePop(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
-{
- if (cctxt->inode == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "xsltCompilerNodePop: Top-node mismatch.\n");
- return;
- }
- /*
- * NOTE: Be carefull with the @node, since it might be
- * a doc-node.
- */
- if (cctxt->inode->node != node) {
- xmlGenericError(xmlGenericErrorContext,
- "xsltCompilerNodePop: Node mismatch.\n");
- goto mismatch;
- }
- if (cctxt->inode->depth != cctxt->depth) {
- xmlGenericError(xmlGenericErrorContext,
- "xsltCompilerNodePop: Depth mismatch.\n");
- goto mismatch;
- }
- cctxt->depth--;
- /*
- * Pop information of variables.
- */
- if ((cctxt->ivar) && (cctxt->ivar->depth > cctxt->depth))
- xsltCompilerVarInfoPop(cctxt);
-
- cctxt->inode = cctxt->inode->prev;
- if (cctxt->inode != NULL)
- cctxt->inode->curChildType = 0;
- return;
-
-mismatch:
- {
- const xmlChar *nsName = NULL, *name = NULL;
- const xmlChar *infnsName = NULL, *infname = NULL;
-
- if (node) {
- if (node->type == XML_ELEMENT_NODE) {
- name = node->name;
- if (node->ns != NULL)
- nsName = node->ns->href;
- else
- nsName = BAD_CAST "";
- } else {
- name = BAD_CAST "#document";
- nsName = BAD_CAST "";
- }
- } else
- name = BAD_CAST "Not given";
-
- if (cctxt->inode->node) {
- if (node->type == XML_ELEMENT_NODE) {
- infname = cctxt->inode->node->name;
- if (cctxt->inode->node->ns != NULL)
- infnsName = cctxt->inode->node->ns->href;
- else
- infnsName = BAD_CAST "";
- } else {
- infname = BAD_CAST "#document";
- infnsName = BAD_CAST "";
- }
- } else
- infname = BAD_CAST "Not given";
-
-
- xmlGenericError(xmlGenericErrorContext,
- "xsltCompilerNodePop: Given : '%s' URI '%s'\n",
- name, nsName);
- xmlGenericError(xmlGenericErrorContext,
- "xsltCompilerNodePop: Expected: '%s' URI '%s'\n",
- infname, infnsName);
- }
-}
-
-/*
-* xsltCompilerBuildInScopeNsList:
-*
-* Create and store the list of in-scope namespaces for the given
-* node in the stylesheet. If there are no changes in the in-scope
-* namespaces then the last ns-info of the ancestor axis will be returned.
-* Compilation-time only.
-*
-* Returns the ns-info or NULL if there are no namespaces in scope.
-*/
-static xsltNsListContainerPtr
-xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
-{
- xsltNsListContainerPtr nsi = NULL;
- xmlNsPtr *list = NULL, ns;
- int i, maxns = 5;
- /*
- * Create a new ns-list for this position in the node-tree.
- * xmlGetNsList() will return NULL, if there are no ns-decls in the
- * tree. Note that the ns-decl for the XML namespace is not added
- * to the resulting list; the XPath module handles the XML namespace
- * internally.
- */
- while (node != NULL) {
- if (node->type == XML_ELEMENT_NODE) {
- ns = node->nsDef;
- while (ns != NULL) {
- if (nsi == NULL) {
- nsi = (xsltNsListContainerPtr)
- xmlMalloc(sizeof(xsltNsListContainer));
- if (nsi == NULL) {
- xsltTransformError(NULL, cctxt->style, NULL,
- "xsltCompilerBuildInScopeNsList: "
- "malloc failed!\n");
- goto internal_err;
- }
- memset(nsi, 0, sizeof(xsltNsListContainer));
- nsi->list =
- (xmlNsPtr *) xmlMalloc(maxns * sizeof(xmlNsPtr));
- if (nsi->list == NULL) {
- xsltTransformError(NULL, cctxt->style, NULL,
- "xsltCompilerBuildInScopeNsList: "
- "malloc failed!\n");
- goto internal_err;
- }
- nsi->list[0] = NULL;
- }
- /*
- * Skip shadowed namespace bindings.
- */
- for (i = 0; i < nsi->totalNumber; i++) {
- if ((ns->prefix == nsi->list[i]->prefix) ||
- (xmlStrEqual(ns->prefix, nsi->list[i]->prefix)))
- break;
- }
- if (i >= nsi->totalNumber) {
- if (nsi->totalNumber +1 >= maxns) {
- maxns *= 2;
- nsi->list =
- (xmlNsPtr *) xmlRealloc(nsi->list,
- maxns * sizeof(xmlNsPtr));
- if (nsi->list == NULL) {
- xsltTransformError(NULL, cctxt->style, NULL,
- "xsltCompilerBuildInScopeNsList: "
- "realloc failed!\n");
- goto internal_err;
- }
- }
- nsi->list[nsi->totalNumber++] = ns;
- nsi->list[nsi->totalNumber] = NULL;
- }
-
- ns = ns->next;
- }
- }
- node = node->parent;
- }
- if (nsi == NULL)
- return(NULL);
- /*
- * Move the default namespace to last position.
- */
- nsi->xpathNumber = nsi->totalNumber;
- for (i = 0; i < nsi->totalNumber; i++) {
- if (nsi->list[i]->prefix == NULL) {
- ns = nsi->list[i];
- nsi->list[i] = nsi->list[nsi->totalNumber-1];
- nsi->list[nsi->totalNumber-1] = ns;
- nsi->xpathNumber--;
- break;
- }
- }
- /*
- * Store the ns-list in the stylesheet.
- */
- if (xsltPointerListAddSize(
- (xsltPointerListPtr)cctxt->psData->inScopeNamespaces,
- (void *) nsi, 5) == -1)
- {
- xmlFree(nsi);
- nsi = NULL;
- xsltTransformError(NULL, cctxt->style, NULL,
- "xsltCompilerBuildInScopeNsList: failed to add ns-info.\n");
- goto internal_err;
- }
- /*
- * Notify of change in status wrt namespaces.
- */
- if (cctxt->inode != NULL)
- cctxt->inode->nsChanged = 1;
-
- return(nsi);
-
-internal_err:
- if (list != NULL)
- xmlFree(list);
- cctxt->style->errors++;
- return(NULL);
-}
-
-static int
-xsltParseNsPrefixList(xsltCompilerCtxtPtr cctxt,
- xsltPointerListPtr list,
- xmlNodePtr node,
- const xmlChar *value)
-{
- xmlChar *cur, *end;
- xmlNsPtr ns;
-
- if ((cctxt == NULL) || (value == NULL) || (list == NULL))
- return(-1);
-
- list->number = 0;
-
- cur = (xmlChar *) value;
- while (*cur != 0) {
- while (IS_BLANK(*cur)) cur++;
- if (*cur == 0)
- break;
- end = cur;
- while ((*end != 0) && (!IS_BLANK(*end))) end++;
- cur = xmlStrndup(cur, end - cur);
- if (cur == NULL) {
- cur = end;
- continue;
- }
- /*
- * TODO: Export and use xmlSearchNsByPrefixStrict()
- * in Libxml2, tree.c, since xmlSearchNs() is in most
- * cases not efficient and in some cases not correct.
- *
- * XSLT-2 TODO: XSLT 2.0 allows an additional "#all" value.
- */
- if ((cur[0] == '#') &&
- xmlStrEqual(cur, (const xmlChar *)"#default"))
- ns = xmlSearchNs(cctxt->style->doc, node, NULL);
- else
- ns = xmlSearchNs(cctxt->style->doc, node, cur);
-
- if (ns == NULL) {
- /*
- * TODO: Better to report the attr-node, otherwise
- * the user won't know which attribute was invalid.
- */
- xsltTransformError(NULL, cctxt->style, node,
- "No namespace binding in scope for prefix '%s'.\n", cur);
- /*
- * XSLT-1.0: "It is an error if there is no namespace
- * bound to the prefix on the element bearing the
- * exclude-result-prefixes or xsl:exclude-result-prefixes
- * attribute."
- */
- cctxt->style->errors++;
- } else {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "resolved prefix '%s'\n", cur);
-#endif
- /*
- * Note that we put the namespace name into the dict.
- */
- if (xsltPointerListAddSize(list,
- (void *) xmlDictLookup(cctxt->style->dict,
- ns->href, -1), 5) == -1)
- {
- xmlFree(cur);
- goto internal_err;
- }
- }
- xmlFree(cur);
-
- cur = end;
- }
- return(0);
-
-internal_err:
- cctxt->style->errors++;
- return(-1);
-}
-
-/**
- * xsltCompilerUtilsCreateMergedList:
- * @dest: the destination list (optional)
- * @first: the first list
- * @second: the second list (optional)
- *
- * Appends the content of @second to @first into @destination.
- * If @destination is NULL a new list will be created.
- *
- * Returns the merged list of items or NULL if there's nothing to merge.
- */
-static xsltPointerListPtr
-xsltCompilerUtilsCreateMergedList(xsltPointerListPtr first,
- xsltPointerListPtr second)
-{
- xsltPointerListPtr ret;
- size_t num;
-
- if (first)
- num = first->number;
- else
- num = 0;
- if (second)
- num += second->number;
- if (num == 0)
- return(NULL);
- ret = xsltPointerListCreate(num);
- if (ret == NULL)
- return(NULL);
- /*
- * Copy contents.
- */
- if ((first != NULL) && (first->number != 0)) {
- memcpy(ret->items, first->items,
- first->number * sizeof(void *));
- if ((second != NULL) && (second->number != 0))
- memcpy(ret->items + first->number, second->items,
- second->number * sizeof(void *));
- } else if ((second != NULL) && (second->number != 0))
- memcpy(ret->items, (void *) second->items,
- second->number * sizeof(void *));
- ret->number = num;
- return(ret);
-}
-
-/*
-* xsltParseExclResultPrefixes:
-*
-* Create and store the list of in-scope namespaces for the given
-* node in the stylesheet. If there are no changes in the in-scope
-* namespaces then the last ns-info of the ancestor axis will be returned.
-* Compilation-time only.
-*
-* Returns the ns-info or NULL if there are no namespaces in scope.
-*/
-static xsltPointerListPtr
-xsltParseExclResultPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
- xsltPointerListPtr def,
- int instrCategory)
-{
- xsltPointerListPtr list = NULL;
- xmlChar *value;
- xmlAttrPtr attr;
-
- if ((cctxt == NULL) || (node == NULL))
- return(NULL);
-
- if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
- attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes", NULL);
- else
- attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes",
- XSLT_NAMESPACE);
- if (attr == NULL)
- return(def);
-
- if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
- /*
- * Mark the XSLT attr.
- */
- attr->psvi = (void *) xsltXSLTAttrMarker;
- }
-
- if ((attr->children != NULL) &&
- (attr->children->content != NULL))
- value = attr->children->content;
- else {
- xsltTransformError(NULL, cctxt->style, node,
- "Attribute 'exclude-result-prefixes': Invalid value.\n");
- cctxt->style->errors++;
- return(def);
- }
-
- if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,
- BAD_CAST value) != 0)
- goto exit;
- if (cctxt->tmpList->number == 0)
- goto exit;
- /*
- * Merge the list with the inherited list.
- */
- list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);
- if (list == NULL)
- goto exit;
- /*
- * Store the list in the stylesheet/compiler context.
- */
- if (xsltPointerListAddSize(
- cctxt->psData->exclResultNamespaces, list, 5) == -1)
- {
- xsltPointerListFree(list);
- list = NULL;
- goto exit;
- }
- /*
- * Notify of change in status wrt namespaces.
- */
- if (cctxt->inode != NULL)
- cctxt->inode->nsChanged = 1;
-
-exit:
- if (list != NULL)
- return(list);
- else
- return(def);
-}
-
-/*
-* xsltParseExtElemPrefixes:
-*
-* Create and store the list of in-scope namespaces for the given
-* node in the stylesheet. If there are no changes in the in-scope
-* namespaces then the last ns-info of the ancestor axis will be returned.
-* Compilation-time only.
-*
-* Returns the ns-info or NULL if there are no namespaces in scope.
-*/
-static xsltPointerListPtr
-xsltParseExtElemPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
- xsltPointerListPtr def,
- int instrCategory)
-{
- xsltPointerListPtr list = NULL;
- xmlAttrPtr attr;
- xmlChar *value;
- int i;
-
- if ((cctxt == NULL) || (node == NULL))
- return(NULL);
-
- if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
- attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes", NULL);
- else
- attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes",
- XSLT_NAMESPACE);
- if (attr == NULL)
- return(def);
-
- if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
- /*
- * Mark the XSLT attr.
- */
- attr->psvi = (void *) xsltXSLTAttrMarker;
- }
-
- if ((attr->children != NULL) &&
- (attr->children->content != NULL))
- value = attr->children->content;
- else {
- xsltTransformError(NULL, cctxt->style, node,
- "Attribute 'extension-element-prefixes': Invalid value.\n");
- cctxt->style->errors++;
- return(def);
- }
-
-
- if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,
- BAD_CAST value) != 0)
- goto exit;
-
- if (cctxt->tmpList->number == 0)
- goto exit;
- /*
- * REVISIT: Register the extension namespaces.
- */
- for (i = 0; i < cctxt->tmpList->number; i++)
- xsltRegisterExtPrefix(cctxt->style, NULL,
- BAD_CAST cctxt->tmpList->items[i]);
- /*
- * Merge the list with the inherited list.
- */
- list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);
- if (list == NULL)
- goto exit;
- /*
- * Store the list in the stylesheet.
- */
- if (xsltPointerListAddSize(
- cctxt->psData->extElemNamespaces, list, 5) == -1)
- {
- xsltPointerListFree(list);
- list = NULL;
- goto exit;
- }
- /*
- * Notify of change in status wrt namespaces.
- */
- if (cctxt->inode != NULL)
- cctxt->inode->nsChanged = 1;
-
-exit:
- if (list != NULL)
- return(list);
- else
- return(def);
-}
-
-/*
-* xsltParseAttrXSLTVersion:
-*
-* @cctxt: the compilation context
-* @node: the element-node
-* @isXsltElem: whether this is an XSLT element
-*
-* Parses the attribute xsl:version.
-*
-* Returns 1 if there was such an attribute, 0 if not and
-* -1 if an internal or API error occured.
-*/
-static int
-xsltParseAttrXSLTVersion(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
- int instrCategory)
-{
- xmlChar *value;
- xmlAttrPtr attr;
-
- if ((cctxt == NULL) || (node == NULL))
- return(-1);
-
- if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
- attr = xmlHasNsProp(node, BAD_CAST "version", NULL);
- else
- attr = xmlHasNsProp(node, BAD_CAST "version", XSLT_NAMESPACE);
-
- if (attr == NULL)
- return(0);
-
- attr->psvi = (void *) xsltXSLTAttrMarker;
-
- if ((attr->children != NULL) &&
- (attr->children->content != NULL))
- value = attr->children->content;
- else {
- xsltTransformError(NULL, cctxt->style, node,
- "Attribute 'version': Invalid value.\n");
- cctxt->style->errors++;
- return(1);
- }
-
- if (! xmlStrEqual(value, (const xmlChar *)"1.0")) {
- cctxt->inode->forwardsCompat = 1;
- /*
- * TODO: To what extent do we support the
- * forwards-compatible mode?
- */
- /*
- * Report this only once per compilation episode.
- */
- if (! cctxt->hasForwardsCompat) {
- cctxt->hasForwardsCompat = 1;
- cctxt->errSeverity = XSLT_ERROR_SEVERITY_WARNING;
- xsltTransformError(NULL, cctxt->style, node,
- "Warning: the attribute xsl:version specifies a value "
- "different from '1.0'. Switching to forwards-compatible "
- "mode. Only features of XSLT 1.0 are supported by this "
- "processor.\n");
- cctxt->style->warnings++;
- cctxt->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
- }
- } else {
- cctxt->inode->forwardsCompat = 0;
- }
-
- if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
- /*
- * Set a marker on XSLT attributes.
- */
- attr->psvi = (void *) xsltXSLTAttrMarker;
- }
- return(1);
-}
-
-static int
-xsltParsePreprocessStylesheetTree(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
-{
- xmlNodePtr deleteNode, cur, txt, textNode = NULL;
- xmlDocPtr doc;
- xsltStylesheetPtr style;
- int internalize = 0, findSpaceAttr;
- int xsltStylesheetElemDepth;
- xmlAttrPtr attr;
- xmlChar *value;
- const xmlChar *name, *nsNameXSLT = NULL;
- int strictWhitespace, inXSLText = 0;
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP
- xsltNsMapPtr nsMapItem;
-#endif
-
- if ((cctxt == NULL) || (cctxt->style == NULL) ||
- (node == NULL) || (node->type != XML_ELEMENT_NODE))
- return(-1);
-
- doc = node->doc;
- if (doc == NULL)
- goto internal_err;
-
- style = cctxt->style;
- if ((style->dict != NULL) && (doc->dict == style->dict))
- internalize = 1;
- else
- style->internalized = 0;
-
- /*
- * Init value of xml:space. Since this might be an embedded
- * stylesheet, this is needed to be performed on the element
- * where the stylesheet is rooted at, taking xml:space of
- * ancestors into account.
- */
- if (! cctxt->simplified)
- xsltStylesheetElemDepth = cctxt->depth +1;
- else
- xsltStylesheetElemDepth = 0;
-
- if (xmlNodeGetSpacePreserve(node) != 1)
- cctxt->inode->preserveWhitespace = 0;
- else
- cctxt->inode->preserveWhitespace = 1;
-
- /*
- * Eval if we should keep the old incorrect behaviour.
- */
- strictWhitespace = (cctxt->strict != 0) ? 1 : 0;
-
- nsNameXSLT = xsltConstNamespaceNameXSLT;
-
- deleteNode = NULL;
- cur = node;
- while (cur != NULL) {
- if (deleteNode != NULL) {
-
-#ifdef WITH_XSLT_DEBUG_BLANKS
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParsePreprocessStylesheetTree: removing node\n");
-#endif
- xmlUnlinkNode(deleteNode);
- xmlFreeNode(deleteNode);
- deleteNode = NULL;
- }
- if (cur->type == XML_ELEMENT_NODE) {
-
- /*
- * Clear the PSVI field.
- */
- cur->psvi = NULL;
-
- xsltCompilerNodePush(cctxt, cur);
-
- inXSLText = 0;
- textNode = NULL;
- findSpaceAttr = 1;
- cctxt->inode->stripWhitespace = 0;
- /*
- * TODO: I'd love to use a string pointer comparison here :-/
- */
- if (IS_XSLT_ELEM(cur)) {
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP
- if (cur->ns->href != nsNameXSLT) {
- nsMapItem = xsltNewNamespaceMapItem(cctxt,
- doc, cur->ns, cur);
- if (nsMapItem == NULL)
- goto internal_err;
- cur->ns->href = nsNameXSLT;
- }
-#endif
-
- if (cur->name == NULL)
- goto process_attributes;
- /*
- * Mark the XSLT element for later recognition.
- * TODO: Using the marker is still too dangerous, since if
- * the parsing mechanism leaves out an XSLT element, then
- * this might hit the transformation-mechanism, which
- * will break if it doesn't expect such a marker.
- */
- /* cur->psvi = (void *) xsltXSLTElemMarker; */
-
- /*
- * XSLT 2.0: "Any whitespace text node whose parent is
- * one of the following elements is removed from the "
- * tree, regardless of any xml:space attributes:..."
- * xsl:apply-imports,
- * xsl:apply-templates,
- * xsl:attribute-set,
- * xsl:call-template,
- * xsl:choose,
- * xsl:stylesheet, xsl:transform.
- * XSLT 2.0: xsl:analyze-string,
- * xsl:character-map,
- * xsl:next-match
- *
- * TODO: I'd love to use a string pointer comparison here :-/
- */
- name = cur->name;
- switch (*name) {
- case 't':
- if ((name[0] == 't') && (name[1] == 'e') &&
- (name[2] == 'x') && (name[3] == 't') &&
- (name[4] == 0))
- {
- /*
- * Process the xsl:text element.
- * ----------------------------
- * Mark it for later recognition.
- */
- cur->psvi = (void *) xsltXSLTTextMarker;
- /*
- * For stylesheets, the set of
- * whitespace-preserving element names
- * consists of just xsl:text.
- */
- findSpaceAttr = 0;
- cctxt->inode->preserveWhitespace = 1;
- inXSLText = 1;
- }
- break;
- case 'c':
- if (xmlStrEqual(name, BAD_CAST "choose") ||
- xmlStrEqual(name, BAD_CAST "call-template"))
- cctxt->inode->stripWhitespace = 1;
- break;
- case 'a':
- if (xmlStrEqual(name, BAD_CAST "apply-templates") ||
- xmlStrEqual(name, BAD_CAST "apply-imports") ||
- xmlStrEqual(name, BAD_CAST "attribute-set"))
-
- cctxt->inode->stripWhitespace = 1;
- break;
- default:
- if (xsltStylesheetElemDepth == cctxt->depth) {
- /*
- * This is a xsl:stylesheet/xsl:transform.
- */
- cctxt->inode->stripWhitespace = 1;
- break;
- }
-
- if ((cur->prev != NULL) &&
- (cur->prev->type == XML_TEXT_NODE))
- {
- /*
- * XSLT 2.0 : "Any whitespace text node whose
- * following-sibling node is an xsl:param or
- * xsl:sort element is removed from the tree,
- * regardless of any xml:space attributes."
- */
- if (((*name == 'p') || (*name == 's')) &&
- (xmlStrEqual(name, BAD_CAST "param") ||
- xmlStrEqual(name, BAD_CAST "sort")))
- {
- do {
- if (IS_BLANK_NODE(cur->prev)) {
- txt = cur->prev;
- xmlUnlinkNode(txt);
- xmlFreeNode(txt);
- } else {
- /*
- * This will result in a content
- * error, when hitting the parsing
- * functions.
- */
- break;
- }
- } while (cur->prev);
- }
- }
- break;
- }
- }
-
-process_attributes:
- /*
- * Process attributes.
- * ------------------
- */
- if (cur->properties != NULL) {
- if (cur->children == NULL)
- findSpaceAttr = 0;
- attr = cur->properties;
- do {
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP
- if ((attr->ns) && (attr->ns->href != nsNameXSLT) &&
- xmlStrEqual(attr->ns->href, nsNameXSLT))
- {
- nsMapItem = xsltNewNamespaceMapItem(cctxt,
- doc, attr->ns, cur);
- if (nsMapItem == NULL)
- goto internal_err;
- attr->ns->href = nsNameXSLT;
- }
-#endif
- if (internalize) {
- /*
- * Internalize the attribute's value; the goal is to
- * speed up operations and minimize used space by
- * compiled stylesheets.
- */
- txt = attr->children;
- /*
- * NOTE that this assumes only one
- * text-node in the attribute's content.
- */
- if ((txt != NULL) && (txt->content != NULL) &&
- (!xmlDictOwns(style->dict, txt->content)))
- {
- value = (xmlChar *) xmlDictLookup(style->dict,
- txt->content, -1);
- xmlNodeSetContent(txt, NULL);
- txt->content = value;
- }
- }
- /*
- * Process xml:space attributes.
- * ----------------------------
- */
- if ((findSpaceAttr != 0) &&
- (attr->ns != NULL) &&
- (attr->name != NULL) &&
- (attr->name[0] == 's') &&
- (attr->ns->prefix != NULL) &&
- (attr->ns->prefix[0] == 'x') &&
- (attr->ns->prefix[1] == 'm') &&
- (attr->ns->prefix[2] == 'l') &&
- (attr->ns->prefix[3] == 0))
- {
- value = xmlGetNsProp(cur, BAD_CAST "space",
- XML_XML_NAMESPACE);
- if (value != NULL) {
- if (xmlStrEqual(value, BAD_CAST "preserve")) {
- cctxt->inode->preserveWhitespace = 1;
- } else if (xmlStrEqual(value, BAD_CAST "default")) {
- cctxt->inode->preserveWhitespace = 0;
- } else {
- /* Invalid value for xml:space. */
- xsltTransformError(NULL, style, cur,
- "Attribute xml:space: Invalid value.\n");
- cctxt->style->warnings++;
- }
- findSpaceAttr = 0;
- xmlFree(value);
- }
-
- }
- attr = attr->next;
- } while (attr != NULL);
- }
- /*
- * We'll descend into the children of element nodes only.
- */
- if (cur->children != NULL) {
- cur = cur->children;
- continue;
- }
- } else if ((cur->type == XML_TEXT_NODE) ||
- (cur->type == XML_CDATA_SECTION_NODE))
- {
- /*
- * Merge adjacent text/CDATA-section-nodes
- * ---------------------------------------
- * In order to avoid breaking of existing stylesheets,
- * if the old behaviour is wanted (strictWhitespace == 0),
- * then we *won't* merge adjacent text-nodes
- * (except in xsl:text); this will ensure that whitespace-only
- * text nodes are (incorrectly) not stripped in some cases.
- *
- * Example: : <foo> <!-- bar -->zoo</foo>
- * Corrent (strict) result: <foo> zoo</foo>
- * Incorrect (old) result : <foo>zoo</foo>
- *
- * NOTE that we *will* merge adjacent text-nodes if
- * they are in xsl:text.
- * Example, the following:
- * <xsl:text> <!-- bar -->zoo<xsl:text>
- * will result in both cases in:
- * <xsl:text> zoo<xsl:text>
- */
- cur->type = XML_TEXT_NODE;
- if ((strictWhitespace != 0) || (inXSLText != 0)) {
- /*
- * New behaviour; merge nodes.
- */
- if (textNode == NULL)
- textNode = cur;
- else {
- if (cur->content != NULL)
- xmlNodeAddContent(textNode, cur->content);
- deleteNode = cur;
- }
- if ((cur->next == NULL) ||
- (cur->next->type == XML_ELEMENT_NODE))
- goto end_of_text;
- else
- goto next_sibling;
- } else {
- /*
- * Old behaviour.
- */
- if (textNode == NULL)
- textNode = cur;
- goto end_of_text;
- }
- } else if ((cur->type == XML_COMMENT_NODE) ||
- (cur->type == XML_PI_NODE))
- {
- /*
- * Remove processing instructions and comments.
- */
- deleteNode = cur;
- if ((cur->next == NULL) ||
- (cur->next->type == XML_ELEMENT_NODE))
- goto end_of_text;
- else
- goto next_sibling;
- } else {
- textNode = NULL;
- /*
- * Invalid node-type for this data-model.
- */
- xsltTransformError(NULL, style, cur,
- "Invalid type of node for the XSLT data model.\n");
- cctxt->style->errors++;
- goto next_sibling;
- }
-
-end_of_text:
- if (textNode) {
- value = textNode->content;
- /*
- * At this point all adjacent text/CDATA-section nodes
- * have been merged.
- *
- * Strip whitespace-only text-nodes.
- * (cctxt->inode->stripWhitespace)
- */
- if ((value == NULL) || (*value == 0) ||
- (((cctxt->inode->stripWhitespace) ||
- (! cctxt->inode->preserveWhitespace)) &&
- IS_BLANK(*value) &&
- xsltIsBlank(value)))
- {
- if (textNode != cur) {
- xmlUnlinkNode(textNode);
- xmlFreeNode(textNode);
- } else
- deleteNode = textNode;
- textNode = NULL;
- goto next_sibling;
- }
- /*
- * Convert CDATA-section nodes to text-nodes.
- * TODO: Can this produce problems?
- */
- if (textNode->type != XML_TEXT_NODE) {
- textNode->type = XML_TEXT_NODE;
- textNode->name = xmlStringText;
- }
- if (internalize &&
- (textNode->content != NULL) &&
- (!xmlDictOwns(style->dict, textNode->content)))
- {
- /*
- * Internalize the string.
- */
- value = (xmlChar *) xmlDictLookup(style->dict,
- textNode->content, -1);
- xmlNodeSetContent(textNode, NULL);
- textNode->content = value;
- }
- textNode = NULL;
- /*
- * Note that "disable-output-escaping" of the xsl:text
- * element will be applied at a later level, when
- * XSLT elements are processed.
- */
- }
-
-next_sibling:
- if (cur->type == XML_ELEMENT_NODE) {
- xsltCompilerNodePop(cctxt, cur);
- }
- if (cur == node)
- break;
- if (cur->next != NULL) {
- cur = cur->next;
- } else {
- cur = cur->parent;
- inXSLText = 0;
- goto next_sibling;
- };
- }
- if (deleteNode != NULL) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParsePreprocessStylesheetTree: removing node\n");
-#endif
- xmlUnlinkNode(deleteNode);
- xmlFreeNode(deleteNode);
- }
- return(0);
-
-internal_err:
- return(-1);
-}
-
-#endif /* XSLT_REFACTORED */
-
-#ifdef XSLT_REFACTORED
-#else
-static void
-xsltPreprocessStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
-{
- xmlNodePtr deleteNode, styleelem;
- int internalize = 0;
-
- if ((style == NULL) || (cur == NULL))
- return;
-
- if ((cur->doc != NULL) && (style->dict != NULL) &&
- (cur->doc->dict == style->dict))
- internalize = 1;
- else
- style->internalized = 0;
-
- if ((cur != NULL) && (IS_XSLT_ELEM(cur)) &&
- (IS_XSLT_NAME(cur, "stylesheet"))) {
- styleelem = cur;
- } else {
- styleelem = NULL;
- }
-
- /*
- * This content comes from the stylesheet
- * For stylesheets, the set of whitespace-preserving
- * element names consists of just xsl:text.
- */
- deleteNode = NULL;
- while (cur != NULL) {
- if (deleteNode != NULL) {
-#ifdef WITH_XSLT_DEBUG_BLANKS
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltPreprocessStylesheet: removing ignorable blank node\n");
-#endif
- xmlUnlinkNode(deleteNode);
- xmlFreeNode(deleteNode);
- deleteNode = NULL;
- }
- if (cur->type == XML_ELEMENT_NODE) {
- int exclPrefixes;
- /*
- * Internalize attributes values.
- */
- if ((internalize) && (cur->properties != NULL)) {
- xmlAttrPtr attr = cur->properties;
- xmlNodePtr txt;
-
- while (attr != NULL) {
- txt = attr->children;
- if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
- (txt->content != NULL) &&
- (!xmlDictOwns(style->dict, txt->content)))
- {
- xmlChar *tmp;
-
- /*
- * internalize the text string, goal is to speed
- * up operations and minimize used space by compiled
- * stylesheets.
- */
- tmp = (xmlChar *) xmlDictLookup(style->dict,
- txt->content, -1);
- if (tmp != txt->content) {
- xmlNodeSetContent(txt, NULL);
- txt->content = tmp;
- }
- }
- attr = attr->next;
- }
- }
- if (IS_XSLT_ELEM(cur)) {
- exclPrefixes = 0;
- if (IS_XSLT_NAME(cur, "text")) {
- for (;exclPrefixes > 0;exclPrefixes--)
- exclPrefixPop(style);
- goto skip_children;
- }
- } else {
- exclPrefixes = xsltParseStylesheetExcludePrefix(style, cur, 0);
- }
-
- if ((cur->nsDef != NULL) && (style->exclPrefixNr > 0)) {
- xmlNsPtr ns = cur->nsDef, prev = NULL, next;
- xmlNodePtr root = NULL;
- int i, moved;
-
- root = xmlDocGetRootElement(cur->doc);
- if ((root != NULL) && (root != cur)) {
- while (ns != NULL) {
- moved = 0;
- next = ns->next;
- for (i = 0;i < style->exclPrefixNr;i++) {
- if ((ns->prefix != NULL) &&
- (xmlStrEqual(ns->href,
- style->exclPrefixTab[i]))) {
- /*
- * Move the namespace definition on the root
- * element to avoid duplicating it without
- * loosing it.
- */
- if (prev == NULL) {
- cur->nsDef = ns->next;
- } else {
- prev->next = ns->next;
- }
- ns->next = root->nsDef;
- root->nsDef = ns;
- moved = 1;
- break;
- }
- }
- if (moved == 0)
- prev = ns;
- ns = next;
- }
- }
- }
- /*
- * If we have prefixes locally, recurse and pop them up when
- * going back
- */
- if (exclPrefixes > 0) {
- xsltPreprocessStylesheet(style, cur->children);
- for (;exclPrefixes > 0;exclPrefixes--)
- exclPrefixPop(style);
- goto skip_children;
- }
- } else if (cur->type == XML_TEXT_NODE) {
- if (IS_BLANK_NODE(cur)) {
- if (xmlNodeGetSpacePreserve(cur->parent) != 1) {
- deleteNode = cur;
- }
- } else if ((cur->content != NULL) && (internalize) &&
- (!xmlDictOwns(style->dict, cur->content))) {
- xmlChar *tmp;
-
- /*
- * internalize the text string, goal is to speed
- * up operations and minimize used space by compiled
- * stylesheets.
- */
- tmp = (xmlChar *) xmlDictLookup(style->dict, cur->content, -1);
- xmlNodeSetContent(cur, NULL);
- cur->content = tmp;
- }
- } else if ((cur->type != XML_ELEMENT_NODE) &&
- (cur->type != XML_CDATA_SECTION_NODE)) {
- deleteNode = cur;
- goto skip_children;
- }
-
- /*
- * Skip to next node. In case of a namespaced element children of
- * the stylesheet and not in the XSLT namespace and not an extension
- * element, ignore its content.
- */
- if ((cur->type == XML_ELEMENT_NODE) && (cur->ns != NULL) &&
- (styleelem != NULL) && (cur->parent == styleelem) &&
- (!xmlStrEqual(cur->ns->href, XSLT_NAMESPACE)) &&
- (!xsltCheckExtURI(style, cur->ns->href))) {
- goto skip_children;
- } else if (cur->children != NULL) {
- if ((cur->children->type != XML_ENTITY_DECL) &&
- (cur->children->type != XML_ENTITY_REF_NODE) &&
- (cur->children->type != XML_ENTITY_NODE)) {
- cur = cur->children;
- continue;
- }
- }
-
-skip_children:
- if (cur->next != NULL) {
- cur = cur->next;
- continue;
- }
- do {
-
- cur = cur->parent;
- if (cur == NULL)
- break;
- if (cur == (xmlNodePtr) style->doc) {
- cur = NULL;
- break;
- }
- if (cur->next != NULL) {
- cur = cur->next;
- break;
- }
- } while (cur != NULL);
- }
- if (deleteNode != NULL) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltPreprocessStylesheet: removing ignorable blank node\n");
-#endif
- xmlUnlinkNode(deleteNode);
- xmlFreeNode(deleteNode);
- }
-}
-#endif /* end of else XSLT_REFACTORED */
-
-/**
- * xsltGatherNamespaces:
- * @style: the XSLT stylesheet
- *
- * Browse the stylesheet and build the namspace hash table which
- * will be used for XPath interpretation. If needed do a bit of normalization
- */
-
-static void
-xsltGatherNamespaces(xsltStylesheetPtr style) {
- xmlNodePtr cur;
- const xmlChar *URI;
-
- if (style == NULL)
- return;
- /*
- * TODO: basically if the stylesheet uses the same prefix for different
- * patterns, well they may be in problem, hopefully they will get
- * a warning first.
- */
- /*
- * TODO: Eliminate the use of the hash for XPath expressions.
- * An expression should be evaluated in the context of the in-scope
- * namespaces; eliminate the restriction of an XML document to contain
- * no duplicate prefixes for different namespace names.
- *
- */
- cur = xmlDocGetRootElement(style->doc);
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE) {
- xmlNsPtr ns = cur->nsDef;
- while (ns != NULL) {
- if (ns->prefix != NULL) {
- if (style->nsHash == NULL) {
- style->nsHash = xmlHashCreate(10);
- if (style->nsHash == NULL) {
- xsltTransformError(NULL, style, cur,
- "xsltGatherNamespaces: failed to create hash table\n");
- style->errors++;
- return;
- }
- }
- URI = xmlHashLookup(style->nsHash, ns->prefix);
- if ((URI != NULL) && (!xmlStrEqual(URI, ns->href))) {
- xsltTransformError(NULL, style, cur,
- "Namespaces prefix %s used for multiple namespaces\n",ns->prefix);
- style->warnings++;
- } else if (URI == NULL) {
- xmlHashUpdateEntry(style->nsHash, ns->prefix,
- (void *) ns->href, (xmlHashDeallocator)xmlFree);
-
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "Added namespace: %s mapped to %s\n", ns->prefix, ns->href);
-#endif
- }
- }
- ns = ns->next;
- }
- }
-
- /*
- * Skip to next node
- */
- if (cur->children != NULL) {
- if (cur->children->type != XML_ENTITY_DECL) {
- cur = cur->children;
- continue;
- }
- }
- if (cur->next != NULL) {
- cur = cur->next;
- continue;
- }
-
- do {
- cur = cur->parent;
- if (cur == NULL)
- break;
- if (cur == (xmlNodePtr) style->doc) {
- cur = NULL;
- break;
- }
- if (cur->next != NULL) {
- cur = cur->next;
- break;
- }
- } while (cur != NULL);
- }
-}
-
-#ifdef XSLT_REFACTORED
-
-static xsltStyleType
-xsltGetXSLTElementTypeByNode(xsltCompilerCtxtPtr cctxt,
- xmlNodePtr node)
-{
- if ((node == NULL) || (node->type != XML_ELEMENT_NODE) ||
- (node->name == NULL))
- return(0);
-
- if (node->name[0] == 'a') {
- if (IS_XSLT_NAME(node, "apply-templates"))
- return(XSLT_FUNC_APPLYTEMPLATES);
- else if (IS_XSLT_NAME(node, "attribute"))
- return(XSLT_FUNC_ATTRIBUTE);
- else if (IS_XSLT_NAME(node, "apply-imports"))
- return(XSLT_FUNC_APPLYIMPORTS);
- else if (IS_XSLT_NAME(node, "attribute-set"))
- return(0);
-
- } else if (node->name[0] == 'c') {
- if (IS_XSLT_NAME(node, "choose"))
- return(XSLT_FUNC_CHOOSE);
- else if (IS_XSLT_NAME(node, "copy"))
- return(XSLT_FUNC_COPY);
- else if (IS_XSLT_NAME(node, "copy-of"))
- return(XSLT_FUNC_COPYOF);
- else if (IS_XSLT_NAME(node, "call-template"))
- return(XSLT_FUNC_CALLTEMPLATE);
- else if (IS_XSLT_NAME(node, "comment"))
- return(XSLT_FUNC_COMMENT);
-
- } else if (node->name[0] == 'd') {
- if (IS_XSLT_NAME(node, "document"))
- return(XSLT_FUNC_DOCUMENT);
- else if (IS_XSLT_NAME(node, "decimal-format"))
- return(0);
-
- } else if (node->name[0] == 'e') {
- if (IS_XSLT_NAME(node, "element"))
- return(XSLT_FUNC_ELEMENT);
-
- } else if (node->name[0] == 'f') {
- if (IS_XSLT_NAME(node, "for-each"))
- return(XSLT_FUNC_FOREACH);
- else if (IS_XSLT_NAME(node, "fallback"))
- return(XSLT_FUNC_FALLBACK);
-
- } else if (*(node->name) == 'i') {
- if (IS_XSLT_NAME(node, "if"))
- return(XSLT_FUNC_IF);
- else if (IS_XSLT_NAME(node, "include"))
- return(0);
- else if (IS_XSLT_NAME(node, "import"))
- return(0);
-
- } else if (*(node->name) == 'k') {
- if (IS_XSLT_NAME(node, "key"))
- return(0);
-
- } else if (*(node->name) == 'm') {
- if (IS_XSLT_NAME(node, "message"))
- return(XSLT_FUNC_MESSAGE);
-
- } else if (*(node->name) == 'n') {
- if (IS_XSLT_NAME(node, "number"))
- return(XSLT_FUNC_NUMBER);
- else if (IS_XSLT_NAME(node, "namespace-alias"))
- return(0);
-
- } else if (*(node->name) == 'o') {
- if (IS_XSLT_NAME(node, "otherwise"))
- return(XSLT_FUNC_OTHERWISE);
- else if (IS_XSLT_NAME(node, "output"))
- return(0);
-
- } else if (*(node->name) == 'p') {
- if (IS_XSLT_NAME(node, "param"))
- return(XSLT_FUNC_PARAM);
- else if (IS_XSLT_NAME(node, "processing-instruction"))
- return(XSLT_FUNC_PI);
- else if (IS_XSLT_NAME(node, "preserve-space"))
- return(0);
-
- } else if (*(node->name) == 's') {
- if (IS_XSLT_NAME(node, "sort"))
- return(XSLT_FUNC_SORT);
- else if (IS_XSLT_NAME(node, "strip-space"))
- return(0);
- else if (IS_XSLT_NAME(node, "stylesheet"))
- return(0);
-
- } else if (node->name[0] == 't') {
- if (IS_XSLT_NAME(node, "text"))
- return(XSLT_FUNC_TEXT);
- else if (IS_XSLT_NAME(node, "template"))
- return(0);
- else if (IS_XSLT_NAME(node, "transform"))
- return(0);
-
- } else if (*(node->name) == 'v') {
- if (IS_XSLT_NAME(node, "value-of"))
- return(XSLT_FUNC_VALUEOF);
- else if (IS_XSLT_NAME(node, "variable"))
- return(XSLT_FUNC_VARIABLE);
-
- } else if (*(node->name) == 'w') {
- if (IS_XSLT_NAME(node, "when"))
- return(XSLT_FUNC_WHEN);
- if (IS_XSLT_NAME(node, "with-param"))
- return(XSLT_FUNC_WITHPARAM);
- }
- return(0);
-}
-
-/**
- * xsltParseAnyXSLTElem:
- *
- * @cctxt: the compilation context
- * @elem: the element node of the XSLT instruction
- *
- * Parses, validates the content models and compiles XSLT instructions.
- *
- * Returns 0 if everything's fine;
- * -1 on API or internal errors.
- */
-int
-xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
-{
- if ((cctxt == NULL) || (elem == NULL) ||
- (elem->type != XML_ELEMENT_NODE))
- return(-1);
-
- elem->psvi = NULL;
-
- if (! (IS_XSLT_ELEM_FAST(elem)))
- return(-1);
- /*
- * Detection of handled content of extension instructions.
- */
- if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
- cctxt->inode->extContentHandled = 1;
- }
-
- xsltCompilerNodePush(cctxt, elem);
- /*
- * URGENT TODO: Find a way to speed up this annoying redundant
- * textual node-name and namespace comparison.
- */
- if (cctxt->inode->prev->curChildType != 0)
- cctxt->inode->type = cctxt->inode->prev->curChildType;
- else
- cctxt->inode->type = xsltGetXSLTElementTypeByNode(cctxt, elem);
- /*
- * Update the in-scope namespaces if needed.
- */
- if (elem->nsDef != NULL)
- cctxt->inode->inScopeNs =
- xsltCompilerBuildInScopeNsList(cctxt, elem);
- /*
- * xsltStylePreCompute():
- * This will compile the information found on the current
- * element's attributes. NOTE that this won't process the
- * children of the instruction.
- */
- xsltStylePreCompute(cctxt->style, elem);
- /*
- * TODO: How to react on errors in xsltStylePreCompute() ?
- */
-
- /*
- * Validate the content model of the XSLT-element.
- */
- switch (cctxt->inode->type) {
- case XSLT_FUNC_APPLYIMPORTS:
- /* EMPTY */
- goto empty_content;
- case XSLT_FUNC_APPLYTEMPLATES:
- /* <!-- Content: (xsl:sort | xsl:with-param)* --> */
- goto apply_templates;
- case XSLT_FUNC_ATTRIBUTE:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_CALLTEMPLATE:
- /* <!-- Content: xsl:with-param* --> */
- goto call_template;
- case XSLT_FUNC_CHOOSE:
- /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */
- goto choose;
- case XSLT_FUNC_COMMENT:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_COPY:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_COPYOF:
- /* EMPTY */
- goto empty_content;
- case XSLT_FUNC_DOCUMENT: /* Extra one */
- /* ?? template ?? */
- goto sequence_constructor;
- case XSLT_FUNC_ELEMENT:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_FALLBACK:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_FOREACH:
- /* <!-- Content: (xsl:sort*, template) --> */
- goto for_each;
- case XSLT_FUNC_IF:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_OTHERWISE:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_MESSAGE:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_NUMBER:
- /* EMPTY */
- goto empty_content;
- case XSLT_FUNC_PARAM:
- /*
- * Check for redefinition.
- */
- if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
- xsltVarInfoPtr ivar = cctxt->ivar;
-
- do {
- if ((ivar->name ==
- ((xsltStyleItemParamPtr) elem->psvi)->name) &&
- (ivar->nsName ==
- ((xsltStyleItemParamPtr) elem->psvi)->ns))
- {
- elem->psvi = NULL;
- xsltTransformError(NULL, cctxt->style, elem,
- "Redefinition of variable or parameter '%s'.\n",
- ivar->name);
- cctxt->style->errors++;
- goto error;
- }
- ivar = ivar->prev;
- } while (ivar != NULL);
- }
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_PI:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_SORT:
- /* EMPTY */
- goto empty_content;
- case XSLT_FUNC_TEXT:
- /* <!-- Content: #PCDATA --> */
- goto text;
- case XSLT_FUNC_VALUEOF:
- /* EMPTY */
- goto empty_content;
- case XSLT_FUNC_VARIABLE:
- /*
- * Check for redefinition.
- */
- if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
- xsltVarInfoPtr ivar = cctxt->ivar;
-
- do {
- if ((ivar->name ==
- ((xsltStyleItemVariablePtr) elem->psvi)->name) &&
- (ivar->nsName ==
- ((xsltStyleItemVariablePtr) elem->psvi)->ns))
- {
- elem->psvi = NULL;
- xsltTransformError(NULL, cctxt->style, elem,
- "Redefinition of variable or parameter '%s'.\n",
- ivar->name);
- cctxt->style->errors++;
- goto error;
- }
- ivar = ivar->prev;
- } while (ivar != NULL);
- }
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_WHEN:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- case XSLT_FUNC_WITHPARAM:
- /* <!-- Content: template --> */
- goto sequence_constructor;
- default:
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseXSLTNode: Unhandled XSLT element '%s'.\n",
- elem->name);
-#endif
- xsltTransformError(NULL, cctxt->style, elem,
- "xsltParseXSLTNode: Internal error; "
- "unhandled XSLT element '%s'.\n", elem->name);
- cctxt->style->errors++;
- goto internal_err;
- }
-
-apply_templates:
- /* <!-- Content: (xsl:sort | xsl:with-param)* --> */
- if (elem->children != NULL) {
- xmlNodePtr child = elem->children;
- do {
- if (child->type == XML_ELEMENT_NODE) {
- if (IS_XSLT_ELEM_FAST(child)) {
- if (xmlStrEqual(child->name, BAD_CAST "with-param")) {
- cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
- xsltParseAnyXSLTElem(cctxt, child);
- } else if (xmlStrEqual(child->name, BAD_CAST "sort")) {
- cctxt->inode->curChildType = XSLT_FUNC_SORT;
- xsltParseAnyXSLTElem(cctxt, child);
- } else
- xsltParseContentError(cctxt->style, child);
- } else
- xsltParseContentError(cctxt->style, child);
- }
- child = child->next;
- } while (child != NULL);
- }
- goto exit;
-
-call_template:
- /* <!-- Content: xsl:with-param* --> */
- if (elem->children != NULL) {
- xmlNodePtr child = elem->children;
- do {
- if (child->type == XML_ELEMENT_NODE) {
- if (IS_XSLT_ELEM_FAST(child)) {
- xsltStyleType type;
-
- type = xsltGetXSLTElementTypeByNode(cctxt, child);
- if (type == XSLT_FUNC_WITHPARAM) {
- cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
- xsltParseAnyXSLTElem(cctxt, child);
- } else {
- xsltParseContentError(cctxt->style, child);
- }
- } else
- xsltParseContentError(cctxt->style, child);
- }
- child = child->next;
- } while (child != NULL);
- }
- goto exit;
-
-text:
- if (elem->children != NULL) {
- xmlNodePtr child = elem->children;
- do {
- if ((child->type != XML_TEXT_NODE) &&
- (child->type != XML_CDATA_SECTION_NODE))
- {
- xsltTransformError(NULL, cctxt->style, elem,
- "The XSLT 'text' element must have only character "
- "data as content.\n");
- }
- child = child->next;
- } while (child != NULL);
- }
- goto exit;
-
-empty_content:
- if (elem->children != NULL) {
- xmlNodePtr child = elem->children;
- /*
- * Relaxed behaviour: we will allow whitespace-only text-nodes.
- */
- do {
- if (((child->type != XML_TEXT_NODE) &&
- (child->type != XML_CDATA_SECTION_NODE)) ||
- (! IS_BLANK_NODE(child)))
- {
- xsltTransformError(NULL, cctxt->style, elem,
- "This XSLT element must have no content.\n");
- cctxt->style->errors++;
- break;
- }
- child = child->next;
- } while (child != NULL);
- }
- goto exit;
-
-choose:
- /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */
- /*
- * TODO: text-nodes in between are *not* allowed in XSLT 1.0.
- * The old behaviour did not check this.
- * NOTE: In XSLT 2.0 they are stripped beforehand
- * if whitespace-only (regardless of xml:space).
- */
- if (elem->children != NULL) {
- xmlNodePtr child = elem->children;
- int nbWhen = 0, nbOtherwise = 0, err = 0;
- do {
- if (child->type == XML_ELEMENT_NODE) {
- if (IS_XSLT_ELEM_FAST(child)) {
- xsltStyleType type;
-
- type = xsltGetXSLTElementTypeByNode(cctxt, child);
- if (type == XSLT_FUNC_WHEN) {
- nbWhen++;
- if (nbOtherwise) {
- xsltParseContentError(cctxt->style, child);
- err = 1;
- break;
- }
- cctxt->inode->curChildType = XSLT_FUNC_WHEN;
- xsltParseAnyXSLTElem(cctxt, child);
- } else if (type == XSLT_FUNC_OTHERWISE) {
- if (! nbWhen) {
- xsltParseContentError(cctxt->style, child);
- err = 1;
- break;
- }
- if (nbOtherwise) {
- xsltTransformError(NULL, cctxt->style, elem,
- "The XSLT 'choose' element must not contain "
- "more than one XSLT 'otherwise' element.\n");
- cctxt->style->errors++;
- err = 1;
- break;
- }
- nbOtherwise++;
- cctxt->inode->curChildType = XSLT_FUNC_OTHERWISE;
- xsltParseAnyXSLTElem(cctxt, child);
- } else
- xsltParseContentError(cctxt->style, child);
- } else
- xsltParseContentError(cctxt->style, child);
- }
- /*
- else
- xsltParseContentError(cctxt, child);
- */
- child = child->next;
- } while (child != NULL);
- if ((! err) && (! nbWhen)) {
- xsltTransformError(NULL, cctxt->style, elem,
- "The XSLT element 'choose' must contain at least one "
- "XSLT element 'when'.\n");
- cctxt->style->errors++;
- }
- }
- goto exit;
-
-for_each:
- /* <!-- Content: (xsl:sort*, template) --> */
- /*
- * NOTE: Text-nodes before xsl:sort are *not* allowed in XSLT 1.0.
- * The old behaviour did not allow this, but it catched this
- * only at transformation-time.
- * In XSLT 2.0 they are stripped beforehand if whitespace-only
- * (regardless of xml:space).
- */
- if (elem->children != NULL) {
- xmlNodePtr child = elem->children;
- /*
- * Parse xsl:sort first.
- */
- do {
- if ((child->type == XML_ELEMENT_NODE) &&
- IS_XSLT_ELEM_FAST(child))
- {
- if (xsltGetXSLTElementTypeByNode(cctxt, child) ==
- XSLT_FUNC_SORT)
- {
- cctxt->inode->curChildType = XSLT_FUNC_SORT;
- xsltParseAnyXSLTElem(cctxt, child);
- } else
- break;
- } else
- break;
- child = child->next;
- } while (child != NULL);
- /*
- * Parse the sequece constructor.
- */
- if (child != NULL)
- xsltParseSequenceConstructor(cctxt, child);
- }
- goto exit;
-
-sequence_constructor:
- /*
- * Parse the sequence constructor.
- */
- if (elem->children != NULL)
- xsltParseSequenceConstructor(cctxt, elem->children);
-
- /*
- * Register information for vars/params. Only needed if there
- * are any following siblings.
- */
- if ((elem->next != NULL) &&
- ((cctxt->inode->type == XSLT_FUNC_VARIABLE) ||
- (cctxt->inode->type == XSLT_FUNC_PARAM)))
- {
- if ((elem->psvi != NULL) &&
- (((xsltStyleBasicItemVariablePtr) elem->psvi)->name))
- {
- xsltCompilerVarInfoPush(cctxt, elem,
- ((xsltStyleBasicItemVariablePtr) elem->psvi)->name,
- ((xsltStyleBasicItemVariablePtr) elem->psvi)->ns);
- }
- }
-
-error:
-exit:
- xsltCompilerNodePop(cctxt, elem);
- return(0);
-
-internal_err:
- xsltCompilerNodePop(cctxt, elem);
- return(-1);
-}
-
-/**
- * xsltForwardsCompatUnkownItemCreate:
- *
- * @cctxt: the compilation context
- *
- * Creates a compiled representation of the unknown
- * XSLT instruction.
- *
- * Returns the compiled representation.
- */
-static xsltStyleItemUknownPtr
-xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)
-{
- xsltStyleItemUknownPtr item;
-
- item = (xsltStyleItemUknownPtr) xmlMalloc(sizeof(xsltStyleItemUknown));
- if (item == NULL) {
- xsltTransformError(NULL, cctxt->style, NULL,
- "Internal error in xsltForwardsCompatUnkownItemCreate(): "
- "Failed to allocate memory.\n");
- cctxt->style->errors++;
- return(NULL);
- }
- memset(item, 0, sizeof(xsltStyleItemUknown));
- item->type = XSLT_FUNC_UNKOWN_FORWARDS_COMPAT;
- /*
- * Store it in the stylesheet.
- */
- item->next = cctxt->style->preComps;
- cctxt->style->preComps = (xsltElemPreCompPtr) item;
- return(item);
-}
-
-/**
- * xsltParseUnknownXSLTElem:
- *
- * @cctxt: the compilation context
- * @node: the element of the unknown XSLT instruction
- *
- * Parses an unknown XSLT element.
- * If forwards compatible mode is enabled this will allow
- * such an unknown XSLT and; otherwise it is rejected.
- *
- * Returns 1 in the unknown XSLT instruction is rejected,
- * 0 if everything's fine and
- * -1 on API or internal errors.
- */
-static int
-xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,
- xmlNodePtr node)
-{
- if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
- return(-1);
-
- /*
- * Detection of handled content of extension instructions.
- */
- if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
- cctxt->inode->extContentHandled = 1;
- }
- if (cctxt->inode->forwardsCompat == 0) {
- /*
- * We are not in forwards-compatible mode, so raise an error.
- */
- xsltTransformError(NULL, cctxt->style, node,
- "Unknown XSLT element '%s'.\n", node->name);
- cctxt->style->errors++;
- return(1);
- }
- /*
- * Forwards-compatible mode.
- * ------------------------
- *
- * Parse/compile xsl:fallback elements.
- *
- * QUESTION: Do we have to raise an error if there's no xsl:fallback?
- * ANSWER: No, since in the stylesheet the fallback behaviour might
- * also be provided by using the XSLT function "element-available".
- */
- if (cctxt->unknownItem == NULL) {
- /*
- * Create a singleton for all unknown XSLT instructions.
- */
- cctxt->unknownItem = xsltForwardsCompatUnkownItemCreate(cctxt);
- if (cctxt->unknownItem == NULL) {
- node->psvi = NULL;
- return(-1);
- }
- }
- node->psvi = cctxt->unknownItem;
- if (node->children == NULL)
- return(0);
- else {
- xmlNodePtr child = node->children;
-
- xsltCompilerNodePush(cctxt, node);
- /*
- * Update the in-scope namespaces if needed.
- */
- if (node->nsDef != NULL)
- cctxt->inode->inScopeNs =
- xsltCompilerBuildInScopeNsList(cctxt, node);
- /*
- * Parse all xsl:fallback children.
- */
- do {
- if ((child->type == XML_ELEMENT_NODE) &&
- IS_XSLT_ELEM_FAST(child) &&
- IS_XSLT_NAME(child, "fallback"))
- {
- cctxt->inode->curChildType = XSLT_FUNC_FALLBACK;
- xsltParseAnyXSLTElem(cctxt, child);
- }
- child = child->next;
- } while (child != NULL);
-
- xsltCompilerNodePop(cctxt, node);
- }
- return(0);
-}
-
-/**
- * xsltParseSequenceConstructor:
- *
- * @cctxt: the compilation context
- * @cur: the start-node of the content to be parsed
- *
- * Parses a "template" content (or "sequence constructor" in XSLT 2.0 terms).
- * This will additionally remove xsl:text elements from the tree.
- */
-void
-xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
-{
- xsltStyleType type;
- xmlNodePtr deleteNode = NULL;
-
- if (cctxt == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "xsltParseSequenceConstructor: Bad arguments\n");
- cctxt->style->errors++;
- return;
- }
- /*
- * Detection of handled content of extension instructions.
- */
- if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
- cctxt->inode->extContentHandled = 1;
- }
- if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
- return;
- /*
- * This is the content reffered to as a "template".
- * E.g. an xsl:element has such content model:
- * <xsl:element
- * name = { qname }
- * namespace = { uri-reference }
- * use-attribute-sets = qnames>
- * <!-- Content: template -->
- *
- * NOTE that in XSLT-2 the term "template" was abandoned due to
- * confusion with xsl:template and the term "sequence constructor"
- * was introduced instead.
- *
- * The following XSLT-instructions are allowed to appear:
- * xsl:apply-templates, xsl:call-template, xsl:apply-imports,
- * xsl:for-each, xsl:value-of, xsl:copy-of, xsl:number,
- * xsl:choose, xsl:if, xsl:text, xsl:copy, xsl:variable,
- * xsl:message, xsl:fallback,
- * xsl:processing-instruction, xsl:comment, xsl:element
- * xsl:attribute.
- * Additional allowed content:
- * 1) extension instructions
- * 2) literal result elements
- * 3) PCDATA
- *
- * NOTE that this content model does *not* allow xsl:param.
- */
- while (cur != NULL) {
- if (deleteNode != NULL) {
-#ifdef WITH_XSLT_DEBUG_BLANKS
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseSequenceConstructor: removing xsl:text element\n");
-#endif
- xmlUnlinkNode(deleteNode);
- xmlFreeNode(deleteNode);
- deleteNode = NULL;
- }
- if (cur->type == XML_ELEMENT_NODE) {
-
- if (cur->psvi == xsltXSLTTextMarker) {
- /*
- * xsl:text elements
- * --------------------------------------------------------
- */
- xmlNodePtr tmp;
-
- cur->psvi = NULL;
- /*
- * Mark the xsl:text element for later deletion.
- */
- deleteNode = cur;
- /*
- * Validate content.
- */
- tmp = cur->children;
- if (tmp) {
- /*
- * We don't expect more than one text-node in the
- * content, since we already merged adjacent
- * text/CDATA-nodes and eliminated PI/comment-nodes.
- */
- if ((tmp->type == XML_TEXT_NODE) ||
- (tmp->next == NULL))
- {
- /*
- * Leave the contained text-node in the tree.
- */
- xmlUnlinkNode(tmp);
- xmlAddPrevSibling(cur, tmp);
- } else {
- tmp = NULL;
- xsltTransformError(NULL, cctxt->style, cur,
- "Element 'xsl:text': Invalid type "
- "of node found in content.\n");
- cctxt->style->errors++;
- }
- }
- if (cur->properties) {
- xmlAttrPtr attr;
- /*
- * TODO: We need to report errors for
- * invalid attrs.
- */
- attr = cur->properties;
- do {
- if ((attr->ns == NULL) &&
- (attr->name != NULL) &&
- (attr->name[0] == 'd') &&
- xmlStrEqual(attr->name,
- BAD_CAST "disable-output-escaping"))
- {
- /*
- * Attr "disable-output-escaping".
- * XSLT-2: This attribute is deprecated.
- */
- if ((attr->children != NULL) &&
- xmlStrEqual(attr->children->content,
- BAD_CAST "yes"))
- {
- /*
- * Disable output escaping for this
- * text node.
- */
- if (tmp)
- tmp->name = xmlStringTextNoenc;
- } else if ((attr->children == NULL) ||
- (attr->children->content == NULL) ||
- (!xmlStrEqual(attr->children->content,
- BAD_CAST "no")))
- {
- xsltTransformError(NULL, cctxt->style,
- cur,
- "Attribute 'disable-output-escaping': "
- "Invalid value. Expected is "
- "'yes' or 'no'.\n");
- cctxt->style->errors++;
- }
- break;
- }
- attr = attr->next;
- } while (attr != NULL);
- }
- } else if (IS_XSLT_ELEM_FAST(cur)) {
- /*
- * TODO: Using the XSLT-marker is still not stable yet.
- */
- /* if (cur->psvi == xsltXSLTElemMarker) { */
- /*
- * XSLT instructions
- * --------------------------------------------------------
- */
- cur->psvi = NULL;
- type = xsltGetXSLTElementTypeByNode(cctxt, cur);
- switch (type) {
- case XSLT_FUNC_APPLYIMPORTS:
- case XSLT_FUNC_APPLYTEMPLATES:
- case XSLT_FUNC_ATTRIBUTE:
- case XSLT_FUNC_CALLTEMPLATE:
- case XSLT_FUNC_CHOOSE:
- case XSLT_FUNC_COMMENT:
- case XSLT_FUNC_COPY:
- case XSLT_FUNC_COPYOF:
- case XSLT_FUNC_DOCUMENT: /* Extra one */
- case XSLT_FUNC_ELEMENT:
- case XSLT_FUNC_FALLBACK:
- case XSLT_FUNC_FOREACH:
- case XSLT_FUNC_IF:
- case XSLT_FUNC_MESSAGE:
- case XSLT_FUNC_NUMBER:
- case XSLT_FUNC_PI:
- case XSLT_FUNC_TEXT:
- case XSLT_FUNC_VALUEOF:
- case XSLT_FUNC_VARIABLE:
- /*
- * Parse the XSLT element.
- */
- cctxt->inode->curChildType = type;
- xsltParseAnyXSLTElem(cctxt, cur);
- break;
- default:
- xsltParseUnknownXSLTElem(cctxt, cur);
- cur = cur->next;
- continue;
- }
- } else {
- /*
- * Non-XSLT elements
- * -----------------
- */
- xsltCompilerNodePush(cctxt, cur);
- /*
- * Update the in-scope namespaces if needed.
- */
- if (cur->nsDef != NULL)
- cctxt->inode->inScopeNs =
- xsltCompilerBuildInScopeNsList(cctxt, cur);
- /*
- * The current element is either a literal result element
- * or an extension instruction.
- *
- * Process attr "xsl:extension-element-prefixes".
- * FUTURE TODO: IIRC in XSLT 2.0 this attribute must be
- * processed by the implementor of the extension function;
- * i.e., it won't be handled by the XSLT processor.
- */
- /* SPEC 1.0:
- * "exclude-result-prefixes" is only allowed on literal
- * result elements and "xsl:exclude-result-prefixes"
- * on xsl:stylesheet/xsl:transform.
- * SPEC 2.0:
- * "There are a number of standard attributes
- * that may appear on any XSLT element: specifically
- * version, exclude-result-prefixes,
- * extension-element-prefixes, xpath-default-namespace,
- * default-collation, and use-when."
- *
- * SPEC 2.0:
- * For literal result elements:
- * "xsl:version, xsl:exclude-result-prefixes,
- * xsl:extension-element-prefixes,
- * xsl:xpath-default-namespace,
- * xsl:default-collation, or xsl:use-when."
- */
- if (cur->properties)
- cctxt->inode->extElemNs =
- xsltParseExtElemPrefixes(cctxt,
- cur, cctxt->inode->extElemNs,
- XSLT_ELEMENT_CATEGORY_LRE);
- /*
- * Eval if we have an extension instruction here.
- */
- if ((cur->ns != NULL) &&
- (cctxt->inode->extElemNs != NULL) &&
- (xsltCheckExtPrefix(cctxt->style, cur->ns->href) == 1))
- {
- /*
- * Extension instructions
- * ----------------------------------------------------
- * Mark the node information.
- */
- cctxt->inode->category = XSLT_ELEMENT_CATEGORY_EXTENSION;
- cctxt->inode->extContentHandled = 0;
- if (cur->psvi != NULL) {
- cur->psvi = NULL;
- /*
- * TODO: Temporary sanity check.
- */
- xsltTransformError(NULL, cctxt->style, cur,
- "Internal error in xsltParseSequenceConstructor(): "
- "Occupied PSVI field.\n");
- cctxt->style->errors++;
- cur = cur->next;
- continue;
- }
- cur->psvi = (void *)
- xsltPreComputeExtModuleElement(cctxt->style, cur);
-
- if (cur->psvi == NULL) {
- /*
- * OLD COMMENT: "Unknown element, maybe registered
- * at the context level. Mark it for later
- * recognition."
- * QUESTION: What does the xsltExtMarker mean?
- * ANSWER: It is used in
- * xsltApplySequenceConstructor() at
- * transformation-time to look out for extension
- * registered in the transformation context.
- */
- cur->psvi = (void *) xsltExtMarker;
- }
- /*
- * BIG NOTE: Now the ugly part. In previous versions
- * of Libxslt (until 1.1.16), all the content of an
- * extension instruction was processed and compiled without
- * the need of the extension-author to explicitely call
- * such a processing;.We now need to mimic this old
- * behaviour in order to avoid breaking old code
- * on the extension-author's side.
- * The mechanism:
- * 1) If the author does *not* set the
- * compile-time-flag @extContentHandled, then we'll
- * parse the content assuming that it's a "template"
- * (or "sequence constructor in XSLT 2.0 terms).
- * NOTE: If the extension is registered at
- * transformation-time only, then there's no way of
- * knowing that content shall be valid, and we'll
- * process the content the same way.
- * 2) If the author *does* set the flag, then we'll assume
- * that the author has handled the parsing him/herself
- * (e.g. called xsltParseSequenceConstructor(), etc.
- * explicitely in his/her code).
- */
- if ((cur->children != NULL) &&
- (cctxt->inode->extContentHandled == 0))
- {
- /*
- * Default parsing of the content using the
- * sequence-constructor model.
- */
- xsltParseSequenceConstructor(cctxt, cur->children);
- }
- } else {
- /*
- * Literal result element
- * ----------------------------------------------------
- * Allowed XSLT attributes:
- * xsl:extension-element-prefixes CDATA #IMPLIED
- * xsl:exclude-result-prefixes CDATA #IMPLIED
- * TODO: xsl:use-attribute-sets %qnames; #IMPLIED
- * xsl:version NMTOKEN #IMPLIED
- */
- cur->psvi = NULL;
- cctxt->inode->category = XSLT_ELEMENT_CATEGORY_LRE;
- if (cur->properties != NULL) {
- xmlAttrPtr attr = cur->properties;
- /*
- * Attribute "xsl:exclude-result-prefixes".
- */
- cctxt->inode->exclResultNs =
- xsltParseExclResultPrefixes(cctxt, cur,
- cctxt->inode->exclResultNs,
- XSLT_ELEMENT_CATEGORY_LRE);
- /*
- * Attribute "xsl:version".
- */
- xsltParseAttrXSLTVersion(cctxt, cur,
- XSLT_ELEMENT_CATEGORY_LRE);
- /*
- * Report invalid XSLT attributes.
- * For XSLT 1.0 only xsl:use-attribute-sets is allowed
- * next to xsl:version, xsl:exclude-result-prefixes and
- * xsl:extension-element-prefixes.
- *
- * Mark all XSLT attributes, in order to skip such
- * attributes when instantiating the LRE.
- */
- do {
- if ((attr->psvi != xsltXSLTAttrMarker) &&
- IS_XSLT_ATTR_FAST(attr))
- {
- if (! xmlStrEqual(attr->name,
- BAD_CAST "use-attribute-sets"))
- {
- xsltTransformError(NULL, cctxt->style,
- cur,
- "Unknown XSLT attribute '%s'.\n",
- attr->name);
- cctxt->style->errors++;
- } else {
- /*
- * XSLT attr marker.
- */
- attr->psvi = (void *) xsltXSLTAttrMarker;
- }
- }
- attr = attr->next;
- } while (attr != NULL);
- }
- /*
- * Create/reuse info for the literal result element.
- */
- if (cctxt->inode->nsChanged)
- xsltLREInfoCreate(cctxt, cur, 1);
- cur->psvi = cctxt->inode->litResElemInfo;
- /*
- * Apply ns-aliasing on the element and on its attributes.
- */
- if (cctxt->hasNsAliases)
- xsltLREBuildEffectiveNs(cctxt, cur);
- /*
- * Compile attribute value templates (AVT).
- */
- if (cur->properties) {
- xmlAttrPtr attr = cur->properties;
-
- while (attr != NULL) {
- xsltCompileAttr(cctxt->style, attr);
- attr = attr->next;
- }
- }
- /*
- * Parse the content, which is defined to be a "template"
- * (or "sequence constructor" in XSLT 2.0 terms).
- */
- if (cur->children != NULL) {
- xsltParseSequenceConstructor(cctxt, cur->children);
- }
- }
- /*
- * Leave the non-XSLT element.
- */
- xsltCompilerNodePop(cctxt, cur);
- }
- }
- cur = cur->next;
- }
- if (deleteNode != NULL) {
-#ifdef WITH_XSLT_DEBUG_BLANKS
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseSequenceConstructor: removing xsl:text element\n");
-#endif
- xmlUnlinkNode(deleteNode);
- xmlFreeNode(deleteNode);
- deleteNode = NULL;
- }
-}
-
-/**
- * xsltParseTemplateContent:
- * @style: the XSLT stylesheet
- * @templ: the node containing the content to be parsed
- *
- * Parses and compiles the content-model of an xsl:template element.
- * Note that this is *not* the "template" content model (or "sequence
- * constructor" in XSLT 2.0); it it allows addional xsl:param
- * elements as immediate children of @templ.
- *
- * Called by:
- * exsltFuncFunctionComp() (EXSLT, functions.c)
- * So this is intended to be called from extension functions.
- */
-void
-xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
- if ((style == NULL) || (templ == NULL) ||
- (templ->type == XML_NAMESPACE_DECL))
- return;
-
- /*
- * Detection of handled content of extension instructions.
- */
- if (XSLT_CCTXT(style)->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
- XSLT_CCTXT(style)->inode->extContentHandled = 1;
- }
-
- if (templ->children != NULL) {
- xmlNodePtr child = templ->children;
- /*
- * Process xsl:param elements, which can only occur as the
- * immediate children of xsl:template (well, and of any
- * user-defined extension instruction if needed).
- */
- do {
- if ((child->type == XML_ELEMENT_NODE) &&
- IS_XSLT_ELEM_FAST(child) &&
- IS_XSLT_NAME(child, "param"))
- {
- XSLT_CCTXT(style)->inode->curChildType = XSLT_FUNC_PARAM;
- xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
- } else
- break;
- child = child->next;
- } while (child != NULL);
- /*
- * Parse the content and register the pattern.
- */
- xsltParseSequenceConstructor(XSLT_CCTXT(style), child);
- }
-}
-
-#else /* XSLT_REFACTORED */
-
-/**
- * xsltParseTemplateContent:
- * @style: the XSLT stylesheet
- * @templ: the container node (can be a document for literal results)
- *
- * parse a template content-model
- * Clean-up the template content from unwanted ignorable blank nodes
- * and process xslt:text
- */
-void
-xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
- xmlNodePtr cur, delete;
-
- if ((style == NULL) || (templ == NULL) ||
- (templ->type == XML_NAMESPACE_DECL)) return;
-
- /*
- * This content comes from the stylesheet
- * For stylesheets, the set of whitespace-preserving
- * element names consists of just xsl:text.
- */
- cur = templ->children;
- delete = NULL;
- while (cur != NULL) {
- if (delete != NULL) {
-#ifdef WITH_XSLT_DEBUG_BLANKS
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseTemplateContent: removing text\n");
-#endif
- xmlUnlinkNode(delete);
- xmlFreeNode(delete);
- delete = NULL;
- }
- if (IS_XSLT_ELEM(cur)) {
- xsltStylePreCompute(style, cur);
-
- if (IS_XSLT_NAME(cur, "text")) {
- /*
- * TODO: Processing of xsl:text should be moved to
- * xsltPreprocessStylesheet(), since otherwise this
- * will be performed for every multiply included
- * stylesheet; i.e. this here is not skipped with
- * the use of the style->nopreproc flag.
- */
- if (cur->children != NULL) {
- xmlChar *prop;
- xmlNodePtr text = cur->children, next;
- int noesc = 0;
-
- prop = xmlGetNsProp(cur,
- (const xmlChar *)"disable-output-escaping",
- NULL);
- if (prop != NULL) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "Disable escaping: %s\n", text->content);
-#endif
- if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
- noesc = 1;
- } else if (!xmlStrEqual(prop,
- (const xmlChar *)"no")){
- xsltTransformError(NULL, style, cur,
- "xsl:text: disable-output-escaping allows only yes or no\n");
- style->warnings++;
-
- }
- xmlFree(prop);
- }
-
- while (text != NULL) {
- if (text->type == XML_COMMENT_NODE) {
- text = text->next;
- continue;
- }
- if ((text->type != XML_TEXT_NODE) &&
- (text->type != XML_CDATA_SECTION_NODE)) {
- xsltTransformError(NULL, style, cur,
- "xsltParseTemplateContent: xslt:text content problem\n");
- style->errors++;
- break;
- }
- if ((noesc) && (text->type != XML_CDATA_SECTION_NODE))
- text->name = xmlStringTextNoenc;
- text = text->next;
- }
-
- /*
- * replace xsl:text by the list of childs
- */
- if (text == NULL) {
- text = cur->children;
- while (text != NULL) {
- if ((style->internalized) &&
- (text->content != NULL) &&
- (!xmlDictOwns(style->dict, text->content))) {
-
- /*
- * internalize the text string
- */
- if (text->doc->dict != NULL) {
- const xmlChar *tmp;
-
- tmp = xmlDictLookup(text->doc->dict,
- text->content, -1);
- if (tmp != text->content) {
- xmlNodeSetContent(text, NULL);
- text->content = (xmlChar *) tmp;
- }
- }
- }
-
- next = text->next;
- xmlUnlinkNode(text);
- xmlAddPrevSibling(cur, text);
- text = next;
- }
- }
- }
- delete = cur;
- goto skip_children;
- }
- }
- 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 if (cur->type == XML_ELEMENT_NODE)
- {
- /*
- * This is an element which will be output as part of the
- * template exectution, precompile AVT if found.
- */
- if ((cur->ns == NULL) && (style->defaultAlias != NULL)) {
- cur->ns = xmlSearchNsByHref(cur->doc, cur,
- style->defaultAlias);
- }
- if (cur->properties != NULL) {
- xmlAttrPtr attr = cur->properties;
-
- while (attr != NULL) {
- xsltCompileAttr(style, attr);
- attr = attr->next;
- }
- }
- }
- /*
- * Skip to next node
- */
- if (cur->children != NULL) {
- if (cur->children->type != XML_ENTITY_DECL) {
- cur = cur->children;
- continue;
- }
- }
-skip_children:
- if (cur->next != NULL) {
- cur = cur->next;
- continue;
- }
-
- do {
- cur = cur->parent;
- if (cur == NULL)
- break;
- if (cur == templ) {
- cur = NULL;
- break;
- }
- if (cur->next != NULL) {
- cur = cur->next;
- break;
- }
- } while (cur != NULL);
- }
- if (delete != NULL) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseTemplateContent: removing text\n");
-#endif
- xmlUnlinkNode(delete);
- xmlFreeNode(delete);
- delete = NULL;
- }
-
- /*
- * Skip the first params
- */
- cur = templ->children;
- while (cur != NULL) {
- if ((IS_XSLT_ELEM(cur)) && (!(IS_XSLT_NAME(cur, "param"))))
- break;
- cur = cur->next;
- }
-
- /*
- * Browse the remainder of the template
- */
- while (cur != NULL) {
- if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "param"))) {
- xmlNodePtr param = cur;
-
- xsltTransformError(NULL, style, cur,
- "xsltParseTemplateContent: ignoring misplaced param element\n");
- if (style != NULL) style->warnings++;
- cur = cur->next;
- xmlUnlinkNode(param);
- xmlFreeNode(param);
- } else
- break;
- }
-}
-
-#endif /* else XSLT_REFACTORED */
-
-/**
- * xsltParseStylesheetKey:
- * @style: the XSLT stylesheet
- * @key: the "key" element
- *
- * <!-- Category: top-level-element -->
- * <xsl:key name = qname, match = pattern, use = expression />
- *
- * parse an XSLT stylesheet key definition and register it
- */
-
-static void
-xsltParseStylesheetKey(xsltStylesheetPtr style, xmlNodePtr key) {
- xmlChar *prop = NULL;
- xmlChar *use = NULL;
- xmlChar *match = NULL;
- xmlChar *name = NULL;
- xmlChar *nameURI = NULL;
-
- if ((style == NULL) || (key == NULL) || (key->type != XML_ELEMENT_NODE))
- return;
-
- /*
- * Get arguments
- */
- prop = xmlGetNsProp(key, (const xmlChar *)"name", NULL);
- if (prop != NULL) {
- const xmlChar *URI;
-
- /*
- * TODO: Don't use xsltGetQNameURI().
- */
- URI = xsltGetQNameURI(key, &prop);
- if (prop == NULL) {
- if (style != NULL) style->errors++;
- goto error;
- } else {
- name = prop;
- if (URI != NULL)
- nameURI = xmlStrdup(URI);
- }
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseStylesheetKey: name %s\n", name);
-#endif
- } else {
- xsltTransformError(NULL, style, key,
- "xsl:key : error missing name\n");
- if (style != NULL) style->errors++;
- goto error;
- }
-
- match = xmlGetNsProp(key, (const xmlChar *)"match", NULL);
- if (match == NULL) {
- xsltTransformError(NULL, style, key,
- "xsl:key : error missing match\n");
- if (style != NULL) style->errors++;
- goto error;
- }
-
- use = xmlGetNsProp(key, (const xmlChar *)"use", NULL);
- if (use == NULL) {
- xsltTransformError(NULL, style, key,
- "xsl:key : error missing use\n");
- if (style != NULL) style->errors++;
- goto error;
- }
-
- /*
- * register the keys
- */
- xsltAddKey(style, name, nameURI, match, use, key);
-
-
-error:
- if (use != NULL)
- xmlFree(use);
- if (match != NULL)
- xmlFree(match);
- if (name != NULL)
- xmlFree(name);
- if (nameURI != NULL)
- xmlFree(nameURI);
-
- if (key->children != NULL) {
- xsltParseContentError(style, key->children);
- }
-}
-
-#ifdef XSLT_REFACTORED
-/**
- * xsltParseXSLTTemplate:
- * @style: the XSLT stylesheet
- * @template: the "template" element
- *
- * parse an XSLT stylesheet template building the associated structures
- * TODO: Is @style ever expected to be NULL?
- *
- * Called from:
- * xsltParseXSLTStylesheet()
- * xsltParseStylesheetTop()
- */
-
-static void
-xsltParseXSLTTemplate(xsltCompilerCtxtPtr cctxt, xmlNodePtr templNode) {
- xsltTemplatePtr templ;
- xmlChar *prop;
- double priority;
-
- if ((cctxt == NULL) || (templNode == NULL) ||
- (templNode->type != XML_ELEMENT_NODE))
- return;
-
- /*
- * Create and link the structure
- */
- templ = xsltNewTemplate();
- if (templ == NULL)
- return;
-
- xsltCompilerNodePush(cctxt, templNode);
- if (templNode->nsDef != NULL)
- cctxt->inode->inScopeNs =
- xsltCompilerBuildInScopeNsList(cctxt, templNode);
-
- templ->next = cctxt->style->templates;
- cctxt->style->templates = templ;
- templ->style = cctxt->style;
-
- /*
- * Attribute "mode".
- */
- prop = xmlGetNsProp(templNode, (const xmlChar *)"mode", NULL);
- if (prop != NULL) {
- const xmlChar *modeURI;
-
- /*
- * TODO: We need a standardized function for extraction
- * of namespace names and local names from QNames.
- * Don't use xsltGetQNameURI() as it cannot channe�
- * reports through the context.
- */
- modeURI = xsltGetQNameURI(templNode, &prop);
- if (prop == NULL) {
- cctxt->style->errors++;
- goto error;
- }
- templ->mode = xmlDictLookup(cctxt->style->dict, prop, -1);
- xmlFree(prop);
- prop = NULL;
- if (xmlValidateNCName(templ->mode, 0)) {
- xsltTransformError(NULL, cctxt->style, templNode,
- "xsl:template: Attribute 'mode': The local part '%s' "
- "of the value is not a valid NCName.\n", templ->name);
- cctxt->style->errors++;
- goto error;
- }
- if (modeURI != NULL)
- templ->modeURI = xmlDictLookup(cctxt->style->dict, modeURI, -1);
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseXSLTTemplate: mode %s\n", templ->mode);
-#endif
- }
- /*
- * Attribute "match".
- */
- prop = xmlGetNsProp(templNode, (const xmlChar *)"match", NULL);
- if (prop != NULL) {
- templ->match = prop;
- prop = NULL;
- }
- /*
- * Attribute "priority".
- */
- prop = xmlGetNsProp(templNode, (const xmlChar *)"priority", NULL);
- if (prop != NULL) {
- priority = xmlXPathStringEvalNumber(prop);
- templ->priority = (float) priority;
- xmlFree(prop);
- prop = NULL;
- }
- /*
- * Attribute "name".
- */
- prop = xmlGetNsProp(templNode, (const xmlChar *)"name", NULL);
- if (prop != NULL) {
- const xmlChar *nameURI;
- xsltTemplatePtr curTempl;
-
- /*
- * TODO: Don't use xsltGetQNameURI().
- */
- nameURI = xsltGetQNameURI(templNode, &prop);
- if (prop == NULL) {
- cctxt->style->errors++;
- goto error;
- }
- templ->name = xmlDictLookup(cctxt->style->dict, prop, -1);
- xmlFree(prop);
- prop = NULL;
- if (xmlValidateNCName(templ->name, 0)) {
- xsltTransformError(NULL, cctxt->style, templNode,
- "xsl:template: Attribute 'name': The local part '%s' of "
- "the value is not a valid NCName.\n", templ->name);
- cctxt->style->errors++;
- goto error;
- }
- if (nameURI != NULL)
- templ->nameURI = xmlDictLookup(cctxt->style->dict, nameURI, -1);
- curTempl = templ->next;
- while (curTempl != NULL) {
- if ((nameURI != NULL && xmlStrEqual(curTempl->name, templ->name) &&
- xmlStrEqual(curTempl->nameURI, nameURI) ) ||
- (nameURI == NULL && curTempl->nameURI == NULL &&
- xmlStrEqual(curTempl->name, templ->name)))
- {
- xsltTransformError(NULL, cctxt->style, templNode,
- "xsl:template: error duplicate name '%s'\n", templ->name);
- cctxt->style->errors++;
- goto error;
- }
- curTempl = curTempl->next;
- }
- }
- if (templNode->children != NULL) {
- xsltParseTemplateContent(cctxt->style, templNode);
- /*
- * MAYBE TODO: Custom behaviour: In order to stay compatible with
- * Xalan and MSXML(.NET), we could allow whitespace
- * to appear before an xml:param element; this whitespace
- * will additionally become part of the "template".
- * NOTE that this is totally deviates from the spec, but
- * is the de facto behaviour of Xalan and MSXML(.NET).
- * Personally I wouldn't allow this, since if we have:
- * <xsl:template ...xml:space="preserve">
- * <xsl:param name="foo"/>
- * <xsl:param name="bar"/>
- * <xsl:param name="zoo"/>
- * ... the whitespace between every xsl:param would be
- * added to the result tree.
- */
- }
-
- templ->elem = templNode;
- templ->content = templNode->children;
- xsltAddTemplate(cctxt->style, templ, templ->mode, templ->modeURI);
-
-error:
- xsltCompilerNodePop(cctxt, templNode);
- return;
-}
-
-#else /* XSLT_REFACTORED */
-
-/**
- * xsltParseStylesheetTemplate:
- * @style: the XSLT stylesheet
- * @template: the "template" element
- *
- * parse an XSLT stylesheet template building the associated structures
- */
-
-static void
-xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
- xsltTemplatePtr ret;
- xmlChar *prop;
- xmlChar *mode = NULL;
- xmlChar *modeURI = NULL;
- double priority;
-
- if ((style == NULL) || (template == NULL) ||
- (template->type != XML_ELEMENT_NODE))
- return;
-
- /*
- * Create and link the structure
- */
- ret = xsltNewTemplate();
- if (ret == NULL)
- return;
- ret->next = style->templates;
- style->templates = ret;
- ret->style = style;
-
- /*
- * Get inherited namespaces
- */
- /*
- * TODO: Apply the optimized in-scope-namespace mechanism
- * as for the other XSLT instructions.
- */
- xsltGetInheritedNsList(style, ret, template);
-
- /*
- * Get arguments
- */
- prop = xmlGetNsProp(template, (const xmlChar *)"mode", NULL);
- if (prop != NULL) {
- const xmlChar *URI;
-
- /*
- * TODO: Don't use xsltGetQNameURI().
- */
- URI = xsltGetQNameURI(template, &prop);
- if (prop == NULL) {
- if (style != NULL) style->errors++;
- goto error;
- } else {
- mode = prop;
- if (URI != NULL)
- modeURI = xmlStrdup(URI);
- }
- ret->mode = xmlDictLookup(style->dict, mode, -1);
- ret->modeURI = xmlDictLookup(style->dict, modeURI, -1);
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseStylesheetTemplate: mode %s\n", mode);
-#endif
- if (mode != NULL) xmlFree(mode);
- if (modeURI != NULL) xmlFree(modeURI);
- }
- prop = xmlGetNsProp(template, (const xmlChar *)"match", NULL);
- if (prop != NULL) {
- if (ret->match != NULL) xmlFree(ret->match);
- ret->match = prop;
- }
-
- prop = xmlGetNsProp(template, (const xmlChar *)"priority", NULL);
- if (prop != NULL) {
- priority = xmlXPathStringEvalNumber(prop);
- ret->priority = (float) priority;
- xmlFree(prop);
- }
-
- prop = xmlGetNsProp(template, (const xmlChar *)"name", NULL);
- if (prop != NULL) {
- const xmlChar *URI;
-
- /*
- * TODO: Don't use xsltGetQNameURI().
- */
- URI = xsltGetQNameURI(template, &prop);
- if (prop == NULL) {
- if (style != NULL) style->errors++;
- goto error;
- } else {
- if (xmlValidateNCName(prop,0)) {
- xsltTransformError(NULL, style, template,
- "xsl:template : error invalid name '%s'\n", prop);
- if (style != NULL) style->errors++;
- goto error;
- }
- ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1);
- xmlFree(prop);
- prop = NULL;
- if (URI != NULL)
- ret->nameURI = xmlDictLookup(style->dict, BAD_CAST URI, -1);
- else
- ret->nameURI = NULL;
- }
- }
-
- /*
- * parse the content and register the pattern
- */
- xsltParseTemplateContent(style, template);
- ret->elem = template;
- ret->content = template->children;
- xsltAddTemplate(style, ret, ret->mode, ret->modeURI);
-
-error:
- return;
-}
-
-#endif /* else XSLT_REFACTORED */
-
-#ifdef XSLT_REFACTORED
-
-/**
- * xsltIncludeComp:
- * @cctxt: the compilation contenxt
- * @node: the xsl:include node
- *
- * Process the xslt include node on the source node
- */
-static xsltStyleItemIncludePtr
-xsltCompileXSLTIncludeElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node) {
- xsltStyleItemIncludePtr item;
-
- if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
- return(NULL);
-
- node->psvi = NULL;
- item = (xsltStyleItemIncludePtr) xmlMalloc(sizeof(xsltStyleItemInclude));
- if (item == NULL) {
- xsltTransformError(NULL, cctxt->style, node,
- "xsltIncludeComp : malloc failed\n");
- cctxt->style->errors++;
- return(NULL);
- }
- memset(item, 0, sizeof(xsltStyleItemInclude));
-
- node->psvi = item;
- item->inst = node;
- item->type = XSLT_FUNC_INCLUDE;
-
- item->next = cctxt->style->preComps;
- cctxt->style->preComps = (xsltElemPreCompPtr) item;
-
- return(item);
-}
-
-/**
- * xsltParseFindTopLevelElem:
- */
-static int
-xsltParseFindTopLevelElem(xsltCompilerCtxtPtr cctxt,
- xmlNodePtr cur,
- const xmlChar *name,
- const xmlChar *namespaceURI,
- int breakOnOtherElem,
- xmlNodePtr *resultNode)
-{
- if (name == NULL)
- return(-1);
-
- *resultNode = NULL;
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE) {
- if ((cur->ns != NULL) && (cur->name != NULL)) {
- if ((*(cur->name) == *name) &&
- xmlStrEqual(cur->name, name) &&
- xmlStrEqual(cur->ns->href, namespaceURI))
- {
- *resultNode = cur;
- return(1);
- }
- }
- if (breakOnOtherElem)
- break;
- }
- cur = cur->next;
- }
- *resultNode = cur;
- return(0);
-}
-
-static int
-xsltParseTopLevelXSLTElem(xsltCompilerCtxtPtr cctxt,
- xmlNodePtr node,
- xsltStyleType type)
-{
- int ret = 0;
-
- /*
- * TODO: The reason why this function exists:
- * due to historical reasons some of the
- * top-level declarations are processed by functions
- * in other files. Since we need still to set
- * up the node-info and generate information like
- * in-scope namespaces, this is a wrapper around
- * those old parsing functions.
- */
- xsltCompilerNodePush(cctxt, node);
- if (node->nsDef != NULL)
- cctxt->inode->inScopeNs =
- xsltCompilerBuildInScopeNsList(cctxt, node);
- cctxt->inode->type = type;
-
- switch (type) {
- case XSLT_FUNC_INCLUDE:
- {
- int oldIsInclude;
-
- if (xsltCompileXSLTIncludeElem(cctxt, node) == NULL)
- goto exit;
- /*
- * Mark this stylesheet tree as being currently included.
- */
- oldIsInclude = cctxt->isInclude;
- cctxt->isInclude = 1;
-
- if (xsltParseStylesheetInclude(cctxt->style, node) != 0) {
- cctxt->style->errors++;
- }
- cctxt->isInclude = oldIsInclude;
- }
- break;
- case XSLT_FUNC_PARAM:
- xsltStylePreCompute(cctxt->style, node);
- xsltParseGlobalParam(cctxt->style, node);
- break;
- case XSLT_FUNC_VARIABLE:
- xsltStylePreCompute(cctxt->style, node);
- xsltParseGlobalVariable(cctxt->style, node);
- break;
- case XSLT_FUNC_ATTRSET:
- xsltParseStylesheetAttributeSet(cctxt->style, node);
- break;
- default:
- xsltTransformError(NULL, cctxt->style, node,
- "Internal error: (xsltParseTopLevelXSLTElem) "
- "Cannot handle this top-level declaration.\n");
- cctxt->style->errors++;
- ret = -1;
- }
-
-exit:
- xsltCompilerNodePop(cctxt, node);
-
- return(ret);
-}
-
-#if 0
-static int
-xsltParseRemoveWhitespace(xmlNodePtr node)
-{
- if ((node == NULL) || (node->children == NULL))
- return(0);
- else {
- xmlNodePtr delNode = NULL, child = node->children;
-
- do {
- if (delNode) {
- xmlUnlinkNode(delNode);
- xmlFreeNode(delNode);
- delNode = NULL;
- }
- if (((child->type == XML_TEXT_NODE) ||
- (child->type == XML_CDATA_SECTION_NODE)) &&
- (IS_BLANK_NODE(child)))
- delNode = child;
- child = child->next;
- } while (child != NULL);
- if (delNode) {
- xmlUnlinkNode(delNode);
- xmlFreeNode(delNode);
- delNode = NULL;
- }
- }
- return(0);
-}
-#endif
-
-static int
-xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
-{
-#ifdef WITH_XSLT_DEBUG_PARSING
- int templates = 0;
-#endif
- xmlNodePtr cur, start = NULL;
- xsltStylesheetPtr style;
-
- if ((cctxt == NULL) || (node == NULL) ||
- (node->type != XML_ELEMENT_NODE))
- return(-1);
-
- style = cctxt->style;
- /*
- * At this stage all import declarations of all stylesheet modules
- * with the same stylesheet level have been processed.
- * Now we can safely parse the rest of the declarations.
- */
- if (IS_XSLT_ELEM_FAST(node) && IS_XSLT_NAME(node, "include"))
- {
- xsltDocumentPtr include;
- /*
- * URGENT TODO: Make this work with simplified stylesheets!
- * I.e., when we won't find an xsl:stylesheet element.
- */
- /*
- * This is as include declaration.
- */
- include = ((xsltStyleItemIncludePtr) node->psvi)->include;
- if (include == NULL) {
- /* TODO: raise error? */
- return(-1);
- }
- /*
- * TODO: Actually an xsl:include should locate an embedded
- * stylesheet as well; so the document-element won't always
- * be the element where the actual stylesheet is rooted at.
- * But such embedded stylesheets are not supported by Libxslt yet.
- */
- node = xmlDocGetRootElement(include->doc);
- if (node == NULL) {
- return(-1);
- }
- }
-
- if (node->children == NULL)
- return(0);
- /*
- * Push the xsl:stylesheet/xsl:transform element.
- */
- xsltCompilerNodePush(cctxt, node);
- cctxt->inode->isRoot = 1;
- cctxt->inode->nsChanged = 0;
- /*
- * Start with the naked dummy info for literal result elements.
- */
- cctxt->inode->litResElemInfo = cctxt->inodeList->litResElemInfo;
-
- /*
- * In every case, we need to have
- * the in-scope namespaces of the element, where the
- * stylesheet is rooted at, regardless if it's an XSLT
- * instruction or a literal result instruction (or if
- * this is an embedded stylesheet).
- */
- cctxt->inode->inScopeNs =
- xsltCompilerBuildInScopeNsList(cctxt, node);
-
- /*
- * Process attributes of xsl:stylesheet/xsl:transform.
- * --------------------------------------------------
- * Allowed are:
- * id = id
- * extension-element-prefixes = tokens
- * exclude-result-prefixes = tokens
- * version = number (mandatory)
- */
- if (xsltParseAttrXSLTVersion(cctxt, node,
- XSLT_ELEMENT_CATEGORY_XSLT) == 0)
- {
- /*
- * Attribute "version".
- * XSLT 1.0: "An xsl:stylesheet element *must* have a version
- * attribute, indicating the version of XSLT that the
- * stylesheet requires".
- * The root element of a simplified stylesheet must also have
- * this attribute.
- */
-#ifdef XSLT_REFACTORED_MANDATORY_VERSION
- if (isXsltElem)
- xsltTransformError(NULL, cctxt->style, node,
- "The attribute 'version' is missing.\n");
- cctxt->style->errors++;
-#else
- /* OLD behaviour. */
- xsltTransformError(NULL, cctxt->style, node,
- "xsl:version is missing: document may not be a stylesheet\n");
- cctxt->style->warnings++;
-#endif
- }
- /*
- * The namespaces declared by the attributes
- * "extension-element-prefixes" and
- * "exclude-result-prefixes" are local to *this*
- * stylesheet tree; i.e., they are *not* visible to
- * other stylesheet-modules, whether imported or included.
- *
- * Attribute "extension-element-prefixes".
- */
- cctxt->inode->extElemNs =
- xsltParseExtElemPrefixes(cctxt, node, NULL,
- XSLT_ELEMENT_CATEGORY_XSLT);
- /*
- * Attribute "exclude-result-prefixes".
- */
- cctxt->inode->exclResultNs =
- xsltParseExclResultPrefixes(cctxt, node, NULL,
- XSLT_ELEMENT_CATEGORY_XSLT);
- /*
- * Create/reuse info for the literal result element.
- */
- if (cctxt->inode->nsChanged)
- xsltLREInfoCreate(cctxt, node, 0);
- /*
- * Processed top-level elements:
- * ----------------------------
- * xsl:variable, xsl:param (QName, in-scope ns,
- * expression (vars allowed))
- * xsl:attribute-set (QName, in-scope ns)
- * xsl:strip-space, xsl:preserve-space (XPath NameTests,
- * in-scope ns)
- * I *think* global scope, merge with includes
- * xsl:output (QName, in-scope ns)
- * xsl:key (QName, in-scope ns, pattern,
- * expression (vars *not* allowed))
- * xsl:decimal-format (QName, needs in-scope ns)
- * xsl:namespace-alias (in-scope ns)
- * global scope, merge with includes
- * xsl:template (last, QName, pattern)
- *
- * (whitespace-only text-nodes have *not* been removed
- * yet; this will be done in xsltParseSequenceConstructor)
- *
- * Report misplaced child-nodes first.
- */
- cur = node->children;
- while (cur != NULL) {
- if (cur->type == XML_TEXT_NODE) {
- xsltTransformError(NULL, style, cur,
- "Misplaced text node (content: '%s').\n",
- (cur->content != NULL) ? cur->content : BAD_CAST "");
- style->errors++;
- } else if (cur->type != XML_ELEMENT_NODE) {
- xsltTransformError(NULL, style, cur, "Misplaced node.\n");
- style->errors++;
- }
- cur = cur->next;
- }
- /*
- * Skip xsl:import elements; they have been processed
- * already.
- */
- cur = node->children;
- while ((cur != NULL) && xsltParseFindTopLevelElem(cctxt, cur,
- BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)
- cur = cur->next;
- if (cur == NULL)
- goto exit;
-
- start = cur;
- /*
- * Process all top-level xsl:param elements.
- */
- while ((cur != NULL) &&
- xsltParseFindTopLevelElem(cctxt, cur,
- BAD_CAST "param", XSLT_NAMESPACE, 0, &cur) == 1)
- {
- xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_PARAM);
- cur = cur->next;
- }
- /*
- * Process all top-level xsl:variable elements.
- */
- cur = start;
- while ((cur != NULL) &&
- xsltParseFindTopLevelElem(cctxt, cur,
- BAD_CAST "variable", XSLT_NAMESPACE, 0, &cur) == 1)
- {
- xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_VARIABLE);
- cur = cur->next;
- }
- /*
- * Process all the rest of top-level elements.
- */
- cur = start;
- while (cur != NULL) {
- /*
- * Process element nodes.
- */
- if (cur->type == XML_ELEMENT_NODE) {
- if (cur->ns == NULL) {
- xsltTransformError(NULL, style, cur,
- "Unexpected top-level element in no namespace.\n");
- style->errors++;
- cur = cur->next;
- continue;
- }
- /*
- * Process all XSLT elements.
- */
- if (IS_XSLT_ELEM_FAST(cur)) {
- /*
- * xsl:import is only allowed at the beginning.
- */
- if (IS_XSLT_NAME(cur, "import")) {
- xsltTransformError(NULL, style, cur,
- "Misplaced xsl:import element.\n");
- style->errors++;
- cur = cur->next;
- continue;
- }
- /*
- * TODO: Change the return type of the parsing functions
- * to int.
- */
- if (IS_XSLT_NAME(cur, "template")) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- templates++;
-#endif
- /*
- * TODO: Is the position of xsl:template in the
- * tree significant? If not it would be easier to
- * parse them at a later stage.
- */
- xsltParseXSLTTemplate(cctxt, cur);
- } else if (IS_XSLT_NAME(cur, "variable")) {
- /* NOP; done already */
- } else if (IS_XSLT_NAME(cur, "param")) {
- /* NOP; done already */
- } else if (IS_XSLT_NAME(cur, "include")) {
- if (cur->psvi != NULL)
- xsltParseXSLTStylesheetElemCore(cctxt, cur);
- else {
- xsltTransformError(NULL, style, cur,
- "Internal error: "
- "(xsltParseXSLTStylesheetElemCore) "
- "The xsl:include element was not compiled.\n");
- style->errors++;
- }
- } else if (IS_XSLT_NAME(cur, "strip-space")) {
- /* No node info needed. */
- xsltParseStylesheetStripSpace(style, cur);
- } else if (IS_XSLT_NAME(cur, "preserve-space")) {
- /* No node info needed. */
- xsltParseStylesheetPreserveSpace(style, cur);
- } else if (IS_XSLT_NAME(cur, "output")) {
- /* No node-info needed. */
- xsltParseStylesheetOutput(style, cur);
- } else if (IS_XSLT_NAME(cur, "key")) {
- /* TODO: node-info needed for expressions ? */
- xsltParseStylesheetKey(style, cur);
- } else if (IS_XSLT_NAME(cur, "decimal-format")) {
- /* No node-info needed. */
- xsltParseStylesheetDecimalFormat(style, cur);
- } else if (IS_XSLT_NAME(cur, "attribute-set")) {
- xsltParseTopLevelXSLTElem(cctxt, cur,
- XSLT_FUNC_ATTRSET);
- } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
- /* NOP; done already */
- } else {
- if (cctxt->inode->forwardsCompat) {
- /*
- * Forwards-compatible mode:
- *
- * XSLT-1: "if it is a top-level element and
- * XSLT 1.0 does not allow such elements as top-level
- * elements, then the element must be ignored along
- * with its content;"
- */
- /*
- * TODO: I don't think we should generate a warning.
- */
- xsltTransformError(NULL, style, cur,
- "Forwards-compatible mode: Ignoring unknown XSLT "
- "element '%s'.\n", cur->name);
- style->warnings++;
- } else {
- xsltTransformError(NULL, style, cur,
- "Unknown XSLT element '%s'.\n", cur->name);
- style->errors++;
- }
- }
- } else {
- xsltTopLevelFunction function;
-
- /*
- * Process non-XSLT elements, which are in a
- * non-NULL namespace.
- */
- /*
- * QUESTION: What does xsltExtModuleTopLevelLookup()
- * do exactly?
- */
- function = xsltExtModuleTopLevelLookup(cur->name,
- cur->ns->href);
- if (function != NULL)
- function(style, cur);
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseXSLTStylesheetElemCore : User-defined "
- "data element '%s'.\n", cur->name);
-#endif
- }
- }
- cur = cur->next;
- }
-
-exit:
-
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "### END of parsing top-level elements of doc '%s'.\n",
- node->doc->URL);
- xsltGenericDebug(xsltGenericDebugContext,
- "### Templates: %d\n", templates);
-#ifdef XSLT_REFACTORED
- xsltGenericDebug(xsltGenericDebugContext,
- "### Max inodes: %d\n", cctxt->maxNodeInfos);
- xsltGenericDebug(xsltGenericDebugContext,
- "### Max LREs : %d\n", cctxt->maxLREs);
-#endif /* XSLT_REFACTORED */
-#endif /* WITH_XSLT_DEBUG_PARSING */
-
- xsltCompilerNodePop(cctxt, node);
- return(0);
-}
-
-/**
- * xsltParseXSLTStylesheet:
- * @cctxt: the compiler context
- * @node: the xsl:stylesheet/xsl:transform element-node
- *
- * Parses the xsl:stylesheet and xsl:transform element.
- *
- * <xsl:stylesheet
- * id = id
- * extension-element-prefixes = tokens
- * exclude-result-prefixes = tokens
- * version = number>
- * <!-- Content: (xsl:import*, top-level-elements) -->
- * </xsl:stylesheet>
- *
- * BIG TODO: The xsl:include stuff.
- *
- * Called by xsltParseStylesheetTree()
- *
- * Returns 0 on success, a positive result on errors and
- * -1 on API or internal errors.
- */
-static int
-xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
-{
- xmlNodePtr cur, start;
-
- if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
- return(-1);
-
- if (node->children == NULL)
- goto exit;
-
- /*
- * Process top-level elements:
- * xsl:import (must be first)
- * xsl:include (this is just a pre-processing)
- */
- cur = node->children;
- /*
- * Process xsl:import elements.
- * XSLT 1.0: "The xsl:import element children must precede all
- * other element children of an xsl:stylesheet element,
- * including any xsl:include element children."
- */
- while ((cur != NULL) &&
- xsltParseFindTopLevelElem(cctxt, cur,
- BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)
- {
- if (xsltParseStylesheetImport(cctxt->style, cur) != 0) {
- cctxt->style->errors++;
- }
- cur = cur->next;
- }
- if (cur == NULL)
- goto exit;
- start = cur;
- /*
- * Pre-process all xsl:include elements.
- */
- cur = start;
- while ((cur != NULL) &&
- xsltParseFindTopLevelElem(cctxt, cur,
- BAD_CAST "include", XSLT_NAMESPACE, 0, &cur) == 1)
- {
- xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_INCLUDE);
- cur = cur->next;
- }
- /*
- * Pre-process all xsl:namespace-alias elements.
- * URGENT TODO: This won't work correctly: the order of included
- * aliases and aliases defined here is significant.
- */
- cur = start;
- while ((cur != NULL) &&
- xsltParseFindTopLevelElem(cctxt, cur,
- BAD_CAST "namespace-alias", XSLT_NAMESPACE, 0, &cur) == 1)
- {
- xsltNamespaceAlias(cctxt->style, cur);
- cur = cur->next;
- }
-
- if (cctxt->isInclude) {
- /*
- * If this stylesheet is intended for inclusion, then
- * we will process only imports and includes.
- */
- goto exit;
- }
- /*
- * Now parse the rest of the top-level elements.
- */
- xsltParseXSLTStylesheetElemCore(cctxt, node);
-exit:
-
- return(0);
-}
-
-#else /* XSLT_REFACTORED */
-
-/**
- * xsltParseStylesheetTop:
- * @style: the XSLT stylesheet
- * @top: the top level "stylesheet" or "transform" element
- *
- * scan the top level elements of an XSL stylesheet
- */
-static void
-xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
- xmlNodePtr cur;
- xmlChar *prop;
-#ifdef WITH_XSLT_DEBUG_PARSING
- int templates = 0;
-#endif
-
- if ((top == NULL) || (top->type != XML_ELEMENT_NODE))
- return;
-
- prop = xmlGetNsProp(top, (const xmlChar *)"version", NULL);
- if (prop == NULL) {
- xsltTransformError(NULL, style, top,
- "xsl:version is missing: document may not be a stylesheet\n");
- if (style != NULL) style->warnings++;
- } else {
- if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
- (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
- xsltTransformError(NULL, style, top,
- "xsl:version: only 1.1 features are supported\n");
- if (style != NULL) {
- style->forwards_compatible = 1;
- style->warnings++;
- }
- }
- xmlFree(prop);
- }
-
- /*
- * process xsl:import elements
- */
- cur = top->children;
- while (cur != NULL) {
- if (IS_BLANK_NODE(cur)) {
- cur = cur->next;
- continue;
- }
- if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "import")) {
- if (xsltParseStylesheetImport(style, cur) != 0)
- if (style != NULL) style->errors++;
- } else
- break;
- cur = cur->next;
- }
-
- /*
- * process other top-level elements
- */
- while (cur != NULL) {
- if (IS_BLANK_NODE(cur)) {
- cur = cur->next;
- continue;
- }
- if (cur->type == XML_TEXT_NODE) {
- if (cur->content != NULL) {
- xsltTransformError(NULL, style, cur,
- "misplaced text node: '%s'\n", cur->content);
- }
- if (style != NULL) style->errors++;
- cur = cur->next;
- continue;
- }
- if ((cur->type == XML_ELEMENT_NODE) && (cur->ns == NULL)) {
- xsltGenericError(xsltGenericErrorContext,
- "Found a top-level element %s with null namespace URI\n",
- cur->name);
- if (style != NULL) style->errors++;
- cur = cur->next;
- continue;
- }
- if ((cur->type == XML_ELEMENT_NODE) && (!(IS_XSLT_ELEM(cur)))) {
- xsltTopLevelFunction function;
-
- function = xsltExtModuleTopLevelLookup(cur->name,
- cur->ns->href);
- if (function != NULL)
- function(style, cur);
-
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseStylesheetTop : found foreign element %s\n",
- cur->name);
-#endif
- cur = cur->next;
- continue;
- }
- if (IS_XSLT_NAME(cur, "import")) {
- xsltTransformError(NULL, style, cur,
- "xsltParseStylesheetTop: ignoring misplaced import element\n");
- if (style != NULL) style->errors++;
- } else if (IS_XSLT_NAME(cur, "include")) {
- if (xsltParseStylesheetInclude(style, cur) != 0)
- if (style != NULL) style->errors++;
- } else if (IS_XSLT_NAME(cur, "strip-space")) {
- xsltParseStylesheetStripSpace(style, cur);
- } else if (IS_XSLT_NAME(cur, "preserve-space")) {
- xsltParseStylesheetPreserveSpace(style, cur);
- } else if (IS_XSLT_NAME(cur, "output")) {
- xsltParseStylesheetOutput(style, cur);
- } else if (IS_XSLT_NAME(cur, "key")) {
- xsltParseStylesheetKey(style, cur);
- } else if (IS_XSLT_NAME(cur, "decimal-format")) {
- xsltParseStylesheetDecimalFormat(style, cur);
- } else if (IS_XSLT_NAME(cur, "attribute-set")) {
- xsltParseStylesheetAttributeSet(style, cur);
- } else if (IS_XSLT_NAME(cur, "variable")) {
- xsltParseGlobalVariable(style, cur);
- } else if (IS_XSLT_NAME(cur, "param")) {
- xsltParseGlobalParam(style, cur);
- } else if (IS_XSLT_NAME(cur, "template")) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- templates++;
-#endif
- xsltParseStylesheetTemplate(style, cur);
- } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
- xsltNamespaceAlias(style, cur);
- } else {
- if ((style != NULL) && (style->forwards_compatible == 0)) {
- xsltTransformError(NULL, style, cur,
- "xsltParseStylesheetTop: unknown %s element\n",
- cur->name);
- if (style != NULL) style->errors++;
- }
- }
- cur = cur->next;
- }
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "parsed %d templates\n", templates);
-#endif
-}
-
-#endif /* else of XSLT_REFACTORED */
-
-#ifdef XSLT_REFACTORED
-/**
- * xsltParseSimplifiedStylesheetTree:
- *
- * @style: the stylesheet (TODO: Change this to the compiler context)
- * @doc: the document containing the stylesheet.
- * @node: the node where the stylesheet is rooted at
- *
- * Returns 0 in case of success, a positive result if an error occurred
- * and -1 on API and internal errors.
- */
-static int
-xsltParseSimplifiedStylesheetTree(xsltCompilerCtxtPtr cctxt,
- xmlDocPtr doc,
- xmlNodePtr node)
-{
- xsltTemplatePtr templ;
-
- if ((cctxt == NULL) || (node == NULL))
- return(-1);
-
- if (xsltParseAttrXSLTVersion(cctxt, node, 0) == XSLT_ELEMENT_CATEGORY_LRE)
- {
- /*
- * TODO: Adjust report, since this might be an
- * embedded stylesheet.
- */
- xsltTransformError(NULL, cctxt->style, node,
- "The attribute 'xsl:version' is missing; cannot identify "
- "this document as an XSLT stylesheet document.\n");
- cctxt->style->errors++;
- return(1);
- }
-
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseSimplifiedStylesheetTree: document is stylesheet\n");
-#endif
-
- /*
- * Create and link the template
- */
- templ = xsltNewTemplate();
- if (templ == NULL) {
- return(-1);
- }
- templ->next = cctxt->style->templates;
- cctxt->style->templates = templ;
- templ->match = xmlStrdup(BAD_CAST "/");
-
- /*
- * Note that we push the document-node in this special case.
- */
- xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);
- /*
- * In every case, we need to have
- * the in-scope namespaces of the element, where the
- * stylesheet is rooted at, regardless if it's an XSLT
- * instruction or a literal result instruction (or if
- * this is an embedded stylesheet).
- */
- cctxt->inode->inScopeNs =
- xsltCompilerBuildInScopeNsList(cctxt, node);
- /*
- * Parse the content and register the match-pattern.
- */
- xsltParseSequenceConstructor(cctxt, node);
- xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);
-
- templ->elem = (xmlNodePtr) doc;
- templ->content = node;
- xsltAddTemplate(cctxt->style, templ, NULL, NULL);
- cctxt->style->literal_result = 1;
- return(0);
-}
-
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP
-/**
- * xsltRestoreDocumentNamespaces:
- * @ns: map of namespaces
- * @doc: the document
- *
- * Restore the namespaces for the document
- *
- * Returns 0 in case of success, -1 in case of failure
- */
-int
-xsltRestoreDocumentNamespaces(xsltNsMapPtr ns, xmlDocPtr doc)
-{
- if (doc == NULL)
- return(-1);
- /*
- * Revert the changes we have applied to the namespace-URIs of
- * ns-decls.
- */
- while (ns != NULL) {
- if ((ns->doc == doc) && (ns->ns != NULL)) {
- ns->ns->href = ns->origNsName;
- ns->origNsName = NULL;
- ns->ns = NULL;
- }
- ns = ns->next;
- }
- return(0);
-}
-#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
-
-/**
- * xsltParseStylesheetProcess:
- * @style: the XSLT stylesheet (the current stylesheet-level)
- * @doc: and xmlDoc parsed XML
- *
- * Parses an XSLT stylesheet, adding the associated structures.
- * Called by:
- * xsltParseStylesheetImportedDoc() (xslt.c)
- * xsltParseStylesheetInclude() (imports.c)
- *
- * Returns the value of the @style parameter if everything
- * went right, NULL if something went amiss.
- */
-xsltStylesheetPtr
-xsltParseStylesheetProcess(xsltStylesheetPtr style, xmlDocPtr doc)
-{
- xsltCompilerCtxtPtr cctxt;
- xmlNodePtr cur;
- int oldIsSimplifiedStylesheet;
-
- xsltInitGlobals();
-
- if ((style == NULL) || (doc == NULL))
- return(NULL);
-
- cctxt = XSLT_CCTXT(style);
-
- cur = xmlDocGetRootElement(doc);
- if (cur == NULL) {
- xsltTransformError(NULL, style, (xmlNodePtr) doc,
- "xsltParseStylesheetProcess : empty stylesheet\n");
- return(NULL);
- }
- oldIsSimplifiedStylesheet = cctxt->simplified;
-
- if ((IS_XSLT_ELEM(cur)) &&
- ((IS_XSLT_NAME(cur, "stylesheet")) ||
- (IS_XSLT_NAME(cur, "transform")))) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseStylesheetProcess : found stylesheet\n");
-#endif
- cctxt->simplified = 0;
- style->literal_result = 0;
- } else {
- cctxt->simplified = 1;
- style->literal_result = 1;
- }
- /*
- * Pre-process the stylesheet if not already done before.
- * This will remove PIs and comments, merge adjacent
- * text nodes, internalize strings, etc.
- */
- if (! style->nopreproc)
- xsltParsePreprocessStylesheetTree(cctxt, cur);
- /*
- * Parse and compile the stylesheet.
- */
- if (style->literal_result == 0) {
- if (xsltParseXSLTStylesheetElem(cctxt, cur) != 0)
- return(NULL);
- } else {
- if (xsltParseSimplifiedStylesheetTree(cctxt, doc, cur) != 0)
- return(NULL);
- }
-
- cctxt->simplified = oldIsSimplifiedStylesheet;
-
- return(style);
-}
-
-#else /* XSLT_REFACTORED */
-
-/**
- * xsltParseStylesheetProcess:
- * @ret: the XSLT stylesheet (the current stylesheet-level)
- * @doc: and xmlDoc parsed XML
- *
- * Parses an XSLT stylesheet, adding the associated structures.
- * Called by:
- * xsltParseStylesheetImportedDoc() (xslt.c)
- * xsltParseStylesheetInclude() (imports.c)
- *
- * Returns the value of the @style parameter if everything
- * went right, NULL if something went amiss.
- */
-xsltStylesheetPtr
-xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
- xmlNodePtr cur;
-
- xsltInitGlobals();
-
- if (doc == NULL)
- return(NULL);
- if (ret == NULL)
- return(ret);
-
- /*
- * First steps, remove blank nodes,
- * locate the xsl:stylesheet element and the
- * namespace declaration.
- */
- cur = xmlDocGetRootElement(doc);
- if (cur == NULL) {
- xsltTransformError(NULL, ret, (xmlNodePtr) doc,
- "xsltParseStylesheetProcess : empty stylesheet\n");
- return(NULL);
- }
-
- if ((IS_XSLT_ELEM(cur)) &&
- ((IS_XSLT_NAME(cur, "stylesheet")) ||
- (IS_XSLT_NAME(cur, "transform")))) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseStylesheetProcess : found stylesheet\n");
-#endif
- ret->literal_result = 0;
- xsltParseStylesheetExcludePrefix(ret, cur, 1);
- xsltParseStylesheetExtPrefix(ret, cur, 1);
- } else {
- xsltParseStylesheetExcludePrefix(ret, cur, 0);
- xsltParseStylesheetExtPrefix(ret, cur, 0);
- ret->literal_result = 1;
- }
- if (!ret->nopreproc) {
- xsltPreprocessStylesheet(ret, cur);
- }
- if (ret->literal_result == 0) {
- xsltParseStylesheetTop(ret, cur);
- } else {
- xmlChar *prop;
- xsltTemplatePtr template;
-
- /*
- * the document itself might be the template, check xsl:version
- */
- prop = xmlGetNsProp(cur, (const xmlChar *)"version", XSLT_NAMESPACE);
- if (prop == NULL) {
- xsltTransformError(NULL, ret, cur,
- "xsltParseStylesheetProcess : document is not a stylesheet\n");
- return(NULL);
- }
-
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseStylesheetProcess : document is stylesheet\n");
-#endif
-
- if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
- (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
- xsltTransformError(NULL, ret, cur,
- "xsl:version: only 1.1 features are supported\n");
- ret->forwards_compatible = 1;
- ret->warnings++;
- }
- xmlFree(prop);
-
- /*
- * Create and link the template
- */
- template = xsltNewTemplate();
- if (template == NULL) {
- return(NULL);
- }
- template->next = ret->templates;
- ret->templates = template;
- template->match = xmlStrdup((const xmlChar *)"/");
-
- /*
- * parse the content and register the pattern
- */
- xsltParseTemplateContent(ret, (xmlNodePtr) doc);
- template->elem = (xmlNodePtr) doc;
- template->content = doc->children;
- xsltAddTemplate(ret, template, NULL, NULL);
- ret->literal_result = 1;
- }
-
- return(ret);
-}
-
-#endif /* else of XSLT_REFACTORED */
-
-/**
- * xsltParseStylesheetImportedDoc:
- * @doc: an xmlDoc parsed XML
- * @parentStyle: pointer to the parent stylesheet (if it exists)
- *
- * parse an XSLT stylesheet building the associated structures
- * except the processing not needed for imported documents.
- *
- * Returns a new XSLT stylesheet structure.
- */
-
-xsltStylesheetPtr
-xsltParseStylesheetImportedDoc(xmlDocPtr doc,
- xsltStylesheetPtr parentStyle) {
- xsltStylesheetPtr retStyle;
-
- if (doc == NULL)
- return(NULL);
-
- retStyle = xsltNewStylesheet();
- if (retStyle == NULL)
- return(NULL);
- /*
- * Set the importing stylesheet module; also used to detect recursion.
- */
- retStyle->parent = parentStyle;
- /*
- * Adjust the string dict.
- */
- if (doc->dict != NULL) {
- xmlDictFree(retStyle->dict);
- retStyle->dict = doc->dict;
-#ifdef WITH_XSLT_DEBUG
- xsltGenericDebug(xsltGenericDebugContext,
- "reusing dictionary from %s for stylesheet\n",
- doc->URL);
-#endif
- xmlDictReference(retStyle->dict);
- }
-
- /*
- * TODO: Eliminate xsltGatherNamespaces(); we must not restrict
- * the stylesheet to containt distinct namespace prefixes.
- */
- xsltGatherNamespaces(retStyle);
-
-#ifdef XSLT_REFACTORED
- {
- xsltCompilerCtxtPtr cctxt;
- xsltStylesheetPtr oldCurSheet;
-
- if (parentStyle == NULL) {
- xsltPrincipalStylesheetDataPtr principalData;
- /*
- * Principal stylesheet
- * --------------------
- */
- retStyle->principal = retStyle;
- /*
- * Create extra data for the principal stylesheet.
- */
- principalData = xsltNewPrincipalStylesheetData();
- if (principalData == NULL) {
- xsltFreeStylesheet(retStyle);
- return(NULL);
- }
- retStyle->principalData = principalData;
- /*
- * Create the compilation context
- * ------------------------------
- * (only once; for the principal stylesheet).
- * This is currently the only function where the
- * compilation context is created.
- */
- cctxt = xsltCompilationCtxtCreate(retStyle);
- if (cctxt == NULL) {
- xsltFreeStylesheet(retStyle);
- return(NULL);
- }
- retStyle->compCtxt = (void *) cctxt;
- cctxt->style = retStyle;
- cctxt->dict = retStyle->dict;
- cctxt->psData = principalData;
- /*
- * Push initial dummy node info.
- */
- cctxt->depth = -1;
- xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);
- } else {
- /*
- * Imported stylesheet.
- */
- retStyle->principal = parentStyle->principal;
- cctxt = parentStyle->compCtxt;
- retStyle->compCtxt = cctxt;
- }
- /*
- * Save the old and set the current stylesheet structure in the
- * compilation context.
- */
- oldCurSheet = cctxt->style;
- cctxt->style = retStyle;
-
- retStyle->doc = doc;
- xsltParseStylesheetProcess(retStyle, doc);
-
- cctxt->style = oldCurSheet;
- if (parentStyle == NULL) {
- /*
- * Pop the initial dummy node info.
- */
- xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);
- } else {
- /*
- * Clear the compilation context of imported
- * stylesheets.
- * TODO: really?
- */
- /* retStyle->compCtxt = NULL; */
- }
- /*
- * Free the stylesheet if there were errors.
- */
- if (retStyle != NULL) {
- if (retStyle->errors != 0) {
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP
- /*
- * Restore all changes made to namespace URIs of ns-decls.
- */
- if (cctxt->psData->nsMap)
- xsltRestoreDocumentNamespaces(cctxt->psData->nsMap, doc);
-#endif
- /*
- * Detach the doc from the stylesheet; otherwise the doc
- * will be freed in xsltFreeStylesheet().
- */
- retStyle->doc = NULL;
- /*
- * Cleanup the doc if its the main stylesheet.
- */
- if (parentStyle == NULL) {
- xsltCleanupStylesheetTree(doc, xmlDocGetRootElement(doc));
- if (retStyle->compCtxt != NULL) {
- xsltCompilationCtxtFree(retStyle->compCtxt);
- retStyle->compCtxt = NULL;
- }
- }
-
- xsltFreeStylesheet(retStyle);
- retStyle = NULL;
- }
- }
- }
-
-#else /* XSLT_REFACTORED */
- /*
- * Old behaviour.
- */
- retStyle->doc = doc;
- if (xsltParseStylesheetProcess(retStyle, doc) == NULL) {
- retStyle->doc = NULL;
- xsltFreeStylesheet(retStyle);
- retStyle = NULL;
- }
- if (retStyle != NULL) {
- if (retStyle->errors != 0) {
- retStyle->doc = NULL;
- if (parentStyle == NULL)
- xsltCleanupStylesheetTree(doc,
- xmlDocGetRootElement(doc));
- xsltFreeStylesheet(retStyle);
- retStyle = NULL;
- }
- }
-#endif /* else of XSLT_REFACTORED */
-
- return(retStyle);
-}
-
-/**
- * xsltParseStylesheetDoc:
- * @doc: and xmlDoc parsed XML
- *
- * parse an XSLT stylesheet, building the associated structures. doc
- * is kept as a reference within the returned stylesheet, so changes
- * to doc after the parsing will be reflected when the stylesheet
- * is applied, and the doc is automatically freed when the
- * stylesheet is closed.
- *
- * Returns a new XSLT stylesheet structure.
- */
-
-xsltStylesheetPtr
-xsltParseStylesheetDoc(xmlDocPtr doc) {
- xsltStylesheetPtr ret;
-
- xsltInitGlobals();
-
- ret = xsltParseStylesheetImportedDoc(doc, NULL);
- if (ret == NULL)
- return(NULL);
-
- xsltResolveStylesheetAttributeSet(ret);
-#ifdef XSLT_REFACTORED
- /*
- * Free the compilation context.
- * TODO: Check if it's better to move this cleanup to
- * xsltParseStylesheetImportedDoc().
- */
- if (ret->compCtxt != NULL) {
- xsltCompilationCtxtFree(XSLT_CCTXT(ret));
- ret->compCtxt = NULL;
- }
-#endif
- return(ret);
-}
-
-/**
- * xsltParseStylesheetFile:
- * @filename: the filename/URL to the stylesheet
- *
- * Load and parse an XSLT stylesheet
- *
- * Returns a new XSLT stylesheet structure.
- */
-
-xsltStylesheetPtr
-xsltParseStylesheetFile(const xmlChar* filename) {
- xsltSecurityPrefsPtr sec;
- xsltStylesheetPtr ret;
- xmlDocPtr doc;
-
- xsltInitGlobals();
-
- if (filename == NULL)
- return(NULL);
-
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltParseStylesheetFile : parse %s\n", filename);
-#endif
-
- /*
- * Security framework check
- */
- sec = xsltGetDefaultSecurityPrefs();
- if (sec != NULL) {
- int res;
-
- res = xsltCheckRead(sec, NULL, filename);
- if (res == 0) {
- xsltTransformError(NULL, NULL, NULL,
- "xsltParseStylesheetFile: read rights for %s denied\n",
- filename);
- return(NULL);
- }
- }
-
- doc = xsltDocDefaultLoader(filename, NULL, XSLT_PARSE_OPTIONS,
- NULL, XSLT_LOAD_START);
- if (doc == NULL) {
- xsltTransformError(NULL, NULL, NULL,
- "xsltParseStylesheetFile : cannot parse %s\n", filename);
- return(NULL);
- }
- ret = xsltParseStylesheetDoc(doc);
- if (ret == NULL) {
- xmlFreeDoc(doc);
- return(NULL);
- }
-
- return(ret);
-}
-
-/************************************************************************
- * *
- * Handling of Stylesheet PI *
- * *
- ************************************************************************/
-
-#define CUR (*cur)
-#define SKIP(val) cur += (val)
-#define NXT(val) cur[(val)]
-#define SKIP_BLANKS \
- while (IS_BLANK(CUR)) NEXT
-#define NEXT ((*cur) ? cur++ : cur)
-
-/**
- * xsltParseStylesheetPI:
- * @value: the value of the PI
- *
- * This function checks that the type is text/xml and extracts
- * the URI-Reference for the stylesheet
- *
- * Returns the URI-Reference for the stylesheet or NULL (it need to
- * be freed by the caller)
- */
-static xmlChar *
-xsltParseStylesheetPI(const xmlChar *value) {
- const xmlChar *cur;
- const xmlChar *start;
- xmlChar *val;
- xmlChar tmp;
- xmlChar *href = NULL;
- int isXml = 0;
-
- if (value == NULL)
- return(NULL);
-
- cur = value;
- while (CUR != 0) {
- SKIP_BLANKS;
- if ((CUR == 't') && (NXT(1) == 'y') && (NXT(2) == 'p') &&
- (NXT(3) == 'e')) {
- SKIP(4);
- SKIP_BLANKS;
- if (CUR != '=')
- continue;
- NEXT;
- if ((CUR != '\'') && (CUR != '"'))
- continue;
- tmp = CUR;
- NEXT;
- start = cur;
- while ((CUR != 0) && (CUR != tmp))
- NEXT;
- if (CUR != tmp)
- continue;
- val = xmlStrndup(start, cur - start);
- NEXT;
- if (val == NULL)
- return(NULL);
- if ((xmlStrcasecmp(val, BAD_CAST "text/xml")) &&
- (xmlStrcasecmp(val, BAD_CAST "text/xsl"))) {
- xmlFree(val);
- break;
- }
- isXml = 1;
- xmlFree(val);
- } else if ((CUR == 'h') && (NXT(1) == 'r') && (NXT(2) == 'e') &&
- (NXT(3) == 'f')) {
- SKIP(4);
- SKIP_BLANKS;
- if (CUR != '=')
- continue;
- NEXT;
- if ((CUR != '\'') && (CUR != '"'))
- continue;
- tmp = CUR;
- NEXT;
- start = cur;
- while ((CUR != 0) && (CUR != tmp))
- NEXT;
- if (CUR != tmp)
- continue;
- if (href == NULL)
- href = xmlStrndup(start, cur - start);
- NEXT;
- } else {
- while ((CUR != 0) && (!IS_BLANK(CUR)))
- NEXT;
- }
-
- }
-
- if (!isXml) {
- if (href != NULL)
- xmlFree(href);
- href = NULL;
- }
- return(href);
-}
-
-/**
- * xsltLoadStylesheetPI:
- * @doc: a document to process
- *
- * This function tries to locate the stylesheet PI in the given document
- * If found, and if contained within the document, it will extract
- * that subtree to build the stylesheet to process @doc (doc itself will
- * be modified). If found but referencing an external document it will
- * attempt to load it and generate a stylesheet from it. In both cases,
- * the resulting stylesheet and the document need to be freed once the
- * transformation is done.
- *
- * Returns a new XSLT stylesheet structure or NULL if not found.
- */
-xsltStylesheetPtr
-xsltLoadStylesheetPI(xmlDocPtr doc) {
- xmlNodePtr child;
- xsltStylesheetPtr ret = NULL;
- xmlChar *href = NULL;
- xmlURIPtr URI;
-
- xsltInitGlobals();
-
- if (doc == NULL)
- return(NULL);
-
- /*
- * Find the text/xml stylesheet PI id any before the root
- */
- child = doc->children;
- while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) {
- if ((child->type == XML_PI_NODE) &&
- (xmlStrEqual(child->name, BAD_CAST "xml-stylesheet"))) {
- href = xsltParseStylesheetPI(child->content);
- if (href != NULL)
- break;
- }
- child = child->next;
- }
-
- /*
- * If found check the href to select processing
- */
- if (href != NULL) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltLoadStylesheetPI : found PI href=%s\n", href);
-#endif
- URI = xmlParseURI((const char *) href);
- if (URI == NULL) {
- xsltTransformError(NULL, NULL, child,
- "xml-stylesheet : href %s is not valid\n", href);
- xmlFree(href);
- return(NULL);
- }
- if ((URI->fragment != NULL) && (URI->scheme == NULL) &&
- (URI->opaque == NULL) && (URI->authority == NULL) &&
- (URI->server == NULL) && (URI->user == NULL) &&
- (URI->path == NULL) && (URI->query == NULL)) {
- xmlAttrPtr ID;
-
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltLoadStylesheetPI : Reference to ID %s\n", href);
-#endif
- if (URI->fragment[0] == '#')
- ID = xmlGetID(doc, (const xmlChar *) &(URI->fragment[1]));
- else
- ID = xmlGetID(doc, (const xmlChar *) URI->fragment);
- if (ID == NULL) {
- xsltTransformError(NULL, NULL, child,
- "xml-stylesheet : no ID %s found\n", URI->fragment);
- } else {
- xmlDocPtr fake;
- xmlNodePtr subtree, newtree;
- xmlNsPtr ns;
-
-#ifdef WITH_XSLT_DEBUG
- xsltGenericDebug(xsltGenericDebugContext,
- "creating new document from %s for embedded stylesheet\n",
- doc->URL);
-#endif
- /*
- * move the subtree in a new document passed to
- * the stylesheet analyzer
- */
- subtree = ID->parent;
- fake = xmlNewDoc(NULL);
- if (fake != NULL) {
- /*
- * Should the dictionary still be shared even though
- * the nodes are being copied rather than moved?
- */
- fake->dict = doc->dict;
- xmlDictReference(doc->dict);
-#ifdef WITH_XSLT_DEBUG
- xsltGenericDebug(xsltGenericDebugContext,
- "reusing dictionary from %s for embedded stylesheet\n",
- doc->URL);
-#endif
-
- newtree = xmlDocCopyNode(subtree, fake, 1);
-
- fake->URL = xmlNodeGetBase(doc, subtree->parent);
-#ifdef WITH_XSLT_DEBUG
- xsltGenericDebug(xsltGenericDebugContext,
- "set base URI for embedded stylesheet as %s\n",
- fake->URL);
-#endif
-
- /*
- * Add all namespaces in scope of embedded stylesheet to
- * root element of newly created stylesheet document
- */
- while ((subtree = subtree->parent) != (xmlNodePtr)doc) {
- for (ns = subtree->ns; ns; ns = ns->next) {
- xmlNewNs(newtree, ns->href, ns->prefix);
- }
- }
-
- xmlAddChild((xmlNodePtr)fake, newtree);
- ret = xsltParseStylesheetDoc(fake);
- if (ret == NULL)
- xmlFreeDoc(fake);
- }
- }
- } else {
- xmlChar *URL, *base;
-
- /*
- * Reference to an external stylesheet
- */
-
- base = xmlNodeGetBase(doc, (xmlNodePtr) doc);
- URL = xmlBuildURI(href, base);
- if (URL != NULL) {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltLoadStylesheetPI : fetching %s\n", URL);
-#endif
- ret = xsltParseStylesheetFile(URL);
- xmlFree(URL);
- } else {
-#ifdef WITH_XSLT_DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltLoadStylesheetPI : fetching %s\n", href);
-#endif
- ret = xsltParseStylesheetFile(href);
- }
- if (base != NULL)
- xmlFree(base);
- }
- xmlFreeURI(URI);
- xmlFree(href);
- }
- return(ret);
-}
« no previous file with comments | « third_party/libxslt/libxslt/xslt.h ('k') | third_party/libxslt/libxslt/xsltInternals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698