/*
* functions.c: Implementation of the XSLT extra functions
*
* Reference:
* http://www.w3.org/TR/1999/REC-xslt-19991116
*
* See Copyright for the status of this software.
*
* daniel@veillard.com
* Bjorn Reese <breese@users.sourceforge.net> for number formatting
*/
#define IN_LIBXSLT
#include "libxslt.h"
#include <string.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/valid.h>
#include <libxml/hash.h>
#include <libxml/xmlerror.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/parserInternals.h>
#include <libxml/uri.h>
#include <libxml/xpointer.h>
#include "xslt.h"
#include "xsltInternals.h"
#include "xsltutils.h"
#include "functions.h"
#include "extensions.h"
#include "numbersInternals.h"
#include "keys.h"
#include "documents.h"
#ifdef WITH_XSLT_DEBUG
#define WITH_XSLT_DEBUG_FUNCTION
#endif
/*
* Some versions of DocBook XSL use the vendor string to detect
* supporting chunking, this is a workaround to be considered
* in the list of decent XSLT processors <grin/>
*/
#define DOCBOOK_XSL_HACK
/**
* xsltXPathFunctionLookup:
* @ctxt: a void * but the XSLT transformation context actually
* @name: the function name
* @ns_uri: the function namespace URI
*
* This is the entry point when a function is needed by the XPath
* interpretor.
*
* Returns the callback function or NULL if not found
*/
xmlXPathFunction
xsltXPathFunctionLookup (xmlXPathContextPtr ctxt,
const xmlChar *name, const xmlChar *ns_uri) {
xmlXPathFunction ret;
if ((ctxt == NULL) || (name == NULL) || (ns_uri == NULL))
return (NULL);
#ifdef WITH_XSLT_DEBUG_FUNCTION
xsltGenericDebug(xsltGenericDebugContext,
"Lookup function {%s}%s\n", ns_uri, name);
#endif
/* give priority to context-level functions */
/*
ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);
*/
XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri);
if (ret == NULL)
ret = xsltExtModuleFunctionLookup(name, ns_uri);
#ifdef WITH_XSLT_DEBUG_FUNCTION
if (ret != NULL)
xsltGenericDebug(xsltGenericDebugContext,
"found function %s\n", name);
#endif
return(ret);
}
/************************************************************************
* *
* Module interfaces *
* *
************************************************************************/
static void
xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)
{
xsltTransformContextPtr tctxt;
xmlURIPtr uri;
xmlChar *fragment;
xsltDocumentPtr idoc; /* document info */
xmlDocPtr doc;
xmlXPathContextPtr xptrctxt = NULL;
xmlXPathObjectPtr resObj = NULL;
tctxt = xsltXPathGetTransformContext(ctxt);
if (tctxt == NULL) {
xsltTransformError(NULL, NULL, NULL,
"document() : internal error tctxt == NULL\n");
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
return;
}
uri = xmlParseURI((const char *) URI);
if (uri == NULL) {
xsltTransformError(tctxt, NULL, NULL,
"document() : failed to parse URI\n");
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
return;
}
/*
* check for and remove fragment identifier
*/
fragment = (xmlChar *)uri->fragment;
if (fragment != NULL) {
xmlChar *newURI;
uri->fragment = NULL;
newURI = xmlSaveUri(uri);
idoc = xsltLoadDocument(tctxt, newURI);
xmlFree(newURI);
} else
idoc = xsltLoadDocument(tctxt, URI);
xmlFreeURI(uri);
if (idoc == NULL) {
if ((URI == NULL) ||
(URI[0] == '#') ||
((tctxt->style->doc != NULL) &&
(xmlStrEqual(tctxt->style->doc->URL, URI))))
{
/*
* This selects the stylesheet's doc itself.
*/
doc = tctxt->style->doc;
} else {
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
if (fragment != NULL)
xmlFree(fragment);
return;
}
} else
doc = idoc->doc;
if (fragment == NULL) {
valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc));
return;
}
/* use XPointer of HTML location for fragment ID */
#ifdef LIBXML_XPTR_ENABLED
xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
if (xptrctxt == NULL) {
xsltTransformError(tctxt, NULL, NULL,
"document() : internal error xptrctxt == NULL\n");
goto out_fragment;
}
resObj = xmlXPtrEval(fragment, xptrctxt);
xmlXPathFreeContext(xptrctxt);
#endif
xmlFree(fragment);
if (resObj == NULL)
goto out_fragment;
switch (resObj->type) {
case XPATH_NODESET:
break;
case XPATH_UNDEFINED:
case XPATH_BOOLEAN:
case XPATH_NUMBER:
case XPATH_STRING:
case XPATH_POINT:
case XPATH_USERS:
case XPATH_XSLT_TREE:
case XPATH_RANGE:
case XPATH_LOCATIONSET:
xsltTransformError(tctxt, NULL, NULL,
"document() : XPointer does not select a node set: #%s\n",
fragment);
goto out_object;
}
valuePush(ctxt, resObj);
return;
out_object:
xmlXPathFreeObject(resObj);
out_fragment:
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
}
/**
* xsltDocumentFunction:
* @ctxt: the XPath Parser context
* @nargs: the number of arguments
*
* Implement the document() XSLT function
* node-set document(object, node-set?)
*/
void
xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)
{
xmlXPathObjectPtr obj, obj2 = NULL;
xmlChar *base = NULL, *URI;
if ((nargs < 1) || (nargs > 2)) {
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
"document() : invalid number of args %d\n",
nargs);
ctxt->error = XPATH_INVALID_ARITY;
return;
}
if (ctxt->value == NULL) {
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
"document() : invalid arg value\n");
ctxt->error = XPATH_INVALID_TYPE;
return;
}
if (nargs == 2) {
if (ctxt->value->type != XPATH_NODESET) {
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
"document() : invalid arg expecting a nodeset\n");
ctxt->error = XPATH_INVALID_TYPE;
return;
}
obj2 = valuePop(ctxt);
}
if (ctxt->value->type == XPATH_NODESET) {
int i;
xmlXPathObjectPtr newobj, ret;
obj = valuePop(ctxt);
ret = xmlXPathNewNodeSet(NULL);
if (obj->nodesetval) {
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
valuePush(ctxt,
xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i]));
xmlXPathStringFunction(ctxt, 1);
if (nargs == 2) {
valuePush(ctxt, xmlXPathObjectCopy(obj2));
} else {
valuePush(ctxt,
xmlXPathNewNodeSet(obj->nodesetval->
nodeTab[i]));
}
xsltDocumentFunction(ctxt, 2);
newobj = valuePop(ctxt);
ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
newobj->nodesetval);
xmlXPathFreeObject(newobj);
}
}
xmlXPathFreeObject(obj);
if (obj2 != NULL)
xmlXPathFreeObject(obj2);
valuePush(ctxt, ret);
return;
}
/*
* Make sure it's converted to a string
*/
xmlXPathStringFunction(ctxt, 1);
if (ctxt->value->type != XPATH_STRING) {
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
"document() : invalid arg expecting a string\n");
ctxt->error = XPATH_INVALID_TYPE;
if (obj2 != NULL)
xmlXPathFreeObject(obj2);
return;
}
obj = valuePop(ctxt);
if (obj->stringval == NULL) {
xt_connmark.rar_Void_ The
版权申诉
19 浏览量
2022-09-24
20:49:50
上传
评论
收藏 7KB RAR 举报
邓凌佳
- 粉丝: 65
- 资源: 1万+