1#define IN_LIBEXSLT
2#include "libexslt/libexslt.h"
3
4#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
5#include <win32config.h>
6#else
7#include "config.h"
8#endif
9
10#include <libxml/tree.h>
11#include <libxml/xpath.h>
12#include <libxml/xpathInternals.h>
13
14#include <libxslt/xsltconfig.h>
15#include <libxslt/xsltutils.h>
16#include <libxslt/xsltInternals.h>
17#include <libxslt/extensions.h>
18#include <libxslt/transform.h>
19#include <libxslt/extra.h>
20#include <libxslt/preproc.h>
21
22#include "exslt.h"
23
24static void
25exsltNodeSetFunction (xmlXPathParserContextPtr ctxt, int nargs) {
26    if (nargs != 1) {
27	xmlXPathSetArityError(ctxt);
28	return;
29    }
30    if (xmlXPathStackIsNodeSet (ctxt)) {
31	xsltFunctionNodeSet (ctxt, nargs);
32	return;
33    } else {
34	xmlDocPtr fragment;
35	xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
36	xmlNodePtr txt;
37	xmlChar *strval;
38	xmlXPathObjectPtr obj;
39	/*
40	* SPEC EXSLT:
41	* "You can also use this function to turn a string into a text
42	* node, which is helpful if you want to pass a string to a
43	* function that only accepts a node-set."
44	*/
45	fragment = xsltCreateRVT(tctxt);
46	if (fragment == NULL) {
47	    xsltTransformError(tctxt, NULL, tctxt->inst,
48		"exsltNodeSetFunction: Failed to create a tree fragment.\n");
49	    tctxt->state = XSLT_STATE_STOPPED;
50	    return;
51	}
52	xsltRegisterLocalRVT(tctxt, fragment);
53
54	strval = xmlXPathPopString (ctxt);
55
56	txt = xmlNewDocText (fragment, strval);
57	xmlAddChild((xmlNodePtr) fragment, txt);
58	obj = xmlXPathNewNodeSet(txt);
59	if (obj == NULL) {
60	    xsltTransformError(tctxt, NULL, tctxt->inst,
61		"exsltNodeSetFunction: Failed to create a node set object.\n");
62	    tctxt->state = XSLT_STATE_STOPPED;
63	} else {
64	    /*
65	     * Mark it as a function result in order to avoid garbage
66	     * collecting of tree fragments
67	     */
68	    xsltExtensionInstructionResultRegister(tctxt, obj);
69	}
70	if (strval != NULL)
71	    xmlFree (strval);
72
73	valuePush (ctxt, obj);
74    }
75}
76
77static void
78exsltObjectTypeFunction (xmlXPathParserContextPtr ctxt, int nargs) {
79    xmlXPathObjectPtr obj, ret;
80
81    if (nargs != 1) {
82	xmlXPathSetArityError(ctxt);
83	return;
84    }
85
86    obj = valuePop(ctxt);
87
88    switch (obj->type) {
89    case XPATH_STRING:
90	ret = xmlXPathNewCString("string");
91	break;
92    case XPATH_NUMBER:
93	ret = xmlXPathNewCString("number");
94	break;
95    case XPATH_BOOLEAN:
96	ret = xmlXPathNewCString("boolean");
97	break;
98    case XPATH_NODESET:
99	ret = xmlXPathNewCString("node-set");
100	break;
101    case XPATH_XSLT_TREE:
102	ret = xmlXPathNewCString("RTF");
103	break;
104    case XPATH_USERS:
105	ret = xmlXPathNewCString("external");
106	break;
107    default:
108	xsltGenericError(xsltGenericErrorContext,
109		"object-type() invalid arg\n");
110	ctxt->error = XPATH_INVALID_TYPE;
111	xmlXPathFreeObject(obj);
112	return;
113    }
114    xmlXPathFreeObject(obj);
115    valuePush(ctxt, ret);
116}
117
118
119/**
120 * exsltCommonRegister:
121 *
122 * Registers the EXSLT - Common module
123 */
124
125void
126exsltCommonRegister (void) {
127    xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
128				  EXSLT_COMMON_NAMESPACE,
129				  exsltNodeSetFunction);
130    xsltRegisterExtModuleFunction((const xmlChar *) "object-type",
131				  EXSLT_COMMON_NAMESPACE,
132				  exsltObjectTypeFunction);
133    xsltRegisterExtModuleElement((const xmlChar *) "document",
134				 EXSLT_COMMON_NAMESPACE,
135				 (xsltPreComputeFunction) xsltDocumentComp,
136				 (xsltTransformFunction) xsltDocumentElem);
137}
138