Esempio n. 1
0
/**
 * xsltElementAvailableFunction:
 * @ctxt:  the XPath Parser context
 * @nargs:  the number of arguments
 *
 * Implement the element-available() XSLT function
 *   boolean element-available(string)
 */
void
xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
    xmlXPathObjectPtr obj;
    xmlChar *prefix, *name;
    const xmlChar *nsURI = NULL;
    xsltTransformContextPtr tctxt;

    if (nargs != 1) {
	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
		"element-available() : expects one string arg\n");
	ctxt->error = XPATH_INVALID_ARITY;
	return;
    }
    xmlXPathStringFunction(ctxt, 1);
    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
	    "element-available() : invalid arg expecting a string\n");
	ctxt->error = XPATH_INVALID_TYPE;
	return;
    }
    obj = valuePop(ctxt);
    tctxt = xsltXPathGetTransformContext(ctxt);
    if (tctxt == NULL) {
	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
		"element-available() : internal error tctxt == NULL\n");
	xmlXPathFreeObject(obj);
	valuePush(ctxt, xmlXPathNewBoolean(0));
	return;
    }


    name = xmlSplitQName2(obj->stringval, &prefix);
    if (name == NULL) {
	xmlNsPtr ns;

	name = xmlStrdup(obj->stringval);
	ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL);
	if (ns != NULL) nsURI = xmlStrdup(ns->href);
    } else {
	nsURI = xmlXPathNsLookup(ctxt->context, prefix);
	if (nsURI == NULL) {
	    xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
		"element-available() : prefix %s is not bound\n", prefix);
	}
    }

    if (xsltExtElementLookup(tctxt, name, nsURI) != NULL) {
	valuePush(ctxt, xmlXPathNewBoolean(1));
    } else {
	valuePush(ctxt, xmlXPathNewBoolean(0));
    }

    xmlXPathFreeObject(obj);
    if (name != NULL)
	xmlFree(name);
    if (prefix != NULL)
	xmlFree(prefix);
}
Esempio n. 2
0
static void
gda_xslt_getnodeset_function (xmlXPathParserContextPtr ctxt, int nargs)
{
	GdaXsltIntCont *data;
	xsltTransformContextPtr tctxt;
	xmlXPathObjectPtr setname, nodeset;
	GdaXsltExCont *execc;
	if (nargs != 1) {
		xsltGenericError (xsltGenericErrorContext,
				  "gda_xslt_getnodeset_function: invalid number of arguments\n");
		return;
	}
	tctxt = xsltXPathGetTransformContext (ctxt);
	if (tctxt == NULL) {
		xsltGenericError (xsltGenericErrorContext,
				  "sqlxslt: failed to get the transformation context\n");
		return;
	}
	execc = (GdaXsltExCont *) tctxt->_private;
	data = (GdaXsltIntCont *) xsltGetExtData (tctxt,
						  BAD_CAST GDA_XSLT_EXTENSION_URI);
	if (data == NULL) {
		xsltGenericError (xsltGenericErrorContext,
				  "sqlxslt: failed to get module data\n");
		return;
	}
	setname = valuePop (ctxt);
	if (setname == NULL) {
		xsltGenericError (xsltGenericErrorContext,
				  "sqlxslt: internal error\n");
		return;
	}

	if (setname->type != XPATH_STRING) {
		valuePush (ctxt, setname);
		xmlXPathStringFunction (ctxt, 1);
		setname = valuePop (ctxt);
		if (setname == NULL) {
			xsltGenericError (xsltGenericErrorContext,
					  "sqlxslt: internal error\n");
			return;
		}
	}
	nodeset =
		_gda_xslt_bk_fun_getnodeset (setname->stringval, execc, data);
	if (nodeset == NULL) {
		xsltGenericError (xsltGenericErrorContext,
				  "exsltDynMapFunctoin: ret == NULL\n");
		return;
	}
	valuePush (ctxt, nodeset);
}
Esempio n. 3
0
/**
 * xsltFunctionAvailableFunction:
 * @ctxt:  the XPath Parser context
 * @nargs:  the number of arguments
 *
 * Implement the function-available() XSLT function
 *   boolean function-available(string)
 */
