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