15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * functions.c: Implementation of the XSLT extra functions
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Reference:
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   http://www.w3.org/TR/1999/REC-xslt-19991116
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See Copyright for the status of this software.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * daniel@veillard.com
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Bjorn Reese <breese@users.sourceforge.net> for number formatting
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IN_LIBXSLT
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "libxslt.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_TYPES_H
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_CTYPE_H
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h>
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xmlmemory.h>
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/parser.h>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/tree.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/valid.h>
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/hash.h>
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xmlerror.h>
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xpath.h>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xpathInternals.h>
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/parserInternals.h>
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/uri.h>
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xpointer.h>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xslt.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xsltInternals.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xsltutils.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "functions.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "extensions.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "numbersInternals.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "keys.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "documents.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WITH_XSLT_DEBUG_FUNCTION
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Some versions of DocBook XSL use the vendor string to detect
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * supporting chunking, this is a workaround to be considered
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the list of decent XSLT processors <grin/>
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DOCBOOK_XSL_HACK
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltXPathFunctionLookup:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  a void * but the XSLT transformation context actually
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @name:  the function name
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ns_uri:  the function namespace URI
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This is the entry point when a function is needed by the XPath
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * interpretor.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the callback function or NULL if not found
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlXPathFunction
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltXPathFunctionLookup (xmlXPathContextPtr ctxt,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 const xmlChar *name, const xmlChar *ns_uri) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFunction ret;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((ctxt == NULL) || (name == NULL) || (ns_uri == NULL))
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return (NULL);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_FUNCTION
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltGenericDebug(xsltGenericDebugContext,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "Lookup function {%s}%s\n", ns_uri, name);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* give priority to context-level functions */
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = xsltExtModuleFunctionLookup(name, ns_uri);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_FUNCTION
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret != NULL)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltGenericDebug(xsltGenericDebugContext,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "found function %s\n", name);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(ret);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/************************************************************************
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *									*
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *			Module interfaces				*
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *									*
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ************************************************************************/
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltTransformContextPtr tctxt;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlURIPtr uri;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *fragment;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltDocumentPtr idoc; /* document info */
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDocPtr doc;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathContextPtr xptrctxt = NULL;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr resObj = NULL;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tctxt = xsltXPathGetTransformContext(ctxt);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tctxt == NULL) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(NULL, NULL, NULL,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "document() : internal error tctxt == NULL\n");
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewNodeSet(NULL));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uri = xmlParseURI((const char *) URI);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (uri == NULL) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(tctxt, NULL, NULL,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "document() : failed to parse URI\n");
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewNodeSet(NULL));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * check for and remove fragment identifier
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fragment = (xmlChar *)uri->fragment;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fragment != NULL) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlChar *newURI;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	uri->fragment = NULL;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	newURI = xmlSaveUri(uri);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	idoc = xsltLoadDocument(tctxt, newURI);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(newURI);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	idoc = xsltLoadDocument(tctxt, URI);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFreeURI(uri);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (idoc == NULL) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((URI == NULL) ||
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (URI[0] == '#') ||
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ((tctxt->style->doc != NULL) &&
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (xmlStrEqual(tctxt->style->doc->URL, URI))))
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * This selects the stylesheet's doc itself.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    doc = tctxt->style->doc;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    valuePush(ctxt, xmlXPathNewNodeSet(NULL));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (fragment != NULL)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xmlFree(fragment);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	doc = idoc->doc;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fragment == NULL) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* use XPointer of HTML location for fragment ID */
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef LIBXML_XPTR_ENABLED
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xptrctxt == NULL) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(tctxt, NULL, NULL,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "document() : internal error xptrctxt == NULL\n");
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto out_fragment;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resObj = xmlXPtrEval(fragment, xptrctxt);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeContext(xptrctxt);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(fragment);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (resObj == NULL)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto out_fragment;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (resObj->type) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case XPATH_NODESET:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    break;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case XPATH_UNDEFINED:
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case XPATH_BOOLEAN:
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case XPATH_NUMBER:
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case XPATH_STRING:
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case XPATH_POINT:
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case XPATH_USERS:
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case XPATH_XSLT_TREE:
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case XPATH_RANGE:
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case XPATH_LOCATIONSET:
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(tctxt, NULL, NULL,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"document() : XPointer does not select a node set: #%s\n",
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		fragment);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto out_object;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    valuePush(ctxt, resObj);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out_object:
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeObject(resObj);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out_fragment:
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    valuePush(ctxt, xmlXPathNewNodeSet(NULL));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltDocumentFunction:
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XPath Parser context
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implement the document() XSLT function
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   node-set document(object, node-set?)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr obj, obj2 = NULL;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *base = NULL, *URI;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 1) || (nargs > 2)) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "document() : invalid number of args %d\n",
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         nargs);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ctxt->error = XPATH_INVALID_ARITY;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ctxt->value == NULL) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "document() : invalid arg value\n");
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ctxt->error = XPATH_INVALID_TYPE;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 2) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ctxt->value->type != XPATH_NODESET) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "document() : invalid arg expecting a nodeset\n");
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ctxt->error = XPATH_INVALID_TYPE;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        obj2 = valuePop(ctxt);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ctxt->value->type == XPATH_NODESET) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int i;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathObjectPtr newobj, ret;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        obj = valuePop(ctxt);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret = xmlXPathNewNodeSet(NULL);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (obj->nodesetval) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < obj->nodesetval->nodeNr; i++) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                valuePush(ctxt,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i]));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                xmlXPathStringFunction(ctxt, 1);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (nargs == 2) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    valuePush(ctxt, xmlXPathObjectCopy(obj2));
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                } else {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    valuePush(ctxt,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              xmlXPathNewNodeSet(obj->nodesetval->
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 nodeTab[i]));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                xsltDocumentFunction(ctxt, 2);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                newobj = valuePop(ctxt);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       newobj->nodesetval);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                xmlXPathFreeObject(newobj);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathFreeObject(obj);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (obj2 != NULL)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xmlXPathFreeObject(obj2);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        valuePush(ctxt, ret);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Make sure it's converted to a string
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathStringFunction(ctxt, 1);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ctxt->value->type != XPATH_STRING) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "document() : invalid arg expecting a string\n");
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ctxt->error = XPATH_INVALID_TYPE;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (obj2 != NULL)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xmlXPathFreeObject(obj2);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj = valuePop(ctxt);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (obj->stringval == NULL) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        valuePush(ctxt, xmlXPathNewNodeSet(NULL));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((obj2 != NULL) && (obj2->nodesetval != NULL) &&
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (obj2->nodesetval->nodeNr > 0) &&
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xmlNodePtr target;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            target = obj2->nodesetval->nodeTab[0];
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((target->type == XML_ATTRIBUTE_NODE) ||
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        (target->type == XML_PI_NODE)) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                target = ((xmlAttrPtr) target)->parent;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base = xmlNodeGetBase(target->doc, target);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xsltTransformContextPtr tctxt;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            tctxt = xsltXPathGetTransformContext(ctxt);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((tctxt != NULL) && (tctxt->inst != NULL)) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            } else if ((tctxt != NULL) && (tctxt->style != NULL) &&
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       (tctxt->style->doc != NULL)) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                base = xmlNodeGetBase(tctxt->style->doc,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      (xmlNodePtr) tctxt->style->doc);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        URI = xmlBuildURI(obj->stringval, base);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (base != NULL)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xmlFree(base);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (URI == NULL) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            valuePush(ctxt, xmlXPathNewNodeSet(NULL));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltDocumentFunctionLoadDocument( ctxt, URI );
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFree(URI);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeObject(obj);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (obj2 != NULL)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathFreeObject(obj2);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltKeyFunction:
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XPath Parser context
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implement the key() XSLT function
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   node-set key(string, object)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr obj1, obj2;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs != 2) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"key() : expects two arguments\n");
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_ARITY;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Get the key's value.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj2 = valuePop(ctxt);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathStringFunction(ctxt, 1);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((obj2 == NULL) ||
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "key() : invalid arg expecting a string\n");
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_TYPE;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathFreeObject(obj2);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * Get the key's name.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj1 = valuePop(ctxt);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((obj2->type == XPATH_NODESET) || (obj2->type == XPATH_XSLT_TREE)) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int i;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathObjectPtr newobj, ret;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = xmlXPathNewNodeSet(NULL);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (obj2->nodesetval != NULL) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    for (i = 0; i < obj2->nodesetval->nodeNr; i++) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		valuePush(ctxt, xmlXPathObjectCopy(obj1));
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		valuePush(ctxt,
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  xmlXPathNewNodeSet(obj2->nodesetval->nodeTab[i]));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xmlXPathStringFunction(ctxt, 1);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltKeyFunction(ctxt, 2);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		newobj = valuePop(ctxt);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						       newobj->nodesetval);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xmlXPathFreeObject(newobj);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, ret);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlNodeSetPtr nodelist = NULL;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlChar *key = NULL, *value;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const xmlChar *keyURI;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformContextPtr tctxt;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlChar *qname, *prefix;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathContextPtr xpctxt = ctxt->context;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlNodePtr tmpNode = NULL;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltDocumentPtr oldDocInfo;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tctxt = xsltXPathGetTransformContext(ctxt);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	oldDocInfo = tctxt->document;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xpctxt->node == NULL) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(tctxt, NULL, tctxt->inst,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"Internal error in xsltKeyFunction(): "
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"The context node is not set on the XPath context.\n");
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    tctxt->state = XSLT_STATE_STOPPED;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * Get the associated namespace URI if qualified name
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	qname = obj1->stringval;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	key = xmlSplitQName2(qname, &prefix);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (key == NULL) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    key = xmlStrdup(obj1->stringval);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    keyURI = NULL;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (prefix != NULL)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xmlFree(prefix);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (prefix != NULL) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		keyURI = xmlXPathNsLookup(xpctxt, prefix);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (keyURI == NULL) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    xsltTransformError(tctxt, NULL, tctxt->inst,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			"key() : prefix %s is not bound\n", prefix);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /*
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    * TODO: Shouldn't we stop here?
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    */
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xmlFree(prefix);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		keyURI = NULL;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * Force conversion of first arg to string
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, obj2);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathStringFunction(ctxt, 1);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(tctxt, NULL, tctxt->inst,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"key() : invalid arg expecting a string\n");
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ctxt->error = XPATH_INVALID_TYPE;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	obj2 = valuePop(ctxt);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	value = obj2->stringval;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* We need to ensure that ctxt->document is available for
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* xsltGetKey().
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* First find the relevant doc, which is the context node's
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* owner doc; using context->doc is not safe, since
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* the doc could have been acquired via the document() function,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* or the doc might be a Result Tree Fragment.
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* FUTURE INFO: In XSLT 2.0 the key() function takes an additional
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* argument indicating the doc to use.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xpctxt->node->type == XML_NAMESPACE_DECL) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * REVISIT: This is a libxml hack! Check xpath.c for details.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * The XPath module sets the owner element of a ns-node on
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    * the ns->next field.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    */
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((((xmlNsPtr) xpctxt->node)->next != NULL) &&
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(((xmlNsPtr) xpctxt->node)->next->type == XML_ELEMENT_NODE))
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tmpNode = (xmlNodePtr) ((xmlNsPtr) xpctxt->node)->next;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    tmpNode = xpctxt->node;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((tmpNode == NULL) || (tmpNode->doc == NULL)) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(tctxt, NULL, tctxt->inst,
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"Internal error in xsltKeyFunction(): "
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"Couldn't get the doc of the XPath context node.\n");
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((tctxt->document == NULL) ||
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (tctxt->document->doc != tmpNode->doc))
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (tmpNode->doc->name && (tmpNode->doc->name[0] == ' ')) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/*
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		* This is a Result Tree Fragment.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*/
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (tmpNode->doc->_private == NULL) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    tmpNode->doc->_private = xsltNewDocument(tctxt, tmpNode->doc);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (tmpNode->doc->_private == NULL)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			goto error;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tctxt->document = (xsltDocumentPtr) tmpNode->doc->_private;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/*
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		* May be the initial source doc or a doc acquired via the
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		* document() function.
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*/
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tctxt->document = xsltFindDocument(tctxt, tmpNode->doc);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (tctxt->document == NULL) {
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltTransformError(tctxt, NULL, tctxt->inst,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    "Internal error in xsltKeyFunction(): "
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    "Could not get the document info of a context doc.\n");
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tctxt->state = XSLT_STATE_STOPPED;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto error;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	* Get/compute the key value.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*/
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	nodelist = xsltGetKey(tctxt, key, keyURI, value);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error:
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tctxt->document = oldDocInfo;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathWrapNodeSet(
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathNodeSetMerge(NULL, nodelist)));
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (key != NULL)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFree(key);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (obj1 != NULL)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathFreeObject(obj1);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (obj2 != NULL)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathFreeObject(obj2);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltUnparsedEntityURIFunction:
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XPath Parser context
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implement the unparsed-entity-uri() XSLT function
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   string unparsed-entity-uri(string)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs){
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr obj;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *str;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs != 1) || (ctxt->value == NULL)) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltGenericError(xsltGenericErrorContext,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"unparsed-entity-uri() : expects one string arg\n");
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_ARITY;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj = valuePop(ctxt);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (obj->type != XPATH_STRING) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	obj = xmlXPathConvertString(obj);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str = obj->stringval;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (str == NULL) {
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlEntityPtr entity;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	entity = xmlGetDocEntity(ctxt->context->doc, str);
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (entity == NULL) {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (entity->URI != NULL)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		valuePush(ctxt, xmlXPathNewString(entity->URI));
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    else
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeObject(obj);
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltFormatNumberFunction:
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XPath Parser context
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implement the format-number() XSLT function
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   string format-number(number, string, string?)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr numberObj = NULL;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr formatObj = NULL;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr decimalObj = NULL;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltStylesheetPtr sheet;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltDecimalFormatPtr formatValues;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *result;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltTransformContextPtr tctxt;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tctxt = xsltXPathGetTransformContext(ctxt);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tctxt == NULL)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sheet = tctxt->style;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sheet == NULL)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    formatValues = sheet->decimalFormat;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (nargs) {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 3:
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	CAST_TO_STRING;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	decimalObj = valuePop(ctxt);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	formatValues = xsltDecimalFormatGetByName(sheet, decimalObj->stringval);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (formatValues == NULL) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(tctxt, NULL, NULL,
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    "format-number() : undeclared decimal format '%s'\n",
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    decimalObj->stringval);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Intentional fall-through */
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2:
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	CAST_TO_STRING;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	formatObj = valuePop(ctxt);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	CAST_TO_NUMBER;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	numberObj = valuePop(ctxt);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	break;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	XP_ERROR(XPATH_INVALID_ARITY);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (formatValues != NULL) {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xsltFormatNumberConversion(formatValues,
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       formatObj->stringval,
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       numberObj->floatval,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       &result) == XPATH_EXPRESSION_OK) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    valuePush(ctxt, xmlXPathNewString(result));
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFree(result);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeObject(numberObj);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeObject(formatObj);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeObject(decimalObj);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltGenerateIdFunction:
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XPath Parser context
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implement the generate-id() XSLT function
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   string generate-id(node-set?)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlNodePtr cur = NULL;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr obj = NULL;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long val;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar str[30];
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDocPtr doc;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 0) {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur = ctxt->context->node;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (nargs == 1) {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlNodeSetPtr nodelist;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int i, ret;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ctxt->error = XPATH_INVALID_TYPE;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"generate-id() : invalid arg expecting a node-set\n");
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	obj = valuePop(ctxt);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	nodelist = obj->nodesetval;
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathFreeObject(obj);
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    valuePush(ctxt, xmlXPathNewCString(""));
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur = nodelist->nodeTab[0];
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 1;i < nodelist->nodeNr;i++) {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (ret == -1)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        cur = nodelist->nodeTab[i];
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"generate-id() : invalid number of args %d\n", nargs);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_ARITY;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Okay this is ugly but should work, use the NodePtr address
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * to forge the ID
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cur->type != XML_NAMESPACE_DECL)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        doc = cur->doc;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlNsPtr ns = (xmlNsPtr) cur;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ns->context != NULL)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            doc = ns->context;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            doc = ctxt->context->doc;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (obj)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathFreeObject(obj);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    val = (long)((char *)cur - (char *)doc);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (val >= 0) {
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sprintf((char *)str, "idp%ld", val);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sprintf((char *)str, "idm%ld", -val);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    valuePush(ctxt, xmlXPathNewString(str));
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltSystemPropertyFunction:
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XPath Parser context
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implement the system-property() XSLT function
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   object system-property(string)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs){
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr obj;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *prefix, *name;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *nsURI = NULL;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs != 1) {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"system-property() : expects one string arg\n");
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_ARITY;
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "system-property() : invalid arg expecting a string\n");
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_TYPE;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj = valuePop(ctxt);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (obj->stringval == NULL) {
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	name = xmlSplitQName2(obj->stringval, &prefix);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (name == NULL) {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    name = xmlStrdup(obj->stringval);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    nsURI = xmlXPathNsLookup(ctxt->context, prefix);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (nsURI == NULL) {
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    "system-property() : prefix %s is not bound\n", prefix);
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlStrEqual(nsURI, XSLT_NAMESPACE)) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DOCBOOK_XSL_HACK
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (xmlStrEqual(name, (const xmlChar *)"vendor")) {
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltStylesheetPtr sheet;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xsltTransformContextPtr tctxt;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tctxt = xsltXPathGetTransformContext(ctxt);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ((tctxt != NULL) && (tctxt->inst != NULL) &&
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (xmlStrEqual(tctxt->inst->name, BAD_CAST "variable")) &&
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (tctxt->inst->parent != NULL) &&
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (xmlStrEqual(tctxt->inst->parent->name,
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 BAD_CAST "template")))
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    sheet = tctxt->style;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		else
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    sheet = NULL;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ((sheet != NULL) && (sheet->doc != NULL) &&
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (sheet->doc->URL != NULL) &&
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (xmlStrstr(sheet->doc->URL,
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       (const xmlChar *)"chunk") != NULL)) {
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    valuePush(ctxt, xmlXPathNewString(
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			(const xmlChar *)"libxslt (SAXON 6.2 compatible)"));
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else {
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    valuePush(ctxt, xmlXPathNewString(
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			(const xmlChar *)XSLT_DEFAULT_VENDOR));
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (xmlStrEqual(name, (const xmlChar *)"vendor")) {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		valuePush(ctxt, xmlXPathNewString(
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  (const xmlChar *)XSLT_DEFAULT_VENDOR));
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (xmlStrEqual(name, (const xmlChar *)"version")) {
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		valuePush(ctxt, xmlXPathNewString(
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (const xmlChar *)XSLT_DEFAULT_VERSION));
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else if (xmlStrEqual(name, (const xmlChar *)"vendor-url")) {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		valuePush(ctxt, xmlXPathNewString(
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (const xmlChar *)XSLT_DEFAULT_URL));
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else {
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (name != NULL)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFree(name);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (prefix != NULL)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFree(prefix);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeObject(obj);
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltElementAvailableFunction:
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XPath Parser context
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implement the element-available() XSLT function
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   boolean element-available(string)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr obj;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *prefix, *name;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *nsURI = NULL;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltTransformContextPtr tctxt;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs != 1) {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"element-available() : expects one string arg\n");
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_ARITY;
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathStringFunction(ctxt, 1);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "element-available() : invalid arg expecting a string\n");
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_TYPE;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj = valuePop(ctxt);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tctxt = xsltXPathGetTransformContext(ctxt);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tctxt == NULL) {
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"element-available() : internal error tctxt == NULL\n");
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathFreeObject(obj);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewBoolean(0));
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = xmlSplitQName2(obj->stringval, &prefix);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name == NULL) {
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlNsPtr ns;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	name = xmlStrdup(obj->stringval);
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ns != NULL) nsURI = xmlStrdup(ns->href);
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	nsURI = xmlXPathNsLookup(ctxt->context, prefix);
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (nsURI == NULL) {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"element-available() : prefix %s is not bound\n", prefix);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xsltExtElementLookup(tctxt, name, nsURI) != NULL) {
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewBoolean(1));
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewBoolean(0));
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeObject(obj);
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name != NULL)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(name);
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (prefix != NULL)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(prefix);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltFunctionAvailableFunction:
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XPath Parser context
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implement the function-available() XSLT function
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   boolean function-available(string)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr obj;
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *prefix, *name;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *nsURI = NULL;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs != 1) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"function-available() : expects one string arg\n");
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_ARITY;
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathStringFunction(ctxt, 1);
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "function-available() : invalid arg expecting a string\n");
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_TYPE;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj = valuePop(ctxt);
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = xmlSplitQName2(obj->stringval, &prefix);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name == NULL) {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	name = xmlStrdup(obj->stringval);
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	nsURI = xmlXPathNsLookup(ctxt->context, prefix);
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (nsURI == NULL) {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"function-available() : prefix %s is not bound\n", prefix);
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xmlXPathFunctionLookupNS(ctxt->context, name, nsURI) != NULL) {
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewBoolean(1));
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewBoolean(0));
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeObject(obj);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name != NULL)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(name);
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (prefix != NULL)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(prefix);
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltCurrentFunction:
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XPath Parser context
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implement the current() XSLT function
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   node-set current()
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltCurrentFunction(xmlXPathParserContextPtr ctxt, int nargs){
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltTransformContextPtr tctxt;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs != 0) {
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"current() : function uses no argument\n");
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->error = XPATH_INVALID_ARITY;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tctxt = xsltXPathGetTransformContext(ctxt);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tctxt == NULL) {
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"current() : internal error tctxt == NULL\n");
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewNodeSet(NULL));
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	valuePush(ctxt, xmlXPathNewNodeSet(tctxt->node)); /* current */
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/************************************************************************
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 									*
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 		Registration of XSLT and libxslt functions		*
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 									*
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ************************************************************************/
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltRegisterAllFunctions:
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  the XPath context
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Registers all default XSLT functions in this context
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltRegisterAllFunctions(xmlXPathContextPtr ctxt)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "current",
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         xsltCurrentFunction);
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "document",
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         xsltDocumentFunction);
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "key", xsltKeyFunction);
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "unparsed-entity-uri",
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         xsltUnparsedEntityURIFunction);
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "format-number",
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         xsltFormatNumberFunction);
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "generate-id",
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         xsltGenerateIdFunction);
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "system-property",
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         xsltSystemPropertyFunction);
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "element-available",
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         xsltElementAvailableFunction);
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "function-available",
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         xsltFunctionAvailableFunction);
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
994