void
xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
    xmlXPathObjectPtr obj;
    xmlChar *prefix, *name;
    const xmlChar *nsURI = NULL;

    if (nargs != 1) {
	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
		"function-available() : expects one string arg\n");
	ctxt->error = XPATH_INVALID_ARITY;
	return;
    }
    xmlXPathStringFunction(ctxt, 1);
    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
	    "function-available() : invalid arg expecting a string\n");
	ctxt->error = XPATH_INVALID_TYPE;
	return;
    }
    obj = valuePop(ctxt);

    name = xmlSplitQName2(obj->stringval, &prefix);
    if (name == NULL) {
	name = xmlStrdup(obj->stringval);
    } else {
	nsURI = xmlXPathNsLookup(ctxt->context, prefix);
	if (nsURI == NULL) {
	    xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
		"function-available() : prefix %s is not bound\n", prefix);
	}
    }

    if (xmlXPathFunctionLookupNS(ctxt->context, name, nsURI) != NULL) {
	valuePush(ctxt, xmlXPathNewBoolean(1));
    } else {
	valuePush(ctxt, xmlXPathNewBoolean(0));
    }

    xmlXPathFreeObject(obj);
    if (name != NULL)
	xmlFree(name);
    if (prefix != NULL)
	xmlFree(prefix);
}
Esempio n. 4
0
/**
 * xsltKeyFunction:
 * @ctxt:  the XPath Parser context
 * @nargs:  the number of arguments
 *
 * Implement the key() XSLT function
 *   node-set key(string, object)
 */
