• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 static void
exsltNodeSetFunction(xmlXPathParserContextPtr ctxt,int nargs)25 exsltNodeSetFunction (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 
77 static void
exsltObjectTypeFunction(xmlXPathParserContextPtr ctxt,int nargs)78 exsltObjectTypeFunction (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 
125 void
exsltCommonRegister(void)126 exsltCommonRegister (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