示例#1
0
文件: functions.c 项目: Paxxi/libxslt
/**
 * 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);
}
示例#2
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);
}