void
xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
    xmlXPathObjectPtr obj1, obj2;

    if (nargs != 2) {
	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
		"key() : expects two arguments\n");
	ctxt->error = XPATH_INVALID_ARITY;
	return;
    }

    /*
    * Get the key's value.
    */
    obj2 = valuePop(ctxt);
    xmlXPathStringFunction(ctxt, 1);
    if ((obj2 == NULL) ||
	(ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
	    "key() : invalid arg expecting a string\n");
	ctxt->error = XPATH_INVALID_TYPE;
	xmlXPathFreeObject(obj2);

	return;
    }
    /*
    * Get the key's name.
    */
    obj1 = valuePop(ctxt);

    if ((obj2->type == XPATH_NODESET) || (obj2->type == XPATH_XSLT_TREE)) {
	int i;
	xmlXPathObjectPtr newobj, ret;

	ret = xmlXPathNewNodeSet(NULL);

	if (obj2->nodesetval != NULL) {
	    for (i = 0; i < obj2->nodesetval->nodeNr; i++) {
		valuePush(ctxt, xmlXPathObjectCopy(obj1));
		valuePush(ctxt,
			  xmlXPathNewNodeSet(obj2->nodesetval->nodeTab[i]));
		xmlXPathStringFunction(ctxt, 1);
		xsltKeyFunction(ctxt, 2);
		newobj = valuePop(ctxt);
		ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
						       newobj->nodesetval);
		xmlXPathFreeObject(newobj);
	    }
	}
	valuePush(ctxt, ret);
    } else {
	xmlNodeSetPtr nodelist = NULL;
	xmlChar *key = NULL, *value;
	const xmlChar *keyURI;
	xsltTransformContextPtr tctxt;
	xmlChar *qname, *prefix;
	xmlXPathContextPtr xpctxt = ctxt->context;
	xmlNodePtr tmpNode = NULL;
	xsltDocumentPtr oldDocInfo;

	tctxt = xsltXPathGetTransformContext(ctxt);

	oldDocInfo = tctxt->document;

	if (xpctxt->node == NULL) {
	    xsltTransformError(tctxt, NULL, tctxt->inst,
		"Internal error in xsltKeyFunction(): "
		"The context node is not set on the XPath context.\n");
	    tctxt->state = XSLT_STATE_STOPPED;
	    goto error;
	}
	/*
	 * Get the associated namespace URI if qualified name
	 */
	qname = obj1->stringval;
	key = xmlSplitQName2(qname, &prefix);
	if (key == NULL) {
	    key = xmlStrdup(obj1->stringval);
	    keyURI = NULL;
	    if (prefix != NULL)
		xmlFree(prefix);
	} else {
	    if (prefix != NULL) {
		keyURI = xmlXPathNsLookup(xpctxt, prefix);
		if (keyURI == NULL) {
		    xsltTransformError(tctxt, NULL, tctxt->inst,
			"key() : prefix %s is not bound\n", prefix);
		    /*
		    * TODO: Shouldn't we stop here?
		    */
		}
		xmlFree(prefix);
	    } else {
		keyURI = NULL;
	    }
	}

	/*
	 * Force conversion of first arg to string
	 */
	valuePush(ctxt, obj2);
	xmlXPathStringFunction(ctxt, 1);
	if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
	    xsltTransformError(tctxt, NULL, tctxt->inst,
		"key() : invalid arg expecting a string\n");
	    ctxt->error = XPATH_INVALID_TYPE;
	    goto error;
	}
	obj2 = valuePop(ctxt);
	value = obj2->stringval;

	/*
	* We need to ensure that ctxt->document is available for
	* xsltGetKey().
	* First find the relevant doc, which is the context node's
	* owner doc; using context->doc is not safe, since
	* the doc could have been acquired via the document() function,
	* or the doc might be a Result Tree Fragment.
	* FUTURE INFO: In XSLT 2.0 the key() function takes an additional
	* argument indicating the doc to use.
	*/
	if (xpctxt->node->type == XML_NAMESPACE_DECL) {
	    /*
	    * REVISIT: This is a libxml hack! Check xpath.c for details.
	    * The XPath module sets the owner element of a ns-node on
	    * the ns->next field.
	    */
	    if ((((xmlNsPtr) xpctxt->node)->next != NULL) &&
		(((xmlNsPtr) xpctxt->node)->next->type == XML_ELEMENT_NODE))
	    {
		tmpNode = (xmlNodePtr) ((xmlNsPtr) xpctxt->node)->next;
	    }
	} else
	    tmpNode = xpctxt->node;

	if ((tmpNode == NULL) || (tmpNode->doc == NULL)) {
	    xsltTransformError(tctxt, NULL, tctxt->inst,
		"Internal error in xsltKeyFunction(): "
		"Couldn't get the doc of the XPath context node.\n");
	    goto error;
	}

	if ((tctxt->document == NULL) ||
	    (tctxt->document->doc != tmpNode->doc))
	{
	    if (tmpNode->doc->name && (tmpNode->doc->name[0] == ' ')) {
		/*
		* This is a Result Tree Fragment.
		*/
		if (tmpNode->doc->_private == NULL) {
		    tmpNode->doc->_private = xsltNewDocument(tctxt, tmpNode->doc);
		    if (tmpNode->doc->_private == NULL)
			goto error;
		}
		tctxt->document = (xsltDocumentPtr) tmpNode->doc->_private;
	    } else {
		/*
		* May be the initial source doc or a doc acquired via the
		* document() function.
		*/
		tctxt->document = xsltFindDocument(tctxt, tmpNode->doc);
	    }
	    if (tctxt->document == NULL) {
		xsltTransformError(tctxt, NULL, tctxt->inst,
		    "Internal error in xsltKeyFunction(): "
		    "Could not get the document info of a context doc.\n");
		tctxt->state = XSLT_STATE_STOPPED;
		goto error;
	    }
	}
	/*
	* Get/compute the key value.
	*/
	nodelist = xsltGetKey(tctxt, key, keyURI, value);

error:
	tctxt->document = oldDocInfo;
	valuePush(ctxt, xmlXPathWrapNodeSet(
	    xmlXPathNodeSetMerge(NULL, nodelist)));
	if (key != NULL)
	    xmlFree(key);
    }

    if (obj1 != NULL)
	xmlXPathFreeObject(obj1);
    if (obj2 != NULL)
	xmlXPathFreeObject(obj2);
}
Esempio n. 5
0
/**
 * xsltDocumentFunction:
 * @ctxt:  the XPath Parser context
 * @nargs:  the number of arguments
 *
 * Implement the document() XSLT function
 *   node-set document(object, node-set?)
 */
