Home | History | Annotate | Download | only in libexslt
      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