__xmlOutputBufferCreateFilename(const char *URI,
                              xmlCharEncodingHandlerPtr encoder,
                              int compression ATTRIBUTE_UNUSED) {
    xmlOutputBufferPtr ret;
    xmlURIPtr puri;
    int i = 0;
    void *context = NULL;
    char *unescaped = NULL;
#ifdef HAVE_ZLIB_H
    int is_file_uri = 1;
#endif

    if (xmlOutputCallbackInitialized == 0)
	xmlRegisterDefaultOutputCallbacks();

    if (URI == NULL) return(NULL);

    puri = xmlParseURI(URI);
    if (puri != NULL) {
#ifdef HAVE_ZLIB_H
        if ((puri->scheme != NULL) &&
	    (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
	    is_file_uri = 0;
#endif
	/*
	 * try to limit the damages of the URI unescaping code.
	 */
	if ((puri->scheme == NULL) ||
	    (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
	    unescaped = xmlURIUnescapeString(URI, 0, NULL);
	xmlFreeURI(puri);
    }

    /*
     * Try to find one of the output accept method accepting that scheme
     * Go in reverse to give precedence to user defined handlers.
     * try with an unescaped version of the URI
     */
    if (unescaped != NULL) {
#ifdef HAVE_ZLIB_H
	if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
	    context = xmlGzfileOpenW(unescaped, compression);
	    if (context != NULL) {
		ret = xmlAllocOutputBufferInternal(encoder);
		if (ret != NULL) {
		    ret->context = context;
		    ret->writecallback = xmlGzfileWrite;
		    ret->closecallback = xmlGzfileClose;
		}
		xmlFree(unescaped);
		return(ret);
	    }
	}
#endif
	for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
	    if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
		(xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) {
#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
		/*  Need to pass compression parameter into HTTP open calls  */
		if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
		    context = xmlIOHTTPOpenW(unescaped, compression);
		else
#endif
		    context = xmlOutputCallbackTable[i].opencallback(unescaped);
		if (context != NULL)
		    break;
	    }
	}
	xmlFree(unescaped);
    }

    /*
     * If this failed try with a non-escaped URI this may be a strange
     * filename
     */
    if (context == NULL) {
#ifdef HAVE_ZLIB_H
	if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
	    context = xmlGzfileOpenW(URI, compression);
	    if (context != NULL) {
		ret = xmlAllocOutputBufferInternal(encoder);
		if (ret != NULL) {
		    ret->context = context;
		    ret->writecallback = xmlGzfileWrite;
		    ret->closecallback = xmlGzfileClose;
		}
		return(ret);
	    }
	}
#endif
	for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
	    if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
		(xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
		/*  Need to pass compression parameter into HTTP open calls  */
		if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
		    context = xmlIOHTTPOpenW(URI, compression);
		else
#endif
		    context = xmlOutputCallbackTable[i].opencallback(URI);
		if (context != NULL)
		    break;
	    }
	}
    }

    if (context == NULL) {
	return(NULL);
    }

    /*
     * Allocate the Output buffer front-end.
     */
    ret = xmlAllocOutputBufferInternal(encoder);
    if (ret != NULL) {
	ret->context = context;
	ret->writecallback = xmlOutputCallbackTable[i].writecallback;
	ret->closecallback = xmlOutputCallbackTable[i].closecallback;
    }
    return(ret);
}