void
xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)
{
    xmlXPathObjectPtr obj, obj2 = NULL;
    xmlChar *base = NULL, *URI;


    if ((nargs < 1) || (nargs > 2)) {
        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
                         "document() : invalid number of args %d\n",
                         nargs);
        ctxt->error = XPATH_INVALID_ARITY;
        return;
    }
    if (ctxt->value == NULL) {
        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
                         "document() : invalid arg value\n");
        ctxt->error = XPATH_INVALID_TYPE;
        return;
    }

    if (nargs == 2) {
        if (ctxt->value->type != XPATH_NODESET) {
            xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
                             "document() : invalid arg expecting a nodeset\n");
            ctxt->error = XPATH_INVALID_TYPE;
            return;
        }

        obj2 = valuePop(ctxt);
    }

    if (ctxt->value->type == XPATH_NODESET) {
        int i;
        xmlXPathObjectPtr newobj, ret;

        obj = valuePop(ctxt);
        ret = xmlXPathNewNodeSet(NULL);

        if ((obj != NULL) && obj->nodesetval) {
            for (i = 0; i < obj->nodesetval->nodeNr; i++) {
                valuePush(ctxt,
                          xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i]));
                xmlXPathStringFunction(ctxt, 1);
                if (nargs == 2) {
                    valuePush(ctxt, xmlXPathObjectCopy(obj2));
                } else {
                    valuePush(ctxt,
                              xmlXPathNewNodeSet(obj->nodesetval->
                                                 nodeTab[i]));
                }
                xsltDocumentFunction(ctxt, 2);
                newobj = valuePop(ctxt);
                ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
                                                       newobj->nodesetval);
                xmlXPathFreeObject(newobj);
            }
        }

        if (obj != NULL)
            xmlXPathFreeObject(obj);
        if (obj2 != NULL)
            xmlXPathFreeObject(obj2);
        valuePush(ctxt, ret);
        return;
    }
    /*
     * Make sure it's converted to a string
     */
    xmlXPathStringFunction(ctxt, 1);
    if (ctxt->value->type != XPATH_STRING) {
        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
                         "document() : invalid arg expecting a string\n");
        ctxt->error = XPATH_INVALID_TYPE;
        if (obj2 != NULL)
            xmlXPathFreeObject(obj2);
        return;
    }
    obj = valuePop(ctxt);
    if (obj->stringval == NULL) {
        valuePush(ctxt, xmlXPathNewNodeSet(NULL));
    } else {
        xsltTransformContextPtr tctxt;
        tctxt = xsltXPathGetTransformContext(ctxt);
        if ((obj2 != NULL) && (obj2->nodesetval != NULL) &&
            (obj2->nodesetval->nodeNr > 0) &&
            IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) {
            xmlNodePtr target;

            target = obj2->nodesetval->nodeTab[0];
            if ((target->type == XML_ATTRIBUTE_NODE) ||
	        (target->type == XML_PI_NODE)) {
                target = ((xmlAttrPtr) target)->parent;
            }
            base = xmlNodeGetBase(target->doc, target);
        } else {
            if ((tctxt != NULL) && (tctxt->inst != NULL)) {
                base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst);
            } else if ((tctxt != NULL) && (tctxt->style != NULL) &&
                       (tctxt->style->doc != NULL)) {
                base = xmlNodeGetBase(tctxt->style->doc,
                                      (xmlNodePtr) tctxt->style->doc);
            }
        }
        URI = xmlBuildURI(obj->stringval, base);
        if (base != NULL)
            xmlFree(base);
        if (URI == NULL) {
            if ((tctxt != NULL) && (tctxt->style != NULL) &&
                (tctxt->style->doc != NULL) &&
                (xmlStrEqual(URI, tctxt->style->doc->URL))) {
                /* This selects the stylesheet's doc itself. */
                valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) tctxt->style->doc));
            } else {
                valuePush(ctxt, xmlXPathNewNodeSet(NULL));
            }
        } else {
	    xsltDocumentFunctionLoadDocument( ctxt, URI );
	    xmlFree(URI);
	}
    }
    xmlXPathFreeObject(obj);
    if (obj2 != NULL)
        xmlXPathFreeObject(obj2);
}
Esempio n. 6
0
void swft_import_png( xmlXPathParserContextPtr ctx, int nargs ) {
	xsltTransformContextPtr tctx;
	char *filename;
	xsltDocumentPtr xsltdoc;
	xmlDocPtr doc = NULL;
	xmlNodePtr node;
	xmlXPathObjectPtr obj;
	char tmp[TMP_STRLEN];
	png_colorp palette;
	int n_pal;
	int format = 5;
	int data_size = 0;

	xmlXPathStringFunction(ctx, 1);
	if (ctx->value->type != XPATH_STRING) {
		xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL,
			 "swft:import-png() : invalid arg expecting a string\n");
		ctx->error = XPATH_INVALID_TYPE;
		return;
	}
	obj = valuePop(ctx);
	if (obj->stringval == NULL) {
		valuePush(ctx, xmlXPathNewNodeSet(NULL));
		return;
	}
		
	tctx = xsltXPathGetTransformContext(ctx);
	
	filename = swft_get_filename(obj->stringval, ctx->context->doc->URL);

	bool quiet = true;
	xmlXPathObjectPtr quietObj = xsltVariableLookup( tctx, (const xmlChar*)"quiet", NULL );
	if (quietObj && quietObj->stringval) {
		quiet = !strcmp("true", (const char*)quietObj->stringval );
	}


	FILE *fp = fopen( filename, "rb" );
	if( !fp ) {
		xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL,
				   "swft:import-png() : failed to read file '%s'\n", filename);
		valuePush(ctx, xmlXPathNewNodeSet(NULL));
		goto fail;
	}
	
	doc = xmlNewDoc( (const xmlChar *)"1.0");
	doc->xmlRootNode = xmlNewDocNode( doc, NULL, (const xmlChar *)"png", NULL );
	node = doc->xmlRootNode;
	
	swft_addFileName( node, filename );
	
	
	// add data
	rewind(fp);
	unsigned char *data, *compressed;
	unsigned long w, h, rowbytes;
	int channels;
	int compressed_size;
	if( !fp ) goto fail;
		
	if( readpng_init( fp, &w, &h ) ) goto fail;
	
	// add w/h
	snprintf(tmp, TMP_STRLEN, "%lu", w);
	xmlSetProp( node, (const xmlChar *)"width", (const xmlChar *)&tmp );
	snprintf(tmp,TMP_STRLEN,"%lu", h);
	xmlSetProp( node, (const xmlChar *)"height", (const xmlChar *)&tmp );

	data = readpng_get_image( 2.2, &channels, &rowbytes, &palette, &n_pal );
	
	if( !quiet ) {
		fprintf(stderr,"Importing PNG: '%s' (%lu bit/pixel)\n", filename, (rowbytes*8)/w );
	}
	
	if( channels == 4 && rowbytes == (4*w) ) {
		int c;
		float a;
		unsigned char r,g,b;
		for( int i=0; i<w*h*4; i+=4 ) {
			a = data[i+3]/255.0;
			r = (unsigned char)((data[i+0])*a);
			g = (unsigned char)((data[i+1])*a);
			b = (unsigned char)((data[i+2])*a);
			data[i] = data[i+3];
			data[i+1] = r;
			data[i+2] = g;
			data[i+3] = b;
		}
		data_size = w*h*4;
	} else if( channels == 3 && rowbytes == (3*w) ) {
		unsigned char *rgba = new unsigned char[ w*h*4 ];
		
		for( int i=0; i<w*h; i++ ) {
			rgba[i*4] = 0xff;
			rgba[(i*4)+3] = data[(i*3)+2];
			rgba[(i*4)+2] = data[(i*3)+1];
			rgba[(i*4)+1] = data[(i*3)];
		}
		data = rgba;
		data_size = w*h*4;
	} else if( channels == 1 && rowbytes == w ) {
		unsigned char *img_data = data;
		format = 3;
		int bpr = rowbytes;
		bpr += (rowbytes % 4) ? 4 - (rowbytes % 4) : 0;
		if( n_pal ) {
			data_size = (4*n_pal) + (bpr*h);
			data = new unsigned char[ data_size ];
			for( int i=0; i<n_pal; i++ ) {
				unsigned char *entry = &data[(i*4)];
				entry[2] = palette[i].blue;
				entry[1] = palette[i].green;
				entry[0] = palette[i].red;
				entry[3] = 0xff;
			}
		} else {
			n_pal = 0xff;
			data_size = (4*n_pal) + (bpr*h);
			data = new unsigned char[ data_size ];
			for( int i=0; i<n_pal; i++ ) {
				unsigned char *entry = &data[(i*4)];
				entry[2] = i;
				entry[1] = i;
				entry[0] = i;
				entry[3] = 0xff;
			}
		}
		
		/* copy row by row with 32bit alignment */
		unsigned char *dst = &data[ (4*n_pal) ];
		unsigned char *src = img_data;
		memset( dst, 0, bpr*h );
		for( int y=0; y<h; y++ ) {
			memcpy( dst, src, rowbytes );
			dst += bpr;
			src += rowbytes;
		}
			
		snprintf(tmp,TMP_STRLEN,"%i", n_pal-1 );
		xmlSetProp( node, (const xmlChar *)"n_colormap", (const xmlChar *)&tmp );
	} else {
		fprintf(stderr,
				"WARNING: can only import 8bit palette, 24 or 32bit "
				"RGB(A) PNGs (%s has %i channels, rowstride %lu)\n",
				filename, channels, rowbytes);
		goto fail;
	}

	// format is 5 for RGB(A), 3 for palette (4 for 16bit, unused)
	snprintf(tmp,TMP_STRLEN,"%i", format );
	xmlSetProp( node, (const xmlChar *)"format", (const xmlChar *)&tmp );
	
	compressed_size = data_size;
	if( compressed_size < 1024 ) compressed_size = 1024;
	compressed = new unsigned char[ compressed_size ];
	if( compress( data, data_size, compressed, &compressed_size ) ) {
		swft_addData( node, (char*)compressed, compressed_size );
		valuePush( ctx, xmlXPathNewNodeSet( (xmlNodePtr)doc ) );
	}
	
	goto end;
	
