libs: Import code from upstream libxslt 1.1.34.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9d9d4fcc37
commit
c638618cbc
|
@ -701,6 +701,8 @@ XMKMF
|
||||||
PTHREAD_LIBS
|
PTHREAD_LIBS
|
||||||
ZLIB_PE_LIBS
|
ZLIB_PE_LIBS
|
||||||
ZLIB_PE_CFLAGS
|
ZLIB_PE_CFLAGS
|
||||||
|
XSLT_PE_LIBS
|
||||||
|
XSLT_PE_CFLAGS
|
||||||
XML2_PE_LIBS
|
XML2_PE_LIBS
|
||||||
XML2_PE_CFLAGS
|
XML2_PE_CFLAGS
|
||||||
TIFF_PE_LIBS
|
TIFF_PE_LIBS
|
||||||
|
@ -1796,6 +1798,7 @@ enable_wbemuuid
|
||||||
enable_wine
|
enable_wine
|
||||||
enable_wmcodecdspuuid
|
enable_wmcodecdspuuid
|
||||||
enable_xml2
|
enable_xml2
|
||||||
|
enable_xslt
|
||||||
enable_zlib
|
enable_zlib
|
||||||
enable_loader
|
enable_loader
|
||||||
enable_nls
|
enable_nls
|
||||||
|
@ -1937,6 +1940,8 @@ TIFF_PE_CFLAGS
|
||||||
TIFF_PE_LIBS
|
TIFF_PE_LIBS
|
||||||
XML2_PE_CFLAGS
|
XML2_PE_CFLAGS
|
||||||
XML2_PE_LIBS
|
XML2_PE_LIBS
|
||||||
|
XSLT_PE_CFLAGS
|
||||||
|
XSLT_PE_LIBS
|
||||||
ZLIB_PE_CFLAGS
|
ZLIB_PE_CFLAGS
|
||||||
ZLIB_PE_LIBS
|
ZLIB_PE_LIBS
|
||||||
XMKMF
|
XMKMF
|
||||||
|
@ -2735,6 +2740,11 @@ Some influential environment variables:
|
||||||
version
|
version
|
||||||
XML2_PE_LIBS
|
XML2_PE_LIBS
|
||||||
Linker flags for the PE libxml2, overriding the bundled version
|
Linker flags for the PE libxml2, overriding the bundled version
|
||||||
|
XSLT_PE_CFLAGS
|
||||||
|
C compiler flags for the PE libxslt, overriding the bundled
|
||||||
|
version
|
||||||
|
XSLT_PE_LIBS
|
||||||
|
Linker flags for the PE libxslt, overriding the bundled version
|
||||||
ZLIB_PE_CFLAGS
|
ZLIB_PE_CFLAGS
|
||||||
C compiler flags for the PE zlib, overriding the bundled version
|
C compiler flags for the PE zlib, overriding the bundled version
|
||||||
ZLIB_PE_LIBS
|
ZLIB_PE_LIBS
|
||||||
|
@ -10777,6 +10787,19 @@ fi
|
||||||
$as_echo "$as_me:${as_lineno-$LINENO}: libxml2 cflags: $XML2_PE_CFLAGS" >&5
|
$as_echo "$as_me:${as_lineno-$LINENO}: libxml2 cflags: $XML2_PE_CFLAGS" >&5
|
||||||
$as_echo "$as_me:${as_lineno-$LINENO}: libxml2 libs: $XML2_PE_LIBS" >&5
|
$as_echo "$as_me:${as_lineno-$LINENO}: libxml2 libs: $XML2_PE_LIBS" >&5
|
||||||
|
|
||||||
|
if ${XSLT_PE_CFLAGS:+false} :; then :
|
||||||
|
XSLT_PE_CFLAGS="-I\$(top_srcdir)/libs/xslt"
|
||||||
|
else
|
||||||
|
enable_libxslt=no
|
||||||
|
fi
|
||||||
|
if ${XSLT_PE_LIBS:+false} :; then :
|
||||||
|
XSLT_PE_LIBS=xslt
|
||||||
|
else
|
||||||
|
enable_libxslt=no
|
||||||
|
fi
|
||||||
|
$as_echo "$as_me:${as_lineno-$LINENO}: libxslt cflags: $XSLT_PE_CFLAGS" >&5
|
||||||
|
$as_echo "$as_me:${as_lineno-$LINENO}: libxslt libs: $XSLT_PE_LIBS" >&5
|
||||||
|
|
||||||
if ${ZLIB_PE_CFLAGS:+false} :; then :
|
if ${ZLIB_PE_CFLAGS:+false} :; then :
|
||||||
ZLIB_PE_CFLAGS="-I\$(top_srcdir)/libs/zlib -DFAR= -DZ_SOLO"
|
ZLIB_PE_CFLAGS="-I\$(top_srcdir)/libs/zlib -DFAR= -DZ_SOLO"
|
||||||
else
|
else
|
||||||
|
@ -19432,6 +19455,8 @@ TIFF_PE_CFLAGS = $TIFF_PE_CFLAGS
|
||||||
TIFF_PE_LIBS = $TIFF_PE_LIBS
|
TIFF_PE_LIBS = $TIFF_PE_LIBS
|
||||||
XML2_PE_CFLAGS = $XML2_PE_CFLAGS
|
XML2_PE_CFLAGS = $XML2_PE_CFLAGS
|
||||||
XML2_PE_LIBS = $XML2_PE_LIBS
|
XML2_PE_LIBS = $XML2_PE_LIBS
|
||||||
|
XSLT_PE_CFLAGS = $XSLT_PE_CFLAGS
|
||||||
|
XSLT_PE_LIBS = $XSLT_PE_LIBS
|
||||||
ZLIB_PE_CFLAGS = $ZLIB_PE_CFLAGS
|
ZLIB_PE_CFLAGS = $ZLIB_PE_CFLAGS
|
||||||
ZLIB_PE_LIBS = $ZLIB_PE_LIBS
|
ZLIB_PE_LIBS = $ZLIB_PE_LIBS
|
||||||
PTHREAD_LIBS = $PTHREAD_LIBS
|
PTHREAD_LIBS = $PTHREAD_LIBS
|
||||||
|
@ -20731,6 +20756,7 @@ wine_fn_config_makefile libs/wbemuuid enable_wbemuuid
|
||||||
wine_fn_config_makefile libs/wine enable_wine
|
wine_fn_config_makefile libs/wine enable_wine
|
||||||
wine_fn_config_makefile libs/wmcodecdspuuid enable_wmcodecdspuuid
|
wine_fn_config_makefile libs/wmcodecdspuuid enable_wmcodecdspuuid
|
||||||
wine_fn_config_makefile libs/xml2 enable_xml2
|
wine_fn_config_makefile libs/xml2 enable_xml2
|
||||||
|
wine_fn_config_makefile libs/xslt enable_xslt
|
||||||
wine_fn_config_makefile libs/zlib enable_zlib
|
wine_fn_config_makefile libs/zlib enable_zlib
|
||||||
wine_fn_config_makefile loader enable_loader
|
wine_fn_config_makefile loader enable_loader
|
||||||
wine_fn_config_makefile nls enable_nls
|
wine_fn_config_makefile nls enable_nls
|
||||||
|
|
|
@ -1065,6 +1065,7 @@ WINE_EXTLIB_FLAGS(LCMS2, lcms2, lcms2, "-I\$(top_srcdir)/libs/lcms2/include")
|
||||||
WINE_EXTLIB_FLAGS(PNG, png, "png \$(ZLIB_PE_LIBS)", "-I\$(top_srcdir)/libs/png")
|
WINE_EXTLIB_FLAGS(PNG, png, "png \$(ZLIB_PE_LIBS)", "-I\$(top_srcdir)/libs/png")
|
||||||
WINE_EXTLIB_FLAGS(TIFF, tiff, tiff, "-I\$(top_srcdir)/libs/tiff/libtiff")
|
WINE_EXTLIB_FLAGS(TIFF, tiff, tiff, "-I\$(top_srcdir)/libs/tiff/libtiff")
|
||||||
WINE_EXTLIB_FLAGS(XML2, libxml2, xml2, "-I\$(top_srcdir)/libs/xml2/include -DLIBXML_STATIC")
|
WINE_EXTLIB_FLAGS(XML2, libxml2, xml2, "-I\$(top_srcdir)/libs/xml2/include -DLIBXML_STATIC")
|
||||||
|
WINE_EXTLIB_FLAGS(XSLT, libxslt, xslt, "-I\$(top_srcdir)/libs/xslt")
|
||||||
WINE_EXTLIB_FLAGS(ZLIB, zlib, z, "-I\$(top_srcdir)/libs/zlib -DFAR= -DZ_SOLO")
|
WINE_EXTLIB_FLAGS(ZLIB, zlib, z, "-I\$(top_srcdir)/libs/zlib -DFAR= -DZ_SOLO")
|
||||||
|
|
||||||
dnl **** Check for pthread ****
|
dnl **** Check for pthread ****
|
||||||
|
@ -3775,6 +3776,7 @@ WINE_CONFIG_MAKEFILE(libs/wbemuuid)
|
||||||
WINE_CONFIG_MAKEFILE(libs/wine)
|
WINE_CONFIG_MAKEFILE(libs/wine)
|
||||||
WINE_CONFIG_MAKEFILE(libs/wmcodecdspuuid)
|
WINE_CONFIG_MAKEFILE(libs/wmcodecdspuuid)
|
||||||
WINE_CONFIG_MAKEFILE(libs/xml2)
|
WINE_CONFIG_MAKEFILE(libs/xml2)
|
||||||
|
WINE_CONFIG_MAKEFILE(libs/xslt)
|
||||||
WINE_CONFIG_MAKEFILE(libs/zlib)
|
WINE_CONFIG_MAKEFILE(libs/zlib)
|
||||||
WINE_CONFIG_MAKEFILE(loader)
|
WINE_CONFIG_MAKEFILE(loader)
|
||||||
WINE_CONFIG_MAKEFILE(nls)
|
WINE_CONFIG_MAKEFILE(nls)
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
Daniel Veillard:
|
||||||
|
daniel@veillard.com
|
||||||
|
DV on #gnome IRC channel
|
||||||
|
http://veillard.com/
|
||||||
|
Used to work at W3C, now Red Hat
|
||||||
|
co-chair of W3C XML Linking WG
|
||||||
|
invited expert on the W3C XML Core WG
|
||||||
|
Author of libxml2 upon which this library is based.
|
||||||
|
|
||||||
|
Bjorn Reese:
|
||||||
|
breese@users.sourceforge.net
|
||||||
|
http://home1.stofanet.dk/breese/
|
||||||
|
Software developer at http://www.systematic.dk/
|
||||||
|
Member of the XML-MTF Mapping WG.
|
||||||
|
|
||||||
|
William Brack <wbrack@mmm.com.hk>
|
||||||
|
|
||||||
|
Thomas Broyer <tbroyer@ltgt.net>
|
||||||
|
|
||||||
|
Igor Zlatkovic <igor@zlatkovic.com> for the Windows port
|
||||||
|
|
||||||
|
Patches gently provided by a multitude of people :
|
||||||
|
|
||||||
|
Abhishek Arya <inferno@chromium.org>
|
||||||
|
Ben Walton <bwalton@artsci.utoronto.ca>
|
||||||
|
Bjorn Reese <breese@src.gnome.org>
|
||||||
|
C. M. Sperberg-McQueen <cmsmcq@blackmesatech.com>
|
||||||
|
Colin Walters <walters@verbum.org>
|
||||||
|
Daniel Mustieles <daniel.mustieles@gmail.com>
|
||||||
|
Daniel Richard G <oss@teragram.com>
|
||||||
|
Darin Adler <darin@src.gnome.org>
|
||||||
|
ÉRDI Gergo <cactus@src.gnome.org>
|
||||||
|
Fatih Demir <kabalak@src.gnome.org>
|
||||||
|
Federico Mena Quintero <federico@ximian.com>
|
||||||
|
Frederic Crozat <fcrozat@mandriva.com>
|
||||||
|
Hao Hu <ihaohu@gmail.com>
|
||||||
|
Havoc Pennington <hp@pobox.com>
|
||||||
|
IlyaS <astro.courier@gmail.com>
|
||||||
|
jacob berkman <jacob@ximian.com>
|
||||||
|
Jason Viers <bean@beanalby.net>
|
||||||
|
Jérôme Carretero <cJ-xslt@zougloub.eu>
|
||||||
|
Joachim Breitner <nomeata@debian.org>
|
||||||
|
Johan Dahlin <zilch@src.gnome.org>
|
||||||
|
John Fleck <jfleck@inkstain.net>
|
||||||
|
Jose Maria Celorio <chema@src.gnome.org>
|
||||||
|
Julio M. Merino Vidal <jmmv@NetBSD.org>
|
||||||
|
Kasimier T. Buchcik <kbuchcik@src.gnome.org>
|
||||||
|
Kjartan Maraas <kmaraas@src.gnome.org>
|
||||||
|
Laurence Rowe <l@lrowe.co.uk>
|
||||||
|
Malcolm Purvis <malcolm@purvis.id.au>
|
||||||
|
Martin <gzlist@googlemail.com>
|
||||||
|
Michael Bonfils <murlock42@gmail.com>
|
||||||
|
Mike Hommey <mh@glandium.org>
|
||||||
|
money_seshu Dronamraju <mcseshu@gmail.com>
|
||||||
|
Nick Wellnhofer <wellnhofer@aevum.de>
|
||||||
|
Nix <nix@esperi.org.uk>
|
||||||
|
Pedro F. Giffuni <giffunip@tutopia.com>
|
||||||
|
Peter Williams <peterw@ximian.com>
|
||||||
|
Rob Richards <rrichard@src.gnome.org>
|
||||||
|
Roumen Petrov <bugtrack@roumenpetrov.info>
|
||||||
|
Stefan Kost <ensonic@users.sf.net>
|
||||||
|
Tomasz Kłoczko <kloczek@src.gnome.org>
|
||||||
|
Chris Evans <cevans@chromium.org>
|
|
@ -0,0 +1,53 @@
|
||||||
|
Licence for libxslt except libexslt
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Copyright (C) 2001-2002 Daniel Veillard. All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is fur-
|
||||||
|
nished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
|
||||||
|
NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
|
||||||
|
NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Daniel Veillard shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
ings in this Software without prior written authorization from him.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Licence for libexslt
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Copyright (C) 2001-2002 Thomas Broyer, Charlie Bozeman and Daniel Veillard.
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is fur-
|
||||||
|
nished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
|
||||||
|
NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
|
||||||
|
NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of the authors shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
ings in this Software without prior written authorization from him.
|
||||||
|
----------------------------------------------------------------------
|
|
@ -0,0 +1,23 @@
|
||||||
|
EXTLIB = libxslt.a
|
||||||
|
EXTRAINCL = $(XML2_PE_CFLAGS)
|
||||||
|
|
||||||
|
C_SRCS = \
|
||||||
|
libxslt/attributes.c \
|
||||||
|
libxslt/attrvt.c \
|
||||||
|
libxslt/documents.c \
|
||||||
|
libxslt/extensions.c \
|
||||||
|
libxslt/extra.c \
|
||||||
|
libxslt/functions.c \
|
||||||
|
libxslt/imports.c \
|
||||||
|
libxslt/keys.c \
|
||||||
|
libxslt/namespaces.c \
|
||||||
|
libxslt/numbers.c \
|
||||||
|
libxslt/pattern.c \
|
||||||
|
libxslt/preproc.c \
|
||||||
|
libxslt/security.c \
|
||||||
|
libxslt/templates.c \
|
||||||
|
libxslt/transform.c \
|
||||||
|
libxslt/variables.c \
|
||||||
|
libxslt/xslt.c \
|
||||||
|
libxslt/xsltlocale.c \
|
||||||
|
libxslt/xsltutils.c
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the XSLT attribute handling
|
||||||
|
* Description: this module handles the specificities of attribute
|
||||||
|
* and attribute groups processing.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_ATTRIBUTES_H__
|
||||||
|
#define __XML_XSLT_ATTRIBUTES_H__
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltParseStylesheetAttributeSet (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr cur);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeAttributeSetsHashes (xsltStylesheetPtr style);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltApplyAttributeSet (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
const xmlChar *attributes);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_ATTRIBUTES_H__ */
|
||||||
|
|
|
@ -0,0 +1,396 @@
|
||||||
|
/*
|
||||||
|
* attrvt.c: Implementation of the XSL Transformation 1.0 engine
|
||||||
|
* attribute value template handling part.
|
||||||
|
*
|
||||||
|
* References:
|
||||||
|
* http://www.w3.org/TR/1999/REC-xslt-19991116
|
||||||
|
*
|
||||||
|
* Michael Kay "XSLT Programmer's Reference" pp 637-643
|
||||||
|
* Writing Multiple Output Files
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* daniel@veillard.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IN_LIBXSLT
|
||||||
|
#include "libxslt.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
#include "xslt.h"
|
||||||
|
#include "xsltutils.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "templates.h"
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG
|
||||||
|
#define WITH_XSLT_DEBUG_AVT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_AVT_SEG 10
|
||||||
|
|
||||||
|
typedef struct _xsltAttrVT xsltAttrVT;
|
||||||
|
typedef xsltAttrVT *xsltAttrVTPtr;
|
||||||
|
struct _xsltAttrVT {
|
||||||
|
struct _xsltAttrVT *next; /* next xsltAttrVT */
|
||||||
|
int nb_seg; /* Number of segments */
|
||||||
|
int max_seg; /* max capacity before re-alloc needed */
|
||||||
|
int strstart; /* is the start a string */
|
||||||
|
/*
|
||||||
|
* the namespaces in scope
|
||||||
|
*/
|
||||||
|
xmlNsPtr *nsList;
|
||||||
|
int nsNr;
|
||||||
|
/*
|
||||||
|
* the content is an alternate of string and xmlXPathCompExprPtr
|
||||||
|
*/
|
||||||
|
#if __STDC_VERSION__ >= 199901L
|
||||||
|
/* Using a C99 flexible array member avoids false positives under UBSan */
|
||||||
|
void *segments[];
|
||||||
|
#else
|
||||||
|
void *segments[1];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNewAttrVT:
|
||||||
|
* @style: a XSLT process context
|
||||||
|
*
|
||||||
|
* Build a new xsltAttrVT structure
|
||||||
|
*
|
||||||
|
* Returns the structure or NULL in case of error
|
||||||
|
*/
|
||||||
|
static xsltAttrVTPtr
|
||||||
|
xsltNewAttrVT(xsltStylesheetPtr style) {
|
||||||
|
xsltAttrVTPtr cur;
|
||||||
|
size_t size = sizeof(xsltAttrVT) + MAX_AVT_SEG * sizeof(void*);
|
||||||
|
|
||||||
|
cur = (xsltAttrVTPtr) xmlMalloc(size);
|
||||||
|
if (cur == NULL) {
|
||||||
|
xsltTransformError(NULL, style, NULL,
|
||||||
|
"xsltNewAttrVTPtr : malloc failed\n");
|
||||||
|
if (style != NULL) style->errors++;
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(cur, 0, size);
|
||||||
|
|
||||||
|
cur->nb_seg = 0;
|
||||||
|
cur->max_seg = MAX_AVT_SEG;
|
||||||
|
cur->strstart = 0;
|
||||||
|
cur->next = style->attVTs;
|
||||||
|
/*
|
||||||
|
* Note: this pointer may be changed by a re-alloc within xsltCompileAttr,
|
||||||
|
* so that code may change the stylesheet pointer also!
|
||||||
|
*/
|
||||||
|
style->attVTs = (xsltAttrVTPtr) cur;
|
||||||
|
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeAttrVT:
|
||||||
|
* @avt: pointer to an xsltAttrVT structure
|
||||||
|
*
|
||||||
|
* Free up the memory associated to the attribute value template
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xsltFreeAttrVT(xsltAttrVTPtr avt) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (avt == NULL) return;
|
||||||
|
|
||||||
|
if (avt->strstart == 1) {
|
||||||
|
for (i = 0;i < avt->nb_seg; i += 2)
|
||||||
|
if (avt->segments[i] != NULL)
|
||||||
|
xmlFree((xmlChar *) avt->segments[i]);
|
||||||
|
for (i = 1;i < avt->nb_seg; i += 2)
|
||||||
|
xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]);
|
||||||
|
} else {
|
||||||
|
for (i = 0;i < avt->nb_seg; i += 2)
|
||||||
|
xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]);
|
||||||
|
for (i = 1;i < avt->nb_seg; i += 2)
|
||||||
|
if (avt->segments[i] != NULL)
|
||||||
|
xmlFree((xmlChar *) avt->segments[i]);
|
||||||
|
}
|
||||||
|
if (avt->nsList != NULL)
|
||||||
|
xmlFree(avt->nsList);
|
||||||
|
xmlFree(avt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeAVTList:
|
||||||
|
* @avt: pointer to an list of AVT structures
|
||||||
|
*
|
||||||
|
* Free up the memory associated to the attribute value templates
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeAVTList(void *avt) {
|
||||||
|
xsltAttrVTPtr cur = (xsltAttrVTPtr) avt, next;
|
||||||
|
|
||||||
|
while (cur != NULL) {
|
||||||
|
next = cur->next;
|
||||||
|
xsltFreeAttrVT(cur);
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* xsltSetAttrVTsegment:
|
||||||
|
* @ avt: pointer to an xsltAttrVT structure
|
||||||
|
* @ val: the value to be set to the next available segment
|
||||||
|
*
|
||||||
|
* Within xsltCompileAttr there are several places where a value
|
||||||
|
* needs to be added to the 'segments' array within the xsltAttrVT
|
||||||
|
* structure, and at each place the allocated size may have to be
|
||||||
|
* re-allocated. This routine takes care of that situation.
|
||||||
|
*
|
||||||
|
* Returns the avt pointer, which may have been changed by a re-alloc
|
||||||
|
*/
|
||||||
|
static xsltAttrVTPtr
|
||||||
|
xsltSetAttrVTsegment(xsltAttrVTPtr avt, void *val) {
|
||||||
|
if (avt->nb_seg >= avt->max_seg) {
|
||||||
|
size_t size = sizeof(xsltAttrVT) +
|
||||||
|
(avt->max_seg + MAX_AVT_SEG) * sizeof(void *);
|
||||||
|
xsltAttrVTPtr tmp = (xsltAttrVTPtr) xmlRealloc(avt, size);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
xsltFreeAttrVT(avt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
avt = tmp;
|
||||||
|
memset(&avt->segments[avt->nb_seg], 0, MAX_AVT_SEG*sizeof(void *));
|
||||||
|
avt->max_seg += MAX_AVT_SEG;
|
||||||
|
}
|
||||||
|
avt->segments[avt->nb_seg++] = val;
|
||||||
|
return avt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCompileAttr:
|
||||||
|
* @style: a XSLT process context
|
||||||
|
* @attr: the attribute coming from the stylesheet.
|
||||||
|
*
|
||||||
|
* Precompile an attribute in a stylesheet, basically it checks if it is
|
||||||
|
* an attribute value template, and if yes, establish some structures needed
|
||||||
|
* to process it at transformation time.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltCompileAttr(xsltStylesheetPtr style, xmlAttrPtr attr) {
|
||||||
|
const xmlChar *str;
|
||||||
|
const xmlChar *cur;
|
||||||
|
xmlChar *ret = NULL;
|
||||||
|
xmlChar *expr = NULL;
|
||||||
|
xsltAttrVTPtr avt;
|
||||||
|
int i = 0, lastavt = 0;
|
||||||
|
|
||||||
|
if ((style == NULL) || (attr == NULL) || (attr->children == NULL))
|
||||||
|
return;
|
||||||
|
if ((attr->children->type != XML_TEXT_NODE) ||
|
||||||
|
(attr->children->next != NULL)) {
|
||||||
|
xsltTransformError(NULL, style, attr->parent,
|
||||||
|
"Attribute '%s': The content is expected to be a single text "
|
||||||
|
"node when compiling an AVT.\n", attr->name);
|
||||||
|
style->errors++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
str = attr->children->content;
|
||||||
|
if ((xmlStrchr(str, '{') == NULL) &&
|
||||||
|
(xmlStrchr(str, '}') == NULL)) return;
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG_AVT
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Found AVT %s: %s\n", attr->name, str);
|
||||||
|
#endif
|
||||||
|
if (attr->psvi != NULL) {
|
||||||
|
#ifdef WITH_XSLT_DEBUG_AVT
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"AVT %s: already compiled\n", attr->name);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Create a new AVT object.
|
||||||
|
*/
|
||||||
|
avt = xsltNewAttrVT(style);
|
||||||
|
if (avt == NULL)
|
||||||
|
return;
|
||||||
|
attr->psvi = avt;
|
||||||
|
|
||||||
|
avt->nsList = xmlGetNsList(attr->doc, attr->parent);
|
||||||
|
if (avt->nsList != NULL) {
|
||||||
|
while (avt->nsList[i] != NULL)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
avt->nsNr = i;
|
||||||
|
|
||||||
|
cur = str;
|
||||||
|
while (*cur != 0) {
|
||||||
|
if (*cur == '{') {
|
||||||
|
if (*(cur+1) == '{') { /* escaped '{' */
|
||||||
|
cur++;
|
||||||
|
ret = xmlStrncat(ret, str, cur - str);
|
||||||
|
cur++;
|
||||||
|
str = cur;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*(cur+1) == '}') { /* skip empty AVT */
|
||||||
|
ret = xmlStrncat(ret, str, cur - str);
|
||||||
|
cur += 2;
|
||||||
|
str = cur;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((ret != NULL) || (cur - str > 0)) {
|
||||||
|
ret = xmlStrncat(ret, str, cur - str);
|
||||||
|
str = cur;
|
||||||
|
if (avt->nb_seg == 0)
|
||||||
|
avt->strstart = 1;
|
||||||
|
if ((avt = xsltSetAttrVTsegment(avt, (void *) ret)) == NULL)
|
||||||
|
goto error;
|
||||||
|
ret = NULL;
|
||||||
|
lastavt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur++;
|
||||||
|
while ((*cur != 0) && (*cur != '}')) {
|
||||||
|
/* Need to check for literal (bug539741) */
|
||||||
|
if ((*cur == '\'') || (*cur == '"')) {
|
||||||
|
char delim = *(cur++);
|
||||||
|
while ((*cur != 0) && (*cur != delim))
|
||||||
|
cur++;
|
||||||
|
if (*cur != 0)
|
||||||
|
cur++; /* skip the ending delimiter */
|
||||||
|
} else
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
if (*cur == 0) {
|
||||||
|
xsltTransformError(NULL, style, attr->parent,
|
||||||
|
"Attribute '%s': The AVT has an unmatched '{'.\n",
|
||||||
|
attr->name);
|
||||||
|
style->errors++;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
expr = xmlStrndup(str, cur - str);
|
||||||
|
if (expr == NULL) {
|
||||||
|
/*
|
||||||
|
* TODO: What needs to be done here?
|
||||||
|
*/
|
||||||
|
XSLT_TODO
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
xmlXPathCompExprPtr comp;
|
||||||
|
|
||||||
|
comp = xsltXPathCompile(style, expr);
|
||||||
|
if (comp == NULL) {
|
||||||
|
xsltTransformError(NULL, style, attr->parent,
|
||||||
|
"Attribute '%s': Failed to compile the expression "
|
||||||
|
"'%s' in the AVT.\n", attr->name, expr);
|
||||||
|
style->errors++;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (avt->nb_seg == 0)
|
||||||
|
avt->strstart = 0;
|
||||||
|
if (lastavt == 1) {
|
||||||
|
if ((avt = xsltSetAttrVTsegment(avt, NULL)) == NULL)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if ((avt = xsltSetAttrVTsegment(avt, (void *) comp)) == NULL)
|
||||||
|
goto error;
|
||||||
|
lastavt = 1;
|
||||||
|
xmlFree(expr);
|
||||||
|
expr = NULL;
|
||||||
|
}
|
||||||
|
cur++;
|
||||||
|
str = cur;
|
||||||
|
} else if (*cur == '}') {
|
||||||
|
cur++;
|
||||||
|
if (*cur == '}') { /* escaped '}' */
|
||||||
|
ret = xmlStrncat(ret, str, cur - str);
|
||||||
|
cur++;
|
||||||
|
str = cur;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
xsltTransformError(NULL, style, attr->parent,
|
||||||
|
"Attribute '%s': The AVT has an unmatched '}'.\n",
|
||||||
|
attr->name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
if ((ret != NULL) || (cur - str > 0)) {
|
||||||
|
ret = xmlStrncat(ret, str, cur - str);
|
||||||
|
str = cur;
|
||||||
|
if (avt->nb_seg == 0)
|
||||||
|
avt->strstart = 1;
|
||||||
|
if ((avt = xsltSetAttrVTsegment(avt, (void *) ret)) == NULL)
|
||||||
|
goto error;
|
||||||
|
ret = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (avt == NULL) {
|
||||||
|
xsltTransformError(NULL, style, attr->parent,
|
||||||
|
"xsltCompileAttr: malloc problem\n");
|
||||||
|
} else {
|
||||||
|
if (attr->psvi != avt) { /* may have changed from realloc */
|
||||||
|
attr->psvi = avt;
|
||||||
|
/*
|
||||||
|
* This is a "hack", but I can't see any clean method of
|
||||||
|
* doing it. If a re-alloc has taken place, then the pointer
|
||||||
|
* for this AVT may have changed. style->attVTs was set by
|
||||||
|
* xsltNewAttrVT, so it needs to be re-set to the new value!
|
||||||
|
*/
|
||||||
|
style->attVTs = avt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret != NULL)
|
||||||
|
xmlFree(ret);
|
||||||
|
if (expr != NULL)
|
||||||
|
xmlFree(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltEvalAVT:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @avt: the prevompiled attribute value template info
|
||||||
|
* @node: the node hosting the attribute
|
||||||
|
*
|
||||||
|
* Process the given AVT, and return the new string value.
|
||||||
|
*
|
||||||
|
* Returns the computed string value or NULL, must be deallocated by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
xmlChar *
|
||||||
|
xsltEvalAVT(xsltTransformContextPtr ctxt, void *avt, xmlNodePtr node) {
|
||||||
|
xmlChar *ret = NULL, *tmp;
|
||||||
|
xmlXPathCompExprPtr comp;
|
||||||
|
xsltAttrVTPtr cur = (xsltAttrVTPtr) avt;
|
||||||
|
int i;
|
||||||
|
int str;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (avt == NULL) || (node == NULL))
|
||||||
|
return(NULL);
|
||||||
|
str = cur->strstart;
|
||||||
|
for (i = 0;i < cur->nb_seg;i++) {
|
||||||
|
if (str) {
|
||||||
|
ret = xmlStrcat(ret, (const xmlChar *) cur->segments[i]);
|
||||||
|
} else {
|
||||||
|
comp = (xmlXPathCompExprPtr) cur->segments[i];
|
||||||
|
tmp = xsltEvalXPathStringNs(ctxt, comp, cur->nsNr, cur->nsList);
|
||||||
|
if (tmp != NULL) {
|
||||||
|
if (ret != NULL) {
|
||||||
|
ret = xmlStrcat(ret, tmp);
|
||||||
|
xmlFree(tmp);
|
||||||
|
} else {
|
||||||
|
ret = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str = !str;
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
|
@ -0,0 +1,436 @@
|
||||||
|
/*
|
||||||
|
* documents.c: Implementation of the documents handling
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* daniel@veillard.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IN_LIBXSLT
|
||||||
|
#include "libxslt.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/hash.h>
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/parserInternals.h>
|
||||||
|
#include "xslt.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "xsltutils.h"
|
||||||
|
#include "documents.h"
|
||||||
|
#include "transform.h"
|
||||||
|
#include "imports.h"
|
||||||
|
#include "keys.h"
|
||||||
|
#include "security.h"
|
||||||
|
|
||||||
|
#ifdef LIBXML_XINCLUDE_ENABLED
|
||||||
|
#include <libxml/xinclude.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WITH_XSLT_DEBUG_DOCUMENTS
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG
|
||||||
|
#define WITH_XSLT_DEBUG_DOCUMENTS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Hooks for the document loader *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltDocDefaultLoaderFunc:
|
||||||
|
* @URI: the URI of the document to load
|
||||||
|
* @dict: the dictionary to use when parsing that document
|
||||||
|
* @options: parsing options, a set of xmlParserOption
|
||||||
|
* @ctxt: the context, either a stylesheet or a transformation context
|
||||||
|
* @type: the xsltLoadType indicating the kind of loading required
|
||||||
|
*
|
||||||
|
* Default function to load document not provided by the compilation or
|
||||||
|
* transformation API themselve, for example when an xsl:import,
|
||||||
|
* xsl:include is found at compilation time or when a document()
|
||||||
|
* call is made at runtime.
|
||||||
|
*
|
||||||
|
* Returns the pointer to the document (which will be modified and
|
||||||
|
* freed by the engine later), or NULL in case of error.
|
||||||
|
*/
|
||||||
|
static xmlDocPtr
|
||||||
|
xsltDocDefaultLoaderFunc(const xmlChar * URI, xmlDictPtr dict, int options,
|
||||||
|
void *ctxt ATTRIBUTE_UNUSED,
|
||||||
|
xsltLoadType type ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
xmlParserCtxtPtr pctxt;
|
||||||
|
xmlParserInputPtr inputStream;
|
||||||
|
xmlDocPtr doc;
|
||||||
|
|
||||||
|
pctxt = xmlNewParserCtxt();
|
||||||
|
if (pctxt == NULL)
|
||||||
|
return(NULL);
|
||||||
|
if ((dict != NULL) && (pctxt->dict != NULL)) {
|
||||||
|
xmlDictFree(pctxt->dict);
|
||||||
|
pctxt->dict = NULL;
|
||||||
|
}
|
||||||
|
if (dict != NULL) {
|
||||||
|
pctxt->dict = dict;
|
||||||
|
xmlDictReference(pctxt->dict);
|
||||||
|
#ifdef WITH_XSLT_DEBUG
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Reusing dictionary for document\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
xmlCtxtUseOptions(pctxt, options);
|
||||||
|
inputStream = xmlLoadExternalEntity((const char *) URI, NULL, pctxt);
|
||||||
|
if (inputStream == NULL) {
|
||||||
|
xmlFreeParserCtxt(pctxt);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
inputPush(pctxt, inputStream);
|
||||||
|
if (pctxt->directory == NULL)
|
||||||
|
pctxt->directory = xmlParserGetDirectory((const char *) URI);
|
||||||
|
|
||||||
|
xmlParseDocument(pctxt);
|
||||||
|
|
||||||
|
if (pctxt->wellFormed) {
|
||||||
|
doc = pctxt->myDoc;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
doc = NULL;
|
||||||
|
xmlFreeDoc(pctxt->myDoc);
|
||||||
|
pctxt->myDoc = NULL;
|
||||||
|
}
|
||||||
|
xmlFreeParserCtxt(pctxt);
|
||||||
|
|
||||||
|
return(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xsltDocLoaderFunc xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltSetLoaderFunc:
|
||||||
|
* @f: the new function to handle document loading.
|
||||||
|
*
|
||||||
|
* Set the new function to load document, if NULL it resets it to the
|
||||||
|
* default function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
xsltSetLoaderFunc(xsltDocLoaderFunc f) {
|
||||||
|
if (f == NULL)
|
||||||
|
xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
|
||||||
|
else
|
||||||
|
xsltDocDefaultLoader = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Module interfaces *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNewDocument:
|
||||||
|
* @ctxt: an XSLT transformation context (or NULL)
|
||||||
|
* @doc: a parsed XML document
|
||||||
|
*
|
||||||
|
* Register a new document, apply key computations
|
||||||
|
*
|
||||||
|
* Returns a handler to the document
|
||||||
|
*/
|
||||||
|
xsltDocumentPtr
|
||||||
|
xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc) {
|
||||||
|
xsltDocumentPtr cur;
|
||||||
|
|
||||||
|
cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
|
||||||
|
if (cur == NULL) {
|
||||||
|
xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
|
||||||
|
"xsltNewDocument : malloc failed\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(cur, 0, sizeof(xsltDocument));
|
||||||
|
cur->doc = doc;
|
||||||
|
if (ctxt != NULL) {
|
||||||
|
if (! XSLT_IS_RES_TREE_FRAG(doc)) {
|
||||||
|
cur->next = ctxt->docList;
|
||||||
|
ctxt->docList = cur;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* A key with a specific name for a specific document
|
||||||
|
* will only be computed if there's a call to the key()
|
||||||
|
* function using that specific name for that specific
|
||||||
|
* document. I.e. computation of keys will be done in
|
||||||
|
* xsltGetKey() (keys.c) on an on-demand basis.
|
||||||
|
*
|
||||||
|
* xsltInitCtxtKeys(ctxt, cur); not called here anymore
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNewStyleDocument:
|
||||||
|
* @style: an XSLT style sheet
|
||||||
|
* @doc: a parsed XML document
|
||||||
|
*
|
||||||
|
* Register a new document, apply key computations
|
||||||
|
*
|
||||||
|
* Returns a handler to the document
|
||||||
|
*/
|
||||||
|
xsltDocumentPtr
|
||||||
|
xsltNewStyleDocument(xsltStylesheetPtr style, xmlDocPtr doc) {
|
||||||
|
xsltDocumentPtr cur;
|
||||||
|
|
||||||
|
cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
|
||||||
|
if (cur == NULL) {
|
||||||
|
xsltTransformError(NULL, style, (xmlNodePtr) doc,
|
||||||
|
"xsltNewStyleDocument : malloc failed\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(cur, 0, sizeof(xsltDocument));
|
||||||
|
cur->doc = doc;
|
||||||
|
if (style != NULL) {
|
||||||
|
cur->next = style->docList;
|
||||||
|
style->docList = cur;
|
||||||
|
}
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeStyleDocuments:
|
||||||
|
* @style: an XSLT stylesheet (representing a stylesheet-level)
|
||||||
|
*
|
||||||
|
* Frees the node-trees (and xsltDocument structures) of all
|
||||||
|
* stylesheet-modules of the stylesheet-level represented by
|
||||||
|
* the given @style.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeStyleDocuments(xsltStylesheetPtr style) {
|
||||||
|
xsltDocumentPtr doc, cur;
|
||||||
|
#ifdef XSLT_REFACTORED_XSLT_NSCOMP
|
||||||
|
xsltNsMapPtr nsMap;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (style == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef XSLT_REFACTORED_XSLT_NSCOMP
|
||||||
|
if (XSLT_HAS_INTERNAL_NSMAP(style))
|
||||||
|
nsMap = XSLT_GET_INTERNAL_NSMAP(style);
|
||||||
|
else
|
||||||
|
nsMap = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cur = style->docList;
|
||||||
|
while (cur != NULL) {
|
||||||
|
doc = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
#ifdef XSLT_REFACTORED_XSLT_NSCOMP
|
||||||
|
/*
|
||||||
|
* Restore all changed namespace URIs of ns-decls.
|
||||||
|
*/
|
||||||
|
if (nsMap)
|
||||||
|
xsltRestoreDocumentNamespaces(nsMap, doc->doc);
|
||||||
|
#endif
|
||||||
|
xsltFreeDocumentKeys(doc);
|
||||||
|
if (!doc->main)
|
||||||
|
xmlFreeDoc(doc->doc);
|
||||||
|
xmlFree(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeDocuments:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
*
|
||||||
|
* Free up all the space used by the loaded documents
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeDocuments(xsltTransformContextPtr ctxt) {
|
||||||
|
xsltDocumentPtr doc, cur;
|
||||||
|
|
||||||
|
cur = ctxt->docList;
|
||||||
|
while (cur != NULL) {
|
||||||
|
doc = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
xsltFreeDocumentKeys(doc);
|
||||||
|
if (!doc->main)
|
||||||
|
xmlFreeDoc(doc->doc);
|
||||||
|
xmlFree(doc);
|
||||||
|
}
|
||||||
|
cur = ctxt->styleList;
|
||||||
|
while (cur != NULL) {
|
||||||
|
doc = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
xsltFreeDocumentKeys(doc);
|
||||||
|
if (!doc->main)
|
||||||
|
xmlFreeDoc(doc->doc);
|
||||||
|
xmlFree(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltLoadDocument:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @URI: the computed URI of the document
|
||||||
|
*
|
||||||
|
* Try to load a document (not a stylesheet)
|
||||||
|
* within the XSLT transformation context
|
||||||
|
*
|
||||||
|
* Returns the new xsltDocumentPtr or NULL in case of error
|
||||||
|
*/
|
||||||
|
xsltDocumentPtr
|
||||||
|
xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) {
|
||||||
|
xsltDocumentPtr ret;
|
||||||
|
xmlDocPtr doc;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (URI == NULL))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Security framework check
|
||||||
|
*/
|
||||||
|
if (ctxt->sec != NULL) {
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = xsltCheckRead(ctxt->sec, ctxt, URI);
|
||||||
|
if (res <= 0) {
|
||||||
|
if (res == 0)
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"xsltLoadDocument: read rights for %s denied\n",
|
||||||
|
URI);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk the context list to find the document if preparsed
|
||||||
|
*/
|
||||||
|
ret = ctxt->docList;
|
||||||
|
while (ret != NULL) {
|
||||||
|
if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
|
||||||
|
(xmlStrEqual(ret->doc->URL, URI)))
|
||||||
|
return(ret);
|
||||||
|
ret = ret->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
doc = xsltDocDefaultLoader(URI, ctxt->dict, ctxt->parserOptions,
|
||||||
|
(void *) ctxt, XSLT_LOAD_DOCUMENT);
|
||||||
|
|
||||||
|
if (doc == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
if (ctxt->xinclude != 0) {
|
||||||
|
#ifdef LIBXML_XINCLUDE_ENABLED
|
||||||
|
#if LIBXML_VERSION >= 20603
|
||||||
|
xmlXIncludeProcessFlags(doc, ctxt->parserOptions);
|
||||||
|
#else
|
||||||
|
xmlXIncludeProcess(doc);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"xsltLoadDocument(%s) : XInclude processing not compiled in\n",
|
||||||
|
URI);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Apply white-space stripping if asked for
|
||||||
|
*/
|
||||||
|
if (xsltNeedElemSpaceHandling(ctxt))
|
||||||
|
xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));
|
||||||
|
if (ctxt->debugStatus == XSLT_DEBUG_NONE)
|
||||||
|
xmlXPathOrderDocElems(doc);
|
||||||
|
|
||||||
|
ret = xsltNewDocument(ctxt, doc);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltLoadStyleDocument:
|
||||||
|
* @style: an XSLT style sheet
|
||||||
|
* @URI: the computed URI of the document
|
||||||
|
*
|
||||||
|
* Try to load a stylesheet document within the XSLT transformation context
|
||||||
|
*
|
||||||
|
* Returns the new xsltDocumentPtr or NULL in case of error
|
||||||
|
*/
|
||||||
|
xsltDocumentPtr
|
||||||
|
xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {
|
||||||
|
xsltDocumentPtr ret;
|
||||||
|
xmlDocPtr doc;
|
||||||
|
xsltSecurityPrefsPtr sec;
|
||||||
|
|
||||||
|
if ((style == NULL) || (URI == NULL))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Security framework check
|
||||||
|
*/
|
||||||
|
sec = xsltGetDefaultSecurityPrefs();
|
||||||
|
if (sec != NULL) {
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = xsltCheckRead(sec, NULL, URI);
|
||||||
|
if (res <= 0) {
|
||||||
|
if (res == 0)
|
||||||
|
xsltTransformError(NULL, NULL, NULL,
|
||||||
|
"xsltLoadStyleDocument: read rights for %s denied\n",
|
||||||
|
URI);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk the context list to find the document if preparsed
|
||||||
|
*/
|
||||||
|
ret = style->docList;
|
||||||
|
while (ret != NULL) {
|
||||||
|
if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
|
||||||
|
(xmlStrEqual(ret->doc->URL, URI)))
|
||||||
|
return(ret);
|
||||||
|
ret = ret->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
doc = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
|
||||||
|
(void *) style, XSLT_LOAD_STYLESHEET);
|
||||||
|
if (doc == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
ret = xsltNewStyleDocument(style, doc);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFindDocument:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @doc: a parsed XML document
|
||||||
|
*
|
||||||
|
* Try to find a document within the XSLT transformation context.
|
||||||
|
* This will not find document infos for temporary
|
||||||
|
* Result Tree Fragments.
|
||||||
|
*
|
||||||
|
* Returns the desired xsltDocumentPtr or NULL in case of error
|
||||||
|
*/
|
||||||
|
xsltDocumentPtr
|
||||||
|
xsltFindDocument (xsltTransformContextPtr ctxt, xmlDocPtr doc) {
|
||||||
|
xsltDocumentPtr ret;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (doc == NULL))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk the context list to find the document
|
||||||
|
*/
|
||||||
|
ret = ctxt->docList;
|
||||||
|
while (ret != NULL) {
|
||||||
|
if (ret->doc == doc)
|
||||||
|
return(ret);
|
||||||
|
ret = ret->next;
|
||||||
|
}
|
||||||
|
if (doc == ctxt->style->doc)
|
||||||
|
return(ctxt->document);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the document handling
|
||||||
|
* Description: implements document loading and cache (multiple
|
||||||
|
* document() reference for the same resources must
|
||||||
|
* be equal.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_DOCUMENTS_H__
|
||||||
|
#define __XML_XSLT_DOCUMENTS_H__
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
XSLTPUBFUN xsltDocumentPtr XSLTCALL
|
||||||
|
xsltNewDocument (xsltTransformContextPtr ctxt,
|
||||||
|
xmlDocPtr doc);
|
||||||
|
XSLTPUBFUN xsltDocumentPtr XSLTCALL
|
||||||
|
xsltLoadDocument (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *URI);
|
||||||
|
XSLTPUBFUN xsltDocumentPtr XSLTCALL
|
||||||
|
xsltFindDocument (xsltTransformContextPtr ctxt,
|
||||||
|
xmlDocPtr doc);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeDocuments (xsltTransformContextPtr ctxt);
|
||||||
|
|
||||||
|
XSLTPUBFUN xsltDocumentPtr XSLTCALL
|
||||||
|
xsltLoadStyleDocument (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *URI);
|
||||||
|
XSLTPUBFUN xsltDocumentPtr XSLTCALL
|
||||||
|
xsltNewStyleDocument (xsltStylesheetPtr style,
|
||||||
|
xmlDocPtr doc);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeStyleDocuments (xsltStylesheetPtr style);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hooks for document loading
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltLoadType:
|
||||||
|
*
|
||||||
|
* Enum defining the kind of loader requirement.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
XSLT_LOAD_START = 0, /* loading for a top stylesheet */
|
||||||
|
XSLT_LOAD_STYLESHEET = 1, /* loading for a stylesheet include/import */
|
||||||
|
XSLT_LOAD_DOCUMENT = 2 /* loading document at transformation time */
|
||||||
|
} xsltLoadType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltDocLoaderFunc:
|
||||||
|
* @URI: the URI of the document to load
|
||||||
|
* @dict: the dictionary to use when parsing that document
|
||||||
|
* @options: parsing options, a set of xmlParserOption
|
||||||
|
* @ctxt: the context, either a stylesheet or a transformation context
|
||||||
|
* @type: the xsltLoadType indicating the kind of loading required
|
||||||
|
*
|
||||||
|
* An xsltDocLoaderFunc is a signature for a function which can be
|
||||||
|
* registered to load document not provided by the compilation or
|
||||||
|
* transformation API themselve, for example when an xsl:import,
|
||||||
|
* xsl:include is found at compilation time or when a document()
|
||||||
|
* call is made at runtime.
|
||||||
|
*
|
||||||
|
* Returns the pointer to the document (which will be modified and
|
||||||
|
* freed by the engine later), or NULL in case of error.
|
||||||
|
*/
|
||||||
|
typedef xmlDocPtr (*xsltDocLoaderFunc) (const xmlChar *URI,
|
||||||
|
xmlDictPtr dict,
|
||||||
|
int options,
|
||||||
|
void *ctxt,
|
||||||
|
xsltLoadType type);
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSetLoaderFunc (xsltDocLoaderFunc f);
|
||||||
|
|
||||||
|
/* the loader may be needed by extension libraries so it is exported */
|
||||||
|
XSLTPUBVAR xsltDocLoaderFunc xsltDocDefaultLoader;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_DOCUMENTS_H__ */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,262 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the extension support
|
||||||
|
* Description: This provide the API needed for simple and module
|
||||||
|
* extension support.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_EXTENSION_H__
|
||||||
|
#define __XML_XSLT_EXTENSION_H__
|
||||||
|
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension Modules API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltInitGlobals:
|
||||||
|
*
|
||||||
|
* Initialize the global variables for extensions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltInitGlobals (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltStyleExtInitFunction:
|
||||||
|
* @ctxt: an XSLT stylesheet
|
||||||
|
* @URI: the namespace URI for the extension
|
||||||
|
*
|
||||||
|
* A function called at initialization time of an XSLT extension module.
|
||||||
|
*
|
||||||
|
* Returns a pointer to the module specific data for this transformation.
|
||||||
|
*/
|
||||||
|
typedef void * (*xsltStyleExtInitFunction) (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *URI);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltStyleExtShutdownFunction:
|
||||||
|
* @ctxt: an XSLT stylesheet
|
||||||
|
* @URI: the namespace URI for the extension
|
||||||
|
* @data: the data associated to this module
|
||||||
|
*
|
||||||
|
* A function called at shutdown time of an XSLT extension module.
|
||||||
|
*/
|
||||||
|
typedef void (*xsltStyleExtShutdownFunction) (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *URI,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltExtInitFunction:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @URI: the namespace URI for the extension
|
||||||
|
*
|
||||||
|
* A function called at initialization time of an XSLT extension module.
|
||||||
|
*
|
||||||
|
* Returns a pointer to the module specific data for this transformation.
|
||||||
|
*/
|
||||||
|
typedef void * (*xsltExtInitFunction) (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *URI);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltExtShutdownFunction:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @URI: the namespace URI for the extension
|
||||||
|
* @data: the data associated to this module
|
||||||
|
*
|
||||||
|
* A function called at shutdown time of an XSLT extension module.
|
||||||
|
*/
|
||||||
|
typedef void (*xsltExtShutdownFunction) (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *URI,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRegisterExtModule (const xmlChar *URI,
|
||||||
|
xsltExtInitFunction initFunc,
|
||||||
|
xsltExtShutdownFunction shutdownFunc);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRegisterExtModuleFull
|
||||||
|
(const xmlChar * URI,
|
||||||
|
xsltExtInitFunction initFunc,
|
||||||
|
xsltExtShutdownFunction shutdownFunc,
|
||||||
|
xsltStyleExtInitFunction styleInitFunc,
|
||||||
|
xsltStyleExtShutdownFunction styleShutdownFunc);
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltUnregisterExtModule (const xmlChar * URI);
|
||||||
|
|
||||||
|
XSLTPUBFUN void * XSLTCALL
|
||||||
|
xsltGetExtData (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *URI);
|
||||||
|
|
||||||
|
XSLTPUBFUN void * XSLTCALL
|
||||||
|
xsltStyleGetExtData (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *URI);
|
||||||
|
#ifdef XSLT_REFACTORED
|
||||||
|
XSLTPUBFUN void * XSLTCALL
|
||||||
|
xsltStyleStylesheetLevelGetExtData(
|
||||||
|
xsltStylesheetPtr style,
|
||||||
|
const xmlChar * URI);
|
||||||
|
#endif
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltShutdownCtxtExts (xsltTransformContextPtr ctxt);
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltShutdownExts (xsltStylesheetPtr style);
|
||||||
|
|
||||||
|
XSLTPUBFUN xsltTransformContextPtr XSLTCALL
|
||||||
|
xsltXPathGetTransformContext
|
||||||
|
(xmlXPathParserContextPtr ctxt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* extension functions
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRegisterExtModuleFunction
|
||||||
|
(const xmlChar *name,
|
||||||
|
const xmlChar *URI,
|
||||||
|
xmlXPathFunction function);
|
||||||
|
XSLTPUBFUN xmlXPathFunction XSLTCALL
|
||||||
|
xsltExtModuleFunctionLookup (const xmlChar *name,
|
||||||
|
const xmlChar *URI);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltUnregisterExtModuleFunction
|
||||||
|
(const xmlChar *name,
|
||||||
|
const xmlChar *URI);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* extension elements
|
||||||
|
*/
|
||||||
|
typedef xsltElemPreCompPtr (*xsltPreComputeFunction)
|
||||||
|
(xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltTransformFunction function);
|
||||||
|
|
||||||
|
XSLTPUBFUN xsltElemPreCompPtr XSLTCALL
|
||||||
|
xsltNewElemPreComp (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltTransformFunction function);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltInitElemPreComp (xsltElemPreCompPtr comp,
|
||||||
|
xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltTransformFunction function,
|
||||||
|
xsltElemPreCompDeallocator freeFunc);
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRegisterExtModuleElement
|
||||||
|
(const xmlChar *name,
|
||||||
|
const xmlChar *URI,
|
||||||
|
xsltPreComputeFunction precomp,
|
||||||
|
xsltTransformFunction transform);
|
||||||
|
XSLTPUBFUN xsltTransformFunction XSLTCALL
|
||||||
|
xsltExtElementLookup (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *URI);
|
||||||
|
XSLTPUBFUN xsltTransformFunction XSLTCALL
|
||||||
|
xsltExtModuleElementLookup
|
||||||
|
(const xmlChar *name,
|
||||||
|
const xmlChar *URI);
|
||||||
|
XSLTPUBFUN xsltPreComputeFunction XSLTCALL
|
||||||
|
xsltExtModuleElementPreComputeLookup
|
||||||
|
(const xmlChar *name,
|
||||||
|
const xmlChar *URI);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltUnregisterExtModuleElement
|
||||||
|
(const xmlChar *name,
|
||||||
|
const xmlChar *URI);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* top-level elements
|
||||||
|
*/
|
||||||
|
typedef void (*xsltTopLevelFunction) (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr inst);
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRegisterExtModuleTopLevel
|
||||||
|
(const xmlChar *name,
|
||||||
|
const xmlChar *URI,
|
||||||
|
xsltTopLevelFunction function);
|
||||||
|
XSLTPUBFUN xsltTopLevelFunction XSLTCALL
|
||||||
|
xsltExtModuleTopLevelLookup
|
||||||
|
(const xmlChar *name,
|
||||||
|
const xmlChar *URI);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltUnregisterExtModuleTopLevel
|
||||||
|
(const xmlChar *name,
|
||||||
|
const xmlChar *URI);
|
||||||
|
|
||||||
|
|
||||||
|
/* These 2 functions are deprecated for use within modules. */
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRegisterExtFunction (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *URI,
|
||||||
|
xmlXPathFunction function);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRegisterExtElement (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *URI,
|
||||||
|
xsltTransformFunction function);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extension Prefix handling API.
|
||||||
|
* Those are used by the XSLT (pre)processor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRegisterExtPrefix (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *prefix,
|
||||||
|
const xmlChar *URI);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltCheckExtPrefix (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *URI);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltCheckExtURI (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *URI);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltInitCtxtExts (xsltTransformContextPtr ctxt);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeCtxtExts (xsltTransformContextPtr ctxt);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeExts (xsltStylesheetPtr style);
|
||||||
|
|
||||||
|
XSLTPUBFUN xsltElemPreCompPtr XSLTCALL
|
||||||
|
xsltPreComputeExtModuleElement
|
||||||
|
(xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr inst);
|
||||||
|
/*
|
||||||
|
* Extension Infos access.
|
||||||
|
* Used by exslt initialisation
|
||||||
|
*/
|
||||||
|
|
||||||
|
XSLTPUBFUN xmlHashTablePtr XSLTCALL
|
||||||
|
xsltGetExtInfo (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *URI);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test module http://xmlsoft.org/XSLT/
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltRegisterTestModule (void);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltDebugDumpExtensions (FILE * output);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_EXTENSION_H__ */
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
* extra.c: Implementation of non-standard features
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* Michael Kay "XSLT Programmer's Reference" pp 637-643
|
||||||
|
* The node-set() extension function
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* daniel@veillard.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IN_LIBXSLT
|
||||||
|
#include "libxslt.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/hash.h>
|
||||||
|
#include <libxml/xmlerror.h>
|
||||||
|
#include <libxml/parserInternals.h>
|
||||||
|
#include "xslt.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "xsltutils.h"
|
||||||
|
#include "extensions.h"
|
||||||
|
#include "variables.h"
|
||||||
|
#include "transform.h"
|
||||||
|
#include "extra.h"
|
||||||
|
#include "preproc.h"
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG
|
||||||
|
#define WITH_XSLT_DEBUG_EXTRA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Handling of XSLT debugging *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltDebug:
|
||||||
|
* @ctxt: an XSLT processing context
|
||||||
|
* @node: The current node
|
||||||
|
* @inst: the instruction in the stylesheet
|
||||||
|
* @comp: precomputed information
|
||||||
|
*
|
||||||
|
* Process an debug node
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltDebug(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED,
|
||||||
|
xmlNodePtr inst ATTRIBUTE_UNUSED,
|
||||||
|
xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "Templates:\n");
|
||||||
|
for (i = 0, j = ctxt->templNr - 1; ((i < 15) && (j >= 0)); i++, j--) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "#%d ", i);
|
||||||
|
if (ctxt->templTab[j]->name != NULL)
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "name %s ",
|
||||||
|
ctxt->templTab[j]->name);
|
||||||
|
if (ctxt->templTab[j]->match != NULL)
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "name %s ",
|
||||||
|
ctxt->templTab[j]->match);
|
||||||
|
if (ctxt->templTab[j]->mode != NULL)
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "name %s ",
|
||||||
|
ctxt->templTab[j]->mode);
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "\n");
|
||||||
|
}
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "Variables:\n");
|
||||||
|
for (i = 0, j = ctxt->varsNr - 1; ((i < 15) && (j >= 0)); i++, j--) {
|
||||||
|
xsltStackElemPtr cur;
|
||||||
|
|
||||||
|
if (ctxt->varsTab[j] == NULL)
|
||||||
|
continue;
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "#%d\n", i);
|
||||||
|
cur = ctxt->varsTab[j];
|
||||||
|
while (cur != NULL) {
|
||||||
|
if (cur->comp == NULL) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"corrupted !!!\n");
|
||||||
|
} else if (cur->comp->type == XSLT_FUNC_PARAM) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "param ");
|
||||||
|
} else if (cur->comp->type == XSLT_FUNC_VARIABLE) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "var ");
|
||||||
|
}
|
||||||
|
if (cur->name != NULL)
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "%s ",
|
||||||
|
cur->name);
|
||||||
|
else
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "noname !!!!");
|
||||||
|
#ifdef LIBXML_DEBUG_ENABLED
|
||||||
|
if (cur->value != NULL) {
|
||||||
|
if ((xsltGenericDebugContext == stdout) ||
|
||||||
|
(xsltGenericDebugContext == stderr))
|
||||||
|
xmlXPathDebugDumpObject((FILE*)xsltGenericDebugContext,
|
||||||
|
cur->value, 1);
|
||||||
|
} else {
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "NULL !!!!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
xsltGenericError(xsltGenericErrorContext, "\n");
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Classic extensions as described by M. Kay *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFunctionNodeSet:
|
||||||
|
* @ctxt: the XPath Parser context
|
||||||
|
* @nargs: the number of arguments
|
||||||
|
*
|
||||||
|
* Implement the node-set() XSLT function
|
||||||
|
* node-set node-set(result-tree)
|
||||||
|
*
|
||||||
|
* This function is available in libxslt, saxon or xt namespace.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFunctionNodeSet(xmlXPathParserContextPtr ctxt, int nargs){
|
||||||
|
if (nargs != 1) {
|
||||||
|
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
||||||
|
"node-set() : expects one result-tree arg\n");
|
||||||
|
ctxt->error = XPATH_INVALID_ARITY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((ctxt->value == NULL) ||
|
||||||
|
((ctxt->value->type != XPATH_XSLT_TREE) &&
|
||||||
|
(ctxt->value->type != XPATH_NODESET))) {
|
||||||
|
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
||||||
|
"node-set() invalid arg expecting a result tree\n");
|
||||||
|
ctxt->error = XPATH_INVALID_TYPE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ctxt->value->type == XPATH_XSLT_TREE) {
|
||||||
|
ctxt->value->type = XPATH_NODESET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltRegisterExtras:
|
||||||
|
* @ctxt: a XSLT process context
|
||||||
|
*
|
||||||
|
* Registers the built-in extensions. This function is deprecated, use
|
||||||
|
* xsltRegisterAllExtras instead.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltRegisterExtras(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED) {
|
||||||
|
xsltRegisterAllExtras();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltRegisterAllExtras:
|
||||||
|
*
|
||||||
|
* Registers the built-in extensions
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltRegisterAllExtras (void) {
|
||||||
|
xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
|
||||||
|
XSLT_LIBXSLT_NAMESPACE,
|
||||||
|
xsltFunctionNodeSet);
|
||||||
|
xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
|
||||||
|
XSLT_SAXON_NAMESPACE,
|
||||||
|
xsltFunctionNodeSet);
|
||||||
|
xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
|
||||||
|
XSLT_XT_NAMESPACE,
|
||||||
|
xsltFunctionNodeSet);
|
||||||
|
xsltRegisterExtModuleElement((const xmlChar *) "debug",
|
||||||
|
XSLT_LIBXSLT_NAMESPACE,
|
||||||
|
NULL,
|
||||||
|
xsltDebug);
|
||||||
|
xsltRegisterExtModuleElement((const xmlChar *) "output",
|
||||||
|
XSLT_SAXON_NAMESPACE,
|
||||||
|
xsltDocumentComp,
|
||||||
|
xsltDocumentElem);
|
||||||
|
xsltRegisterExtModuleElement((const xmlChar *) "write",
|
||||||
|
XSLT_XALAN_NAMESPACE,
|
||||||
|
xsltDocumentComp,
|
||||||
|
xsltDocumentElem);
|
||||||
|
xsltRegisterExtModuleElement((const xmlChar *) "document",
|
||||||
|
XSLT_XT_NAMESPACE,
|
||||||
|
xsltDocumentComp,
|
||||||
|
xsltDocumentElem);
|
||||||
|
xsltRegisterExtModuleElement((const xmlChar *) "document",
|
||||||
|
XSLT_NAMESPACE,
|
||||||
|
xsltDocumentComp,
|
||||||
|
xsltDocumentElem);
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the non-standard features
|
||||||
|
* Description: implement some extension outside the XSLT namespace
|
||||||
|
* but not EXSLT with is in a different library.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_EXTRA_H__
|
||||||
|
#define __XML_XSLT_EXTRA_H__
|
||||||
|
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_LIBXSLT_NAMESPACE:
|
||||||
|
*
|
||||||
|
* This is the libxslt namespace for specific extensions.
|
||||||
|
*/
|
||||||
|
#define XSLT_LIBXSLT_NAMESPACE ((xmlChar *) "http://xmlsoft.org/XSLT/namespace")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_SAXON_NAMESPACE:
|
||||||
|
*
|
||||||
|
* This is Michael Kay's Saxon processor namespace for extensions.
|
||||||
|
*/
|
||||||
|
#define XSLT_SAXON_NAMESPACE ((xmlChar *) "http://icl.com/saxon")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_XT_NAMESPACE:
|
||||||
|
*
|
||||||
|
* This is James Clark's XT processor namespace for extensions.
|
||||||
|
*/
|
||||||
|
#define XSLT_XT_NAMESPACE ((xmlChar *) "http://www.jclark.com/xt")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_XALAN_NAMESPACE:
|
||||||
|
*
|
||||||
|
* This is the Apache project XALAN processor namespace for extensions.
|
||||||
|
*/
|
||||||
|
#define XSLT_XALAN_NAMESPACE ((xmlChar *) \
|
||||||
|
"org.apache.xalan.xslt.extensions.Redirect")
|
||||||
|
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFunctionNodeSet (xmlXPathParserContextPtr ctxt,
|
||||||
|
int nargs);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltDebug (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltRegisterExtras (xsltTransformContextPtr ctxt);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltRegisterAllExtras (void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_EXTRA_H__ */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the XSLT functions not from XPath
|
||||||
|
* Description: a set of extra functions coming from XSLT but not in XPath
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard and Bjorn Reese <breese@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_FUNCTIONS_H__
|
||||||
|
#define __XML_XSLT_FUNCTIONS_H__
|
||||||
|
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_REGISTER_FUNCTION_LOOKUP:
|
||||||
|
*
|
||||||
|
* Registering macro, not general purpose at all but used in different modules.
|
||||||
|
*/
|
||||||
|
#define XSLT_REGISTER_FUNCTION_LOOKUP(ctxt) \
|
||||||
|
xmlXPathRegisterFuncLookup((ctxt)->xpathCtxt, \
|
||||||
|
xsltXPathFunctionLookup, \
|
||||||
|
(void *)(ctxt->xpathCtxt));
|
||||||
|
|
||||||
|
XSLTPUBFUN xmlXPathFunction XSLTCALL
|
||||||
|
xsltXPathFunctionLookup (void *vctxt,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *ns_uri);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interfaces for the functions implementations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltDocumentFunction (xmlXPathParserContextPtr ctxt,
|
||||||
|
int nargs);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltKeyFunction (xmlXPathParserContextPtr ctxt,
|
||||||
|
int nargs);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltUnparsedEntityURIFunction (xmlXPathParserContextPtr ctxt,
|
||||||
|
int nargs);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFormatNumberFunction (xmlXPathParserContextPtr ctxt,
|
||||||
|
int nargs);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltGenerateIdFunction (xmlXPathParserContextPtr ctxt,
|
||||||
|
int nargs);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSystemPropertyFunction (xmlXPathParserContextPtr ctxt,
|
||||||
|
int nargs);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltElementAvailableFunction (xmlXPathParserContextPtr ctxt,
|
||||||
|
int nargs);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFunctionAvailableFunction (xmlXPathParserContextPtr ctxt,
|
||||||
|
int nargs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* And the registration
|
||||||
|
*/
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltRegisterAllFunctions (xmlXPathContextPtr ctxt);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_FUNCTIONS_H__ */
|
||||||
|
|
|
@ -0,0 +1,414 @@
|
||||||
|
/*
|
||||||
|
* imports.c: Implementation of the XSLT imports
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* http://www.w3.org/TR/1999/REC-xslt-19991116
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* daniel@veillard.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IN_LIBXSLT
|
||||||
|
#include "libxslt.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_MATH_H
|
||||||
|
#include <math.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FLOAT_H
|
||||||
|
#include <float.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_IEEEFP_H
|
||||||
|
#include <ieeefp.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NAN_H
|
||||||
|
#include <nan.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/hash.h>
|
||||||
|
#include <libxml/xmlerror.h>
|
||||||
|
#include <libxml/uri.h>
|
||||||
|
#include "xslt.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "xsltutils.h"
|
||||||
|
#include "preproc.h"
|
||||||
|
#include "imports.h"
|
||||||
|
#include "documents.h"
|
||||||
|
#include "security.h"
|
||||||
|
#include "pattern.h"
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Module interfaces *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
/**
|
||||||
|
* xsltFixImportedCompSteps:
|
||||||
|
* @master: the "master" stylesheet
|
||||||
|
* @style: the stylesheet being imported by the master
|
||||||
|
*
|
||||||
|
* normalize the comp steps for the stylesheet being imported
|
||||||
|
* by the master, together with any imports within that.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void xsltFixImportedCompSteps(xsltStylesheetPtr master,
|
||||||
|
xsltStylesheetPtr style) {
|
||||||
|
xsltStylesheetPtr res;
|
||||||
|
xmlHashScan(style->templatesHash, xsltNormalizeCompSteps, master);
|
||||||
|
master->extrasNr += style->extrasNr;
|
||||||
|
for (res = style->imports; res != NULL; res = res->next) {
|
||||||
|
xsltFixImportedCompSteps(master, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltParseStylesheetImport:
|
||||||
|
* @style: the XSLT stylesheet
|
||||||
|
* @cur: the import element
|
||||||
|
*
|
||||||
|
* parse an XSLT stylesheet import element
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success -1 in case of failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
|
||||||
|
int ret = -1;
|
||||||
|
xmlDocPtr import = NULL;
|
||||||
|
xmlChar *base = NULL;
|
||||||
|
xmlChar *uriRef = NULL;
|
||||||
|
xmlChar *URI = NULL;
|
||||||
|
xsltStylesheetPtr res;
|
||||||
|
xsltSecurityPrefsPtr sec;
|
||||||
|
|
||||||
|
if ((cur == NULL) || (style == NULL))
|
||||||
|
return (ret);
|
||||||
|
|
||||||
|
uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL);
|
||||||
|
if (uriRef == NULL) {
|
||||||
|
xsltTransformError(NULL, style, cur,
|
||||||
|
"xsl:import : missing href attribute\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = xmlNodeGetBase(style->doc, cur);
|
||||||
|
URI = xmlBuildURI(uriRef, base);
|
||||||
|
if (URI == NULL) {
|
||||||
|
xsltTransformError(NULL, style, cur,
|
||||||
|
"xsl:import : invalid URI reference %s\n", uriRef);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = style;
|
||||||
|
while (res != NULL) {
|
||||||
|
if (res->doc == NULL)
|
||||||
|
break;
|
||||||
|
if (xmlStrEqual(res->doc->URL, URI)) {
|
||||||
|
xsltTransformError(NULL, style, cur,
|
||||||
|
"xsl:import : recursion detected on imported URL %s\n", URI);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
res = res->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Security framework check
|
||||||
|
*/
|
||||||
|
sec = xsltGetDefaultSecurityPrefs();
|
||||||
|
if (sec != NULL) {
|
||||||
|
int secres;
|
||||||
|
|
||||||
|
secres = xsltCheckRead(sec, NULL, URI);
|
||||||
|
if (secres <= 0) {
|
||||||
|
if (secres == 0)
|
||||||
|
xsltTransformError(NULL, NULL, NULL,
|
||||||
|
"xsl:import: read rights for %s denied\n",
|
||||||
|
URI);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
|
||||||
|
(void *) style, XSLT_LOAD_STYLESHEET);
|
||||||
|
if (import == NULL) {
|
||||||
|
xsltTransformError(NULL, style, cur,
|
||||||
|
"xsl:import : unable to load %s\n", URI);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = xsltParseStylesheetImportedDoc(import, style);
|
||||||
|
if (res != NULL) {
|
||||||
|
res->next = style->imports;
|
||||||
|
style->imports = res;
|
||||||
|
if (style->parent == NULL) {
|
||||||
|
xsltFixImportedCompSteps(style, res);
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
xmlFreeDoc(import);
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (uriRef != NULL)
|
||||||
|
xmlFree(uriRef);
|
||||||
|
if (base != NULL)
|
||||||
|
xmlFree(base);
|
||||||
|
if (URI != NULL)
|
||||||
|
xmlFree(URI);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltParseStylesheetInclude:
|
||||||
|
* @style: the XSLT stylesheet
|
||||||
|
* @cur: the include node
|
||||||
|
*
|
||||||
|
* parse an XSLT stylesheet include element
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success -1 in case of failure
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
|
||||||
|
int ret = -1;
|
||||||
|
xmlDocPtr oldDoc;
|
||||||
|
xmlChar *base = NULL;
|
||||||
|
xmlChar *uriRef = NULL;
|
||||||
|
xmlChar *URI = NULL;
|
||||||
|
xsltStylesheetPtr result;
|
||||||
|
xsltDocumentPtr include;
|
||||||
|
xsltDocumentPtr docptr;
|
||||||
|
int oldNopreproc;
|
||||||
|
|
||||||
|
if ((cur == NULL) || (style == NULL))
|
||||||
|
return (ret);
|
||||||
|
|
||||||
|
uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL);
|
||||||
|
if (uriRef == NULL) {
|
||||||
|
xsltTransformError(NULL, style, cur,
|
||||||
|
"xsl:include : missing href attribute\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = xmlNodeGetBase(style->doc, cur);
|
||||||
|
URI = xmlBuildURI(uriRef, base);
|
||||||
|
if (URI == NULL) {
|
||||||
|
xsltTransformError(NULL, style, cur,
|
||||||
|
"xsl:include : invalid URI reference %s\n", uriRef);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* in order to detect recursion, we check all previously included
|
||||||
|
* stylesheets.
|
||||||
|
*/
|
||||||
|
docptr = style->includes;
|
||||||
|
while (docptr != NULL) {
|
||||||
|
if (xmlStrEqual(docptr->doc->URL, URI)) {
|
||||||
|
xsltTransformError(NULL, style, cur,
|
||||||
|
"xsl:include : recursion detected on included URL %s\n", URI);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
docptr = docptr->includes;
|
||||||
|
}
|
||||||
|
|
||||||
|
include = xsltLoadStyleDocument(style, URI);
|
||||||
|
if (include == NULL) {
|
||||||
|
xsltTransformError(NULL, style, cur,
|
||||||
|
"xsl:include : unable to load %s\n", URI);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#ifdef XSLT_REFACTORED
|
||||||
|
if (IS_XSLT_ELEM_FAST(cur) && (cur->psvi != NULL)) {
|
||||||
|
((xsltStyleItemIncludePtr) cur->psvi)->include = include;
|
||||||
|
} else {
|
||||||
|
xsltTransformError(NULL, style, cur,
|
||||||
|
"Internal error: (xsltParseStylesheetInclude) "
|
||||||
|
"The xsl:include element was not compiled.\n", URI);
|
||||||
|
style->errors++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
oldDoc = style->doc;
|
||||||
|
style->doc = include->doc;
|
||||||
|
/* chain to stylesheet for recursion checking */
|
||||||
|
include->includes = style->includes;
|
||||||
|
style->includes = include;
|
||||||
|
oldNopreproc = style->nopreproc;
|
||||||
|
style->nopreproc = include->preproc;
|
||||||
|
/*
|
||||||
|
* TODO: This will change some values of the
|
||||||
|
* including stylesheet with every included module
|
||||||
|
* (e.g. excluded-result-prefixes)
|
||||||
|
* We need to strictly seperate such stylesheet-owned values.
|
||||||
|
*/
|
||||||
|
result = xsltParseStylesheetProcess(style, include->doc);
|
||||||
|
style->nopreproc = oldNopreproc;
|
||||||
|
include->preproc = 1;
|
||||||
|
style->includes = include->includes;
|
||||||
|
style->doc = oldDoc;
|
||||||
|
if (result == NULL) {
|
||||||
|
ret = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (uriRef != NULL)
|
||||||
|
xmlFree(uriRef);
|
||||||
|
if (base != NULL)
|
||||||
|
xmlFree(base);
|
||||||
|
if (URI != NULL)
|
||||||
|
xmlFree(URI);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNextImport:
|
||||||
|
* @cur: the current XSLT stylesheet
|
||||||
|
*
|
||||||
|
* Find the next stylesheet in import precedence.
|
||||||
|
*
|
||||||
|
* Returns the next stylesheet or NULL if it was the last one
|
||||||
|
*/
|
||||||
|
|
||||||
|
xsltStylesheetPtr
|
||||||
|
xsltNextImport(xsltStylesheetPtr cur) {
|
||||||
|
if (cur == NULL)
|
||||||
|
return(NULL);
|
||||||
|
if (cur->imports != NULL)
|
||||||
|
return(cur->imports);
|
||||||
|
if (cur->next != NULL)
|
||||||
|
return(cur->next) ;
|
||||||
|
do {
|
||||||
|
cur = cur->parent;
|
||||||
|
if (cur == NULL) break;
|
||||||
|
if (cur->next != NULL) return(cur->next);
|
||||||
|
} while (cur != NULL);
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNeedElemSpaceHandling:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
*
|
||||||
|
* Checks whether that stylesheet requires white-space stripping
|
||||||
|
*
|
||||||
|
* Returns 1 if space should be stripped, 0 if not
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt) {
|
||||||
|
xsltStylesheetPtr style;
|
||||||
|
|
||||||
|
if (ctxt == NULL)
|
||||||
|
return(0);
|
||||||
|
style = ctxt->style;
|
||||||
|
while (style != NULL) {
|
||||||
|
if (style->stripSpaces != NULL)
|
||||||
|
return(1);
|
||||||
|
style = xsltNextImport(style);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFindElemSpaceHandling:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @node: an XML node
|
||||||
|
*
|
||||||
|
* Find strip-space or preserve-space information for an element
|
||||||
|
* respect the import precedence or the wildcards
|
||||||
|
*
|
||||||
|
* Returns 1 if space should be stripped, 0 if not, and 2 if everything
|
||||||
|
* should be CDTATA wrapped.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
||||||
|
xsltStylesheetPtr style;
|
||||||
|
const xmlChar *val;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (node == NULL))
|
||||||
|
return(0);
|
||||||
|
style = ctxt->style;
|
||||||
|
while (style != NULL) {
|
||||||
|
if (node->ns != NULL) {
|
||||||
|
val = (const xmlChar *)
|
||||||
|
xmlHashLookup2(style->stripSpaces, node->name, node->ns->href);
|
||||||
|
if (val == NULL) {
|
||||||
|
val = (const xmlChar *)
|
||||||
|
xmlHashLookup2(style->stripSpaces, BAD_CAST "*",
|
||||||
|
node->ns->href);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val = (const xmlChar *)
|
||||||
|
xmlHashLookup2(style->stripSpaces, node->name, NULL);
|
||||||
|
}
|
||||||
|
if (val != NULL) {
|
||||||
|
if (xmlStrEqual(val, (xmlChar *) "strip"))
|
||||||
|
return(1);
|
||||||
|
if (xmlStrEqual(val, (xmlChar *) "preserve"))
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (style->stripAll == 1)
|
||||||
|
return(1);
|
||||||
|
if (style->stripAll == -1)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
style = xsltNextImport(style);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFindTemplate:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @name: the template name
|
||||||
|
* @nameURI: the template name URI
|
||||||
|
*
|
||||||
|
* Finds the named template, apply import precedence rule.
|
||||||
|
* REVISIT TODO: We'll change the nameURI fields of
|
||||||
|
* templates to be in the string dict, so if the
|
||||||
|
* specified @nameURI is in the same dict, then use pointer
|
||||||
|
* comparison. Check if this can be done in a sane way.
|
||||||
|
* Maybe this function is not needed internally at
|
||||||
|
* transformation-time if we hard-wire the called templates
|
||||||
|
* to the caller.
|
||||||
|
*
|
||||||
|
* Returns the xsltTemplatePtr or NULL if not found
|
||||||
|
*/
|
||||||
|
xsltTemplatePtr
|
||||||
|
xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||||
|
const xmlChar *nameURI) {
|
||||||
|
xsltTemplatePtr cur;
|
||||||
|
xsltStylesheetPtr style;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (name == NULL))
|
||||||
|
return(NULL);
|
||||||
|
style = ctxt->style;
|
||||||
|
while (style != NULL) {
|
||||||
|
if (style->namedTemplates != NULL) {
|
||||||
|
cur = (xsltTemplatePtr)
|
||||||
|
xmlHashLookup2(style->namedTemplates, name, nameURI);
|
||||||
|
if (cur != NULL)
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
style = xsltNextImport(style);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the XSLT import support
|
||||||
|
* Description: macros and fuctions needed to implement and
|
||||||
|
* access the import tree
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_IMPORTS_H__
|
||||||
|
#define __XML_XSLT_IMPORTS_H__
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_GET_IMPORT_PTR:
|
||||||
|
*
|
||||||
|
* A macro to import pointers from the stylesheet cascading order.
|
||||||
|
*/
|
||||||
|
#define XSLT_GET_IMPORT_PTR(res, style, name) { \
|
||||||
|
xsltStylesheetPtr st = style; \
|
||||||
|
res = NULL; \
|
||||||
|
while (st != NULL) { \
|
||||||
|
if (st->name != NULL) { res = st->name; break; } \
|
||||||
|
st = xsltNextImport(st); \
|
||||||
|
}}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_GET_IMPORT_INT:
|
||||||
|
*
|
||||||
|
* A macro to import intergers from the stylesheet cascading order.
|
||||||
|
*/
|
||||||
|
#define XSLT_GET_IMPORT_INT(res, style, name) { \
|
||||||
|
xsltStylesheetPtr st = style; \
|
||||||
|
res = -1; \
|
||||||
|
while (st != NULL) { \
|
||||||
|
if (st->name != -1) { res = st->name; break; } \
|
||||||
|
st = xsltNextImport(st); \
|
||||||
|
}}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module interfaces
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltParseStylesheetImport(xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr cur);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltParseStylesheetInclude
|
||||||
|
(xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr cur);
|
||||||
|
XSLTPUBFUN xsltStylesheetPtr XSLTCALL
|
||||||
|
xsltNextImport (xsltStylesheetPtr style);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node);
|
||||||
|
XSLTPUBFUN xsltTemplatePtr XSLTCALL
|
||||||
|
xsltFindTemplate (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *nameURI);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_IMPORTS_H__ */
|
||||||
|
|
|
@ -0,0 +1,947 @@
|
||||||
|
/*
|
||||||
|
* keys.c: Implemetation of the keys support
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* http://www.w3.org/TR/1999/REC-xslt-19991116
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* daniel@veillard.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IN_LIBXSLT
|
||||||
|
#include "libxslt.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/valid.h>
|
||||||
|
#include <libxml/hash.h>
|
||||||
|
#include <libxml/xmlerror.h>
|
||||||
|
#include <libxml/parserInternals.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include "xslt.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "xsltutils.h"
|
||||||
|
#include "imports.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "keys.h"
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG
|
||||||
|
#define WITH_XSLT_DEBUG_KEYS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
xsltInitDocKeyTable(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||||
|
const xmlChar *nameURI);
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Type functions *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNewKeyDef:
|
||||||
|
* @name: the key name or NULL
|
||||||
|
* @nameURI: the name URI or NULL
|
||||||
|
*
|
||||||
|
* Create a new XSLT KeyDef
|
||||||
|
*
|
||||||
|
* Returns the newly allocated xsltKeyDefPtr or NULL in case of error
|
||||||
|
*/
|
||||||
|
static xsltKeyDefPtr
|
||||||
|
xsltNewKeyDef(const xmlChar *name, const xmlChar *nameURI) {
|
||||||
|
xsltKeyDefPtr cur;
|
||||||
|
|
||||||
|
cur = (xsltKeyDefPtr) xmlMalloc(sizeof(xsltKeyDef));
|
||||||
|
if (cur == NULL) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL,
|
||||||
|
"xsltNewKeyDef : malloc failed\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(cur, 0, sizeof(xsltKeyDef));
|
||||||
|
if (name != NULL)
|
||||||
|
cur->name = xmlStrdup(name);
|
||||||
|
if (nameURI != NULL)
|
||||||
|
cur->nameURI = xmlStrdup(nameURI);
|
||||||
|
cur->nsList = NULL;
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeKeyDef:
|
||||||
|
* @keyd: an XSLT key definition
|
||||||
|
*
|
||||||
|
* Free up the memory allocated by @keyd
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xsltFreeKeyDef(xsltKeyDefPtr keyd) {
|
||||||
|
if (keyd == NULL)
|
||||||
|
return;
|
||||||
|
if (keyd->comp != NULL)
|
||||||
|
xmlXPathFreeCompExpr(keyd->comp);
|
||||||
|
if (keyd->usecomp != NULL)
|
||||||
|
xmlXPathFreeCompExpr(keyd->usecomp);
|
||||||
|
if (keyd->name != NULL)
|
||||||
|
xmlFree(keyd->name);
|
||||||
|
if (keyd->nameURI != NULL)
|
||||||
|
xmlFree(keyd->nameURI);
|
||||||
|
if (keyd->match != NULL)
|
||||||
|
xmlFree(keyd->match);
|
||||||
|
if (keyd->use != NULL)
|
||||||
|
xmlFree(keyd->use);
|
||||||
|
if (keyd->nsList != NULL)
|
||||||
|
xmlFree(keyd->nsList);
|
||||||
|
memset(keyd, -1, sizeof(xsltKeyDef));
|
||||||
|
xmlFree(keyd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeKeyDefList:
|
||||||
|
* @keyd: an XSLT key definition list
|
||||||
|
*
|
||||||
|
* Free up the memory allocated by all the elements of @keyd
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xsltFreeKeyDefList(xsltKeyDefPtr keyd) {
|
||||||
|
xsltKeyDefPtr cur;
|
||||||
|
|
||||||
|
while (keyd != NULL) {
|
||||||
|
cur = keyd;
|
||||||
|
keyd = keyd->next;
|
||||||
|
xsltFreeKeyDef(cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNewKeyTable:
|
||||||
|
* @name: the key name or NULL
|
||||||
|
* @nameURI: the name URI or NULL
|
||||||
|
*
|
||||||
|
* Create a new XSLT KeyTable
|
||||||
|
*
|
||||||
|
* Returns the newly allocated xsltKeyTablePtr or NULL in case of error
|
||||||
|
*/
|
||||||
|
static xsltKeyTablePtr
|
||||||
|
xsltNewKeyTable(const xmlChar *name, const xmlChar *nameURI) {
|
||||||
|
xsltKeyTablePtr cur;
|
||||||
|
|
||||||
|
cur = (xsltKeyTablePtr) xmlMalloc(sizeof(xsltKeyTable));
|
||||||
|
if (cur == NULL) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL,
|
||||||
|
"xsltNewKeyTable : malloc failed\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(cur, 0, sizeof(xsltKeyTable));
|
||||||
|
if (name != NULL)
|
||||||
|
cur->name = xmlStrdup(name);
|
||||||
|
if (nameURI != NULL)
|
||||||
|
cur->nameURI = xmlStrdup(nameURI);
|
||||||
|
cur->keys = xmlHashCreate(0);
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xsltFreeNodeSetEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
|
||||||
|
xmlXPathFreeNodeSet((xmlNodeSetPtr) payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeKeyTable:
|
||||||
|
* @keyt: an XSLT key table
|
||||||
|
*
|
||||||
|
* Free up the memory allocated by @keyt
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xsltFreeKeyTable(xsltKeyTablePtr keyt) {
|
||||||
|
if (keyt == NULL)
|
||||||
|
return;
|
||||||
|
if (keyt->name != NULL)
|
||||||
|
xmlFree(keyt->name);
|
||||||
|
if (keyt->nameURI != NULL)
|
||||||
|
xmlFree(keyt->nameURI);
|
||||||
|
if (keyt->keys != NULL)
|
||||||
|
xmlHashFree(keyt->keys, xsltFreeNodeSetEntry);
|
||||||
|
memset(keyt, -1, sizeof(xsltKeyTable));
|
||||||
|
xmlFree(keyt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeKeyTableList:
|
||||||
|
* @keyt: an XSLT key table list
|
||||||
|
*
|
||||||
|
* Free up the memory allocated by all the elements of @keyt
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xsltFreeKeyTableList(xsltKeyTablePtr keyt) {
|
||||||
|
xsltKeyTablePtr cur;
|
||||||
|
|
||||||
|
while (keyt != NULL) {
|
||||||
|
cur = keyt;
|
||||||
|
keyt = keyt->next;
|
||||||
|
xsltFreeKeyTable(cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* The interpreter for the precompiled patterns *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeKeys:
|
||||||
|
* @style: an XSLT stylesheet
|
||||||
|
*
|
||||||
|
* Free up the memory used by XSLT keys in a stylesheet
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeKeys(xsltStylesheetPtr style) {
|
||||||
|
if (style->keys)
|
||||||
|
xsltFreeKeyDefList((xsltKeyDefPtr) style->keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* skipString:
|
||||||
|
* @cur: the current pointer
|
||||||
|
* @end: the current offset
|
||||||
|
*
|
||||||
|
* skip a string delimited by " or '
|
||||||
|
*
|
||||||
|
* Returns the byte after the string or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
skipString(const xmlChar *cur, int end) {
|
||||||
|
xmlChar limit;
|
||||||
|
|
||||||
|
if ((cur == NULL) || (end < 0)) return(-1);
|
||||||
|
if ((cur[end] == '\'') || (cur[end] == '"')) limit = cur[end];
|
||||||
|
else return(end);
|
||||||
|
end++;
|
||||||
|
while (cur[end] != 0) {
|
||||||
|
if (cur[end] == limit)
|
||||||
|
return(end + 1);
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* skipPredicate:
|
||||||
|
* @cur: the current pointer
|
||||||
|
* @end: the current offset
|
||||||
|
*
|
||||||
|
* skip a predicate
|
||||||
|
*
|
||||||
|
* Returns the byte after the predicate or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
skipPredicate(const xmlChar *cur, int end) {
|
||||||
|
int level = 0;
|
||||||
|
|
||||||
|
if ((cur == NULL) || (end < 0)) return(-1);
|
||||||
|
if (cur[end] != '[') return(end);
|
||||||
|
end++;
|
||||||
|
while (cur[end] != 0) {
|
||||||
|
if ((cur[end] == '\'') || (cur[end] == '"')) {
|
||||||
|
end = skipString(cur, end);
|
||||||
|
if (end <= 0)
|
||||||
|
return(-1);
|
||||||
|
continue;
|
||||||
|
} else if (cur[end] == '[') {
|
||||||
|
level += 1;
|
||||||
|
} else if (cur[end] == ']') {
|
||||||
|
if (level == 0)
|
||||||
|
return(end + 1);
|
||||||
|
level -= 1;
|
||||||
|
}
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltAddKey:
|
||||||
|
* @style: an XSLT stylesheet
|
||||||
|
* @name: the key name or NULL
|
||||||
|
* @nameURI: the name URI or NULL
|
||||||
|
* @match: the match value
|
||||||
|
* @use: the use value
|
||||||
|
* @inst: the key instruction
|
||||||
|
*
|
||||||
|
* add a key definition to a stylesheet
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success, and -1 in case of failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltAddKey(xsltStylesheetPtr style, const xmlChar *name,
|
||||||
|
const xmlChar *nameURI, const xmlChar *match,
|
||||||
|
const xmlChar *use, xmlNodePtr inst) {
|
||||||
|
xsltKeyDefPtr key;
|
||||||
|
xmlChar *pattern = NULL;
|
||||||
|
int current, end, start, i = 0;
|
||||||
|
|
||||||
|
if ((style == NULL) || (name == NULL) || (match == NULL) || (use == NULL))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Add key %s, match %s, use %s\n", name, match, use);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
key = xsltNewKeyDef(name, nameURI);
|
||||||
|
key->match = xmlStrdup(match);
|
||||||
|
key->use = xmlStrdup(use);
|
||||||
|
key->inst = inst;
|
||||||
|
key->nsList = xmlGetNsList(inst->doc, inst);
|
||||||
|
if (key->nsList != NULL) {
|
||||||
|
while (key->nsList[i] != NULL)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
key->nsNr = i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split the | and register it as as many keys
|
||||||
|
*/
|
||||||
|
current = end = 0;
|
||||||
|
while (match[current] != 0) {
|
||||||
|
start = current;
|
||||||
|
while (IS_BLANK_CH(match[current]))
|
||||||
|
current++;
|
||||||
|
end = current;
|
||||||
|
while ((match[end] != 0) && (match[end] != '|')) {
|
||||||
|
if (match[end] == '[') {
|
||||||
|
end = skipPredicate(match, end);
|
||||||
|
if (end <= 0) {
|
||||||
|
xsltTransformError(NULL, style, inst,
|
||||||
|
"xsl:key : 'match' pattern is malformed: %s",
|
||||||
|
key->match);
|
||||||
|
if (style != NULL) style->errors++;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
if (current == end) {
|
||||||
|
xsltTransformError(NULL, style, inst,
|
||||||
|
"xsl:key : 'match' pattern is empty\n");
|
||||||
|
if (style != NULL) style->errors++;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (match[start] != '/') {
|
||||||
|
pattern = xmlStrcat(pattern, (xmlChar *)"//");
|
||||||
|
if (pattern == NULL) {
|
||||||
|
if (style != NULL) style->errors++;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pattern = xmlStrncat(pattern, &match[start], end - start);
|
||||||
|
if (pattern == NULL) {
|
||||||
|
if (style != NULL) style->errors++;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match[end] == '|') {
|
||||||
|
pattern = xmlStrcat(pattern, (xmlChar *)"|");
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
current = end;
|
||||||
|
}
|
||||||
|
if (pattern == NULL) {
|
||||||
|
xsltTransformError(NULL, style, inst,
|
||||||
|
"xsl:key : 'match' pattern is empty\n");
|
||||||
|
if (style != NULL) style->errors++;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
" resulting pattern %s\n", pattern);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* XSLT-1: "It is an error for the value of either the use
|
||||||
|
* attribute or the match attribute to contain a
|
||||||
|
* VariableReference."
|
||||||
|
* TODO: We should report a variable-reference at compile-time.
|
||||||
|
* Maybe a search for "$", if it occurs outside of quotation
|
||||||
|
* marks, could be sufficient.
|
||||||
|
*/
|
||||||
|
#ifdef XML_XPATH_NOVAR
|
||||||
|
key->comp = xsltXPathCompileFlags(style, pattern, XML_XPATH_NOVAR);
|
||||||
|
#else
|
||||||
|
key->comp = xsltXPathCompile(style, pattern);
|
||||||
|
#endif
|
||||||
|
if (key->comp == NULL) {
|
||||||
|
xsltTransformError(NULL, style, inst,
|
||||||
|
"xsl:key : 'match' pattern compilation failed '%s'\n",
|
||||||
|
pattern);
|
||||||
|
if (style != NULL) style->errors++;
|
||||||
|
}
|
||||||
|
#ifdef XML_XPATH_NOVAR
|
||||||
|
key->usecomp = xsltXPathCompileFlags(style, use, XML_XPATH_NOVAR);
|
||||||
|
#else
|
||||||
|
key->usecomp = xsltXPathCompile(style, use);
|
||||||
|
#endif
|
||||||
|
if (key->usecomp == NULL) {
|
||||||
|
xsltTransformError(NULL, style, inst,
|
||||||
|
"xsl:key : 'use' expression compilation failed '%s'\n",
|
||||||
|
use);
|
||||||
|
if (style != NULL) style->errors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sometimes the stylesheet writer use the order to ease the
|
||||||
|
* resolution of keys when they are dependant, keep the provided
|
||||||
|
* order so add the new one at the end.
|
||||||
|
*/
|
||||||
|
if (style->keys == NULL) {
|
||||||
|
style->keys = key;
|
||||||
|
} else {
|
||||||
|
xsltKeyDefPtr prev = style->keys;
|
||||||
|
|
||||||
|
while (prev->next != NULL)
|
||||||
|
prev = prev->next;
|
||||||
|
|
||||||
|
prev->next = key;
|
||||||
|
}
|
||||||
|
key->next = NULL;
|
||||||
|
key = NULL;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (pattern != NULL)
|
||||||
|
xmlFree(pattern);
|
||||||
|
if (key != NULL)
|
||||||
|
xsltFreeKeyDef(key);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltGetKey:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @name: the key name or NULL
|
||||||
|
* @nameURI: the name URI or NULL
|
||||||
|
* @value: the key value to look for
|
||||||
|
*
|
||||||
|
* Looks up a key of the in current source doc (the document info
|
||||||
|
* on @ctxt->document). Computes the key if not already done
|
||||||
|
* for the current source doc.
|
||||||
|
*
|
||||||
|
* Returns the nodeset resulting from the query or NULL
|
||||||
|
*/
|
||||||
|
xmlNodeSetPtr
|
||||||
|
xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||||
|
const xmlChar *nameURI, const xmlChar *value) {
|
||||||
|
xmlNodeSetPtr ret;
|
||||||
|
xsltKeyTablePtr table;
|
||||||
|
int init_table = 0;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (name == NULL) || (value == NULL) ||
|
||||||
|
(ctxt->document == NULL))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Get key %s, value %s\n", name, value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* keys are computed only on-demand on first key access for a document
|
||||||
|
*/
|
||||||
|
if ((ctxt->document->nbKeysComputed < ctxt->nbKeys) &&
|
||||||
|
(ctxt->keyInitLevel == 0)) {
|
||||||
|
/*
|
||||||
|
* If non-recursive behaviour, just try to initialize all keys
|
||||||
|
*/
|
||||||
|
if (xsltInitAllDocKeys(ctxt))
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
retry:
|
||||||
|
table = (xsltKeyTablePtr) ctxt->document->keys;
|
||||||
|
while (table != NULL) {
|
||||||
|
if (((nameURI != NULL) == (table->nameURI != NULL)) &&
|
||||||
|
xmlStrEqual(table->name, name) &&
|
||||||
|
xmlStrEqual(table->nameURI, nameURI))
|
||||||
|
{
|
||||||
|
ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
table = table->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ctxt->keyInitLevel != 0) && (init_table == 0)) {
|
||||||
|
/*
|
||||||
|
* Apparently one key is recursive and this one is needed,
|
||||||
|
* initialize just it, that time and retry
|
||||||
|
*/
|
||||||
|
xsltInitDocKeyTable(ctxt, name, nameURI);
|
||||||
|
init_table = 1;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltInitDocKeyTable:
|
||||||
|
*
|
||||||
|
* INTERNAL ROUTINE ONLY
|
||||||
|
*
|
||||||
|
* Check if any keys on the current document need to be computed
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xsltInitDocKeyTable(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||||
|
const xmlChar *nameURI)
|
||||||
|
{
|
||||||
|
xsltStylesheetPtr style;
|
||||||
|
xsltKeyDefPtr keyd = NULL;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
#ifdef KEY_INIT_DEBUG
|
||||||
|
fprintf(stderr, "xsltInitDocKeyTable %s\n", name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
style = ctxt->style;
|
||||||
|
while (style != NULL) {
|
||||||
|
keyd = (xsltKeyDefPtr) style->keys;
|
||||||
|
while (keyd != NULL) {
|
||||||
|
if (((keyd->nameURI != NULL) ==
|
||||||
|
(nameURI != NULL)) &&
|
||||||
|
xmlStrEqual(keyd->name, name) &&
|
||||||
|
xmlStrEqual(keyd->nameURI, nameURI))
|
||||||
|
{
|
||||||
|
xsltInitCtxtKey(ctxt, ctxt->document, keyd);
|
||||||
|
if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
|
||||||
|
return(0);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
keyd = keyd->next;
|
||||||
|
}
|
||||||
|
style = xsltNextImport(style);
|
||||||
|
}
|
||||||
|
if (found == 0) {
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltInitDocKeyTable: did not found %s\n", name));
|
||||||
|
#endif
|
||||||
|
xsltTransformError(ctxt, NULL, keyd? keyd->inst : NULL,
|
||||||
|
"Failed to find key definition for %s\n", name);
|
||||||
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
#ifdef KEY_INIT_DEBUG
|
||||||
|
fprintf(stderr, "xsltInitDocKeyTable %s done\n", name);
|
||||||
|
#endif
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltInitAllDocKeys:
|
||||||
|
* @ctxt: transformation context
|
||||||
|
*
|
||||||
|
* INTERNAL ROUTINE ONLY
|
||||||
|
*
|
||||||
|
* Check if any keys on the current document need to be computed
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success, -1 in case of failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltInitAllDocKeys(xsltTransformContextPtr ctxt)
|
||||||
|
{
|
||||||
|
xsltStylesheetPtr style;
|
||||||
|
xsltKeyDefPtr keyd;
|
||||||
|
xsltKeyTablePtr table;
|
||||||
|
|
||||||
|
if (ctxt == NULL)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
#ifdef KEY_INIT_DEBUG
|
||||||
|
fprintf(stderr, "xsltInitAllDocKeys %d %d\n",
|
||||||
|
ctxt->document->nbKeysComputed, ctxt->nbKeys);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: This could be further optimized
|
||||||
|
*/
|
||||||
|
style = ctxt->style;
|
||||||
|
while (style) {
|
||||||
|
keyd = (xsltKeyDefPtr) style->keys;
|
||||||
|
while (keyd != NULL) {
|
||||||
|
#ifdef KEY_INIT_DEBUG
|
||||||
|
fprintf(stderr, "Init key %s\n", keyd->name);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Check if keys with this QName have been already
|
||||||
|
* computed.
|
||||||
|
*/
|
||||||
|
table = (xsltKeyTablePtr) ctxt->document->keys;
|
||||||
|
while (table) {
|
||||||
|
if (((keyd->nameURI != NULL) == (table->nameURI != NULL)) &&
|
||||||
|
xmlStrEqual(keyd->name, table->name) &&
|
||||||
|
xmlStrEqual(keyd->nameURI, table->nameURI))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
table = table->next;
|
||||||
|
}
|
||||||
|
if (table == NULL) {
|
||||||
|
/*
|
||||||
|
* Keys with this QName have not been yet computed.
|
||||||
|
*/
|
||||||
|
xsltInitDocKeyTable(ctxt, keyd->name, keyd->nameURI);
|
||||||
|
}
|
||||||
|
keyd = keyd->next;
|
||||||
|
}
|
||||||
|
style = xsltNextImport(style);
|
||||||
|
}
|
||||||
|
#ifdef KEY_INIT_DEBUG
|
||||||
|
fprintf(stderr, "xsltInitAllDocKeys: done\n");
|
||||||
|
#endif
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltInitCtxtKey:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @idoc: the document information (holds key values)
|
||||||
|
* @keyDef: the key definition
|
||||||
|
*
|
||||||
|
* Computes the key tables this key and for the current input document.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc,
|
||||||
|
xsltKeyDefPtr keyDef)
|
||||||
|
{
|
||||||
|
int i, len, k;
|
||||||
|
xmlNodeSetPtr matchList = NULL, keylist;
|
||||||
|
xmlXPathObjectPtr matchRes = NULL, useRes = NULL;
|
||||||
|
xmlChar *str = NULL;
|
||||||
|
xsltKeyTablePtr table;
|
||||||
|
xmlNodePtr oldInst, cur;
|
||||||
|
xmlNodePtr oldContextNode;
|
||||||
|
xsltDocumentPtr oldDocInfo;
|
||||||
|
int oldXPPos, oldXPSize;
|
||||||
|
xmlNodePtr oldXPNode;
|
||||||
|
xmlDocPtr oldXPDoc;
|
||||||
|
int oldXPNsNr;
|
||||||
|
xmlNsPtr *oldXPNamespaces;
|
||||||
|
xmlXPathContextPtr xpctxt;
|
||||||
|
|
||||||
|
#ifdef KEY_INIT_DEBUG
|
||||||
|
fprintf(stderr, "xsltInitCtxtKey %s : %d\n", keyDef->name, ctxt->keyInitLevel);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((keyDef->comp == NULL) || (keyDef->usecomp == NULL))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detect recursive keys
|
||||||
|
*/
|
||||||
|
if (ctxt->keyInitLevel > ctxt->nbKeys) {
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltInitCtxtKey: key definition of %s is recursive\n",
|
||||||
|
keyDef->name));
|
||||||
|
#endif
|
||||||
|
xsltTransformError(ctxt, NULL, keyDef->inst,
|
||||||
|
"Key definition for %s is recursive\n", keyDef->name);
|
||||||
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
ctxt->keyInitLevel++;
|
||||||
|
|
||||||
|
xpctxt = ctxt->xpathCtxt;
|
||||||
|
idoc->nbKeysComputed++;
|
||||||
|
/*
|
||||||
|
* Save context state.
|
||||||
|
*/
|
||||||
|
oldInst = ctxt->inst;
|
||||||
|
oldDocInfo = ctxt->document;
|
||||||
|
oldContextNode = ctxt->node;
|
||||||
|
|
||||||
|
oldXPNode = xpctxt->node;
|
||||||
|
oldXPDoc = xpctxt->doc;
|
||||||
|
oldXPPos = xpctxt->proximityPosition;
|
||||||
|
oldXPSize = xpctxt->contextSize;
|
||||||
|
oldXPNsNr = xpctxt->nsNr;
|
||||||
|
oldXPNamespaces = xpctxt->namespaces;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up contexts.
|
||||||
|
*/
|
||||||
|
ctxt->document = idoc;
|
||||||
|
ctxt->node = (xmlNodePtr) idoc->doc;
|
||||||
|
ctxt->inst = keyDef->inst;
|
||||||
|
|
||||||
|
xpctxt->doc = idoc->doc;
|
||||||
|
xpctxt->node = (xmlNodePtr) idoc->doc;
|
||||||
|
/* TODO : clarify the use of namespaces in keys evaluation */
|
||||||
|
xpctxt->namespaces = keyDef->nsList;
|
||||||
|
xpctxt->nsNr = keyDef->nsNr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Evaluate the 'match' expression of the xsl:key.
|
||||||
|
* TODO: The 'match' is a *pattern*.
|
||||||
|
*/
|
||||||
|
matchRes = xmlXPathCompiledEval(keyDef->comp, xpctxt);
|
||||||
|
if (matchRes == NULL) {
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltInitCtxtKey: %s evaluation failed\n", keyDef->match));
|
||||||
|
#endif
|
||||||
|
xsltTransformError(ctxt, NULL, keyDef->inst,
|
||||||
|
"Failed to evaluate the 'match' expression.\n");
|
||||||
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
if (matchRes->type == XPATH_NODESET) {
|
||||||
|
matchList = matchRes->nodesetval;
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
if (matchList != NULL)
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltInitCtxtKey: %s evaluates to %d nodes\n",
|
||||||
|
keyDef->match, matchList->nodeNr));
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Is not a node set, but must be.
|
||||||
|
*/
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltInitCtxtKey: %s is not a node set\n", keyDef->match));
|
||||||
|
#endif
|
||||||
|
xsltTransformError(ctxt, NULL, keyDef->inst,
|
||||||
|
"The 'match' expression did not evaluate to a node set.\n");
|
||||||
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((matchList == NULL) || (matchList->nodeNr <= 0))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiple key definitions for the same name are allowed, so
|
||||||
|
* we must check if the key is already present for this doc
|
||||||
|
*/
|
||||||
|
table = (xsltKeyTablePtr) idoc->keys;
|
||||||
|
while (table != NULL) {
|
||||||
|
if (xmlStrEqual(table->name, keyDef->name) &&
|
||||||
|
(((keyDef->nameURI == NULL) && (table->nameURI == NULL)) ||
|
||||||
|
((keyDef->nameURI != NULL) && (table->nameURI != NULL) &&
|
||||||
|
(xmlStrEqual(table->nameURI, keyDef->nameURI)))))
|
||||||
|
break;
|
||||||
|
table = table->next;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* If the key was not previously defined, create it now and
|
||||||
|
* chain it to the list of keys for the doc
|
||||||
|
*/
|
||||||
|
if (table == NULL) {
|
||||||
|
table = xsltNewKeyTable(keyDef->name, keyDef->nameURI);
|
||||||
|
if (table == NULL)
|
||||||
|
goto error;
|
||||||
|
table->next = idoc->keys;
|
||||||
|
idoc->keys = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SPEC XSLT 1.0 (XSLT 2.0 does not clarify the context size!)
|
||||||
|
* "...the use attribute of the xsl:key element is evaluated with x as
|
||||||
|
" the current node and with a node list containing just x as the
|
||||||
|
* current node list"
|
||||||
|
*/
|
||||||
|
xpctxt->contextSize = 1;
|
||||||
|
xpctxt->proximityPosition = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < matchList->nodeNr; i++) {
|
||||||
|
cur = matchList->nodeTab[i];
|
||||||
|
if (! IS_XSLT_REAL_NODE(cur))
|
||||||
|
continue;
|
||||||
|
ctxt->node = cur;
|
||||||
|
xpctxt->node = cur;
|
||||||
|
/*
|
||||||
|
* Process the 'use' of the xsl:key.
|
||||||
|
* SPEC XSLT 1.0:
|
||||||
|
* "The use attribute is an expression specifying the values of
|
||||||
|
* the key; the expression is evaluated once for each node that
|
||||||
|
* matches the pattern."
|
||||||
|
*/
|
||||||
|
if (useRes != NULL)
|
||||||
|
xmlXPathFreeObject(useRes);
|
||||||
|
useRes = xmlXPathCompiledEval(keyDef->usecomp, xpctxt);
|
||||||
|
if (useRes == NULL) {
|
||||||
|
xsltTransformError(ctxt, NULL, keyDef->inst,
|
||||||
|
"Failed to evaluate the 'use' expression.\n");
|
||||||
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (useRes->type == XPATH_NODESET) {
|
||||||
|
if ((useRes->nodesetval != NULL) &&
|
||||||
|
(useRes->nodesetval->nodeNr != 0))
|
||||||
|
{
|
||||||
|
len = useRes->nodesetval->nodeNr;
|
||||||
|
str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[0]);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
len = 1;
|
||||||
|
if (useRes->type == XPATH_STRING) {
|
||||||
|
/*
|
||||||
|
* Consume the string value.
|
||||||
|
*/
|
||||||
|
str = useRes->stringval;
|
||||||
|
useRes->stringval = NULL;
|
||||||
|
} else {
|
||||||
|
str = xmlXPathCastToString(useRes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Process all strings.
|
||||||
|
*/
|
||||||
|
k = 0;
|
||||||
|
while (1) {
|
||||||
|
if (str == NULL)
|
||||||
|
goto next_string;
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsl:key : node associated to ('%s', '%s')\n", keyDef->name, str));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
keylist = xmlHashLookup(table->keys, str);
|
||||||
|
if (keylist == NULL) {
|
||||||
|
keylist = xmlXPathNodeSetCreate(cur);
|
||||||
|
if (keylist == NULL)
|
||||||
|
goto error;
|
||||||
|
xmlHashAddEntry(table->keys, str, keylist);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* TODO: How do we know if this function failed?
|
||||||
|
*/
|
||||||
|
xmlXPathNodeSetAdd(keylist, cur);
|
||||||
|
}
|
||||||
|
switch (cur->type) {
|
||||||
|
case XML_ELEMENT_NODE:
|
||||||
|
case XML_TEXT_NODE:
|
||||||
|
case XML_CDATA_SECTION_NODE:
|
||||||
|
case XML_PI_NODE:
|
||||||
|
case XML_COMMENT_NODE:
|
||||||
|
cur->psvi = keyDef;
|
||||||
|
break;
|
||||||
|
case XML_ATTRIBUTE_NODE:
|
||||||
|
((xmlAttrPtr) cur)->psvi = keyDef;
|
||||||
|
break;
|
||||||
|
case XML_DOCUMENT_NODE:
|
||||||
|
case XML_HTML_DOCUMENT_NODE:
|
||||||
|
((xmlDocPtr) cur)->psvi = keyDef;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xmlFree(str);
|
||||||
|
str = NULL;
|
||||||
|
|
||||||
|
next_string:
|
||||||
|
k++;
|
||||||
|
if (k >= len)
|
||||||
|
break;
|
||||||
|
str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
error:
|
||||||
|
ctxt->keyInitLevel--;
|
||||||
|
/*
|
||||||
|
* Restore context state.
|
||||||
|
*/
|
||||||
|
xpctxt->node = oldXPNode;
|
||||||
|
xpctxt->doc = oldXPDoc;
|
||||||
|
xpctxt->nsNr = oldXPNsNr;
|
||||||
|
xpctxt->namespaces = oldXPNamespaces;
|
||||||
|
xpctxt->proximityPosition = oldXPPos;
|
||||||
|
xpctxt->contextSize = oldXPSize;
|
||||||
|
|
||||||
|
ctxt->node = oldContextNode;
|
||||||
|
ctxt->document = oldDocInfo;
|
||||||
|
ctxt->inst = oldInst;
|
||||||
|
|
||||||
|
if (str)
|
||||||
|
xmlFree(str);
|
||||||
|
if (useRes != NULL)
|
||||||
|
xmlXPathFreeObject(useRes);
|
||||||
|
if (matchRes != NULL)
|
||||||
|
xmlXPathFreeObject(matchRes);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltInitCtxtKeys:
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @idoc: a document info
|
||||||
|
*
|
||||||
|
* Computes all the keys tables for the current input document.
|
||||||
|
* Should be done before global varibales are initialized.
|
||||||
|
* NOTE: Not used anymore in the refactored code.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltInitCtxtKeys(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc) {
|
||||||
|
xsltStylesheetPtr style;
|
||||||
|
xsltKeyDefPtr keyDef;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (idoc == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef KEY_INIT_DEBUG
|
||||||
|
fprintf(stderr, "xsltInitCtxtKeys on document\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG_KEYS
|
||||||
|
if ((idoc->doc != NULL) && (idoc->doc->URL != NULL))
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n",
|
||||||
|
idoc->doc->URL));
|
||||||
|
#endif
|
||||||
|
style = ctxt->style;
|
||||||
|
while (style != NULL) {
|
||||||
|
keyDef = (xsltKeyDefPtr) style->keys;
|
||||||
|
while (keyDef != NULL) {
|
||||||
|
xsltInitCtxtKey(ctxt, idoc, keyDef);
|
||||||
|
|
||||||
|
keyDef = keyDef->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
style = xsltNextImport(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef KEY_INIT_DEBUG
|
||||||
|
fprintf(stderr, "xsltInitCtxtKeys on document: done\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeDocumentKeys:
|
||||||
|
* @idoc: a XSLT document
|
||||||
|
*
|
||||||
|
* Free the keys associated to a document
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeDocumentKeys(xsltDocumentPtr idoc) {
|
||||||
|
if (idoc != NULL)
|
||||||
|
xsltFreeKeyTableList(idoc->keys);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the key matching used in key() and template matches.
|
||||||
|
* Description: implementation of the key mechanims.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_KEY_H__
|
||||||
|
#define __XML_XSLT_KEY_H__
|
||||||
|
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NODE_IS_KEYED:
|
||||||
|
*
|
||||||
|
* check for bit 15 set
|
||||||
|
*/
|
||||||
|
#define NODE_IS_KEYED (1 >> 15)
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltAddKey (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *nameURI,
|
||||||
|
const xmlChar *match,
|
||||||
|
const xmlChar *use,
|
||||||
|
xmlNodePtr inst);
|
||||||
|
XSLTPUBFUN xmlNodeSetPtr XSLTCALL
|
||||||
|
xsltGetKey (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *nameURI,
|
||||||
|
const xmlChar *value);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltInitCtxtKeys (xsltTransformContextPtr ctxt,
|
||||||
|
xsltDocumentPtr doc);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeKeys (xsltStylesheetPtr style);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeDocumentKeys (xsltDocumentPtr doc);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_H__ */
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Summary: internal header only used during the compilation of libxslt
|
||||||
|
* Description: internal header only used during the compilation of libxslt
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XSLT_LIBXSLT_H__
|
||||||
|
#define __XSLT_LIBXSLT_H__
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <win32config.h>
|
||||||
|
#else
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <libxslt/xsltconfig.h>
|
||||||
|
#include <libxml/xmlversion.h>
|
||||||
|
|
||||||
|
#if !defined LIBXSLT_PUBLIC
|
||||||
|
#if (defined (__CYGWIN__) || defined _MSC_VER) && !defined IN_LIBXSLT && !defined LIBXSLT_STATIC
|
||||||
|
#define LIBXSLT_PUBLIC __declspec(dllimport)
|
||||||
|
#else
|
||||||
|
#define LIBXSLT_PUBLIC
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <io.h>
|
||||||
|
#include <direct.h>
|
||||||
|
#define mkdir(p,m) _mkdir(p)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ! __XSLT_LIBXSLT_H__ */
|
|
@ -0,0 +1,853 @@
|
||||||
|
/*
|
||||||
|
* namespaces.c: Implementation of the XSLT namespaces handling
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* http://www.w3.org/TR/1999/REC-xslt-19991116
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* daniel@veillard.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IN_LIBXSLT
|
||||||
|
#include "libxslt.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_MATH_H
|
||||||
|
#include <math.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FLOAT_H
|
||||||
|
#include <float.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_IEEEFP_H
|
||||||
|
#include <ieeefp.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NAN_H
|
||||||
|
#include <nan.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
#ifndef XSLT_NEED_TRIO
|
||||||
|
#include <stdio.h>
|
||||||
|
#else
|
||||||
|
#include <trio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/hash.h>
|
||||||
|
#include <libxml/xmlerror.h>
|
||||||
|
#include <libxml/uri.h>
|
||||||
|
#include "xslt.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "xsltutils.h"
|
||||||
|
#include "namespaces.h"
|
||||||
|
#include "imports.h"
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Module interfaces *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#ifdef XSLT_REFACTORED
|
||||||
|
static xsltNsAliasPtr
|
||||||
|
xsltNewNsAlias(xsltCompilerCtxtPtr cctxt)
|
||||||
|
{
|
||||||
|
xsltNsAliasPtr ret;
|
||||||
|
|
||||||
|
if (cctxt == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
ret = (xsltNsAliasPtr) xmlMalloc(sizeof(xsltNsAlias));
|
||||||
|
if (ret == NULL) {
|
||||||
|
xsltTransformError(NULL, cctxt->style, NULL,
|
||||||
|
"Internal error in xsltNewNsAlias(): Memory allocation failed.\n");
|
||||||
|
cctxt->style->errors++;
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(ret, 0, sizeof(xsltNsAlias));
|
||||||
|
/*
|
||||||
|
* TODO: Store the item at current stylesheet-level.
|
||||||
|
*/
|
||||||
|
ret->next = cctxt->nsAliases;
|
||||||
|
cctxt->nsAliases = ret;
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
#endif /* XSLT_REFACTORED */
|
||||||
|
/**
|
||||||
|
* xsltNamespaceAlias:
|
||||||
|
* @style: the XSLT stylesheet
|
||||||
|
* @node: the xsl:namespace-alias node
|
||||||
|
*
|
||||||
|
* Read the stylesheet-prefix and result-prefix attributes, register
|
||||||
|
* them as well as the corresponding namespace.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node)
|
||||||
|
{
|
||||||
|
xmlChar *resultPrefix = NULL;
|
||||||
|
xmlChar *stylePrefix = NULL;
|
||||||
|
xmlNsPtr literalNs = NULL;
|
||||||
|
xmlNsPtr targetNs = NULL;
|
||||||
|
|
||||||
|
#ifdef XSLT_REFACTORED
|
||||||
|
xsltNsAliasPtr alias;
|
||||||
|
|
||||||
|
if ((style == NULL) || (node == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SPEC XSLT 1.0:
|
||||||
|
* "If a namespace URI is declared to be an alias for multiple
|
||||||
|
* different namespace URIs, then the declaration with the highest
|
||||||
|
* import precedence is used. It is an error if there is more than
|
||||||
|
* one such declaration. An XSLT processor may signal the error;
|
||||||
|
* if it does not signal the error, it must recover by choosing,
|
||||||
|
* from amongst the declarations with the highest import precedence,
|
||||||
|
* the one that occurs last in the stylesheet."
|
||||||
|
*
|
||||||
|
* SPEC TODO: Check for the errors mentioned above.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* NOTE that the XSLT 2.0 also *does* use the NULL namespace if
|
||||||
|
* "#default" is used and there's no default namespace is scope.
|
||||||
|
* I.e., this is *not* an error.
|
||||||
|
* Most XSLT 1.0 implementations work this way.
|
||||||
|
* The XSLT 1.0 spec has nothing to say on the subject.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Attribute "stylesheet-prefix".
|
||||||
|
*/
|
||||||
|
stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL);
|
||||||
|
if (stylePrefix == NULL) {
|
||||||
|
xsltTransformError(NULL, style, node,
|
||||||
|
"The attribute 'stylesheet-prefix' is missing.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default"))
|
||||||
|
literalNs = xmlSearchNs(node->doc, node, NULL);
|
||||||
|
else {
|
||||||
|
literalNs = xmlSearchNs(node->doc, node, stylePrefix);
|
||||||
|
if (literalNs == NULL) {
|
||||||
|
xsltTransformError(NULL, style, node,
|
||||||
|
"Attribute 'stylesheet-prefix': There's no namespace "
|
||||||
|
"declaration in scope for the prefix '%s'.\n",
|
||||||
|
stylePrefix);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Attribute "result-prefix".
|
||||||
|
*/
|
||||||
|
resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL);
|
||||||
|
if (resultPrefix == NULL) {
|
||||||
|
xsltTransformError(NULL, style, node,
|
||||||
|
"The attribute 'result-prefix' is missing.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default"))
|
||||||
|
targetNs = xmlSearchNs(node->doc, node, NULL);
|
||||||
|
else {
|
||||||
|
targetNs = xmlSearchNs(node->doc, node, resultPrefix);
|
||||||
|
|
||||||
|
if (targetNs == NULL) {
|
||||||
|
xsltTransformError(NULL, style, node,
|
||||||
|
"Attribute 'result-prefix': There's no namespace "
|
||||||
|
"declaration in scope for the prefix '%s'.\n",
|
||||||
|
stylePrefix);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Same alias for multiple different target namespace URIs:
|
||||||
|
* TODO: The one with the highest import precedence is used.
|
||||||
|
* Example:
|
||||||
|
* <xsl:namespace-alias stylesheet-prefix="foo"
|
||||||
|
* result-prefix="bar"/>
|
||||||
|
*
|
||||||
|
* <xsl:namespace-alias stylesheet-prefix="foo"
|
||||||
|
* result-prefix="zar"/>
|
||||||
|
*
|
||||||
|
* Same target namespace URI for multiple different aliases:
|
||||||
|
* All alias-definitions will be used.
|
||||||
|
* Example:
|
||||||
|
* <xsl:namespace-alias stylesheet-prefix="bar"
|
||||||
|
* result-prefix="foo"/>
|
||||||
|
*
|
||||||
|
* <xsl:namespace-alias stylesheet-prefix="zar"
|
||||||
|
* result-prefix="foo"/>
|
||||||
|
* Cases using #default:
|
||||||
|
* <xsl:namespace-alias stylesheet-prefix="#default"
|
||||||
|
* result-prefix="#default"/>
|
||||||
|
* TODO: Has this an effect at all?
|
||||||
|
*
|
||||||
|
* <xsl:namespace-alias stylesheet-prefix="foo"
|
||||||
|
* result-prefix="#default"/>
|
||||||
|
* From namespace to no namespace.
|
||||||
|
*
|
||||||
|
* <xsl:namespace-alias stylesheet-prefix="#default"
|
||||||
|
* result-prefix="foo"/>
|
||||||
|
* From no namespace to namespace.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store the ns-node in the alias-object.
|
||||||
|
*/
|
||||||
|
alias = xsltNewNsAlias(XSLT_CCTXT(style));
|
||||||
|
if (alias == NULL)
|
||||||
|
return;
|
||||||
|
alias->literalNs = literalNs;
|
||||||
|
alias->targetNs = targetNs;
|
||||||
|
XSLT_CCTXT(style)->hasNsAliases = 1;
|
||||||
|
|
||||||
|
|
||||||
|
#else /* XSLT_REFACTORED */
|
||||||
|
const xmlChar *literalNsName;
|
||||||
|
const xmlChar *targetNsName;
|
||||||
|
|
||||||
|
|
||||||
|
if ((style == NULL) || (node == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL);
|
||||||
|
if (stylePrefix == NULL) {
|
||||||
|
xsltTransformError(NULL, style, node,
|
||||||
|
"namespace-alias: stylesheet-prefix attribute missing\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL);
|
||||||
|
if (resultPrefix == NULL) {
|
||||||
|
xsltTransformError(NULL, style, node,
|
||||||
|
"namespace-alias: result-prefix attribute missing\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default")) {
|
||||||
|
literalNs = xmlSearchNs(node->doc, node, NULL);
|
||||||
|
if (literalNs == NULL) {
|
||||||
|
literalNsName = NULL;
|
||||||
|
} else
|
||||||
|
literalNsName = literalNs->href; /* Yes - set for nsAlias table */
|
||||||
|
} else {
|
||||||
|
literalNs = xmlSearchNs(node->doc, node, stylePrefix);
|
||||||
|
|
||||||
|
if ((literalNs == NULL) || (literalNs->href == NULL)) {
|
||||||
|
xsltTransformError(NULL, style, node,
|
||||||
|
"namespace-alias: prefix %s not bound to any namespace\n",
|
||||||
|
stylePrefix);
|
||||||
|
goto error;
|
||||||
|
} else
|
||||||
|
literalNsName = literalNs->href;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When "#default" is used for result, if a default namespace has not
|
||||||
|
* been explicitly declared the special value UNDEFINED_DEFAULT_NS is
|
||||||
|
* put into the nsAliases table
|
||||||
|
*/
|
||||||
|
if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default")) {
|
||||||
|
targetNs = xmlSearchNs(node->doc, node, NULL);
|
||||||
|
if (targetNs == NULL) {
|
||||||
|
targetNsName = UNDEFINED_DEFAULT_NS;
|
||||||
|
} else
|
||||||
|
targetNsName = targetNs->href;
|
||||||
|
} else {
|
||||||
|
targetNs = xmlSearchNs(node->doc, node, resultPrefix);
|
||||||
|
|
||||||
|
if ((targetNs == NULL) || (targetNs->href == NULL)) {
|
||||||
|
xsltTransformError(NULL, style, node,
|
||||||
|
"namespace-alias: prefix %s not bound to any namespace\n",
|
||||||
|
resultPrefix);
|
||||||
|
goto error;
|
||||||
|
} else
|
||||||
|
targetNsName = targetNs->href;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Special case: if #default is used for
|
||||||
|
* the stylesheet-prefix (literal namespace) and there's no default
|
||||||
|
* namespace in scope, we'll use style->defaultAlias for this.
|
||||||
|
*/
|
||||||
|
if (literalNsName == NULL) {
|
||||||
|
if (targetNs != NULL) {
|
||||||
|
/*
|
||||||
|
* BUG TODO: Is it not sufficient to have only 1 field for
|
||||||
|
* this, since subsequently alias declarations will
|
||||||
|
* overwrite this.
|
||||||
|
* Example:
|
||||||
|
* <xsl:namespace-alias result-prefix="foo"
|
||||||
|
* stylesheet-prefix="#default"/>
|
||||||
|
* <xsl:namespace-alias result-prefix="bar"
|
||||||
|
* stylesheet-prefix="#default"/>
|
||||||
|
* The mapping for "foo" won't be visible anymore.
|
||||||
|
*/
|
||||||
|
style->defaultAlias = targetNs->href;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (style->nsAliases == NULL)
|
||||||
|
style->nsAliases = xmlHashCreate(10);
|
||||||
|
if (style->nsAliases == NULL) {
|
||||||
|
xsltTransformError(NULL, style, node,
|
||||||
|
"namespace-alias: cannot create hash table\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
xmlHashAddEntry((xmlHashTablePtr) style->nsAliases,
|
||||||
|
literalNsName, (void *) targetNsName);
|
||||||
|
}
|
||||||
|
#endif /* else of XSLT_REFACTORED */
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (stylePrefix != NULL)
|
||||||
|
xmlFree(stylePrefix);
|
||||||
|
if (resultPrefix != NULL)
|
||||||
|
xmlFree(resultPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltGetSpecialNamespace:
|
||||||
|
* @ctxt: the transformation context
|
||||||
|
* @invocNode: the invoking node; e.g. a literal result element/attr;
|
||||||
|
* only used for error reports
|
||||||
|
* @nsName: the namespace name (or NULL)
|
||||||
|
* @nsPrefix: the suggested namespace prefix (or NULL)
|
||||||
|
* @target: the result element on which to anchor a namespace
|
||||||
|
*
|
||||||
|
* Find a matching (prefix and ns-name) ns-declaration
|
||||||
|
* for the requested @nsName and @nsPrefix in the result tree.
|
||||||
|
* If none is found then a new ns-declaration will be
|
||||||
|
* added to @resultElem. If, in this case, the given prefix is
|
||||||
|
* already in use, then a ns-declaration with a modified ns-prefix
|
||||||
|
* be we created. Note that this function's priority is to
|
||||||
|
* preserve ns-prefixes; it will only change a prefix if there's
|
||||||
|
* a namespace clash.
|
||||||
|
* If both @nsName and @nsPrefix are NULL, then this will try to
|
||||||
|
* "undeclare" a default namespace by declaring an xmlns="".
|
||||||
|
*
|
||||||
|
* Returns a namespace declaration or NULL.
|
||||||
|
*/
|
||||||
|
xmlNsPtr
|
||||||
|
xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
|
||||||
|
const xmlChar *nsName, const xmlChar *nsPrefix,
|
||||||
|
xmlNodePtr target)
|
||||||
|
{
|
||||||
|
xmlNsPtr ns;
|
||||||
|
int prefixOccupied = 0;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (target == NULL) ||
|
||||||
|
(target->type != XML_ELEMENT_NODE))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: Namespace exclusion and ns-aliasing is performed at
|
||||||
|
* compilation-time in the refactored code; so this need not be done
|
||||||
|
* here (it was in the old code).
|
||||||
|
* NOTE: @invocNode was named @cur in the old code and was documented to
|
||||||
|
* be an input node; since it was only used to anchor an error report
|
||||||
|
* somewhere, we can safely change this to @invocNode, which now
|
||||||
|
* will be the XSLT instruction (also a literal result element/attribute),
|
||||||
|
* which was responsible for this call.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* OPTIMIZE TODO: This all could be optimized by keeping track of
|
||||||
|
* the ns-decls currently in-scope via a specialized context.
|
||||||
|
*/
|
||||||
|
if ((nsPrefix == NULL) && ((nsName == NULL) || (nsName[0] == 0))) {
|
||||||
|
/*
|
||||||
|
* NOTE: the "undeclaration" of the default namespace was
|
||||||
|
* part of the logic of the old xsltGetSpecialNamespace() code,
|
||||||
|
* so we'll keep that mechanism.
|
||||||
|
* Related to the old code: bug #302020:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* OPTIMIZE TODO: This all could be optimized by keeping track of
|
||||||
|
* the ns-decls currently in-scope via a specialized context.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Search on the result element itself.
|
||||||
|
*/
|
||||||
|
if (target->nsDef != NULL) {
|
||||||
|
ns = target->nsDef;
|
||||||
|
do {
|
||||||
|
if (ns->prefix == NULL) {
|
||||||
|
if ((ns->href != NULL) && (ns->href[0] != 0)) {
|
||||||
|
/*
|
||||||
|
* Raise a namespace normalization error.
|
||||||
|
*/
|
||||||
|
xsltTransformError(ctxt, NULL, invocNode,
|
||||||
|
"Namespace normalization error: Cannot undeclare "
|
||||||
|
"the default namespace, since the default namespace "
|
||||||
|
"'%s' is already declared on the result element "
|
||||||
|
"'%s'.\n", ns->href, target->name);
|
||||||
|
return(NULL);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* The default namespace was undeclared on the
|
||||||
|
* result element.
|
||||||
|
*/
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ns = ns->next;
|
||||||
|
} while (ns != NULL);
|
||||||
|
}
|
||||||
|
if ((target->parent != NULL) &&
|
||||||
|
(target->parent->type == XML_ELEMENT_NODE))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The parent element is in no namespace, so assume
|
||||||
|
* that there is no default namespace in scope.
|
||||||
|
*/
|
||||||
|
if (target->parent->ns == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
ns = xmlSearchNs(target->doc, target->parent,
|
||||||
|
NULL);
|
||||||
|
/*
|
||||||
|
* Fine if there's no default ns is scope, or if the
|
||||||
|
* default ns was undeclared.
|
||||||
|
*/
|
||||||
|
if ((ns == NULL) || (ns->href == NULL) || (ns->href[0] == 0))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Undeclare the default namespace.
|
||||||
|
*/
|
||||||
|
xmlNewNs(target, BAD_CAST "", NULL);
|
||||||
|
/* TODO: Check result */
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Handle the XML namespace.
|
||||||
|
* QUESTION: Is this faster than using xmlStrEqual() anyway?
|
||||||
|
*/
|
||||||
|
if ((nsPrefix != NULL) &&
|
||||||
|
(nsPrefix[0] == 'x') && (nsPrefix[1] == 'm') &&
|
||||||
|
(nsPrefix[2] == 'l') && (nsPrefix[3] == 0))
|
||||||
|
{
|
||||||
|
return(xmlSearchNs(target->doc, target, nsPrefix));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* First: search on the result element itself.
|
||||||
|
*/
|
||||||
|
if (target->nsDef != NULL) {
|
||||||
|
ns = target->nsDef;
|
||||||
|
do {
|
||||||
|
if ((ns->prefix == NULL) == (nsPrefix == NULL)) {
|
||||||
|
if (ns->prefix == nsPrefix) {
|
||||||
|
if (xmlStrEqual(ns->href, nsName))
|
||||||
|
return(ns);
|
||||||
|
prefixOccupied = 1;
|
||||||
|
break;
|
||||||
|
} else if (xmlStrEqual(ns->prefix, nsPrefix)) {
|
||||||
|
if (xmlStrEqual(ns->href, nsName))
|
||||||
|
return(ns);
|
||||||
|
prefixOccupied = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ns = ns->next;
|
||||||
|
} while (ns != NULL);
|
||||||
|
}
|
||||||
|
if (prefixOccupied) {
|
||||||
|
/*
|
||||||
|
* If the ns-prefix is occupied by an other ns-decl on the
|
||||||
|
* result element, then this means:
|
||||||
|
* 1) The desired prefix is shadowed
|
||||||
|
* 2) There's no way around changing the prefix
|
||||||
|
*
|
||||||
|
* Try a desperate search for an in-scope ns-decl
|
||||||
|
* with a matching ns-name before we use the last option,
|
||||||
|
* which is to recreate the ns-decl with a modified prefix.
|
||||||
|
*/
|
||||||
|
ns = xmlSearchNsByHref(target->doc, target, nsName);
|
||||||
|
if (ns != NULL)
|
||||||
|
return(ns);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fallback to changing the prefix.
|
||||||
|
*/
|
||||||
|
} else if ((target->parent != NULL) &&
|
||||||
|
(target->parent->type == XML_ELEMENT_NODE))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Try to find a matching ns-decl in the ancestor-axis.
|
||||||
|
*
|
||||||
|
* Check the common case: The parent element of the current
|
||||||
|
* result element is in the same namespace (with an equal ns-prefix).
|
||||||
|
*/
|
||||||
|
if ((target->parent->ns != NULL) &&
|
||||||
|
((target->parent->ns->prefix != NULL) == (nsPrefix != NULL)))
|
||||||
|
{
|
||||||
|
ns = target->parent->ns;
|
||||||
|
|
||||||
|
if (nsPrefix == NULL) {
|
||||||
|
if (xmlStrEqual(ns->href, nsName))
|
||||||
|
return(ns);
|
||||||
|
} else if (xmlStrEqual(ns->prefix, nsPrefix) &&
|
||||||
|
xmlStrEqual(ns->href, nsName))
|
||||||
|
{
|
||||||
|
return(ns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Lookup the remaining in-scope namespaces.
|
||||||
|
*/
|
||||||
|
ns = xmlSearchNs(target->doc, target->parent, nsPrefix);
|
||||||
|
if (ns != NULL) {
|
||||||
|
if (xmlStrEqual(ns->href, nsName))
|
||||||
|
return(ns);
|
||||||
|
/*
|
||||||
|
* Now check for a nasty case: We need to ensure that the new
|
||||||
|
* ns-decl won't shadow a prefix in-use by an existing attribute.
|
||||||
|
* <foo xmlns:a="urn:test:a">
|
||||||
|
* <bar a:a="val-a">
|
||||||
|
* <xsl:attribute xmlns:a="urn:test:b" name="a:b">
|
||||||
|
* val-b</xsl:attribute>
|
||||||
|
* </bar>
|
||||||
|
* </foo>
|
||||||
|
*/
|
||||||
|
if (target->properties) {
|
||||||
|
xmlAttrPtr attr = target->properties;
|
||||||
|
do {
|
||||||
|
if ((attr->ns) &&
|
||||||
|
xmlStrEqual(attr->ns->prefix, nsPrefix))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Bad, this prefix is already in use.
|
||||||
|
* Since we'll change the prefix anyway, try
|
||||||
|
* a search for a matching ns-decl based on the
|
||||||
|
* namespace name.
|
||||||
|
*/
|
||||||
|
ns = xmlSearchNsByHref(target->doc, target, nsName);
|
||||||
|
if (ns != NULL)
|
||||||
|
return(ns);
|
||||||
|
goto declare_new_prefix;
|
||||||
|
}
|
||||||
|
attr = attr->next;
|
||||||
|
} while (attr != NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Either no matching ns-prefix was found or the namespace is
|
||||||
|
* shadowed.
|
||||||
|
* Create a new ns-decl on the current result element.
|
||||||
|
*
|
||||||
|
* Hmm, we could also try to reuse an in-scope
|
||||||
|
* namespace with a matching ns-name but a different
|
||||||
|
* ns-prefix.
|
||||||
|
* What has higher priority?
|
||||||
|
* 1) If keeping the prefix: create a new ns-decl.
|
||||||
|
* 2) If reusal: first lookup ns-names; then fallback
|
||||||
|
* to creation of a new ns-decl.
|
||||||
|
* REVISIT: this currently uses case 1) although
|
||||||
|
* the old way was use xmlSearchNsByHref() and to let change
|
||||||
|
* the prefix.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
ns = xmlSearchNsByHref(target->doc, target, nsName);
|
||||||
|
if (ns != NULL)
|
||||||
|
return(ns);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Create the ns-decl on the current result element.
|
||||||
|
*/
|
||||||
|
ns = xmlNewNs(target, nsName, nsPrefix);
|
||||||
|
/* TODO: check errors */
|
||||||
|
return(ns);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* This is either the root of the tree or something weird is going on.
|
||||||
|
*/
|
||||||
|
ns = xmlNewNs(target, nsName, nsPrefix);
|
||||||
|
/* TODO: Check result */
|
||||||
|
return(ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_new_prefix:
|
||||||
|
/*
|
||||||
|
* Fallback: we need to generate a new prefix and declare the namespace
|
||||||
|
* on the result element.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
xmlChar pref[30];
|
||||||
|
int counter = 1;
|
||||||
|
|
||||||
|
if (nsPrefix == NULL) {
|
||||||
|
nsPrefix = BAD_CAST "ns";
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
snprintf((char *) pref, 30, "%s_%d", nsPrefix, counter++);
|
||||||
|
ns = xmlSearchNs(target->doc, target, BAD_CAST pref);
|
||||||
|
if (counter > 1000) {
|
||||||
|
xsltTransformError(ctxt, NULL, invocNode,
|
||||||
|
"Internal error in xsltAcquireResultInScopeNs(): "
|
||||||
|
"Failed to compute a unique ns-prefix for the "
|
||||||
|
"generated element");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
} while (ns != NULL);
|
||||||
|
ns = xmlNewNs(target, nsName, BAD_CAST pref);
|
||||||
|
/* TODO: Check result */
|
||||||
|
return(ns);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltGetNamespace:
|
||||||
|
* @ctxt: a transformation context
|
||||||
|
* @cur: the input node
|
||||||
|
* @ns: the namespace
|
||||||
|
* @out: the output node (or its parent)
|
||||||
|
*
|
||||||
|
* Find a matching (prefix and ns-name) ns-declaration
|
||||||
|
* for the requested @ns->prefix and @ns->href in the result tree.
|
||||||
|
* If none is found then a new ns-declaration will be
|
||||||
|
* added to @resultElem. If, in this case, the given prefix is
|
||||||
|
* already in use, then a ns-declaration with a modified ns-prefix
|
||||||
|
* be we created.
|
||||||
|
*
|
||||||
|
* Called by:
|
||||||
|
* - xsltCopyPropList() (*not* anymore)
|
||||||
|
* - xsltShallowCopyElement()
|
||||||
|
* - xsltCopyTreeInternal() (*not* anymore)
|
||||||
|
* - xsltApplySequenceConstructor() (*not* in the refactored code),
|
||||||
|
* - xsltElement() (*not* anymore)
|
||||||
|
*
|
||||||
|
* Returns a namespace declaration or NULL in case of
|
||||||
|
* namespace fixup failures or API or internal errors.
|
||||||
|
*/
|
||||||
|
xmlNsPtr
|
||||||
|
xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns,
|
||||||
|
xmlNodePtr out)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ns == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
#ifdef XSLT_REFACTORED
|
||||||
|
/*
|
||||||
|
* Namespace exclusion and ns-aliasing is performed at
|
||||||
|
* compilation-time in the refactored code.
|
||||||
|
* Additionally, aliasing is not intended for non Literal
|
||||||
|
* Result Elements.
|
||||||
|
*/
|
||||||
|
return(xsltGetSpecialNamespace(ctxt, cur, ns->href, ns->prefix, out));
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
xsltStylesheetPtr style;
|
||||||
|
const xmlChar *URI = NULL; /* the replacement URI */
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (cur == NULL) || (out == NULL))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
style = ctxt->style;
|
||||||
|
while (style != NULL) {
|
||||||
|
if (style->nsAliases != NULL)
|
||||||
|
URI = (const xmlChar *)
|
||||||
|
xmlHashLookup(style->nsAliases, ns->href);
|
||||||
|
if (URI != NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
style = xsltNextImport(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (URI == UNDEFINED_DEFAULT_NS) {
|
||||||
|
return(xsltGetSpecialNamespace(ctxt, cur, NULL, NULL, out));
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* TODO: Removed, since wrong. If there was no default
|
||||||
|
* namespace in the stylesheet then this must resolve to
|
||||||
|
* the NULL namespace.
|
||||||
|
*/
|
||||||
|
xmlNsPtr dflt;
|
||||||
|
dflt = xmlSearchNs(cur->doc, cur, NULL);
|
||||||
|
if (dflt != NULL)
|
||||||
|
URI = dflt->href;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
} else if (URI == NULL)
|
||||||
|
URI = ns->href;
|
||||||
|
|
||||||
|
return(xsltGetSpecialNamespace(ctxt, cur, URI, ns->prefix, out));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltGetPlainNamespace:
|
||||||
|
* @ctxt: a transformation context
|
||||||
|
* @cur: the input node
|
||||||
|
* @ns: the namespace
|
||||||
|
* @out: the result element
|
||||||
|
*
|
||||||
|
* Obsolete.
|
||||||
|
* *Not* called by any Libxslt/Libexslt function.
|
||||||
|
* Exaclty the same as xsltGetNamespace().
|
||||||
|
*
|
||||||
|
* Returns a namespace declaration or NULL in case of
|
||||||
|
* namespace fixup failures or API or internal errors.
|
||||||
|
*/
|
||||||
|
xmlNsPtr
|
||||||
|
xsltGetPlainNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur,
|
||||||
|
xmlNsPtr ns, xmlNodePtr out)
|
||||||
|
{
|
||||||
|
return(xsltGetNamespace(ctxt, cur, ns, out));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCopyNamespaceList:
|
||||||
|
* @ctxt: a transformation context
|
||||||
|
* @node: the target node
|
||||||
|
* @cur: the first namespace
|
||||||
|
*
|
||||||
|
* Do a copy of an namespace list. If @node is non-NULL the
|
||||||
|
* new namespaces are added automatically. This handles namespaces
|
||||||
|
* aliases.
|
||||||
|
* This function is intended only for *internal* use at
|
||||||
|
* transformation-time for copying ns-declarations of Literal
|
||||||
|
* Result Elements.
|
||||||
|
*
|
||||||
|
* Called by:
|
||||||
|
* xsltCopyTreeInternal() (transform.c)
|
||||||
|
* xsltShallowCopyElem() (transform.c)
|
||||||
|
*
|
||||||
|
* REVISIT: This function won't be used in the refactored code.
|
||||||
|
*
|
||||||
|
* Returns: a new xmlNsPtr, or NULL in case of error.
|
||||||
|
*/
|
||||||
|
xmlNsPtr
|
||||||
|
xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
||||||
|
xmlNsPtr cur) {
|
||||||
|
xmlNsPtr ret = NULL, tmp;
|
||||||
|
xmlNsPtr p = NULL,q;
|
||||||
|
|
||||||
|
if (cur == NULL)
|
||||||
|
return(NULL);
|
||||||
|
if (cur->type != XML_NAMESPACE_DECL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One can add namespaces only on element nodes
|
||||||
|
*/
|
||||||
|
if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
|
||||||
|
node = NULL;
|
||||||
|
|
||||||
|
while (cur != NULL) {
|
||||||
|
if (cur->type != XML_NAMESPACE_DECL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avoid duplicating namespace declarations in the tree if
|
||||||
|
* a matching declaration is in scope.
|
||||||
|
*/
|
||||||
|
if (node != NULL) {
|
||||||
|
if ((node->ns != NULL) &&
|
||||||
|
(xmlStrEqual(node->ns->prefix, cur->prefix)) &&
|
||||||
|
(xmlStrEqual(node->ns->href, cur->href))) {
|
||||||
|
cur = cur->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmp = xmlSearchNs(node->doc, node, cur->prefix);
|
||||||
|
if ((tmp != NULL) && (xmlStrEqual(tmp->href, cur->href))) {
|
||||||
|
cur = cur->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef XSLT_REFACTORED
|
||||||
|
/*
|
||||||
|
* Namespace exclusion and ns-aliasing is performed at
|
||||||
|
* compilation-time in the refactored code.
|
||||||
|
*/
|
||||||
|
q = xmlNewNs(node, cur->href, cur->prefix);
|
||||||
|
if (p == NULL) {
|
||||||
|
ret = p = q;
|
||||||
|
} else {
|
||||||
|
p->next = q;
|
||||||
|
p = q;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* TODO: Remove this if the refactored code gets enabled.
|
||||||
|
*/
|
||||||
|
if (!xmlStrEqual(cur->href, XSLT_NAMESPACE)) {
|
||||||
|
const xmlChar *URI;
|
||||||
|
/* TODO apply cascading */
|
||||||
|
URI = (const xmlChar *) xmlHashLookup(ctxt->style->nsAliases,
|
||||||
|
cur->href);
|
||||||
|
if (URI == UNDEFINED_DEFAULT_NS) {
|
||||||
|
cur = cur->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (URI != NULL) {
|
||||||
|
q = xmlNewNs(node, URI, cur->prefix);
|
||||||
|
} else {
|
||||||
|
q = xmlNewNs(node, cur->href, cur->prefix);
|
||||||
|
}
|
||||||
|
if (p == NULL) {
|
||||||
|
ret = p = q;
|
||||||
|
} else {
|
||||||
|
p->next = q;
|
||||||
|
p = q;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCopyNamespace:
|
||||||
|
* @ctxt: a transformation context
|
||||||
|
* @elem: the target element node
|
||||||
|
* @ns: the namespace node
|
||||||
|
*
|
||||||
|
* Copies a namespace node (declaration). If @elem is not NULL,
|
||||||
|
* then the new namespace will be declared on @elem.
|
||||||
|
*
|
||||||
|
* Returns: a new xmlNsPtr, or NULL in case of an error.
|
||||||
|
*/
|
||||||
|
xmlNsPtr
|
||||||
|
xsltCopyNamespace(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
|
||||||
|
xmlNodePtr elem, xmlNsPtr ns)
|
||||||
|
{
|
||||||
|
if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
|
||||||
|
return(NULL);
|
||||||
|
/*
|
||||||
|
* One can add namespaces only on element nodes
|
||||||
|
*/
|
||||||
|
if ((elem != NULL) && (elem->type != XML_ELEMENT_NODE))
|
||||||
|
return(xmlNewNs(NULL, ns->href, ns->prefix));
|
||||||
|
else
|
||||||
|
return(xmlNewNs(elem, ns->href, ns->prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeNamespaceAliasHashes:
|
||||||
|
* @style: an XSLT stylesheet
|
||||||
|
*
|
||||||
|
* Free up the memory used by namespaces aliases
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeNamespaceAliasHashes(xsltStylesheetPtr style) {
|
||||||
|
if (style->nsAliases != NULL)
|
||||||
|
xmlHashFree((xmlHashTablePtr) style->nsAliases, NULL);
|
||||||
|
style->nsAliases = NULL;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the XSLT namespace handling
|
||||||
|
* Description: set of function easing the processing and generation
|
||||||
|
* of namespace nodes in XSLT.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_NAMESPACES_H__
|
||||||
|
#define __XML_XSLT_NAMESPACES_H__
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used within nsAliases hashtable when the default namespace is required
|
||||||
|
* but it's not been explicitly defined
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* UNDEFINED_DEFAULT_NS:
|
||||||
|
*
|
||||||
|
* Special value for undefined namespace, internal
|
||||||
|
*/
|
||||||
|
#define UNDEFINED_DEFAULT_NS (const xmlChar *) -1L
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltNamespaceAlias (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr node);
|
||||||
|
XSLTPUBFUN xmlNsPtr XSLTCALL
|
||||||
|
xsltGetNamespace (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr cur,
|
||||||
|
xmlNsPtr ns,
|
||||||
|
xmlNodePtr out);
|
||||||
|
XSLTPUBFUN xmlNsPtr XSLTCALL
|
||||||
|
xsltGetPlainNamespace (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr cur,
|
||||||
|
xmlNsPtr ns,
|
||||||
|
xmlNodePtr out);
|
||||||
|
XSLTPUBFUN xmlNsPtr XSLTCALL
|
||||||
|
xsltGetSpecialNamespace (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr cur,
|
||||||
|
const xmlChar *URI,
|
||||||
|
const xmlChar *prefix,
|
||||||
|
xmlNodePtr out);
|
||||||
|
XSLTPUBFUN xmlNsPtr XSLTCALL
|
||||||
|
xsltCopyNamespace (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr elem,
|
||||||
|
xmlNsPtr ns);
|
||||||
|
XSLTPUBFUN xmlNsPtr XSLTCALL
|
||||||
|
xsltCopyNamespaceList (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNsPtr cur);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeNamespaceAliasHashes
|
||||||
|
(xsltStylesheetPtr style);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_NAMESPACES_H__ */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Summary: Implementation of the XSLT number functions
|
||||||
|
* Description: Implementation of the XSLT number functions
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Bjorn Reese <breese@users.sourceforge.net> and Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_NUMBERSINTERNALS_H__
|
||||||
|
#define __XML_XSLT_NUMBERSINTERNALS_H__
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct _xsltCompMatch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNumberData:
|
||||||
|
*
|
||||||
|
* This data structure is just a wrapper to pass xsl:number data in.
|
||||||
|
*/
|
||||||
|
typedef struct _xsltNumberData xsltNumberData;
|
||||||
|
typedef xsltNumberData *xsltNumberDataPtr;
|
||||||
|
|
||||||
|
struct _xsltNumberData {
|
||||||
|
const xmlChar *level;
|
||||||
|
const xmlChar *count;
|
||||||
|
const xmlChar *from;
|
||||||
|
const xmlChar *value;
|
||||||
|
const xmlChar *format;
|
||||||
|
int has_format;
|
||||||
|
int digitsPerGroup;
|
||||||
|
int groupingCharacter;
|
||||||
|
int groupingCharacterLen;
|
||||||
|
xmlDocPtr doc;
|
||||||
|
xmlNodePtr node;
|
||||||
|
struct _xsltCompMatch *countPat;
|
||||||
|
struct _xsltCompMatch *fromPat;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* accelerators
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFormatNumberInfo,:
|
||||||
|
*
|
||||||
|
* This data structure lists the various parameters needed to format numbers.
|
||||||
|
*/
|
||||||
|
typedef struct _xsltFormatNumberInfo xsltFormatNumberInfo;
|
||||||
|
typedef xsltFormatNumberInfo *xsltFormatNumberInfoPtr;
|
||||||
|
|
||||||
|
struct _xsltFormatNumberInfo {
|
||||||
|
int integer_hash; /* Number of '#' in integer part */
|
||||||
|
int integer_digits; /* Number of '0' in integer part */
|
||||||
|
int frac_digits; /* Number of '0' in fractional part */
|
||||||
|
int frac_hash; /* Number of '#' in fractional part */
|
||||||
|
int group; /* Number of chars per display 'group' */
|
||||||
|
int multiplier; /* Scaling for percent or permille */
|
||||||
|
char add_decimal; /* Flag for whether decimal point appears in pattern */
|
||||||
|
char is_multiplier_set; /* Flag to catch multiple occurences of percent/permille */
|
||||||
|
char is_negative_pattern;/* Flag for processing -ve prefix/suffix */
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __XML_XSLT_NUMBERSINTERNALS_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the pattern matching used in template matches.
|
||||||
|
* Description: the implementation of the lookup of the right template
|
||||||
|
* for a given node must be really fast in order to keep
|
||||||
|
* decent performances.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_PATTERN_H__
|
||||||
|
#define __XML_XSLT_PATTERN_H__
|
||||||
|
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "xsltexports.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCompMatch:
|
||||||
|
*
|
||||||
|
* Data structure used for the implementation of patterns.
|
||||||
|
* It is kept private (in pattern.c).
|
||||||
|
*/
|
||||||
|
typedef struct _xsltCompMatch xsltCompMatch;
|
||||||
|
typedef xsltCompMatch *xsltCompMatchPtr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pattern related interfaces.
|
||||||
|
*/
|
||||||
|
|
||||||
|
XSLTPUBFUN xsltCompMatchPtr XSLTCALL
|
||||||
|
xsltCompilePattern (const xmlChar *pattern,
|
||||||
|
xmlDocPtr doc,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xsltStylesheetPtr style,
|
||||||
|
xsltTransformContextPtr runtime);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeCompMatchList (xsltCompMatchPtr comp);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltTestCompMatchList (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xsltCompMatchPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltCompMatchClearCache (xsltTransformContextPtr ctxt,
|
||||||
|
xsltCompMatchPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltNormalizeCompSteps (void *payload,
|
||||||
|
void *data,
|
||||||
|
const xmlChar *name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Template related interfaces.
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltAddTemplate (xsltStylesheetPtr style,
|
||||||
|
xsltTemplatePtr cur,
|
||||||
|
const xmlChar *mode,
|
||||||
|
const xmlChar *modeURI);
|
||||||
|
XSLTPUBFUN xsltTemplatePtr XSLTCALL
|
||||||
|
xsltGetTemplate (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xsltStylesheetPtr style);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeTemplateHashes (xsltStylesheetPtr style);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltCleanupTemplates (xsltStylesheetPtr style);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int xsltMatchPattern (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
const xmlChar *pattern,
|
||||||
|
xmlDocPtr ctxtdoc,
|
||||||
|
xmlNodePtr ctxtnode);
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_PATTERN_H__ */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Summary: precomputing stylesheets
|
||||||
|
* Description: this is the compilation phase, where most of the
|
||||||
|
* stylesheet is "compiled" into faster to use data.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_PRECOMP_H__
|
||||||
|
#define __XML_XSLT_PRECOMP_H__
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interfaces
|
||||||
|
*/
|
||||||
|
extern const xmlChar *xsltExtMarker;
|
||||||
|
|
||||||
|
XSLTPUBFUN xsltElemPreCompPtr XSLTCALL
|
||||||
|
xsltDocumentComp (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltTransformFunction function);
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltStylePreCompute (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr inst);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeStylePreComps (xsltStylesheetPtr style);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_PRECOMP_H__ */
|
||||||
|
|
|
@ -0,0 +1,482 @@
|
||||||
|
/*
|
||||||
|
* security.c: Implementation of the XSLT security framework
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* daniel@veillard.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IN_LIBXSLT
|
||||||
|
#include "libxslt.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_MATH_H
|
||||||
|
#include <math.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FLOAT_H
|
||||||
|
#include <float.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_IEEEFP_H
|
||||||
|
#include <ieeefp.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NAN_H
|
||||||
|
#include <nan.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
#include <windows.h>
|
||||||
|
#ifndef INVALID_FILE_ATTRIBUTES
|
||||||
|
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_STAT
|
||||||
|
# ifdef HAVE__STAT
|
||||||
|
/* MS C library seems to define stat and _stat. The definition
|
||||||
|
* is identical. Still, mapping them to each other causes a warning. */
|
||||||
|
# ifndef _MSC_VER
|
||||||
|
# define stat(x,y) _stat(x,y)
|
||||||
|
# endif
|
||||||
|
# define HAVE_STAT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/uri.h>
|
||||||
|
#include "xslt.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "xsltutils.h"
|
||||||
|
#include "extensions.h"
|
||||||
|
#include "security.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct _xsltSecurityPrefs {
|
||||||
|
xsltSecurityCheck readFile;
|
||||||
|
xsltSecurityCheck createFile;
|
||||||
|
xsltSecurityCheck createDir;
|
||||||
|
xsltSecurityCheck readNet;
|
||||||
|
xsltSecurityCheck writeNet;
|
||||||
|
};
|
||||||
|
|
||||||
|
static xsltSecurityPrefsPtr xsltDefaultSecurityPrefs = NULL;
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Module interfaces *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNewSecurityPrefs:
|
||||||
|
*
|
||||||
|
* Create a new security preference block
|
||||||
|
*
|
||||||
|
* Returns a pointer to the new block or NULL in case of error
|
||||||
|
*/
|
||||||
|
xsltSecurityPrefsPtr
|
||||||
|
xsltNewSecurityPrefs(void) {
|
||||||
|
xsltSecurityPrefsPtr ret;
|
||||||
|
|
||||||
|
xsltInitGlobals();
|
||||||
|
|
||||||
|
ret = (xsltSecurityPrefsPtr) xmlMalloc(sizeof(xsltSecurityPrefs));
|
||||||
|
if (ret == NULL) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL,
|
||||||
|
"xsltNewSecurityPrefs : malloc failed\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(ret, 0, sizeof(xsltSecurityPrefs));
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeSecurityPrefs:
|
||||||
|
* @sec: the security block to free
|
||||||
|
*
|
||||||
|
* Free up a security preference block
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeSecurityPrefs(xsltSecurityPrefsPtr sec) {
|
||||||
|
if (sec == NULL)
|
||||||
|
return;
|
||||||
|
xmlFree(sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltSetSecurityPrefs:
|
||||||
|
* @sec: the security block to update
|
||||||
|
* @option: the option to update
|
||||||
|
* @func: the user callback to use for this option
|
||||||
|
*
|
||||||
|
* Update the security option to use the new callback checking function
|
||||||
|
*
|
||||||
|
* Returns -1 in case of error, 0 otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltSetSecurityPrefs(xsltSecurityPrefsPtr sec, xsltSecurityOption option,
|
||||||
|
xsltSecurityCheck func) {
|
||||||
|
xsltInitGlobals();
|
||||||
|
if (sec == NULL)
|
||||||
|
return(-1);
|
||||||
|
switch (option) {
|
||||||
|
case XSLT_SECPREF_READ_FILE:
|
||||||
|
sec->readFile = func; return(0);
|
||||||
|
case XSLT_SECPREF_WRITE_FILE:
|
||||||
|
sec->createFile = func; return(0);
|
||||||
|
case XSLT_SECPREF_CREATE_DIRECTORY:
|
||||||
|
sec->createDir = func; return(0);
|
||||||
|
case XSLT_SECPREF_READ_NETWORK:
|
||||||
|
sec->readNet = func; return(0);
|
||||||
|
case XSLT_SECPREF_WRITE_NETWORK:
|
||||||
|
sec->writeNet = func; return(0);
|
||||||
|
}
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltGetSecurityPrefs:
|
||||||
|
* @sec: the security block to update
|
||||||
|
* @option: the option to lookup
|
||||||
|
*
|
||||||
|
* Lookup the security option to get the callback checking function
|
||||||
|
*
|
||||||
|
* Returns NULL if not found, the function otherwise
|
||||||
|
*/
|
||||||
|
xsltSecurityCheck
|
||||||
|
xsltGetSecurityPrefs(xsltSecurityPrefsPtr sec, xsltSecurityOption option) {
|
||||||
|
if (sec == NULL)
|
||||||
|
return(NULL);
|
||||||
|
switch (option) {
|
||||||
|
case XSLT_SECPREF_READ_FILE:
|
||||||
|
return(sec->readFile);
|
||||||
|
case XSLT_SECPREF_WRITE_FILE:
|
||||||
|
return(sec->createFile);
|
||||||
|
case XSLT_SECPREF_CREATE_DIRECTORY:
|
||||||
|
return(sec->createDir);
|
||||||
|
case XSLT_SECPREF_READ_NETWORK:
|
||||||
|
return(sec->readNet);
|
||||||
|
case XSLT_SECPREF_WRITE_NETWORK:
|
||||||
|
return(sec->writeNet);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltSetDefaultSecurityPrefs:
|
||||||
|
* @sec: the security block to use
|
||||||
|
*
|
||||||
|
* Set the default security preference application-wide
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltSetDefaultSecurityPrefs(xsltSecurityPrefsPtr sec) {
|
||||||
|
|
||||||
|
xsltDefaultSecurityPrefs = sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltGetDefaultSecurityPrefs:
|
||||||
|
*
|
||||||
|
* Get the default security preference application-wide
|
||||||
|
*
|
||||||
|
* Returns the current xsltSecurityPrefsPtr in use or NULL if none
|
||||||
|
*/
|
||||||
|
xsltSecurityPrefsPtr
|
||||||
|
xsltGetDefaultSecurityPrefs(void) {
|
||||||
|
return(xsltDefaultSecurityPrefs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltSetCtxtSecurityPrefs:
|
||||||
|
* @sec: the security block to use
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
*
|
||||||
|
* Set the security preference for a specific transformation
|
||||||
|
*
|
||||||
|
* Returns -1 in case of error, 0 otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltSetCtxtSecurityPrefs(xsltSecurityPrefsPtr sec,
|
||||||
|
xsltTransformContextPtr ctxt) {
|
||||||
|
if (ctxt == NULL)
|
||||||
|
return(-1);
|
||||||
|
ctxt->sec = (void *) sec;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltSecurityAllow:
|
||||||
|
* @sec: the security block to use
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @value: unused
|
||||||
|
*
|
||||||
|
* Function used to always allow an operation
|
||||||
|
*
|
||||||
|
* Returns 1 always
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltSecurityAllow(xsltSecurityPrefsPtr sec ATTRIBUTE_UNUSED,
|
||||||
|
xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
|
||||||
|
const char *value ATTRIBUTE_UNUSED) {
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltSecurityForbid:
|
||||||
|
* @sec: the security block to use
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @value: unused
|
||||||
|
*
|
||||||
|
* Function used to always forbid an operation
|
||||||
|
*
|
||||||
|
* Returns 0 always
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltSecurityForbid(xsltSecurityPrefsPtr sec ATTRIBUTE_UNUSED,
|
||||||
|
xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
|
||||||
|
const char *value ATTRIBUTE_UNUSED) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Internal interfaces *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCheckFilename
|
||||||
|
* @path: the path to check
|
||||||
|
*
|
||||||
|
* function checks to see if @path is a valid source
|
||||||
|
* (file, socket...) for XML.
|
||||||
|
*
|
||||||
|
* TODO: remove at some point !!!
|
||||||
|
* Local copy of xmlCheckFilename to avoid a hard dependency on
|
||||||
|
* a new version of libxml2
|
||||||
|
*
|
||||||
|
* if stat is not available on the target machine,
|
||||||
|
* returns 1. if stat fails, returns 0 (if calling
|
||||||
|
* stat on the filename fails, it can't be right).
|
||||||
|
* if stat succeeds and the file is a directory,
|
||||||
|
* returns 2. otherwise returns 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
xsltCheckFilename (const char *path)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_STAT
|
||||||
|
struct stat stat_buffer;
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
DWORD dwAttrs;
|
||||||
|
|
||||||
|
dwAttrs = GetFileAttributes(path);
|
||||||
|
if (dwAttrs != INVALID_FILE_ATTRIBUTES) {
|
||||||
|
if (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (stat(path, &stat_buffer) == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef S_ISDIR
|
||||||
|
if (S_ISDIR(stat_buffer.st_mode)) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
xsltCheckWritePath(xsltSecurityPrefsPtr sec,
|
||||||
|
xsltTransformContextPtr ctxt,
|
||||||
|
const char *path)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
xsltSecurityCheck check;
|
||||||
|
char *directory;
|
||||||
|
|
||||||
|
check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_WRITE_FILE);
|
||||||
|
if (check != NULL) {
|
||||||
|
ret = check(sec, ctxt, path);
|
||||||
|
if (ret == 0) {
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"File write for %s refused\n", path);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
directory = xmlParserGetDirectory (path);
|
||||||
|
|
||||||
|
if (directory != NULL) {
|
||||||
|
ret = xsltCheckFilename(directory);
|
||||||
|
if (ret == 0) {
|
||||||
|
/*
|
||||||
|
* The directory doesn't exist check for creation
|
||||||
|
*/
|
||||||
|
check = xsltGetSecurityPrefs(sec,
|
||||||
|
XSLT_SECPREF_CREATE_DIRECTORY);
|
||||||
|
if (check != NULL) {
|
||||||
|
ret = check(sec, ctxt, directory);
|
||||||
|
if (ret == 0) {
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"Directory creation for %s refused\n",
|
||||||
|
path);
|
||||||
|
xmlFree(directory);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = xsltCheckWritePath(sec, ctxt, directory);
|
||||||
|
if (ret == 1)
|
||||||
|
ret = mkdir(directory, 0755);
|
||||||
|
}
|
||||||
|
xmlFree(directory);
|
||||||
|
if (ret < 0)
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCheckWrite:
|
||||||
|
* @sec: the security options
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @URL: the resource to be written
|
||||||
|
*
|
||||||
|
* Check if the resource is allowed to be written, if necessary makes
|
||||||
|
* some preliminary work like creating directories
|
||||||
|
*
|
||||||
|
* Return 1 if write is allowed, 0 if not and -1 in case or error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltCheckWrite(xsltSecurityPrefsPtr sec,
|
||||||
|
xsltTransformContextPtr ctxt, const xmlChar *URL) {
|
||||||
|
int ret;
|
||||||
|
xmlURIPtr uri;
|
||||||
|
xsltSecurityCheck check;
|
||||||
|
|
||||||
|
uri = xmlParseURI((const char *)URL);
|
||||||
|
if (uri == NULL) {
|
||||||
|
uri = xmlCreateURI();
|
||||||
|
if (uri == NULL) {
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"xsltCheckWrite: out of memory for %s\n", URL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
uri->path = (char *)xmlStrdup(URL);
|
||||||
|
}
|
||||||
|
if ((uri->scheme == NULL) ||
|
||||||
|
(xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
if ((uri->path)&&(uri->path[0]=='/')&&
|
||||||
|
(uri->path[1]!='\0')&&(uri->path[2]==':'))
|
||||||
|
ret = xsltCheckWritePath(sec, ctxt, uri->path+1);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Check if we are allowed to write this file
|
||||||
|
*/
|
||||||
|
ret = xsltCheckWritePath(sec, ctxt, uri->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret <= 0) {
|
||||||
|
xmlFreeURI(uri);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Check if we are allowed to write this network resource
|
||||||
|
*/
|
||||||
|
check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_WRITE_NETWORK);
|
||||||
|
if (check != NULL) {
|
||||||
|
ret = check(sec, ctxt, (const char *)URL);
|
||||||
|
if (ret == 0) {
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"File write for %s refused\n", URL);
|
||||||
|
xmlFreeURI(uri);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFreeURI(uri);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCheckRead:
|
||||||
|
* @sec: the security options
|
||||||
|
* @ctxt: an XSLT transformation context
|
||||||
|
* @URL: the resource to be read
|
||||||
|
*
|
||||||
|
* Check if the resource is allowed to be read
|
||||||
|
*
|
||||||
|
* Return 1 if read is allowed, 0 if not and -1 in case or error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltCheckRead(xsltSecurityPrefsPtr sec,
|
||||||
|
xsltTransformContextPtr ctxt, const xmlChar *URL) {
|
||||||
|
int ret;
|
||||||
|
xmlURIPtr uri;
|
||||||
|
xsltSecurityCheck check;
|
||||||
|
|
||||||
|
uri = xmlParseURI((const char *)URL);
|
||||||
|
if (uri == NULL) {
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"xsltCheckRead: URL parsing failed for %s\n",
|
||||||
|
URL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
if ((uri->scheme == NULL) ||
|
||||||
|
(xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if we are allowed to read this file
|
||||||
|
*/
|
||||||
|
check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_READ_FILE);
|
||||||
|
if (check != NULL) {
|
||||||
|
ret = check(sec, ctxt, uri->path);
|
||||||
|
if (ret == 0) {
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"Local file read for %s refused\n", URL);
|
||||||
|
xmlFreeURI(uri);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Check if we are allowed to write this network resource
|
||||||
|
*/
|
||||||
|
check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_READ_NETWORK);
|
||||||
|
if (check != NULL) {
|
||||||
|
ret = check(sec, ctxt, (const char *)URL);
|
||||||
|
if (ret == 0) {
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"Network file read for %s refused\n", URL);
|
||||||
|
xmlFreeURI(uri);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFreeURI(uri);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the libxslt security framework
|
||||||
|
* Description: the libxslt security framework allow to restrict
|
||||||
|
* the access to new resources (file or URL) from
|
||||||
|
* the stylesheet at runtime.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_SECURITY_H__
|
||||||
|
#define __XML_XSLT_SECURITY_H__
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltSecurityPref:
|
||||||
|
*
|
||||||
|
* structure to indicate the preferences for security in the XSLT
|
||||||
|
* transformation.
|
||||||
|
*/
|
||||||
|
typedef struct _xsltSecurityPrefs xsltSecurityPrefs;
|
||||||
|
typedef xsltSecurityPrefs *xsltSecurityPrefsPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltSecurityOption:
|
||||||
|
*
|
||||||
|
* the set of option that can be configured
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
XSLT_SECPREF_READ_FILE = 1,
|
||||||
|
XSLT_SECPREF_WRITE_FILE,
|
||||||
|
XSLT_SECPREF_CREATE_DIRECTORY,
|
||||||
|
XSLT_SECPREF_READ_NETWORK,
|
||||||
|
XSLT_SECPREF_WRITE_NETWORK
|
||||||
|
} xsltSecurityOption;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltSecurityCheck:
|
||||||
|
*
|
||||||
|
* User provided function to check the value of a string like a file
|
||||||
|
* path or an URL ...
|
||||||
|
*/
|
||||||
|
typedef int (*xsltSecurityCheck) (xsltSecurityPrefsPtr sec,
|
||||||
|
xsltTransformContextPtr ctxt,
|
||||||
|
const char *value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module interfaces
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN xsltSecurityPrefsPtr XSLTCALL
|
||||||
|
xsltNewSecurityPrefs (void);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeSecurityPrefs (xsltSecurityPrefsPtr sec);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSetSecurityPrefs (xsltSecurityPrefsPtr sec,
|
||||||
|
xsltSecurityOption option,
|
||||||
|
xsltSecurityCheck func);
|
||||||
|
XSLTPUBFUN xsltSecurityCheck XSLTCALL
|
||||||
|
xsltGetSecurityPrefs (xsltSecurityPrefsPtr sec,
|
||||||
|
xsltSecurityOption option);
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSetDefaultSecurityPrefs (xsltSecurityPrefsPtr sec);
|
||||||
|
XSLTPUBFUN xsltSecurityPrefsPtr XSLTCALL
|
||||||
|
xsltGetDefaultSecurityPrefs (void);
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSetCtxtSecurityPrefs (xsltSecurityPrefsPtr sec,
|
||||||
|
xsltTransformContextPtr ctxt);
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSecurityAllow (xsltSecurityPrefsPtr sec,
|
||||||
|
xsltTransformContextPtr ctxt,
|
||||||
|
const char *value);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSecurityForbid (xsltSecurityPrefsPtr sec,
|
||||||
|
xsltTransformContextPtr ctxt,
|
||||||
|
const char *value);
|
||||||
|
/*
|
||||||
|
* internal interfaces
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltCheckWrite (xsltSecurityPrefsPtr sec,
|
||||||
|
xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *URL);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltCheckRead (xsltSecurityPrefsPtr sec,
|
||||||
|
xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *URL);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_SECURITY_H__ */
|
||||||
|
|
|
@ -0,0 +1,864 @@
|
||||||
|
/*
|
||||||
|
* templates.c: Implementation of the template processing
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* http://www.w3.org/TR/1999/REC-xslt-19991116
|
||||||
|
*
|
||||||
|
* 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/globals.h>
|
||||||
|
#include <libxml/xmlerror.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/dict.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
#include <libxml/parserInternals.h>
|
||||||
|
#include "xslt.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "xsltutils.h"
|
||||||
|
#include "variables.h"
|
||||||
|
#include "functions.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "transform.h"
|
||||||
|
#include "namespaces.h"
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
#ifdef WITH_XSLT_DEBUG
|
||||||
|
#define WITH_XSLT_DEBUG_TEMPLATES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Module interfaces *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltEvalXPathPredicate:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @comp: the XPath compiled expression
|
||||||
|
* @nsList: the namespaces in scope
|
||||||
|
* @nsNr: the number of namespaces in scope
|
||||||
|
*
|
||||||
|
* Process the expression using XPath and evaluate the result as
|
||||||
|
* an XPath predicate
|
||||||
|
*
|
||||||
|
* Returns 1 is the predicate was true, 0 otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
|
||||||
|
xmlNsPtr *nsList, int nsNr) {
|
||||||
|
int ret;
|
||||||
|
xmlXPathObjectPtr res;
|
||||||
|
int oldNsNr;
|
||||||
|
xmlNsPtr *oldNamespaces;
|
||||||
|
xmlNodePtr oldInst;
|
||||||
|
int oldProximityPosition, oldContextSize;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (ctxt->inst == NULL)) {
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"xsltEvalXPathPredicate: No context or instruction\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
oldContextSize = ctxt->xpathCtxt->contextSize;
|
||||||
|
oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
|
||||||
|
oldNsNr = ctxt->xpathCtxt->nsNr;
|
||||||
|
oldNamespaces = ctxt->xpathCtxt->namespaces;
|
||||||
|
oldInst = ctxt->inst;
|
||||||
|
|
||||||
|
ctxt->xpathCtxt->node = ctxt->node;
|
||||||
|
ctxt->xpathCtxt->namespaces = nsList;
|
||||||
|
ctxt->xpathCtxt->nsNr = nsNr;
|
||||||
|
|
||||||
|
res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
|
||||||
|
|
||||||
|
if (res != NULL) {
|
||||||
|
ret = xmlXPathEvalPredicate(ctxt->xpathCtxt, res);
|
||||||
|
xmlXPathFreeObject(res);
|
||||||
|
#ifdef WITH_XSLT_DEBUG_TEMPLATES
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltEvalXPathPredicate: returns %d\n", ret));
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#ifdef WITH_XSLT_DEBUG_TEMPLATES
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltEvalXPathPredicate: failed\n"));
|
||||||
|
#endif
|
||||||
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
ctxt->xpathCtxt->nsNr = oldNsNr;
|
||||||
|
|
||||||
|
ctxt->xpathCtxt->namespaces = oldNamespaces;
|
||||||
|
ctxt->inst = oldInst;
|
||||||
|
ctxt->xpathCtxt->contextSize = oldContextSize;
|
||||||
|
ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltEvalXPathStringNs:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @comp: the compiled XPath expression
|
||||||
|
* @nsNr: the number of namespaces in the list
|
||||||
|
* @nsList: the list of in-scope namespaces to use
|
||||||
|
*
|
||||||
|
* Process the expression using XPath, allowing to pass a namespace mapping
|
||||||
|
* context and get a string
|
||||||
|
*
|
||||||
|
* Returns the computed string value or NULL, must be deallocated by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
xmlChar *
|
||||||
|
xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
|
||||||
|
int nsNr, xmlNsPtr *nsList) {
|
||||||
|
xmlChar *ret = NULL;
|
||||||
|
xmlXPathObjectPtr res;
|
||||||
|
xmlNodePtr oldInst;
|
||||||
|
xmlNodePtr oldNode;
|
||||||
|
int oldPos, oldSize;
|
||||||
|
int oldNsNr;
|
||||||
|
xmlNsPtr *oldNamespaces;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (ctxt->inst == NULL)) {
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"xsltEvalXPathStringNs: No context or instruction\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
oldInst = ctxt->inst;
|
||||||
|
oldNode = ctxt->node;
|
||||||
|
oldPos = ctxt->xpathCtxt->proximityPosition;
|
||||||
|
oldSize = ctxt->xpathCtxt->contextSize;
|
||||||
|
oldNsNr = ctxt->xpathCtxt->nsNr;
|
||||||
|
oldNamespaces = ctxt->xpathCtxt->namespaces;
|
||||||
|
|
||||||
|
ctxt->xpathCtxt->node = ctxt->node;
|
||||||
|
/* TODO: do we need to propagate the namespaces here ? */
|
||||||
|
ctxt->xpathCtxt->namespaces = nsList;
|
||||||
|
ctxt->xpathCtxt->nsNr = nsNr;
|
||||||
|
res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
|
||||||
|
if (res != NULL) {
|
||||||
|
if (res->type != XPATH_STRING)
|
||||||
|
res = xmlXPathConvertString(res);
|
||||||
|
if (res->type == XPATH_STRING) {
|
||||||
|
ret = res->stringval;
|
||||||
|
res->stringval = NULL;
|
||||||
|
} else {
|
||||||
|
xsltTransformError(ctxt, NULL, NULL,
|
||||||
|
"xpath : string() function didn't return a String\n");
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(res);
|
||||||
|
} else {
|
||||||
|
ctxt->state = XSLT_STATE_STOPPED;
|
||||||
|
}
|
||||||
|
#ifdef WITH_XSLT_DEBUG_TEMPLATES
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltEvalXPathString: returns %s\n", ret));
|
||||||
|
#endif
|
||||||
|
ctxt->inst = oldInst;
|
||||||
|
ctxt->node = oldNode;
|
||||||
|
ctxt->xpathCtxt->contextSize = oldSize;
|
||||||
|
ctxt->xpathCtxt->proximityPosition = oldPos;
|
||||||
|
ctxt->xpathCtxt->nsNr = oldNsNr;
|
||||||
|
ctxt->xpathCtxt->namespaces = oldNamespaces;
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltEvalXPathString:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @comp: the compiled XPath expression
|
||||||
|
*
|
||||||
|
* Process the expression using XPath and get a string
|
||||||
|
*
|
||||||
|
* Returns the computed string value or NULL, must be deallocated by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
xmlChar *
|
||||||
|
xsltEvalXPathString(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp) {
|
||||||
|
return(xsltEvalXPathStringNs(ctxt, comp, 0, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltEvalTemplateString:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @contextNode: the current node in the source tree
|
||||||
|
* @inst: the XSLT instruction (xsl:comment, xsl:processing-instruction)
|
||||||
|
*
|
||||||
|
* Processes the sequence constructor of the given instruction on
|
||||||
|
* @contextNode and converts the resulting tree to a string.
|
||||||
|
* This is needed by e.g. xsl:comment and xsl:processing-instruction.
|
||||||
|
*
|
||||||
|
* Returns the computed string value or NULL; it's up to the caller to
|
||||||
|
* free the result.
|
||||||
|
*/
|
||||||
|
xmlChar *
|
||||||
|
xsltEvalTemplateString(xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr contextNode,
|
||||||
|
xmlNodePtr inst)
|
||||||
|
{
|
||||||
|
xmlNodePtr oldInsert, insert = NULL;
|
||||||
|
xmlChar *ret;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL) ||
|
||||||
|
(inst->type != XML_ELEMENT_NODE))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
if (inst->children == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This creates a temporary element-node to add the resulting
|
||||||
|
* text content to.
|
||||||
|
* OPTIMIZE TODO: Keep such an element-node in the transformation
|
||||||
|
* context to avoid creating it every time.
|
||||||
|
*/
|
||||||
|
insert = xmlNewDocNode(ctxt->output, NULL,
|
||||||
|
(const xmlChar *)"fake", NULL);
|
||||||
|
if (insert == NULL) {
|
||||||
|
xsltTransformError(ctxt, NULL, contextNode,
|
||||||
|
"Failed to create temporary node\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
oldInsert = ctxt->insert;
|
||||||
|
ctxt->insert = insert;
|
||||||
|
/*
|
||||||
|
* OPTIMIZE TODO: if inst->children consists only of text-nodes.
|
||||||
|
*/
|
||||||
|
xsltApplyOneTemplate(ctxt, contextNode, inst->children, NULL, NULL);
|
||||||
|
|
||||||
|
ctxt->insert = oldInsert;
|
||||||
|
|
||||||
|
ret = xmlNodeGetContent(insert);
|
||||||
|
if (insert != NULL)
|
||||||
|
xmlFreeNode(insert);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltAttrTemplateValueProcessNode:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @str: the attribute template node value
|
||||||
|
* @inst: the instruction (or LRE) in the stylesheet holding the
|
||||||
|
* attribute with an AVT
|
||||||
|
*
|
||||||
|
* Process the given string, allowing to pass a namespace mapping
|
||||||
|
* context and return the new string value.
|
||||||
|
*
|
||||||
|
* Called by:
|
||||||
|
* - xsltAttrTemplateValueProcess() (templates.c)
|
||||||
|
* - xsltEvalAttrValueTemplate() (templates.c)
|
||||||
|
*
|
||||||
|
* QUESTION: Why is this function public? It is not used outside
|
||||||
|
* of templates.c.
|
||||||
|
*
|
||||||
|
* Returns the computed string value or NULL, must be deallocated by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
xmlChar *
|
||||||
|
xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *str, xmlNodePtr inst)
|
||||||
|
{
|
||||||
|
xmlChar *ret = NULL;
|
||||||
|
const xmlChar *cur;
|
||||||
|
xmlChar *expr, *val;
|
||||||
|
xmlNsPtr *nsList = NULL;
|
||||||
|
int nsNr = 0;
|
||||||
|
|
||||||
|
if (str == NULL) return(NULL);
|
||||||
|
if (*str == 0)
|
||||||
|
return(xmlStrndup((xmlChar *)"", 0));
|
||||||
|
|
||||||
|
cur = str;
|
||||||
|
while (*cur != 0) {
|
||||||
|
if (*cur == '{') {
|
||||||
|
if (*(cur+1) == '{') { /* escaped '{' */
|
||||||
|
cur++;
|
||||||
|
ret = xmlStrncat(ret, str, cur - str);
|
||||||
|
cur++;
|
||||||
|
str = cur;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ret = xmlStrncat(ret, str, cur - str);
|
||||||
|
str = cur;
|
||||||
|
cur++;
|
||||||
|
while ((*cur != 0) && (*cur != '}')) {
|
||||||
|
/* Need to check for literal (bug539741) */
|
||||||
|
if ((*cur == '\'') || (*cur == '"')) {
|
||||||
|
char delim = *(cur++);
|
||||||
|
while ((*cur != 0) && (*cur != delim))
|
||||||
|
cur++;
|
||||||
|
if (*cur != 0)
|
||||||
|
cur++; /* skip the ending delimiter */
|
||||||
|
} else
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
if (*cur == 0) {
|
||||||
|
xsltTransformError(ctxt, NULL, inst,
|
||||||
|
"xsltAttrTemplateValueProcessNode: unmatched '{'\n");
|
||||||
|
ret = xmlStrncat(ret, str, cur - str);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
expr = xmlStrndup(str, cur - str);
|
||||||
|
if (expr == NULL)
|
||||||
|
goto exit;
|
||||||
|
else if (*expr == '{') {
|
||||||
|
ret = xmlStrcat(ret, expr);
|
||||||
|
xmlFree(expr);
|
||||||
|
} else {
|
||||||
|
xmlXPathCompExprPtr comp;
|
||||||
|
/*
|
||||||
|
* TODO: keep precompiled form around
|
||||||
|
*/
|
||||||
|
if ((nsList == NULL) && (inst != NULL)) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
nsList = xmlGetNsList(inst->doc, inst);
|
||||||
|
if (nsList != NULL) {
|
||||||
|
while (nsList[i] != NULL)
|
||||||
|
i++;
|
||||||
|
nsNr = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
comp = xmlXPathCtxtCompile(ctxt->xpathCtxt, expr);
|
||||||
|
val = xsltEvalXPathStringNs(ctxt, comp, nsNr, nsList);
|
||||||
|
xmlXPathFreeCompExpr(comp);
|
||||||
|
xmlFree(expr);
|
||||||
|
if (val != NULL) {
|
||||||
|
ret = xmlStrcat(ret, val);
|
||||||
|
xmlFree(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur++;
|
||||||
|
str = cur;
|
||||||
|
} else if (*cur == '}') {
|
||||||
|
cur++;
|
||||||
|
if (*cur == '}') { /* escaped '}' */
|
||||||
|
ret = xmlStrncat(ret, str, cur - str);
|
||||||
|
cur++;
|
||||||
|
str = cur;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
xsltTransformError(ctxt, NULL, inst,
|
||||||
|
"xsltAttrTemplateValueProcessNode: unmatched '}'\n");
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
if (cur != str) {
|
||||||
|
ret = xmlStrncat(ret, str, cur - str);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (nsList != NULL)
|
||||||
|
xmlFree(nsList);
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltAttrTemplateValueProcess:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @str: the attribute template node value
|
||||||
|
*
|
||||||
|
* Process the given node and return the new string value.
|
||||||
|
*
|
||||||
|
* Returns the computed string value or NULL, must be deallocated by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
xmlChar *
|
||||||
|
xsltAttrTemplateValueProcess(xsltTransformContextPtr ctxt, const xmlChar *str) {
|
||||||
|
return(xsltAttrTemplateValueProcessNode(ctxt, str, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltEvalAttrValueTemplate:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @inst: the instruction (or LRE) in the stylesheet holding the
|
||||||
|
* attribute with an AVT
|
||||||
|
* @name: the attribute QName
|
||||||
|
* @ns: the attribute namespace URI
|
||||||
|
*
|
||||||
|
* Evaluate a attribute value template, i.e. the attribute value can
|
||||||
|
* contain expressions contained in curly braces ({}) and those are
|
||||||
|
* substituted by they computed value.
|
||||||
|
*
|
||||||
|
* Returns the computed string value or NULL, must be deallocated by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
xmlChar *
|
||||||
|
xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst,
|
||||||
|
const xmlChar *name, const xmlChar *ns)
|
||||||
|
{
|
||||||
|
xmlChar *ret;
|
||||||
|
xmlChar *expr;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (inst == NULL) || (name == NULL) ||
|
||||||
|
(inst->type != XML_ELEMENT_NODE))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
expr = xsltGetNsProp(inst, name, ns);
|
||||||
|
if (expr == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: though now {} is detected ahead, it would still be good to
|
||||||
|
* optimize both functions to keep the splitted value if the
|
||||||
|
* attribute content and the XPath precompiled expressions around
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = xsltAttrTemplateValueProcessNode(ctxt, expr, inst);
|
||||||
|
#ifdef WITH_XSLT_DEBUG_TEMPLATES
|
||||||
|
XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"xsltEvalAttrValueTemplate: %s returns %s\n", expr, ret));
|
||||||
|
#endif
|
||||||
|
if (expr != NULL)
|
||||||
|
xmlFree(expr);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltEvalStaticAttrValueTemplate:
|
||||||
|
* @style: the XSLT stylesheet
|
||||||
|
* @inst: the instruction (or LRE) in the stylesheet holding the
|
||||||
|
* attribute with an AVT
|
||||||
|
* @name: the attribute Name
|
||||||
|
* @ns: the attribute namespace URI
|
||||||
|
* @found: indicator whether the attribute is present
|
||||||
|
*
|
||||||
|
* Check if an attribute value template has a static value, i.e. the
|
||||||
|
* attribute value does not contain expressions contained in curly braces ({})
|
||||||
|
*
|
||||||
|
* Returns the static string value or NULL, must be deallocated by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
const xmlChar *
|
||||||
|
xsltEvalStaticAttrValueTemplate(xsltStylesheetPtr style, xmlNodePtr inst,
|
||||||
|
const xmlChar *name, const xmlChar *ns, int *found) {
|
||||||
|
const xmlChar *ret;
|
||||||
|
xmlChar *expr;
|
||||||
|
|
||||||
|
if ((style == NULL) || (inst == NULL) || (name == NULL) ||
|
||||||
|
(inst->type != XML_ELEMENT_NODE))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
expr = xsltGetNsProp(inst, name, ns);
|
||||||
|
if (expr == NULL) {
|
||||||
|
*found = 0;
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
*found = 1;
|
||||||
|
|
||||||
|
ret = xmlStrchr(expr, '{');
|
||||||
|
if (ret != NULL) {
|
||||||
|
xmlFree(expr);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
ret = xmlDictLookup(style->dict, expr, -1);
|
||||||
|
xmlFree(expr);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltAttrTemplateProcess:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @target: the element where the attribute will be grafted
|
||||||
|
* @attr: the attribute node of a literal result element
|
||||||
|
*
|
||||||
|
* Process one attribute of a Literal Result Element (in the stylesheet).
|
||||||
|
* Evaluates Attribute Value Templates and copies the attribute over to
|
||||||
|
* the result element.
|
||||||
|
* This does *not* process attribute sets (xsl:use-attribute-set).
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Returns the generated attribute node.
|
||||||
|
*/
|
||||||
|
xmlAttrPtr
|
||||||
|
xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
|
||||||
|
xmlAttrPtr attr)
|
||||||
|
{
|
||||||
|
const xmlChar *value;
|
||||||
|
xmlAttrPtr ret;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (attr == NULL) || (target == NULL) ||
|
||||||
|
(target->type != XML_ELEMENT_NODE))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
if (attr->type != XML_ATTRIBUTE_NODE)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip all XSLT attributes.
|
||||||
|
*/
|
||||||
|
#ifdef XSLT_REFACTORED
|
||||||
|
if (attr->psvi == xsltXSLTAttrMarker)
|
||||||
|
return(NULL);
|
||||||
|
#else
|
||||||
|
if ((attr->ns != NULL) && xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
|
||||||
|
return(NULL);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Get the value.
|
||||||
|
*/
|
||||||
|
if (attr->children != NULL) {
|
||||||
|
if ((attr->children->type != XML_TEXT_NODE) ||
|
||||||
|
(attr->children->next != NULL))
|
||||||
|
{
|
||||||
|
xsltTransformError(ctxt, NULL, attr->parent,
|
||||||
|
"Internal error: The children of an attribute node of a "
|
||||||
|
"literal result element are not in the expected form.\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
value = attr->children->content;
|
||||||
|
if (value == NULL)
|
||||||
|
value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
|
||||||
|
} else
|
||||||
|
value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
|
||||||
|
/*
|
||||||
|
* Overwrite duplicates.
|
||||||
|
*/
|
||||||
|
ret = target->properties;
|
||||||
|
while (ret != NULL) {
|
||||||
|
if (((attr->ns != NULL) == (ret->ns != NULL)) &&
|
||||||
|
xmlStrEqual(ret->name, attr->name) &&
|
||||||
|
((attr->ns == NULL) || xmlStrEqual(ret->ns->href, attr->ns->href)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = ret->next;
|
||||||
|
}
|
||||||
|
if (ret != NULL) {
|
||||||
|
/* free the existing value */
|
||||||
|
xmlFreeNodeList(ret->children);
|
||||||
|
ret->children = ret->last = NULL;
|
||||||
|
/*
|
||||||
|
* Adjust ns-prefix if needed.
|
||||||
|
*/
|
||||||
|
if ((ret->ns != NULL) &&
|
||||||
|
(! xmlStrEqual(ret->ns->prefix, attr->ns->prefix)))
|
||||||
|
{
|
||||||
|
ret->ns = xsltGetNamespace(ctxt, attr->parent, attr->ns, target);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* create a new attribute */
|
||||||
|
if (attr->ns != NULL)
|
||||||
|
ret = xmlNewNsProp(target,
|
||||||
|
xsltGetNamespace(ctxt, attr->parent, attr->ns, target),
|
||||||
|
attr->name, NULL);
|
||||||
|
else
|
||||||
|
ret = xmlNewNsProp(target, NULL, attr->name, NULL);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Set the value.
|
||||||
|
*/
|
||||||
|
if (ret != NULL) {
|
||||||
|
xmlNodePtr text;
|
||||||
|
|
||||||
|
text = xmlNewText(NULL);
|
||||||
|
if (text != NULL) {
|
||||||
|
ret->last = ret->children = text;
|
||||||
|
text->parent = (xmlNodePtr) ret;
|
||||||
|
text->doc = ret->doc;
|
||||||
|
|
||||||
|
if (attr->psvi != NULL) {
|
||||||
|
/*
|
||||||
|
* Evaluate the Attribute Value Template.
|
||||||
|
*/
|
||||||
|
xmlChar *val;
|
||||||
|
val = xsltEvalAVT(ctxt, attr->psvi, attr->parent);
|
||||||
|
if (val == NULL) {
|
||||||
|
/*
|
||||||
|
* TODO: Damn, we need an easy mechanism to report
|
||||||
|
* qualified names!
|
||||||
|
*/
|
||||||
|
if (attr->ns) {
|
||||||
|
xsltTransformError(ctxt, NULL, attr->parent,
|
||||||
|
"Internal error: Failed to evaluate the AVT "
|
||||||
|
"of attribute '{%s}%s'.\n",
|
||||||
|
attr->ns->href, attr->name);
|
||||||
|
} else {
|
||||||
|
xsltTransformError(ctxt, NULL, attr->parent,
|
||||||
|
"Internal error: Failed to evaluate the AVT "
|
||||||
|
"of attribute '%s'.\n",
|
||||||
|
attr->name);
|
||||||
|
}
|
||||||
|
text->content = xmlStrdup(BAD_CAST "");
|
||||||
|
} else {
|
||||||
|
text->content = val;
|
||||||
|
}
|
||||||
|
} else if ((ctxt->internalized) && (target != NULL) &&
|
||||||
|
(target->doc != NULL) &&
|
||||||
|
(target->doc->dict == ctxt->dict) &&
|
||||||
|
xmlDictOwns(ctxt->dict, value)) {
|
||||||
|
text->content = (xmlChar *) value;
|
||||||
|
} else {
|
||||||
|
text->content = xmlStrdup(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (attr->ns) {
|
||||||
|
xsltTransformError(ctxt, NULL, attr->parent,
|
||||||
|
"Internal error: Failed to create attribute '{%s}%s'.\n",
|
||||||
|
attr->ns->href, attr->name);
|
||||||
|
} else {
|
||||||
|
xsltTransformError(ctxt, NULL, attr->parent,
|
||||||
|
"Internal error: Failed to create attribute '%s'.\n",
|
||||||
|
attr->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltAttrListTemplateProcess:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @target: the element where the attributes will be grafted
|
||||||
|
* @attrs: the first attribute
|
||||||
|
*
|
||||||
|
* Processes all attributes of a Literal Result Element.
|
||||||
|
* Attribute references are applied via xsl:use-attribute-set
|
||||||
|
* attributes.
|
||||||
|
* Copies all non XSLT-attributes over to the @target element
|
||||||
|
* and evaluates Attribute Value Templates.
|
||||||
|
*
|
||||||
|
* Called by xsltApplySequenceConstructor() (transform.c).
|
||||||
|
*
|
||||||
|
* Returns a new list of attribute nodes, or NULL in case of error.
|
||||||
|
* (Don't assign the result to @target->properties; if
|
||||||
|
* the result is NULL, you'll get memory leaks, since the
|
||||||
|
* attributes will be disattached.)
|
||||||
|
*/
|
||||||
|
xmlAttrPtr
|
||||||
|
xsltAttrListTemplateProcess(xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr target, xmlAttrPtr attrs)
|
||||||
|
{
|
||||||
|
xmlAttrPtr attr, copy, last = NULL;
|
||||||
|
xmlNodePtr oldInsert, text;
|
||||||
|
xmlNsPtr origNs = NULL, copyNs = NULL;
|
||||||
|
const xmlChar *value;
|
||||||
|
xmlChar *valueAVT;
|
||||||
|
int hasAttr = 0;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (target == NULL) || (attrs == NULL) ||
|
||||||
|
(target->type != XML_ELEMENT_NODE))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
oldInsert = ctxt->insert;
|
||||||
|
ctxt->insert = target;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Apply attribute-sets.
|
||||||
|
*/
|
||||||
|
attr = attrs;
|
||||||
|
do {
|
||||||
|
#ifdef XSLT_REFACTORED
|
||||||
|
if ((attr->psvi == xsltXSLTAttrMarker) &&
|
||||||
|
xmlStrEqual(attr->name, (const xmlChar *)"use-attribute-sets"))
|
||||||
|
{
|
||||||
|
xsltApplyAttributeSet(ctxt, ctxt->node, (xmlNodePtr) attr, NULL);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if ((attr->ns != NULL) &&
|
||||||
|
xmlStrEqual(attr->name, (const xmlChar *)"use-attribute-sets") &&
|
||||||
|
xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
|
||||||
|
{
|
||||||
|
xsltApplyAttributeSet(ctxt, ctxt->node, (xmlNodePtr) attr, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
attr = attr->next;
|
||||||
|
} while (attr != NULL);
|
||||||
|
|
||||||
|
if (target->properties != NULL) {
|
||||||
|
hasAttr = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instantiate LRE-attributes.
|
||||||
|
*/
|
||||||
|
attr = attrs;
|
||||||
|
do {
|
||||||
|
/*
|
||||||
|
* Skip XSLT attributes.
|
||||||
|
*/
|
||||||
|
#ifdef XSLT_REFACTORED
|
||||||
|
if (attr->psvi == xsltXSLTAttrMarker) {
|
||||||
|
goto next_attribute;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if ((attr->ns != NULL) &&
|
||||||
|
xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
|
||||||
|
{
|
||||||
|
goto next_attribute;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Get the value.
|
||||||
|
*/
|
||||||
|
if (attr->children != NULL) {
|
||||||
|
if ((attr->children->type != XML_TEXT_NODE) ||
|
||||||
|
(attr->children->next != NULL))
|
||||||
|
{
|
||||||
|
xsltTransformError(ctxt, NULL, attr->parent,
|
||||||
|
"Internal error: The children of an attribute node of a "
|
||||||
|
"literal result element are not in the expected form.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
value = attr->children->content;
|
||||||
|
if (value == NULL)
|
||||||
|
value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
|
||||||
|
} else
|
||||||
|
value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the namespace. Avoid lookups of same namespaces.
|
||||||
|
*/
|
||||||
|
if (attr->ns != origNs) {
|
||||||
|
origNs = attr->ns;
|
||||||
|
if (attr->ns != NULL) {
|
||||||
|
#ifdef XSLT_REFACTORED
|
||||||
|
copyNs = xsltGetSpecialNamespace(ctxt, attr->parent,
|
||||||
|
attr->ns->href, attr->ns->prefix, target);
|
||||||
|
#else
|
||||||
|
copyNs = xsltGetNamespace(ctxt, attr->parent,
|
||||||
|
attr->ns, target);
|
||||||
|
#endif
|
||||||
|
if (copyNs == NULL)
|
||||||
|
goto error;
|
||||||
|
} else
|
||||||
|
copyNs = NULL;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Create a new attribute.
|
||||||
|
*/
|
||||||
|
if (hasAttr) {
|
||||||
|
copy = xmlSetNsProp(target, copyNs, attr->name, NULL);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Avoid checking for duplicate attributes if there aren't
|
||||||
|
* any attribute sets.
|
||||||
|
*/
|
||||||
|
copy = xmlNewDocProp(target->doc, attr->name, NULL);
|
||||||
|
|
||||||
|
if (copy != NULL) {
|
||||||
|
copy->ns = copyNs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attach it to the target element.
|
||||||
|
*/
|
||||||
|
copy->parent = target;
|
||||||
|
if (last == NULL) {
|
||||||
|
target->properties = copy;
|
||||||
|
last = copy;
|
||||||
|
} else {
|
||||||
|
last->next = copy;
|
||||||
|
copy->prev = last;
|
||||||
|
last = copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (copy == NULL) {
|
||||||
|
if (attr->ns) {
|
||||||
|
xsltTransformError(ctxt, NULL, attr->parent,
|
||||||
|
"Internal error: Failed to create attribute '{%s}%s'.\n",
|
||||||
|
attr->ns->href, attr->name);
|
||||||
|
} else {
|
||||||
|
xsltTransformError(ctxt, NULL, attr->parent,
|
||||||
|
"Internal error: Failed to create attribute '%s'.\n",
|
||||||
|
attr->name);
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the value.
|
||||||
|
*/
|
||||||
|
text = xmlNewText(NULL);
|
||||||
|
if (text != NULL) {
|
||||||
|
copy->last = copy->children = text;
|
||||||
|
text->parent = (xmlNodePtr) copy;
|
||||||
|
text->doc = copy->doc;
|
||||||
|
|
||||||
|
if (attr->psvi != NULL) {
|
||||||
|
/*
|
||||||
|
* Evaluate the Attribute Value Template.
|
||||||
|
*/
|
||||||
|
valueAVT = xsltEvalAVT(ctxt, attr->psvi, attr->parent);
|
||||||
|
if (valueAVT == NULL) {
|
||||||
|
/*
|
||||||
|
* TODO: Damn, we need an easy mechanism to report
|
||||||
|
* qualified names!
|
||||||
|
*/
|
||||||
|
if (attr->ns) {
|
||||||
|
xsltTransformError(ctxt, NULL, attr->parent,
|
||||||
|
"Internal error: Failed to evaluate the AVT "
|
||||||
|
"of attribute '{%s}%s'.\n",
|
||||||
|
attr->ns->href, attr->name);
|
||||||
|
} else {
|
||||||
|
xsltTransformError(ctxt, NULL, attr->parent,
|
||||||
|
"Internal error: Failed to evaluate the AVT "
|
||||||
|
"of attribute '%s'.\n",
|
||||||
|
attr->name);
|
||||||
|
}
|
||||||
|
text->content = xmlStrdup(BAD_CAST "");
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
text->content = valueAVT;
|
||||||
|
}
|
||||||
|
} else if ((ctxt->internalized) &&
|
||||||
|
(target->doc != NULL) &&
|
||||||
|
(target->doc->dict == ctxt->dict) &&
|
||||||
|
xmlDictOwns(ctxt->dict, value))
|
||||||
|
{
|
||||||
|
text->content = (xmlChar *) value;
|
||||||
|
} else {
|
||||||
|
text->content = xmlStrdup(value);
|
||||||
|
}
|
||||||
|
if ((copy != NULL) && (text != NULL) &&
|
||||||
|
(xmlIsID(copy->doc, copy->parent, copy)))
|
||||||
|
xmlAddID(NULL, copy->doc, text->content, copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
next_attribute:
|
||||||
|
attr = attr->next;
|
||||||
|
} while (attr != NULL);
|
||||||
|
|
||||||
|
ctxt->insert = oldInsert;
|
||||||
|
return(target->properties);
|
||||||
|
|
||||||
|
error:
|
||||||
|
ctxt->insert = oldInsert;
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltTemplateProcess:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @node: the attribute template node
|
||||||
|
*
|
||||||
|
* Obsolete. Don't use it.
|
||||||
|
*
|
||||||
|
* Returns NULL.
|
||||||
|
*/
|
||||||
|
xmlNodePtr *
|
||||||
|
xsltTemplateProcess(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, xmlNodePtr node) {
|
||||||
|
if (node == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the template processing
|
||||||
|
* Description: This set of routine encapsulates XPath calls
|
||||||
|
* and Attribute Value Templates evaluation.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_TEMPLATES_H__
|
||||||
|
#define __XML_XSLT_TEMPLATES_H__
|
||||||
|
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltEvalXPathPredicate (xsltTransformContextPtr ctxt,
|
||||||
|
xmlXPathCompExprPtr comp,
|
||||||
|
xmlNsPtr *nsList,
|
||||||
|
int nsNr);
|
||||||
|
XSLTPUBFUN xmlChar * XSLTCALL
|
||||||
|
xsltEvalTemplateString (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr contextNode,
|
||||||
|
xmlNodePtr inst);
|
||||||
|
XSLTPUBFUN xmlChar * XSLTCALL
|
||||||
|
xsltEvalAttrValueTemplate (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *ns);
|
||||||
|
XSLTPUBFUN const xmlChar * XSLTCALL
|
||||||
|
xsltEvalStaticAttrValueTemplate (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr node,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *ns,
|
||||||
|
int *found);
|
||||||
|
|
||||||
|
/* TODO: this is obviously broken ... the namespaces should be passed too ! */
|
||||||
|
XSLTPUBFUN xmlChar * XSLTCALL
|
||||||
|
xsltEvalXPathString (xsltTransformContextPtr ctxt,
|
||||||
|
xmlXPathCompExprPtr comp);
|
||||||
|
XSLTPUBFUN xmlChar * XSLTCALL
|
||||||
|
xsltEvalXPathStringNs (xsltTransformContextPtr ctxt,
|
||||||
|
xmlXPathCompExprPtr comp,
|
||||||
|
int nsNr,
|
||||||
|
xmlNsPtr *nsList);
|
||||||
|
|
||||||
|
XSLTPUBFUN xmlNodePtr * XSLTCALL
|
||||||
|
xsltTemplateProcess (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node);
|
||||||
|
XSLTPUBFUN xmlAttrPtr XSLTCALL
|
||||||
|
xsltAttrListTemplateProcess (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr target,
|
||||||
|
xmlAttrPtr cur);
|
||||||
|
XSLTPUBFUN xmlAttrPtr XSLTCALL
|
||||||
|
xsltAttrTemplateProcess (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr target,
|
||||||
|
xmlAttrPtr attr);
|
||||||
|
XSLTPUBFUN xmlChar * XSLTCALL
|
||||||
|
xsltAttrTemplateValueProcess (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar* attr);
|
||||||
|
XSLTPUBFUN xmlChar * XSLTCALL
|
||||||
|
xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar* str,
|
||||||
|
xmlNodePtr node);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_TEMPLATES_H__ */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* Summary: the XSLT engine transformation part.
|
||||||
|
* Description: This module implements the bulk of the actual
|
||||||
|
* transformation processing. Most of the xsl: element
|
||||||
|
* constructs are implemented in this module.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_TRANSFORM_H__
|
||||||
|
#define __XML_XSLT_TRANSFORM_H__
|
||||||
|
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/xmlIO.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include <libxslt/xsltInternals.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XInclude default processing.
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSetXIncludeDefault (int xinclude);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltGetXIncludeDefault (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export context to users.
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN xsltTransformContextPtr XSLTCALL
|
||||||
|
xsltNewTransformContext (xsltStylesheetPtr style,
|
||||||
|
xmlDocPtr doc);
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeTransformContext(xsltTransformContextPtr ctxt);
|
||||||
|
|
||||||
|
XSLTPUBFUN xmlDocPtr XSLTCALL
|
||||||
|
xsltApplyStylesheetUser (xsltStylesheetPtr style,
|
||||||
|
xmlDocPtr doc,
|
||||||
|
const char **params,
|
||||||
|
const char *output,
|
||||||
|
FILE * profile,
|
||||||
|
xsltTransformContextPtr userCtxt);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltProcessOneNode (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xsltStackElemPtr params);
|
||||||
|
/**
|
||||||
|
* Private Interfaces.
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltApplyStripSpaces (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node);
|
||||||
|
XSLTPUBFUN xmlDocPtr XSLTCALL
|
||||||
|
xsltApplyStylesheet (xsltStylesheetPtr style,
|
||||||
|
xmlDocPtr doc,
|
||||||
|
const char **params);
|
||||||
|
XSLTPUBFUN xmlDocPtr XSLTCALL
|
||||||
|
xsltProfileStylesheet (xsltStylesheetPtr style,
|
||||||
|
xmlDocPtr doc,
|
||||||
|
const char **params,
|
||||||
|
FILE * output);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRunStylesheet (xsltStylesheetPtr style,
|
||||||
|
xmlDocPtr doc,
|
||||||
|
const char **params,
|
||||||
|
const char *output,
|
||||||
|
xmlSAXHandlerPtr SAX,
|
||||||
|
xmlOutputBufferPtr IObuf);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltRunStylesheetUser (xsltStylesheetPtr style,
|
||||||
|
xmlDocPtr doc,
|
||||||
|
const char **params,
|
||||||
|
const char *output,
|
||||||
|
xmlSAXHandlerPtr SAX,
|
||||||
|
xmlOutputBufferPtr IObuf,
|
||||||
|
FILE * profile,
|
||||||
|
xsltTransformContextPtr userCtxt);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltApplyOneTemplate (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr list,
|
||||||
|
xsltTemplatePtr templ,
|
||||||
|
xsltStackElemPtr params);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltDocumentElem (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSort (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltCopy (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltText (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltElement (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltComment (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltAttribute (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltProcessingInstruction(xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltCopyOf (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltValueOf (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltNumber (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltApplyImports (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltCallTemplate (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltApplyTemplates (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltChoose (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltIf (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltForEach (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst,
|
||||||
|
xsltElemPreCompPtr comp);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltRegisterAllElement (xsltTransformContextPtr ctxt);
|
||||||
|
|
||||||
|
XSLTPUBFUN xmlNodePtr XSLTCALL
|
||||||
|
xsltCopyTextString (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr target,
|
||||||
|
const xmlChar *string,
|
||||||
|
int noescape);
|
||||||
|
|
||||||
|
/* Following 2 functions needed for libexslt/functions.c */
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltLocalVariablePop (xsltTransformContextPtr ctxt,
|
||||||
|
int limitNr,
|
||||||
|
int level);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltLocalVariablePush (xsltTransformContextPtr ctxt,
|
||||||
|
xsltStackElemPtr variable,
|
||||||
|
int level);
|
||||||
|
/*
|
||||||
|
* Hook for the debugger if activated.
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xslHandleDebugger (xmlNodePtr cur,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xsltTemplatePtr templ,
|
||||||
|
xsltTransformContextPtr ctxt);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_TRANSFORM_H__ */
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
|
||||||
|
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
||||||
|
*
|
||||||
|
*************************************************************************
|
||||||
|
*
|
||||||
|
* http://ctrio.sourceforge.net/
|
||||||
|
*
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TRIO_TRIO_H
|
||||||
|
#define TRIO_TRIO_H
|
||||||
|
|
||||||
|
#if !defined(WITHOUT_TRIO)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use autoconf defines if present. Packages using trio must define
|
||||||
|
* HAVE_CONFIG_H as a compiler option themselves.
|
||||||
|
*/
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "triodef.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#if defined(TRIO_COMPILER_ANCIENT)
|
||||||
|
# include <varargs.h>
|
||||||
|
#else
|
||||||
|
# include <stdarg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Error codes.
|
||||||
|
*
|
||||||
|
* Remember to add a textual description to trio_strerror.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
TRIO_EOF = 1,
|
||||||
|
TRIO_EINVAL = 2,
|
||||||
|
TRIO_ETOOMANY = 3,
|
||||||
|
TRIO_EDBLREF = 4,
|
||||||
|
TRIO_EGAP = 5,
|
||||||
|
TRIO_ENOMEM = 6,
|
||||||
|
TRIO_ERANGE = 7,
|
||||||
|
TRIO_ERRNO = 8,
|
||||||
|
TRIO_ECUSTOM = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Error macros */
|
||||||
|
#define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF)
|
||||||
|
#define TRIO_ERROR_POSITION(x) ((-(x)) >> 8)
|
||||||
|
#define TRIO_ERROR_NAME(x) trio_strerror(x)
|
||||||
|
|
||||||
|
typedef int (*trio_outstream_t) TRIO_PROTO((trio_pointer_t, int));
|
||||||
|
typedef int (*trio_instream_t) TRIO_PROTO((trio_pointer_t));
|
||||||
|
|
||||||
|
TRIO_CONST char *trio_strerror TRIO_PROTO((int));
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Print Functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
int trio_printf TRIO_PROTO((TRIO_CONST char *format, ...));
|
||||||
|
int trio_vprintf TRIO_PROTO((TRIO_CONST char *format, va_list args));
|
||||||
|
int trio_printfv TRIO_PROTO((TRIO_CONST char *format, void **args));
|
||||||
|
|
||||||
|
int trio_fprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...));
|
||||||
|
int trio_vfprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args));
|
||||||
|
int trio_fprintfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args));
|
||||||
|
|
||||||
|
int trio_dprintf TRIO_PROTO((int fd, TRIO_CONST char *format, ...));
|
||||||
|
int trio_vdprintf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args));
|
||||||
|
int trio_dprintfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args));
|
||||||
|
|
||||||
|
int trio_cprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
|
||||||
|
TRIO_CONST char *format, ...));
|
||||||
|
int trio_vcprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
|
||||||
|
TRIO_CONST char *format, va_list args));
|
||||||
|
int trio_cprintfv TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
|
||||||
|
TRIO_CONST char *format, void **args));
|
||||||
|
|
||||||
|
int trio_sprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, ...));
|
||||||
|
int trio_vsprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, va_list args));
|
||||||
|
int trio_sprintfv TRIO_PROTO((char *buffer, TRIO_CONST char *format, void **args));
|
||||||
|
|
||||||
|
int trio_snprintf TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...));
|
||||||
|
int trio_vsnprintf TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
|
||||||
|
va_list args));
|
||||||
|
int trio_snprintfv TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
|
||||||
|
void **args));
|
||||||
|
|
||||||
|
int trio_snprintfcat TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...));
|
||||||
|
int trio_vsnprintfcat TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
|
||||||
|
va_list args));
|
||||||
|
|
||||||
|
char *trio_aprintf TRIO_PROTO((TRIO_CONST char *format, ...));
|
||||||
|
char *trio_vaprintf TRIO_PROTO((TRIO_CONST char *format, va_list args));
|
||||||
|
|
||||||
|
int trio_asprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, ...));
|
||||||
|
int trio_vasprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, va_list args));
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Scan Functions
|
||||||
|
*/
|
||||||
|
int trio_scanf TRIO_PROTO((TRIO_CONST char *format, ...));
|
||||||
|
int trio_vscanf TRIO_PROTO((TRIO_CONST char *format, va_list args));
|
||||||
|
int trio_scanfv TRIO_PROTO((TRIO_CONST char *format, void **args));
|
||||||
|
|
||||||
|
int trio_fscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...));
|
||||||
|
int trio_vfscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args));
|
||||||
|
int trio_fscanfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args));
|
||||||
|
|
||||||
|
int trio_dscanf TRIO_PROTO((int fd, TRIO_CONST char *format, ...));
|
||||||
|
int trio_vdscanf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args));
|
||||||
|
int trio_dscanfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args));
|
||||||
|
|
||||||
|
int trio_cscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
|
||||||
|
TRIO_CONST char *format, ...));
|
||||||
|
int trio_vcscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
|
||||||
|
TRIO_CONST char *format, va_list args));
|
||||||
|
int trio_cscanfv TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
|
||||||
|
TRIO_CONST char *format, void **args));
|
||||||
|
|
||||||
|
int trio_sscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, ...));
|
||||||
|
int trio_vsscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, va_list args));
|
||||||
|
int trio_sscanfv TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, void **args));
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Locale Functions
|
||||||
|
*/
|
||||||
|
void trio_locale_set_decimal_point TRIO_PROTO((char *decimalPoint));
|
||||||
|
void trio_locale_set_thousand_separator TRIO_PROTO((char *thousandSeparator));
|
||||||
|
void trio_locale_set_grouping TRIO_PROTO((char *grouping));
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Renaming
|
||||||
|
*/
|
||||||
|
#ifdef TRIO_REPLACE_STDIO
|
||||||
|
/* Replace the <stdio.h> functions */
|
||||||
|
#ifndef HAVE_PRINTF
|
||||||
|
# define printf trio_printf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_VPRINTF
|
||||||
|
# define vprintf trio_vprintf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_FPRINTF
|
||||||
|
# define fprintf trio_fprintf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_VFPRINTF
|
||||||
|
# define vfprintf trio_vfprintf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_SPRINTF
|
||||||
|
# define sprintf trio_sprintf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_VSPRINTF
|
||||||
|
# define vsprintf trio_vsprintf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_SNPRINTF
|
||||||
|
# define snprintf trio_snprintf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_VSNPRINTF
|
||||||
|
# define vsnprintf trio_vsnprintf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_SCANF
|
||||||
|
# define scanf trio_scanf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_VSCANF
|
||||||
|
# define vscanf trio_vscanf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_FSCANF
|
||||||
|
# define fscanf trio_fscanf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_VFSCANF
|
||||||
|
# define vfscanf trio_vfscanf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_SSCANF
|
||||||
|
# define sscanf trio_sscanf
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_VSSCANF
|
||||||
|
# define vsscanf trio_vsscanf
|
||||||
|
#endif
|
||||||
|
/* These aren't stdio functions, but we make them look similar */
|
||||||
|
#define dprintf trio_dprintf
|
||||||
|
#define vdprintf trio_vdprintf
|
||||||
|
#define aprintf trio_aprintf
|
||||||
|
#define vaprintf trio_vaprintf
|
||||||
|
#define asprintf trio_asprintf
|
||||||
|
#define vasprintf trio_vasprintf
|
||||||
|
#define dscanf trio_dscanf
|
||||||
|
#define vdscanf trio_vdscanf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* WITHOUT_TRIO */
|
||||||
|
|
||||||
|
#endif /* TRIO_TRIO_H */
|
|
@ -0,0 +1,220 @@
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
|
||||||
|
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
||||||
|
*
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TRIO_TRIODEF_H
|
||||||
|
#define TRIO_TRIODEF_H
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Platform and compiler support detection
|
||||||
|
*/
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define TRIO_COMPILER_GCC
|
||||||
|
#elif defined(__SUNPRO_C)
|
||||||
|
# define TRIO_COMPILER_SUNPRO
|
||||||
|
#elif defined(__SUNPRO_CC)
|
||||||
|
# define TRIO_COMPILER_SUNPRO
|
||||||
|
# define __SUNPRO_C __SUNPRO_CC
|
||||||
|
#elif defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__)
|
||||||
|
# define TRIO_COMPILER_XLC
|
||||||
|
#elif defined(_AIX) && !defined(__GNUC__)
|
||||||
|
# define TRIO_COMPILER_XLC /* Workaround for old xlc */
|
||||||
|
#elif defined(__DECC) || defined(__DECCXX)
|
||||||
|
# define TRIO_COMPILER_DECC
|
||||||
|
#elif defined(__osf__) && defined(__LANGUAGE_C__)
|
||||||
|
# define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define TRIO_COMPILER_MSVC
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
|
# define TRIO_COMPILER_BCB
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(VMS) || defined(__VMS)
|
||||||
|
/*
|
||||||
|
* VMS is placed first to avoid identifying the platform as Unix
|
||||||
|
* based on the DECC compiler later on.
|
||||||
|
*/
|
||||||
|
# define TRIO_PLATFORM_VMS
|
||||||
|
#elif defined(unix) || defined(__unix) || defined(__unix__)
|
||||||
|
# define TRIO_PLATFORM_UNIX
|
||||||
|
#elif defined(TRIO_COMPILER_XLC) || defined(_AIX)
|
||||||
|
# define TRIO_PLATFORM_UNIX
|
||||||
|
#elif defined(TRIO_COMPILER_DECC) || defined(__osf___)
|
||||||
|
# define TRIO_PLATFORM_UNIX
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
# define TRIO_PLATFORM_UNIX
|
||||||
|
#elif defined(__QNX__)
|
||||||
|
# define TRIO_PLATFORM_UNIX
|
||||||
|
# define TRIO_PLATFORM_QNX
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
# define TRIO_PLATFORM_UNIX
|
||||||
|
#elif defined(AMIGA) && defined(TRIO_COMPILER_GCC)
|
||||||
|
# define TRIO_PLATFORM_UNIX
|
||||||
|
#elif defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32)
|
||||||
|
# define TRIO_PLATFORM_WIN32
|
||||||
|
#elif defined(mpeix) || defined(__mpexl)
|
||||||
|
# define TRIO_PLATFORM_MPEIX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_AIX)
|
||||||
|
# define TRIO_PLATFORM_AIX
|
||||||
|
#elif defined(__hpux)
|
||||||
|
# define TRIO_PLATFORM_HPUX
|
||||||
|
#elif defined(sun) || defined(__sun__)
|
||||||
|
# if defined(__SVR4) || defined(__svr4__)
|
||||||
|
# define TRIO_PLATFORM_SOLARIS
|
||||||
|
# else
|
||||||
|
# define TRIO_PLATFORM_SUNOS
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__STDC__) || defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
|
||||||
|
# define TRIO_COMPILER_SUPPORTS_C89
|
||||||
|
# if defined(__STDC_VERSION__)
|
||||||
|
# define TRIO_COMPILER_SUPPORTS_C90
|
||||||
|
# if (__STDC_VERSION__ >= 199409L)
|
||||||
|
# define TRIO_COMPILER_SUPPORTS_C94
|
||||||
|
# endif
|
||||||
|
# if (__STDC_VERSION__ >= 199901L)
|
||||||
|
# define TRIO_COMPILER_SUPPORTS_C99
|
||||||
|
# endif
|
||||||
|
# elif defined(TRIO_COMPILER_SUNPRO)
|
||||||
|
# if (__SUNPRO_C >= 0x420)
|
||||||
|
# define TRIO_COMPILER_SUPPORTS_C94
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_XOPEN_SOURCE)
|
||||||
|
# if defined(_XOPEN_SOURCE_EXTENDED)
|
||||||
|
# define TRIO_COMPILER_SUPPORTS_UNIX95
|
||||||
|
# endif
|
||||||
|
# if (_XOPEN_VERSION >= 500)
|
||||||
|
# define TRIO_COMPILER_SUPPORTS_UNIX98
|
||||||
|
# endif
|
||||||
|
# if (_XOPEN_VERSION >= 600)
|
||||||
|
# define TRIO_COMPILER_SUPPORTS_UNIX01
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Generic defines
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(TRIO_PUBLIC)
|
||||||
|
# define TRIO_PUBLIC
|
||||||
|
#endif
|
||||||
|
#if !defined(TRIO_PRIVATE)
|
||||||
|
# define TRIO_PRIVATE static
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !(defined(TRIO_COMPILER_SUPPORTS_C89) || defined(__cplusplus))
|
||||||
|
# define TRIO_COMPILER_ANCIENT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TRIO_COMPILER_ANCIENT)
|
||||||
|
# define TRIO_CONST
|
||||||
|
# define TRIO_VOLATILE
|
||||||
|
# define TRIO_SIGNED
|
||||||
|
typedef double trio_long_double_t;
|
||||||
|
typedef char * trio_pointer_t;
|
||||||
|
# define TRIO_SUFFIX_LONG(x) x
|
||||||
|
# define TRIO_PROTO(x) ()
|
||||||
|
# define TRIO_NOARGS
|
||||||
|
# define TRIO_ARGS1(list,a1) list a1;
|
||||||
|
# define TRIO_ARGS2(list,a1,a2) list a1; a2;
|
||||||
|
# define TRIO_ARGS3(list,a1,a2,a3) list a1; a2; a3;
|
||||||
|
# define TRIO_ARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4;
|
||||||
|
# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5;
|
||||||
|
# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) list a1; a2; a3; a4; a5; a6;
|
||||||
|
# define TRIO_VARGS2(list,a1,a2) list a1; a2
|
||||||
|
# define TRIO_VARGS3(list,a1,a2,a3) list a1; a2; a3
|
||||||
|
# define TRIO_VARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4
|
||||||
|
# define TRIO_VARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5
|
||||||
|
# define TRIO_VA_DECL va_dcl
|
||||||
|
# define TRIO_VA_START(x,y) va_start(x)
|
||||||
|
# define TRIO_VA_END(x) va_end(x)
|
||||||
|
#else /* ANSI C */
|
||||||
|
# define TRIO_CONST const
|
||||||
|
# define TRIO_VOLATILE volatile
|
||||||
|
# define TRIO_SIGNED signed
|
||||||
|
typedef long double trio_long_double_t;
|
||||||
|
typedef void * trio_pointer_t;
|
||||||
|
# define TRIO_SUFFIX_LONG(x) x ## L
|
||||||
|
# define TRIO_PROTO(x) x
|
||||||
|
# define TRIO_NOARGS void
|
||||||
|
# define TRIO_ARGS1(list,a1) (a1)
|
||||||
|
# define TRIO_ARGS2(list,a1,a2) (a1,a2)
|
||||||
|
# define TRIO_ARGS3(list,a1,a2,a3) (a1,a2,a3)
|
||||||
|
# define TRIO_ARGS4(list,a1,a2,a3,a4) (a1,a2,a3,a4)
|
||||||
|
# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) (a1,a2,a3,a4,a5)
|
||||||
|
# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) (a1,a2,a3,a4,a5,a6)
|
||||||
|
# define TRIO_VARGS2 TRIO_ARGS2
|
||||||
|
# define TRIO_VARGS3 TRIO_ARGS3
|
||||||
|
# define TRIO_VARGS4 TRIO_ARGS4
|
||||||
|
# define TRIO_VARGS5 TRIO_ARGS5
|
||||||
|
# define TRIO_VA_DECL ...
|
||||||
|
# define TRIO_VA_START(x,y) va_start(x,y)
|
||||||
|
# define TRIO_VA_END(x) va_end(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TRIO_COMPILER_SUPPORTS_C99) || defined(__cplusplus)
|
||||||
|
# define TRIO_INLINE inline
|
||||||
|
#elif defined(TRIO_COMPILER_GCC)
|
||||||
|
# define TRIO_INLINE __inline__
|
||||||
|
#elif defined(TRIO_COMPILER_MSVC)
|
||||||
|
# define TRIO_INLINE _inline
|
||||||
|
#elif defined(TRIO_COMPILER_BCB)
|
||||||
|
# define TRIO_INLINE __inline
|
||||||
|
#else
|
||||||
|
# define TRIO_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Workarounds
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(TRIO_PLATFORM_VMS)
|
||||||
|
/*
|
||||||
|
* Computations done with constants at compile time can trigger these
|
||||||
|
* even when compiling with IEEE enabled.
|
||||||
|
*/
|
||||||
|
# pragma message disable (UNDERFLOW, FLOATOVERFL)
|
||||||
|
|
||||||
|
# if (__CRTL_VER < 80000000)
|
||||||
|
/*
|
||||||
|
* Although the compiler supports C99 language constructs, the C
|
||||||
|
* run-time library does not contain all C99 functions.
|
||||||
|
*
|
||||||
|
* This was the case for 70300022. Update the 80000000 value when
|
||||||
|
* it has been accurately determined what version of the library
|
||||||
|
* supports C99.
|
||||||
|
*/
|
||||||
|
# if defined(TRIO_COMPILER_SUPPORTS_C99)
|
||||||
|
# undef TRIO_COMPILER_SUPPORTS_C99
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not all preprocessors supports the LL token.
|
||||||
|
*/
|
||||||
|
#if defined(TRIO_COMPILER_BCB)
|
||||||
|
#else
|
||||||
|
# define TRIO_COMPILER_SUPPORTS_LL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* TRIO_TRIODEF_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Summary: interface for the variable matching and lookup.
|
||||||
|
* Description: interface for the variable matching and lookup.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_VARIABLES_H__
|
||||||
|
#define __XML_XSLT_VARIABLES_H__
|
||||||
|
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "functions.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_REGISTER_VARIABLE_LOOKUP:
|
||||||
|
*
|
||||||
|
* Registering macro, not general purpose at all but used in different modules.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define XSLT_REGISTER_VARIABLE_LOOKUP(ctxt) \
|
||||||
|
xmlXPathRegisterVariableLookup((ctxt)->xpathCtxt, \
|
||||||
|
xsltXPathVariableLookup, (void *)(ctxt)); \
|
||||||
|
xsltRegisterAllFunctions((ctxt)->xpathCtxt); \
|
||||||
|
xsltRegisterAllElement(ctxt); \
|
||||||
|
(ctxt)->xpathCtxt->extra = ctxt
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flags for memory management of RVTs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_RVT_LOCAL:
|
||||||
|
*
|
||||||
|
* RVT is destroyed after the current instructions ends.
|
||||||
|
*/
|
||||||
|
#define XSLT_RVT_LOCAL ((void *)1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_RVT_FUNC_RESULT:
|
||||||
|
*
|
||||||
|
* RVT is part of results returned with func:result. The RVT won't be
|
||||||
|
* destroyed after exiting a template and will be reset to XSLT_RVT_LOCAL or
|
||||||
|
* XSLT_RVT_VARIABLE in the template that receives the return value.
|
||||||
|
*/
|
||||||
|
#define XSLT_RVT_FUNC_RESULT ((void *)2)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_RVT_GLOBAL:
|
||||||
|
*
|
||||||
|
* RVT is part of a global variable.
|
||||||
|
*/
|
||||||
|
#define XSLT_RVT_GLOBAL ((void *)3)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interfaces for the variable module.
|
||||||
|
*/
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltEvalGlobalVariables (xsltTransformContextPtr ctxt);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltEvalUserParams (xsltTransformContextPtr ctxt,
|
||||||
|
const char **params);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltQuoteUserParams (xsltTransformContextPtr ctxt,
|
||||||
|
const char **params);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltEvalOneUserParam (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar * name,
|
||||||
|
const xmlChar * value);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltQuoteOneUserParam (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar * name,
|
||||||
|
const xmlChar * value);
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltParseGlobalVariable (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr cur);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltParseGlobalParam (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr cur);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltParseStylesheetVariable (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr cur);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltParseStylesheetParam (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr cur);
|
||||||
|
XSLTPUBFUN xsltStackElemPtr XSLTCALL
|
||||||
|
xsltParseStylesheetCallerParam (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr cur);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltAddStackElemList (xsltTransformContextPtr ctxt,
|
||||||
|
xsltStackElemPtr elems);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeGlobalVariables (xsltTransformContextPtr ctxt);
|
||||||
|
XSLTPUBFUN xmlXPathObjectPtr XSLTCALL
|
||||||
|
xsltVariableLookup (xsltTransformContextPtr ctxt,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *ns_uri);
|
||||||
|
XSLTPUBFUN xmlXPathObjectPtr XSLTCALL
|
||||||
|
xsltXPathVariableLookup (void *ctxt,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *ns_uri);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_VARIABLES_H__ */
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
* Summary: Windows configuration header
|
||||||
|
* Description: Windows configuration header
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Igor Zlatkovic
|
||||||
|
*/
|
||||||
|
#ifndef __LIBXSLT_WIN32_CONFIG__
|
||||||
|
#define __LIBXSLT_WIN32_CONFIG__
|
||||||
|
|
||||||
|
#define HAVE_CTYPE_H 1
|
||||||
|
#define HAVE_STDLIB_H 1
|
||||||
|
#define HAVE_STDARG_H 1
|
||||||
|
#define HAVE_MALLOC_H 1
|
||||||
|
#define HAVE_TIME_H 1
|
||||||
|
#define HAVE_LOCALTIME 1
|
||||||
|
#define HAVE_GMTIME 1
|
||||||
|
#define HAVE_TIME 1
|
||||||
|
#define HAVE_MATH_H 1
|
||||||
|
#define HAVE_FCNTL_H 1
|
||||||
|
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#define HAVE_ISINF
|
||||||
|
#define HAVE_ISNAN
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* MS C-runtime has functions which can be used in order to determine if
|
||||||
|
a given floating-point variable contains NaN, (+-)INF. These are
|
||||||
|
preferred, because floating-point technology is considered propriatary
|
||||||
|
by MS and we can assume that their functions know more about their
|
||||||
|
oddities than we do. */
|
||||||
|
#include <float.h>
|
||||||
|
/* Bjorn Reese figured a quite nice construct for isinf() using the
|
||||||
|
_fpclass() function. */
|
||||||
|
#ifndef isinf
|
||||||
|
#define isinf(d) ((_fpclass(d) == _FPCLASS_PINF) ? 1 \
|
||||||
|
: ((_fpclass(d) == _FPCLASS_NINF) ? -1 : 0))
|
||||||
|
#endif
|
||||||
|
/* _isnan(x) returns nonzero if (x == NaN) and zero otherwise. */
|
||||||
|
#ifndef isnan
|
||||||
|
#define isnan(d) (_isnan(d))
|
||||||
|
#endif
|
||||||
|
#else /* _MSC_VER */
|
||||||
|
static int isinf (double d) {
|
||||||
|
int expon = 0;
|
||||||
|
double val = frexp (d, &expon);
|
||||||
|
if (expon == 1025) {
|
||||||
|
if (val == 0.5) {
|
||||||
|
return 1;
|
||||||
|
} else if (val == -0.5) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static int isnan (double d) {
|
||||||
|
int expon = 0;
|
||||||
|
double val = frexp (d, &expon);
|
||||||
|
if (expon == 1025) {
|
||||||
|
if (val == 0.5) {
|
||||||
|
return 0;
|
||||||
|
} else if (val == -0.5) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
|
#include <direct.h>
|
||||||
|
|
||||||
|
/* snprintf emulation taken from http://stackoverflow.com/a/8712996/1956010 */
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define snprintf c99_snprintf
|
||||||
|
#define vsnprintf c99_vsnprintf
|
||||||
|
|
||||||
|
__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
|
||||||
|
{
|
||||||
|
int count = -1;
|
||||||
|
|
||||||
|
if (size != 0)
|
||||||
|
count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
|
||||||
|
if (count == -1)
|
||||||
|
count = _vscprintf(format, ap);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
count = c99_vsnprintf(outBuf, size, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined(_MSC_VER) && _MSC_VER < 1900 */
|
||||||
|
|
||||||
|
#define HAVE_SYS_STAT_H
|
||||||
|
#define HAVE_STAT
|
||||||
|
#define HAVE_STRING_H
|
||||||
|
|
||||||
|
#include <libxml/xmlversion.h>
|
||||||
|
|
||||||
|
#ifndef ATTRIBUTE_UNUSED
|
||||||
|
#define ATTRIBUTE_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _WINSOCKAPI_
|
||||||
|
|
||||||
|
#endif /* __LIBXSLT_WIN32_CONFIG__ */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* Summary: Interfaces, constants and types related to the XSLT engine
|
||||||
|
* Description: Interfaces, constants and types related to the XSLT engine
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_H__
|
||||||
|
#define __XML_XSLT_H__
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_DEFAULT_VERSION:
|
||||||
|
*
|
||||||
|
* The default version of XSLT supported.
|
||||||
|
*/
|
||||||
|
#define XSLT_DEFAULT_VERSION "1.0"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_DEFAULT_VENDOR:
|
||||||
|
*
|
||||||
|
* The XSLT "vendor" string for this processor.
|
||||||
|
*/
|
||||||
|
#define XSLT_DEFAULT_VENDOR "libxslt"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_DEFAULT_URL:
|
||||||
|
*
|
||||||
|
* The XSLT "vendor" URL for this processor.
|
||||||
|
*/
|
||||||
|
#define XSLT_DEFAULT_URL "http://xmlsoft.org/XSLT/"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_NAMESPACE:
|
||||||
|
*
|
||||||
|
* The XSLT specification namespace.
|
||||||
|
*/
|
||||||
|
#define XSLT_NAMESPACE ((const xmlChar *)"http://www.w3.org/1999/XSL/Transform")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_PARSE_OPTIONS:
|
||||||
|
*
|
||||||
|
* The set of options to pass to an xmlReadxxx when loading files for
|
||||||
|
* XSLT consumption.
|
||||||
|
*/
|
||||||
|
#define XSLT_PARSE_OPTIONS \
|
||||||
|
XML_PARSE_NOENT | XML_PARSE_DTDLOAD | XML_PARSE_DTDATTR | XML_PARSE_NOCDATA
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltMaxDepth:
|
||||||
|
*
|
||||||
|
* This value is used to detect templates loops.
|
||||||
|
*/
|
||||||
|
XSLTPUBVAR int xsltMaxDepth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * xsltMaxVars:
|
||||||
|
* *
|
||||||
|
* * This value is used to detect templates loops.
|
||||||
|
* */
|
||||||
|
XSLTPUBVAR int xsltMaxVars;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltEngineVersion:
|
||||||
|
*
|
||||||
|
* The version string for libxslt.
|
||||||
|
*/
|
||||||
|
XSLTPUBVAR const char *xsltEngineVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltLibxsltVersion:
|
||||||
|
*
|
||||||
|
* The version of libxslt compiled.
|
||||||
|
*/
|
||||||
|
XSLTPUBVAR const int xsltLibxsltVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltLibxmlVersion:
|
||||||
|
*
|
||||||
|
* The version of libxml libxslt was compiled against.
|
||||||
|
*/
|
||||||
|
XSLTPUBVAR const int xsltLibxmlVersion;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global initialization function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltInit (void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global cleanup function.
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltCleanupGlobals (void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_H__ */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,180 @@
|
||||||
|
/*
|
||||||
|
* Summary: compile-time version information for the XSLT engine
|
||||||
|
* Description: compile-time version information for the XSLT engine
|
||||||
|
* this module is autogenerated.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLTCONFIG_H__
|
||||||
|
#define __XML_XSLTCONFIG_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LIBXSLT_DOTTED_VERSION:
|
||||||
|
*
|
||||||
|
* the version string like "1.2.3"
|
||||||
|
*/
|
||||||
|
#define LIBXSLT_DOTTED_VERSION "1.1.34"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LIBXSLT_VERSION:
|
||||||
|
*
|
||||||
|
* the version number: 1.2.3 value is 10203
|
||||||
|
*/
|
||||||
|
#define LIBXSLT_VERSION 10134
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LIBXSLT_VERSION_STRING:
|
||||||
|
*
|
||||||
|
* the version number string, 1.2.3 value is "10203"
|
||||||
|
*/
|
||||||
|
#define LIBXSLT_VERSION_STRING "10134"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LIBXSLT_VERSION_EXTRA:
|
||||||
|
*
|
||||||
|
* extra version information, used to show a CVS compilation
|
||||||
|
*/
|
||||||
|
#define LIBXSLT_VERSION_EXTRA ""
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WITH_XSLT_DEBUG:
|
||||||
|
*
|
||||||
|
* Activate the compilation of the debug reporting. Speed penalty
|
||||||
|
* is insignifiant and being able to run xsltpoc -v is useful. On
|
||||||
|
* by default unless --without-debug is passed to configure
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
#define WITH_XSLT_DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/**
|
||||||
|
* DEBUG_MEMORY:
|
||||||
|
*
|
||||||
|
* should be activated only when debugging libxslt. It replaces the
|
||||||
|
* allocator with a collect and debug shell to the libc allocator.
|
||||||
|
* Use configure --with-mem-debug to activate it on both library
|
||||||
|
*/
|
||||||
|
#define DEBUG_MEMORY
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEBUG_MEMORY_LOCATION:
|
||||||
|
*
|
||||||
|
* should be activated only when debugging libxslt.
|
||||||
|
* DEBUG_MEMORY_LOCATION should be activated only when libxml has
|
||||||
|
* been configured with --with-debug-mem too
|
||||||
|
*/
|
||||||
|
#define DEBUG_MEMORY_LOCATION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_NEED_TRIO:
|
||||||
|
*
|
||||||
|
* should be activated if the existing libc library lacks some of the
|
||||||
|
* string formatting function, in that case reuse the Trio ones already
|
||||||
|
* compiled in the libxml2 library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define XSLT_NEED_TRIO
|
||||||
|
#endif
|
||||||
|
#ifdef __VMS
|
||||||
|
#define HAVE_MATH_H 1
|
||||||
|
#define HAVE_SYS_STAT_H 1
|
||||||
|
#ifndef XSLT_NEED_TRIO
|
||||||
|
#define XSLT_NEED_TRIO
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XSLT_NEED_TRIO
|
||||||
|
#define TRIO_REPLACE_STDIO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WITH_XSLT_DEBUGGER:
|
||||||
|
*
|
||||||
|
* Activate the compilation of the debugger support. Speed penalty
|
||||||
|
* is insignifiant.
|
||||||
|
* On by default unless --without-debugger is passed to configure
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
#ifndef WITH_DEBUGGER
|
||||||
|
#define WITH_DEBUGGER
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WITH_PROFILER:
|
||||||
|
*
|
||||||
|
* Activate the compilation of the profiler. Speed penalty
|
||||||
|
* is insignifiant.
|
||||||
|
* On by default unless --without-profiler is passed to configure
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
#ifndef WITH_PROFILER
|
||||||
|
#define WITH_PROFILER
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WITH_MODULES:
|
||||||
|
*
|
||||||
|
* Whether module support is configured into libxslt
|
||||||
|
* Note: no default module path for win32 platforms
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
#ifndef WITH_MODULES
|
||||||
|
#define WITH_MODULES
|
||||||
|
#endif
|
||||||
|
#define LIBXSLT_DEFAULT_PLUGINS_PATH() "/usr/local/lib/libxslt-plugins"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ATTRIBUTE_UNUSED:
|
||||||
|
*
|
||||||
|
* This macro is used to flag unused function parameters to GCC
|
||||||
|
*/
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#ifndef ATTRIBUTE_UNUSED
|
||||||
|
#define ATTRIBUTE_UNUSED __attribute__((unused))
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define ATTRIBUTE_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LIBXSLT_ATTR_FORMAT:
|
||||||
|
*
|
||||||
|
* This macro is used to indicate to GCC the parameters are printf-like
|
||||||
|
*/
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define LIBXSLT_ATTR_FORMAT(fmt,args) __attribute__((__format__(__printf__,fmt,args)))
|
||||||
|
#else
|
||||||
|
#define LIBXSLT_ATTR_FORMAT(fmt,args)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LIBXSLT_PUBLIC:
|
||||||
|
*
|
||||||
|
* This macro is used to declare PUBLIC variables for Cygwin and for MSC on Windows
|
||||||
|
*/
|
||||||
|
#if !defined LIBXSLT_PUBLIC
|
||||||
|
#if (defined(__CYGWIN__) || defined _MSC_VER) && !defined IN_LIBXSLT && !defined LIBXSLT_STATIC
|
||||||
|
#define LIBXSLT_PUBLIC __declspec(dllimport)
|
||||||
|
#else
|
||||||
|
#define LIBXSLT_PUBLIC
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLTCONFIG_H__ */
|
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* Summary: macros for marking symbols as exportable/importable.
|
||||||
|
* Description: macros for marking symbols as exportable/importable.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Igor Zlatkovic <igor@zlatkovic.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XSLT_EXPORTS_H__
|
||||||
|
#define __XSLT_EXPORTS_H__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLTPUBFUN:
|
||||||
|
* XSLTPUBFUN, XSLTPUBVAR, XSLTCALL
|
||||||
|
*
|
||||||
|
* Macros which declare an exportable function, an exportable variable and
|
||||||
|
* the calling convention used for functions.
|
||||||
|
*
|
||||||
|
* Please use an extra block for every platform/compiler combination when
|
||||||
|
* modifying this, rather than overlong #ifdef lines. This helps
|
||||||
|
* readability as well as the fact that different compilers on the same
|
||||||
|
* platform might need different definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLTPUBFUN:
|
||||||
|
*
|
||||||
|
* Macros which declare an exportable function
|
||||||
|
*/
|
||||||
|
#define XSLTPUBFUN
|
||||||
|
/**
|
||||||
|
* XSLTPUBVAR:
|
||||||
|
*
|
||||||
|
* Macros which declare an exportable variable
|
||||||
|
*/
|
||||||
|
#define XSLTPUBVAR extern
|
||||||
|
/**
|
||||||
|
* XSLTCALL:
|
||||||
|
*
|
||||||
|
* Macros which declare the called convention for exported functions
|
||||||
|
*/
|
||||||
|
#define XSLTCALL
|
||||||
|
|
||||||
|
/** DOC_DISABLE */
|
||||||
|
|
||||||
|
/* Windows platform with MS compiler */
|
||||||
|
#if defined(_WIN32) && defined(_MSC_VER)
|
||||||
|
#undef XSLTPUBFUN
|
||||||
|
#undef XSLTPUBVAR
|
||||||
|
#undef XSLTCALL
|
||||||
|
#if defined(IN_LIBXSLT) && !defined(LIBXSLT_STATIC)
|
||||||
|
#define XSLTPUBFUN __declspec(dllexport)
|
||||||
|
#define XSLTPUBVAR __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define XSLTPUBFUN
|
||||||
|
#if !defined(LIBXSLT_STATIC)
|
||||||
|
#define XSLTPUBVAR __declspec(dllimport) extern
|
||||||
|
#else
|
||||||
|
#define XSLTPUBVAR extern
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#define XSLTCALL __cdecl
|
||||||
|
#if !defined _REENTRANT
|
||||||
|
#define _REENTRANT
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Windows platform with Borland compiler */
|
||||||
|
#if defined(_WIN32) && defined(__BORLANDC__)
|
||||||
|
#undef XSLTPUBFUN
|
||||||
|
#undef XSLTPUBVAR
|
||||||
|
#undef XSLTCALL
|
||||||
|
#if defined(IN_LIBXSLT) && !defined(LIBXSLT_STATIC)
|
||||||
|
#define XSLTPUBFUN __declspec(dllexport)
|
||||||
|
#define XSLTPUBVAR __declspec(dllexport) extern
|
||||||
|
#else
|
||||||
|
#define XSLTPUBFUN
|
||||||
|
#if !defined(LIBXSLT_STATIC)
|
||||||
|
#define XSLTPUBVAR __declspec(dllimport) extern
|
||||||
|
#else
|
||||||
|
#define XSLTPUBVAR extern
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#define XSLTCALL __cdecl
|
||||||
|
#if !defined _REENTRANT
|
||||||
|
#define _REENTRANT
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Windows platform with GNU compiler (Mingw) */
|
||||||
|
#if defined(_WIN32) && defined(__MINGW32__)
|
||||||
|
#undef XSLTPUBFUN
|
||||||
|
#undef XSLTPUBVAR
|
||||||
|
#undef XSLTCALL
|
||||||
|
/*
|
||||||
|
#if defined(IN_LIBXSLT) && !defined(LIBXSLT_STATIC)
|
||||||
|
*/
|
||||||
|
#if !defined(LIBXSLT_STATIC)
|
||||||
|
#define XSLTPUBFUN __declspec(dllexport)
|
||||||
|
#define XSLTPUBVAR __declspec(dllexport) extern
|
||||||
|
#else
|
||||||
|
#define XSLTPUBFUN
|
||||||
|
#if !defined(LIBXSLT_STATIC)
|
||||||
|
#define XSLTPUBVAR __declspec(dllimport) extern
|
||||||
|
#else
|
||||||
|
#define XSLTPUBVAR extern
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#define XSLTCALL __cdecl
|
||||||
|
#if !defined _REENTRANT
|
||||||
|
#define _REENTRANT
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Cygwin platform (does not define _WIN32), GNU compiler */
|
||||||
|
#if defined(__CYGWIN__)
|
||||||
|
#undef XSLTPUBFUN
|
||||||
|
#undef XSLTPUBVAR
|
||||||
|
#undef XSLTCALL
|
||||||
|
#if defined(IN_LIBXSLT) && !defined(LIBXSLT_STATIC)
|
||||||
|
#define XSLTPUBFUN __declspec(dllexport)
|
||||||
|
#define XSLTPUBVAR __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define XSLTPUBFUN
|
||||||
|
#if !defined(LIBXSLT_STATIC)
|
||||||
|
#define XSLTPUBVAR __declspec(dllimport) extern
|
||||||
|
#else
|
||||||
|
#define XSLTPUBVAR extern
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#define XSLTCALL __cdecl
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Compatibility */
|
||||||
|
#if !defined(LIBXSLT_PUBLIC)
|
||||||
|
#define LIBXSLT_PUBLIC XSLTPUBVAR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XSLT_EXPORTS_H__ */
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,520 @@
|
||||||
|
/*
|
||||||
|
* xsltlocale.c: locale handling
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* RFC 3066: Tags for the Identification of Languages
|
||||||
|
* http://www.ietf.org/rfc/rfc3066.txt
|
||||||
|
* ISO 639-1, ISO 3166-1
|
||||||
|
*
|
||||||
|
* Author: Nick Wellnhofer
|
||||||
|
* winapi port: Roumen Petrov
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IN_LIBXSLT
|
||||||
|
#include "libxslt.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
|
||||||
|
#include "xsltlocale.h"
|
||||||
|
#include "xsltutils.h"
|
||||||
|
|
||||||
|
#define TOUPPER(c) (c & ~0x20)
|
||||||
|
#define TOLOWER(c) (c | 0x20)
|
||||||
|
#define ISALPHA(c) ((unsigned)(TOUPPER(c) - 'A') < 26)
|
||||||
|
|
||||||
|
/*without terminating null character*/
|
||||||
|
#define XSLTMAX_ISO639LANGLEN 8
|
||||||
|
#define XSLTMAX_ISO3166CNTRYLEN 8
|
||||||
|
/* <lang>-<cntry> */
|
||||||
|
#define XSLTMAX_LANGTAGLEN (XSLTMAX_ISO639LANGLEN+1+XSLTMAX_ISO3166CNTRYLEN)
|
||||||
|
|
||||||
|
static const xmlChar* xsltDefaultRegion(const xmlChar *localeName);
|
||||||
|
|
||||||
|
#ifdef XSLT_LOCALE_WINAPI
|
||||||
|
xmlRMutexPtr xsltLocaleMutex = NULL;
|
||||||
|
|
||||||
|
struct xsltRFC1766Info_s {
|
||||||
|
/*note typedef unsigned char xmlChar !*/
|
||||||
|
xmlChar tag[XSLTMAX_LANGTAGLEN+1];
|
||||||
|
/*note typedef LCID xsltLocale !*/
|
||||||
|
xsltLocale lcid;
|
||||||
|
};
|
||||||
|
typedef struct xsltRFC1766Info_s xsltRFC1766Info;
|
||||||
|
|
||||||
|
static int xsltLocaleListSize = 0;
|
||||||
|
static xsltRFC1766Info *xsltLocaleList = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static xsltLocale
|
||||||
|
xslt_locale_WINAPI(const xmlChar *languageTag) {
|
||||||
|
int k;
|
||||||
|
xsltRFC1766Info *p = xsltLocaleList;
|
||||||
|
|
||||||
|
for (k=0; k<xsltLocaleListSize; k++, p++)
|
||||||
|
if (xmlStrcmp(p->tag, languageTag) == 0) return p->lcid;
|
||||||
|
return((xsltLocale)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xsltEnumSupportedLocales(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeLocales:
|
||||||
|
*
|
||||||
|
* Cleanup function for the locale support on shutdown
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeLocales(void) {
|
||||||
|
#ifdef XSLT_LOCALE_WINAPI
|
||||||
|
xmlRMutexLock(xsltLocaleMutex);
|
||||||
|
xmlFree(xsltLocaleList);
|
||||||
|
xsltLocaleList = NULL;
|
||||||
|
xmlRMutexUnlock(xsltLocaleMutex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNewLocale:
|
||||||
|
* @languageTag: RFC 3066 language tag
|
||||||
|
*
|
||||||
|
* Creates a new locale of an opaque system dependent type based on the
|
||||||
|
* language tag.
|
||||||
|
*
|
||||||
|
* Returns the locale or NULL on error or if no matching locale was found
|
||||||
|
*/
|
||||||
|
xsltLocale
|
||||||
|
xsltNewLocale(const xmlChar *languageTag) {
|
||||||
|
#ifdef XSLT_LOCALE_POSIX
|
||||||
|
xsltLocale locale;
|
||||||
|
char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */
|
||||||
|
const xmlChar *p = languageTag;
|
||||||
|
const char *region = NULL;
|
||||||
|
char *q = localeName;
|
||||||
|
int i, llen;
|
||||||
|
|
||||||
|
/* Convert something like "pt-br" to "pt_BR.utf8" */
|
||||||
|
|
||||||
|
if (languageTag == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
|
||||||
|
*q++ = TOLOWER(*p++);
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
llen = i;
|
||||||
|
|
||||||
|
if (*p) {
|
||||||
|
if (*p++ != '-')
|
||||||
|
return(NULL);
|
||||||
|
*q++ = '_';
|
||||||
|
|
||||||
|
for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
|
||||||
|
*q++ = TOUPPER(*p++);
|
||||||
|
|
||||||
|
if (i == 0 || *p)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
memcpy(q, ".utf8", 6);
|
||||||
|
locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
|
||||||
|
if (locale != NULL)
|
||||||
|
return(locale);
|
||||||
|
|
||||||
|
/* Continue without using country code */
|
||||||
|
|
||||||
|
q = localeName + llen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try locale without territory, e.g. for Esperanto (eo) */
|
||||||
|
|
||||||
|
memcpy(q, ".utf8", 6);
|
||||||
|
locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
|
||||||
|
if (locale != NULL)
|
||||||
|
return(locale);
|
||||||
|
|
||||||
|
/* Try to find most common country for language */
|
||||||
|
|
||||||
|
if (llen != 2)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
region = (char *)xsltDefaultRegion((xmlChar *)localeName);
|
||||||
|
if (region == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
q = localeName + llen;
|
||||||
|
*q++ = '_';
|
||||||
|
*q++ = region[0];
|
||||||
|
*q++ = region[1];
|
||||||
|
memcpy(q, ".utf8", 6);
|
||||||
|
locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
|
||||||
|
|
||||||
|
return(locale);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XSLT_LOCALE_WINAPI
|
||||||
|
{
|
||||||
|
xsltLocale locale = (xsltLocale)0;
|
||||||
|
xmlChar localeName[XSLTMAX_LANGTAGLEN+1];
|
||||||
|
xmlChar *q = localeName;
|
||||||
|
const xmlChar *p = languageTag;
|
||||||
|
int i, llen;
|
||||||
|
const xmlChar *region = NULL;
|
||||||
|
|
||||||
|
if (languageTag == NULL) goto end;
|
||||||
|
|
||||||
|
xsltEnumSupportedLocales();
|
||||||
|
|
||||||
|
for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
|
||||||
|
*q++ = TOLOWER(*p++);
|
||||||
|
if (i == 0) goto end;
|
||||||
|
|
||||||
|
llen = i;
|
||||||
|
*q++ = '-';
|
||||||
|
if (*p) { /*if country tag is given*/
|
||||||
|
if (*p++ != '-') goto end;
|
||||||
|
|
||||||
|
for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
|
||||||
|
*q++ = TOUPPER(*p++);
|
||||||
|
if (i == 0 || *p) goto end;
|
||||||
|
|
||||||
|
*q = '\0';
|
||||||
|
locale = xslt_locale_WINAPI(localeName);
|
||||||
|
if (locale != (xsltLocale)0) goto end;
|
||||||
|
}
|
||||||
|
/* Try to find most common country for language */
|
||||||
|
region = xsltDefaultRegion(localeName);
|
||||||
|
if (region == NULL) goto end;
|
||||||
|
|
||||||
|
strcpy((char *) localeName + llen + 1, (char *) region);
|
||||||
|
locale = xslt_locale_WINAPI(localeName);
|
||||||
|
end:
|
||||||
|
return(locale);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XSLT_LOCALE_NONE
|
||||||
|
return(NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const xmlChar*
|
||||||
|
xsltDefaultRegion(const xmlChar *localeName) {
|
||||||
|
xmlChar c;
|
||||||
|
/* region should be xmlChar, but gcc warns on all string assignments */
|
||||||
|
const char *region = NULL;
|
||||||
|
|
||||||
|
c = localeName[1];
|
||||||
|
/* This is based on the locales from glibc 2.3.3 */
|
||||||
|
|
||||||
|
switch (localeName[0]) {
|
||||||
|
case 'a':
|
||||||
|
if (c == 'a' || c == 'm') region = "ET";
|
||||||
|
else if (c == 'f') region = "ZA";
|
||||||
|
else if (c == 'n') region = "ES";
|
||||||
|
else if (c == 'r') region = "AE";
|
||||||
|
else if (c == 'z') region = "AZ";
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
if (c == 'e') region = "BY";
|
||||||
|
else if (c == 'g') region = "BG";
|
||||||
|
else if (c == 'n') region = "BD";
|
||||||
|
else if (c == 'r') region = "FR";
|
||||||
|
else if (c == 's') region = "BA";
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (c == 'a') region = "ES";
|
||||||
|
else if (c == 's') region = "CZ";
|
||||||
|
else if (c == 'y') region = "GB";
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (c == 'a') region = "DK";
|
||||||
|
else if (c == 'e') region = "DE";
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
if (c == 'l') region = "GR";
|
||||||
|
else if (c == 'n' || c == 'o') region = "US";
|
||||||
|
else if (c == 's' || c == 'u') region = "ES";
|
||||||
|
else if (c == 't') region = "EE";
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
if (c == 'a') region = "IR";
|
||||||
|
else if (c == 'i') region = "FI";
|
||||||
|
else if (c == 'o') region = "FO";
|
||||||
|
else if (c == 'r') region = "FR";
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
if (c == 'a') region = "IE";
|
||||||
|
else if (c == 'l') region = "ES";
|
||||||
|
else if (c == 'v') region = "GB";
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
if (c == 'e') region = "IL";
|
||||||
|
else if (c == 'i') region = "IN";
|
||||||
|
else if (c == 'r') region = "HT";
|
||||||
|
else if (c == 'u') region = "HU";
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
if (c == 'd') region = "ID";
|
||||||
|
else if (c == 's') region = "IS";
|
||||||
|
else if (c == 't') region = "IT";
|
||||||
|
else if (c == 'w') region = "IL";
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
if (c == 'a') region = "JP";
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
if (c == 'l') region = "GL";
|
||||||
|
else if (c == 'o') region = "KR";
|
||||||
|
else if (c == 'w') region = "GB";
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
if (c == 't') region = "LT";
|
||||||
|
else if (c == 'v') region = "LV";
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
if (c == 'k') region = "MK";
|
||||||
|
else if (c == 'l' || c == 'r') region = "IN";
|
||||||
|
else if (c == 'n') region = "MN";
|
||||||
|
else if (c == 's') region = "MY";
|
||||||
|
else if (c == 't') region = "MT";
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
if (c == 'b' || c == 'n' || c == 'o') region = "NO";
|
||||||
|
else if (c == 'e') region = "NP";
|
||||||
|
else if (c == 'l') region = "NL";
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
if (c == 'm') region = "ET";
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
if (c == 'a') region = "IN";
|
||||||
|
else if (c == 'l') region = "PL";
|
||||||
|
else if (c == 't') region = "PT";
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
if (c == 'o') region = "RO";
|
||||||
|
else if (c == 'u') region = "RU";
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
switch (c) {
|
||||||
|
case 'e': region = "NO"; break;
|
||||||
|
case 'h': region = "YU"; break;
|
||||||
|
case 'k': region = "SK"; break;
|
||||||
|
case 'l': region = "SI"; break;
|
||||||
|
case 'o': region = "ET"; break;
|
||||||
|
case 'q': region = "AL"; break;
|
||||||
|
case 't': region = "ZA"; break;
|
||||||
|
case 'v': region = "SE"; break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
if (c == 'a' || c == 'e') region = "IN";
|
||||||
|
else if (c == 'h') region = "TH";
|
||||||
|
else if (c == 'i') region = "ER";
|
||||||
|
else if (c == 'r') region = "TR";
|
||||||
|
else if (c == 't') region = "RU";
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
if (c == 'k') region = "UA";
|
||||||
|
else if (c == 'r') region = "PK";
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
if (c == 'i') region = "VN";
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
if (c == 'a') region = "BE";
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
if (c == 'h') region = "ZA";
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
if (c == 'h') region = "CN";
|
||||||
|
else if (c == 'u') region = "ZA";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return((xmlChar *)region);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeLocale:
|
||||||
|
* @locale: the locale to free
|
||||||
|
*
|
||||||
|
* Frees a locale created with xsltNewLocale
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeLocale(xsltLocale locale) {
|
||||||
|
#ifdef XSLT_LOCALE_POSIX
|
||||||
|
freelocale(locale);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltStrxfrm:
|
||||||
|
* @locale: locale created with xsltNewLocale
|
||||||
|
* @string: UTF-8 string to transform
|
||||||
|
*
|
||||||
|
* Transforms a string according to locale. The transformed string must then be
|
||||||
|
* compared with xsltLocaleStrcmp and freed with xmlFree.
|
||||||
|
*
|
||||||
|
* Returns the transformed string or NULL on error
|
||||||
|
*/
|
||||||
|
xsltLocaleChar *
|
||||||
|
xsltStrxfrm(xsltLocale locale, const xmlChar *string)
|
||||||
|
{
|
||||||
|
#ifdef XSLT_LOCALE_NONE
|
||||||
|
return(NULL);
|
||||||
|
#else
|
||||||
|
size_t xstrlen, r;
|
||||||
|
xsltLocaleChar *xstr;
|
||||||
|
|
||||||
|
#ifdef XSLT_LOCALE_POSIX
|
||||||
|
xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1;
|
||||||
|
xstr = (xsltLocaleChar *) xmlMalloc(xstrlen);
|
||||||
|
if (xstr == NULL) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL,
|
||||||
|
"xsltStrxfrm : out of memory error\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, locale);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XSLT_LOCALE_WINAPI
|
||||||
|
xstrlen = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, NULL, 0);
|
||||||
|
if (xstrlen == 0) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
xstr = (xsltLocaleChar*) xmlMalloc(xstrlen * sizeof(xsltLocaleChar));
|
||||||
|
if (xstr == NULL) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
r = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, xstr, xstrlen);
|
||||||
|
if (r == 0) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
|
||||||
|
xmlFree(xstr);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
return(xstr);
|
||||||
|
#endif /* XSLT_LOCALE_WINAPI */
|
||||||
|
|
||||||
|
if (r >= xstrlen) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n");
|
||||||
|
xmlFree(xstr);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(xstr);
|
||||||
|
#endif /* XSLT_LOCALE_NONE */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltLocaleStrcmp:
|
||||||
|
* @locale: a locale identifier
|
||||||
|
* @str1: a string transformed with xsltStrxfrm
|
||||||
|
* @str2: a string transformed with xsltStrxfrm
|
||||||
|
*
|
||||||
|
* Compares two strings transformed with xsltStrxfrm
|
||||||
|
*
|
||||||
|
* Returns a value < 0 if str1 sorts before str2,
|
||||||
|
* a value > 0 if str1 sorts after str2,
|
||||||
|
* 0 if str1 and str2 are equal wrt sorting
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltLocaleStrcmp(xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2) {
|
||||||
|
(void)locale;
|
||||||
|
#ifdef XSLT_LOCALE_WINAPI
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
if (str1 == str2) return(0);
|
||||||
|
if (str1 == NULL) return(-1);
|
||||||
|
if (str2 == NULL) return(1);
|
||||||
|
ret = CompareStringW(locale, 0, str1, -1, str2, -1);
|
||||||
|
if (ret == 0) {
|
||||||
|
xsltTransformError(NULL, NULL, NULL, "xsltLocaleStrcmp : CompareStringW fail\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
return(ret - 2);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return(xmlStrcmp(str1, str2));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XSLT_LOCALE_WINAPI
|
||||||
|
/**
|
||||||
|
* xsltCountSupportedLocales:
|
||||||
|
* @lcid: not used
|
||||||
|
*
|
||||||
|
* callback used to count locales
|
||||||
|
*
|
||||||
|
* Returns TRUE
|
||||||
|
*/
|
||||||
|
BOOL CALLBACK
|
||||||
|
xsltCountSupportedLocales(LPSTR lcid) {
|
||||||
|
(void) lcid;
|
||||||
|
++xsltLocaleListSize;
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltIterateSupportedLocales:
|
||||||
|
* @lcid: not used
|
||||||
|
*
|
||||||
|
* callback used to track locales
|
||||||
|
*
|
||||||
|
* Returns TRUE if not at the end of the array
|
||||||
|
*/
|
||||||
|
BOOL CALLBACK
|
||||||
|
xsltIterateSupportedLocales(LPSTR lcid) {
|
||||||
|
static int count = 0;
|
||||||
|
xmlChar iso639lang [XSLTMAX_ISO639LANGLEN +1];
|
||||||
|
xmlChar iso3136ctry[XSLTMAX_ISO3166CNTRYLEN+1];
|
||||||
|
int k, l;
|
||||||
|
xsltRFC1766Info *p = xsltLocaleList + count;
|
||||||
|
|
||||||
|
k = sscanf(lcid, "%lx", (long*)&p->lcid);
|
||||||
|
if (k < 1) goto end;
|
||||||
|
/*don't count terminating null character*/
|
||||||
|
k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME,
|
||||||
|
(char *) iso639lang, sizeof(iso639lang));
|
||||||
|
if (--k < 1) goto end;
|
||||||
|
l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME,
|
||||||
|
(char *) iso3136ctry, sizeof(iso3136ctry));
|
||||||
|
if (--l < 1) goto end;
|
||||||
|
|
||||||
|
{ /*fill results*/
|
||||||
|
xmlChar *q = p->tag;
|
||||||
|
memcpy(q, iso639lang, k);
|
||||||
|
q += k;
|
||||||
|
*q++ = '-';
|
||||||
|
memcpy(q, iso3136ctry, l);
|
||||||
|
q += l;
|
||||||
|
*q = '\0';
|
||||||
|
}
|
||||||
|
++count;
|
||||||
|
end:
|
||||||
|
return((count < xsltLocaleListSize) ? TRUE : FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
xsltEnumSupportedLocales(void) {
|
||||||
|
xmlRMutexLock(xsltLocaleMutex);
|
||||||
|
if (xsltLocaleListSize <= 0) {
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
EnumSystemLocalesA(xsltCountSupportedLocales, LCID_SUPPORTED);
|
||||||
|
|
||||||
|
len = xsltLocaleListSize * sizeof(xsltRFC1766Info);
|
||||||
|
xsltLocaleList = xmlMalloc(len);
|
||||||
|
memset(xsltLocaleList, 0, len);
|
||||||
|
EnumSystemLocalesA(xsltIterateSupportedLocales, LCID_SUPPORTED);
|
||||||
|
}
|
||||||
|
xmlRMutexUnlock(xsltLocaleMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*def XSLT_LOCALE_WINAPI*/
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Summary: Locale handling
|
||||||
|
* Description: Interfaces for locale handling. Needed for language dependent
|
||||||
|
* sorting.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Nick Wellnhofer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLTLOCALE_H__
|
||||||
|
#define __XML_XSLTLOCALE_H__
|
||||||
|
|
||||||
|
#include <libxml/xmlstring.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_STRXFRM_L
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XSLT_LOCALE_POSIX:
|
||||||
|
* Macro indicating to use POSIX locale extensions
|
||||||
|
*/
|
||||||
|
#define XSLT_LOCALE_POSIX
|
||||||
|
|
||||||
|
#ifdef HAVE_LOCALE_H
|
||||||
|
#include <locale.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_XLOCALE_H
|
||||||
|
#include <xlocale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef locale_t xsltLocale;
|
||||||
|
typedef xmlChar xsltLocaleChar;
|
||||||
|
|
||||||
|
#elif defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XSLT_LOCALE_WINAPI:
|
||||||
|
* Macro indicating to use WinAPI for extended locale support
|
||||||
|
*/
|
||||||
|
#define XSLT_LOCALE_WINAPI
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winnls.h>
|
||||||
|
|
||||||
|
typedef LCID xsltLocale;
|
||||||
|
typedef wchar_t xsltLocaleChar;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XSLT_LOCALE_NONE:
|
||||||
|
* Macro indicating that there's no extended locale support
|
||||||
|
*/
|
||||||
|
#define XSLT_LOCALE_NONE
|
||||||
|
|
||||||
|
typedef void *xsltLocale;
|
||||||
|
typedef xmlChar xsltLocaleChar;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
XSLTPUBFUN xsltLocale XSLTCALL
|
||||||
|
xsltNewLocale (const xmlChar *langName);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeLocale (xsltLocale locale);
|
||||||
|
XSLTPUBFUN xsltLocaleChar * XSLTCALL
|
||||||
|
xsltStrxfrm (xsltLocale locale,
|
||||||
|
const xmlChar *string);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltLocaleStrcmp (xsltLocale locale,
|
||||||
|
const xsltLocaleChar *str1,
|
||||||
|
const xsltLocaleChar *str2);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltFreeLocales (void);
|
||||||
|
|
||||||
|
#endif /* __XML_XSLTLOCALE_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,313 @@
|
||||||
|
/*
|
||||||
|
* Summary: set of utilities for the XSLT engine
|
||||||
|
* Description: interfaces for the utilities module of the XSLT engine.
|
||||||
|
* things like message handling, profiling, and other
|
||||||
|
* generally useful routines.
|
||||||
|
*
|
||||||
|
* Copy: See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Author: Daniel Veillard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLTUTILS_H__
|
||||||
|
#define __XML_XSLTUTILS_H__
|
||||||
|
|
||||||
|
#include <libxslt/xsltconfig.h>
|
||||||
|
#ifdef HAVE_STDARG_H
|
||||||
|
#include <stdarg.h>
|
||||||
|
#endif
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/dict.h>
|
||||||
|
#include <libxml/xmlerror.h>
|
||||||
|
#include "xsltexports.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_TODO:
|
||||||
|
*
|
||||||
|
* Macro to flag unimplemented blocks.
|
||||||
|
*/
|
||||||
|
#define XSLT_TODO \
|
||||||
|
xsltGenericError(xsltGenericErrorContext, \
|
||||||
|
"Unimplemented block at %s:%d\n", \
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_STRANGE:
|
||||||
|
*
|
||||||
|
* Macro to flag that a problem was detected internally.
|
||||||
|
*/
|
||||||
|
#define XSLT_STRANGE \
|
||||||
|
xsltGenericError(xsltGenericErrorContext, \
|
||||||
|
"Internal error at %s:%d\n", \
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IS_XSLT_ELEM:
|
||||||
|
*
|
||||||
|
* Checks that the element pertains to XSLT namespace.
|
||||||
|
*/
|
||||||
|
#define IS_XSLT_ELEM(n) \
|
||||||
|
(((n) != NULL) && ((n)->type == XML_ELEMENT_NODE) && \
|
||||||
|
((n)->ns != NULL) && (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IS_XSLT_NAME:
|
||||||
|
*
|
||||||
|
* Checks the value of an element in XSLT namespace.
|
||||||
|
*/
|
||||||
|
#define IS_XSLT_NAME(n, val) \
|
||||||
|
(xmlStrEqual((n)->name, (const xmlChar *) (val)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IS_XSLT_REAL_NODE:
|
||||||
|
*
|
||||||
|
* Check that a node is a 'real' one: document, element, text or attribute.
|
||||||
|
*/
|
||||||
|
#define IS_XSLT_REAL_NODE(n) \
|
||||||
|
(((n) != NULL) && \
|
||||||
|
(((n)->type == XML_ELEMENT_NODE) || \
|
||||||
|
((n)->type == XML_TEXT_NODE) || \
|
||||||
|
((n)->type == XML_CDATA_SECTION_NODE) || \
|
||||||
|
((n)->type == XML_ATTRIBUTE_NODE) || \
|
||||||
|
((n)->type == XML_DOCUMENT_NODE) || \
|
||||||
|
((n)->type == XML_HTML_DOCUMENT_NODE) || \
|
||||||
|
((n)->type == XML_COMMENT_NODE) || \
|
||||||
|
((n)->type == XML_PI_NODE)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Our own version of namespaced attributes lookup.
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN xmlChar * XSLTCALL
|
||||||
|
xsltGetNsProp (xmlNodePtr node,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *nameSpace);
|
||||||
|
XSLTPUBFUN const xmlChar * XSLTCALL
|
||||||
|
xsltGetCNsProp (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr node,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *nameSpace);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltGetUTF8Char (const unsigned char *utf,
|
||||||
|
int *len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XSLT Debug Tracing Tracing Types
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
XSLT_TRACE_ALL = -1,
|
||||||
|
XSLT_TRACE_NONE = 0,
|
||||||
|
XSLT_TRACE_COPY_TEXT = 1<<0,
|
||||||
|
XSLT_TRACE_PROCESS_NODE = 1<<1,
|
||||||
|
XSLT_TRACE_APPLY_TEMPLATE = 1<<2,
|
||||||
|
XSLT_TRACE_COPY = 1<<3,
|
||||||
|
XSLT_TRACE_COMMENT = 1<<4,
|
||||||
|
XSLT_TRACE_PI = 1<<5,
|
||||||
|
XSLT_TRACE_COPY_OF = 1<<6,
|
||||||
|
XSLT_TRACE_VALUE_OF = 1<<7,
|
||||||
|
XSLT_TRACE_CALL_TEMPLATE = 1<<8,
|
||||||
|
XSLT_TRACE_APPLY_TEMPLATES = 1<<9,
|
||||||
|
XSLT_TRACE_CHOOSE = 1<<10,
|
||||||
|
XSLT_TRACE_IF = 1<<11,
|
||||||
|
XSLT_TRACE_FOR_EACH = 1<<12,
|
||||||
|
XSLT_TRACE_STRIP_SPACES = 1<<13,
|
||||||
|
XSLT_TRACE_TEMPLATES = 1<<14,
|
||||||
|
XSLT_TRACE_KEYS = 1<<15,
|
||||||
|
XSLT_TRACE_VARIABLES = 1<<16
|
||||||
|
} xsltDebugTraceCodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_TRACE:
|
||||||
|
*
|
||||||
|
* Control the type of xsl debugtrace messages emitted.
|
||||||
|
*/
|
||||||
|
#define XSLT_TRACE(ctxt,code,call) \
|
||||||
|
if (ctxt->traceCode && (*(ctxt->traceCode) & code)) \
|
||||||
|
call
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltDebugSetDefaultTrace(xsltDebugTraceCodes val);
|
||||||
|
XSLTPUBFUN xsltDebugTraceCodes XSLTCALL
|
||||||
|
xsltDebugGetDefaultTrace(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XSLT specific error and debug reporting functions.
|
||||||
|
*/
|
||||||
|
XSLTPUBVAR xmlGenericErrorFunc xsltGenericError;
|
||||||
|
XSLTPUBVAR void *xsltGenericErrorContext;
|
||||||
|
XSLTPUBVAR xmlGenericErrorFunc xsltGenericDebug;
|
||||||
|
XSLTPUBVAR void *xsltGenericDebugContext;
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltPrintErrorContext (xsltTransformContextPtr ctxt,
|
||||||
|
xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr node);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltMessage (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr inst);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSetGenericErrorFunc (void *ctx,
|
||||||
|
xmlGenericErrorFunc handler);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSetGenericDebugFunc (void *ctx,
|
||||||
|
xmlGenericErrorFunc handler);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSetTransformErrorFunc (xsltTransformContextPtr ctxt,
|
||||||
|
void *ctx,
|
||||||
|
xmlGenericErrorFunc handler);
|
||||||
|
XSLTPUBFUN void WINAPIV
|
||||||
|
xsltTransformError (xsltTransformContextPtr ctxt,
|
||||||
|
xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr node,
|
||||||
|
const char *msg,
|
||||||
|
...) LIBXSLT_ATTR_FORMAT(4,5);
|
||||||
|
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSetCtxtParseOptions (xsltTransformContextPtr ctxt,
|
||||||
|
int options);
|
||||||
|
/*
|
||||||
|
* Sorting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltDocumentSortFunction (xmlNodeSetPtr list);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSetSortFunc (xsltSortFunc handler);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSetCtxtSortFunc (xsltTransformContextPtr ctxt,
|
||||||
|
xsltSortFunc handler);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltDefaultSortFunction (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr *sorts,
|
||||||
|
int nbsorts);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltDoSortFunction (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr * sorts,
|
||||||
|
int nbsorts);
|
||||||
|
XSLTPUBFUN xmlXPathObjectPtr * XSLTCALL
|
||||||
|
xsltComputeSortResult (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr sort);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* QNames handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
XSLTPUBFUN const xmlChar * XSLTCALL
|
||||||
|
xsltSplitQName (xmlDictPtr dict,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar **prefix);
|
||||||
|
XSLTPUBFUN const xmlChar * XSLTCALL
|
||||||
|
xsltGetQNameURI (xmlNodePtr node,
|
||||||
|
xmlChar **name);
|
||||||
|
|
||||||
|
XSLTPUBFUN const xmlChar * XSLTCALL
|
||||||
|
xsltGetQNameURI2 (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr node,
|
||||||
|
const xmlChar **name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Output, reuse libxml I/O buffers.
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSaveResultTo (xmlOutputBufferPtr buf,
|
||||||
|
xmlDocPtr result,
|
||||||
|
xsltStylesheetPtr style);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSaveResultToFilename (const char *URI,
|
||||||
|
xmlDocPtr result,
|
||||||
|
xsltStylesheetPtr style,
|
||||||
|
int compression);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSaveResultToFile (FILE *file,
|
||||||
|
xmlDocPtr result,
|
||||||
|
xsltStylesheetPtr style);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSaveResultToFd (int fd,
|
||||||
|
xmlDocPtr result,
|
||||||
|
xsltStylesheetPtr style);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSaveResultToString (xmlChar **doc_txt_ptr,
|
||||||
|
int * doc_txt_len,
|
||||||
|
xmlDocPtr result,
|
||||||
|
xsltStylesheetPtr style);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath interface
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
|
||||||
|
xsltXPathCompile (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *str);
|
||||||
|
XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
|
||||||
|
xsltXPathCompileFlags (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *str,
|
||||||
|
int flags);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Profiling.
|
||||||
|
*/
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSaveProfiling (xsltTransformContextPtr ctxt,
|
||||||
|
FILE *output);
|
||||||
|
XSLTPUBFUN xmlDocPtr XSLTCALL
|
||||||
|
xsltGetProfileInformation (xsltTransformContextPtr ctxt);
|
||||||
|
|
||||||
|
XSLTPUBFUN long XSLTCALL
|
||||||
|
xsltTimestamp (void);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltCalibrateAdjust (long delta);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSLT_TIMESTAMP_TICS_PER_SEC:
|
||||||
|
*
|
||||||
|
* Sampling precision for profiling
|
||||||
|
*/
|
||||||
|
#define XSLT_TIMESTAMP_TICS_PER_SEC 100000l
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hooks for the debugger.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
XSLT_DEBUG_NONE = 0, /* no debugging allowed */
|
||||||
|
XSLT_DEBUG_INIT,
|
||||||
|
XSLT_DEBUG_STEP,
|
||||||
|
XSLT_DEBUG_STEPOUT,
|
||||||
|
XSLT_DEBUG_NEXT,
|
||||||
|
XSLT_DEBUG_STOP,
|
||||||
|
XSLT_DEBUG_CONT,
|
||||||
|
XSLT_DEBUG_RUN,
|
||||||
|
XSLT_DEBUG_RUN_RESTART,
|
||||||
|
XSLT_DEBUG_QUIT
|
||||||
|
} xsltDebugStatusCodes;
|
||||||
|
|
||||||
|
XSLTPUBVAR int xslDebugStatus;
|
||||||
|
|
||||||
|
typedef void (*xsltHandleDebuggerCallback) (xmlNodePtr cur, xmlNodePtr node,
|
||||||
|
xsltTemplatePtr templ, xsltTransformContextPtr ctxt);
|
||||||
|
typedef int (*xsltAddCallCallback) (xsltTemplatePtr templ, xmlNodePtr source);
|
||||||
|
typedef void (*xsltDropCallCallback) (void);
|
||||||
|
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xsltSetDebuggerStatus (int value);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltGetDebuggerStatus (void);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xsltSetDebuggerCallbacks (int no, void *block);
|
||||||
|
XSLTPUBFUN int XSLTCALL
|
||||||
|
xslAddCall (xsltTemplatePtr templ,
|
||||||
|
xmlNodePtr source);
|
||||||
|
XSLTPUBFUN void XSLTCALL
|
||||||
|
xslDropCall (void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLTUTILS_H__ */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue