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 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 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 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