fail:
	fprintf( stderr, "WARNING: could not import %s\n", filename );

end:
	if (fp) {
		fclose(fp);
	}
	delete compressed;
	delete filename; 
	readpng_cleanup( true );
}
Esempio n. 7
0
static void
gda_xslt_getxmlvalue_function (xmlXPathParserContextPtr ctxt, int nargs)
{
	GdaXsltIntCont *data;
	xsltTransformContextPtr tctxt;
	xmlXPathObjectPtr set, name, value;
	GdaXsltExCont *execc;

	if (nargs != 2) {
		xsltGenericError (xsltGenericErrorContext,
				  "gda_xslt_getxmlvalue_function: invalid number of arguments\n");
		return;
	}
	tctxt = xsltXPathGetTransformContext (ctxt);
	if (tctxt == NULL) {
		xsltGenericError (xsltGenericErrorContext,
				  "gda_xslt_getxmlvalue_function: failed to get the transformation context\n");
		return;
	}

	execc = (GdaXsltExCont *) tctxt->_private;
	data = (GdaXsltIntCont *) xsltGetExtData (tctxt,
						  BAD_CAST GDA_XSLT_EXTENSION_URI);
	if (data == NULL || execc == NULL) {
		xsltGenericError (xsltGenericErrorContext,
				  "gda_xslt_getxmlvalue_function: failed to get module internal data\n");
		return;
	}
	name = valuePop (ctxt);
	set = valuePop (ctxt);
	if (name == NULL || set == NULL) {
		xsltGenericError (xsltGenericErrorContext,
				  "gda_xslt_getxmlvalue_function: internal error\n");
		return;
	}

	if (name->type != XPATH_STRING) {
		valuePush (ctxt, name);
		xmlXPathStringFunction (ctxt, 1);
		name = valuePop (ctxt);
		if (name == NULL) {
			xsltGenericError (xsltGenericErrorContext,
					  "gda_xslt_getxmlvalue_function: internal error. Name parameter is not a string\n");
			return;
		}
	}
	if (set->type != XPATH_STRING) {
		valuePush (ctxt, set);
		xmlXPathStringFunction (ctxt, 1);
		set = valuePop (ctxt);
		if (set == NULL) {
			xsltGenericError (xsltGenericErrorContext,
					  "gda_xslt_getxmlvalue_function: internal error. Set parameter is not a string\n");
			return;
		}
	}

	value = _gda_xslt_bk_fun_getvalue (set->stringval, name->stringval,
					  execc, data,1);
	if (value == NULL) {
		xsltGenericError (xsltGenericErrorContext,
				  "gda_xslt_getxmlvalue_function: internal error. Empty value\n");
		return;
	}
	valuePush (ctxt, value);
}
Esempio n. 8
0
/**
 * xsltKeyFunction:
 * @ctxt:  the XPath Parser context
 * @nargs:  the number of arguments
 *
 * Implement the key() XSLT function
 *   node-set key(string, object)
 */
void
xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
    xmlNodeSetPtr nodelist;
    xmlXPathObjectPtr obj1, obj2;
    xmlChar *key = NULL, *value;
    const xmlChar *keyURI;
    xsltTransformContextPtr tctxt;

    if (nargs != 2) {
	xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
        xsltGenericError(xsltGenericErrorContext,
		"key() : expects two arguments\n");
	ctxt->error = XPATH_INVALID_ARITY;
	return;
    }

    obj2 = valuePop(ctxt);
    if ((obj2 == NULL) ||
	(ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
	xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
	xsltGenericError(xsltGenericErrorContext,
	    "key() : invalid arg expecting a string\n");
	ctxt->error = XPATH_INVALID_TYPE;
	xmlXPathFreeObject(obj2);

	return;
    }
    obj1 = valuePop(ctxt);

    if (obj2->type == XPATH_NODESET) {
	int i;
	xmlXPathObjectPtr newobj, ret;

	ret = xmlXPathNewNodeSet(NULL);

	if (obj2->nodesetval != NULL) {
	    for (i = 0; i < obj2->nodesetval->nodeNr; i++) {
		valuePush(ctxt, xmlXPathObjectCopy(obj1));
		valuePush(ctxt,
			  xmlXPathNewNodeSet(obj2->nodesetval->nodeTab[i]));
		xmlXPathStringFunction(ctxt, 1);
		xsltKeyFunction(ctxt, 2);
		newobj = valuePop(ctxt);
		ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
						       newobj->nodesetval);
		xmlXPathFreeObject(newobj);
	    }
	}
	valuePush(ctxt, ret);
    } else {
	xmlChar *qname, *prefix;

	/*
	 * Get the associated namespace URI if qualified name
	 */
	qname = obj1->stringval;
	key = xmlSplitQName2(qname, &prefix);
	if (key == NULL) {
	    key = xmlStrdup(obj1->stringval);
	    keyURI = NULL;
	    if (prefix != NULL)
		xmlFree(prefix);
	} else {
	    if (prefix != NULL) {
		keyURI = xmlXPathNsLookup(ctxt->context, prefix);
		if (keyURI == NULL) {
		    xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt),
					  NULL, NULL);
		    xsltGenericError(xsltGenericErrorContext,
			"key() : prefix %s is not bound\n", prefix);
		}
		xmlFree(prefix);
	    } else {
		keyURI = NULL;
	    }
	}

	/*
	 * Force conversion of first arg to string
	 */
	valuePush(ctxt, obj2);
	xmlXPathStringFunction(ctxt, 1);
	if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
	    xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt),
				  NULL, NULL);
	    xsltGenericError(xsltGenericErrorContext,
		"key() : invalid arg expecting a string\n");
	    ctxt->error = XPATH_INVALID_TYPE;
	    xmlXPathFreeObject(obj1);

	    return;
	}
	obj2 = valuePop(ctxt);
	value = obj2->stringval;

	tctxt = xsltXPathGetTransformContext(ctxt);

	nodelist = xsltGetKey(tctxt, key, keyURI, value);
	valuePush(ctxt, xmlXPathWrapNodeSet(
		        xmlXPathNodeSetMerge(NULL, nodelist)));
    }


    if (obj1 != NULL)
	xmlXPathFreeObject(obj1);
    if (obj2 != NULL)
	xmlXPathFreeObject(obj2);
    if (key != NULL)
	xmlFree(key);
}
Esempio n. 9
0
/**
 * xsltDocumentFunction:
 * @ctxt:  the XPath Parser context
 * @nargs:  the number of arguments
 *
 * Implement the document() XSLT function
 *   node-set document(object, node-set?)
 */
void
xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs){
    xsltDocumentPtr doc;
    xmlXPathObjectPtr obj, obj2 = NULL;
    xmlChar *base = NULL, *URI;


    if ((nargs < 1) || (nargs > 2)) {
	xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
        xsltGenericError(xsltGenericErrorContext,
		"document() : invalid number of args %d\n", nargs);
	ctxt->error = XPATH_INVALID_ARITY;
	return;
    }
    if (ctxt->value == NULL) {
	xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
	xsltGenericError(xsltGenericErrorContext,
	    "document() : invalid arg value\n");
	ctxt->error = XPATH_INVALID_TYPE;
	return;
    }

    if (nargs == 2) {
	if (ctxt->value->type != XPATH_NODESET) {
	    xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt),
		                  NULL, NULL);
	    xsltGenericError(xsltGenericErrorContext,
		"document() : invalid arg expecting a nodeset\n");
	    ctxt->error = XPATH_INVALID_TYPE;
	    return;
	}

	obj2 = valuePop(ctxt);
    }

    if (ctxt->value->type == XPATH_NODESET) {
	int i;
	xmlXPathObjectPtr newobj, ret;

	obj = valuePop(ctxt);
	ret = xmlXPathNewNodeSet(NULL);

	if (obj->nodesetval) {
	    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
		valuePush(ctxt,
			  xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i]));
		xmlXPathStringFunction(ctxt, 1);
		if (nargs == 2) {
		    valuePush(ctxt, xmlXPathObjectCopy(obj2));
		} else {
		    valuePush(ctxt,
			      xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i]));
		}
		xsltDocumentFunction(ctxt, 2);
		newobj = valuePop(ctxt);
		ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
						       newobj->nodesetval);
		xmlXPathFreeObject(newobj);
	    }
	}

	xmlXPathFreeObject(obj);
	if (obj2 != NULL)
	    xmlXPathFreeObject(obj2);
	valuePush(ctxt, ret);
	return;
    }
    /*
     * Make sure it's converted to a string
     */
    xmlXPathStringFunction(ctxt, 1);
    if (ctxt->value->type != XPATH_STRING) {
	xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
	xsltGenericError(xsltGenericErrorContext,
	    "document() : invalid arg expecting a string\n");
	ctxt->error = XPATH_INVALID_TYPE;
	if (obj2 != NULL)
	    xmlXPathFreeObject(obj2);
	return;
    }
    obj = valuePop(ctxt);
    if (obj->stringval == NULL) {
	valuePush(ctxt, xmlXPathNewNodeSet(NULL));
    } else {
	if ((obj2 != NULL) && (obj2->nodesetval != NULL) &&
	    (obj2->nodesetval->nodeNr > 0) &&
	    IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) {
	    xmlNodePtr target;

	    target = obj2->nodesetval->nodeTab[0];
	    if (target->type == XML_ATTRIBUTE_NODE) {
		target = ((xmlAttrPtr) target)->parent;
	    }
	    base = xmlNodeGetBase(target->doc, target);
	} else {
	    xsltTransformContextPtr tctxt;
	    
	    tctxt = xsltXPathGetTransformContext(ctxt);
	    if ((tctxt != NULL) && (tctxt->inst != NULL)) {
		base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst);
	    } else if ((tctxt != NULL) && (tctxt->style != NULL) &&
		       (tctxt->style->doc != NULL)) {
		base = xmlNodeGetBase(tctxt->style->doc, 
			              (xmlNodePtr) tctxt->style->doc);
	    }
	}
	URI = xmlBuildURI(obj->stringval, base);
	if (base != NULL)
	    xmlFree(base);
        if (URI == NULL) {
	    valuePush(ctxt, xmlXPathNewNodeSet(NULL));
	} else {
	    xsltTransformContextPtr tctxt;

	    tctxt = xsltXPathGetTransformContext(ctxt);
	    if (tctxt == NULL) {
		xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt),
			              NULL, NULL);
		xsltGenericError(xsltGenericErrorContext,
			"document() : internal error tctxt == NULL\n");
		valuePush(ctxt, xmlXPathNewNodeSet(NULL));
	    } else {
                if (xmlStrEqual(tctxt->style->doc->URL, URI)) {
                    valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr)tctxt->style->doc));
                }
                else {
		    doc = xsltLoadDocument(tctxt, URI);
		    if (doc == NULL)
		        valuePush(ctxt, xmlXPathNewNodeSet(NULL));
		    else {
		        /* TODO: use XPointer of HTML location for fragment ID */
		        /* pbm #xxx can lead to location sets, not nodesets :-) */
		        valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc->doc));
		    }
                }
	    }
	    xmlFree(URI);
	}
    }
    xmlXPathFreeObject(obj);
    if (obj2 != NULL)
	xmlXPathFreeObject(obj2);
}