Edit

kc3-lang/libxml2/xmlwriter.c

Branch :

  • Show log

    Commit

  • Author : William M. Brack
    Date : 2004-01-06 15:19:12
    Hash : 5d4cba41
    Message : fixed Bug130593 fixed compilation warning * configure.in: fixed Bug130593 * xmlwriter.c: fixed compilation warning

  • xmlwriter.c
  • /*
     * xmlwriter.c: XML text writer implementation
     *
     * For license and disclaimer see the license and disclaimer of
     * libxml2.
     *
     * alfred@mickautsch.de
     */
    
    #define IN_LIBXML
    #include <string.h>
    
    #include "libxml.h"
    #include <libxml/xmlmemory.h>
    #include <libxml/parser.h>
    #include <libxml/uri.h>
    #include <libxml/HTMLtree.h>
    
    #ifdef LIBXML_WRITER_ENABLED
    
    #include <libxml/xmlwriter.h>
    
    #define B64LINELEN 72
    #define B64CRLF "\r\n"
    
    /*
     * Types are kept private
     */
    typedef enum {
        XML_TEXTWRITER_NONE = 0,
        XML_TEXTWRITER_NAME,
        XML_TEXTWRITER_ATTRIBUTE,
        XML_TEXTWRITER_TEXT,
        XML_TEXTWRITER_PI,
        XML_TEXTWRITER_PI_TEXT,
        XML_TEXTWRITER_CDATA,
        XML_TEXTWRITER_DTD,
        XML_TEXTWRITER_DTD_TEXT,
        XML_TEXTWRITER_DTD_ELEM,
        XML_TEXTWRITER_DTD_ATTL,
        XML_TEXTWRITER_DTD_ENTY
    } xmlTextWriterState;
    
    typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
    
    struct _xmlTextWriterStackEntry {
        xmlChar *name;
        xmlTextWriterState state;
    };
    
    typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
    struct _xmlTextWriterNsStackEntry {
        xmlChar *prefix;
        xmlChar *uri;
        xmlLinkPtr elem;
    };
    
    struct _xmlTextWriter {
        xmlOutputBufferPtr out; /* output buffer */
        xmlListPtr nodes;       /* element name stack */
        xmlListPtr nsstack;     /* name spaces stack */
        int level;
        int indent;             /* enable indent */
        int doindent;	    /* internal indent flag */
        xmlChar *ichar;            /* indent character */
        char qchar;             /* character used for quoting attribute values */
    };
    
    static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
    static int xmlCmpTextWriterStackEntry(const void *data0,
                                          const void *data1);
    static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
    static int xmlCmpTextWriterNsStackEntry(const void *data0,
                                            const void *data1);
    static int xmlTextWriterWriteMemCallback(void *context,
                                             const xmlChar * str, int len);
    static int xmlTextWriterCloseMemCallback(void *context);
    static int xmlTextWriterWriteDocCallback(void *context,
                                             const xmlChar * str, int len);
    static int xmlTextWriterCloseDocCallback(void *context);
    
    static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);
    static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
                                          const unsigned char *data);
    static void xmlTextWriterStartDocumentCallback(void *ctx);
    static int xmlTextWriterWriteIndent (xmlTextWriterPtr writer);
    
    /**
     * xmlNewTextWriter:
     * @out:  an xmlOutputBufferPtr
     *
     * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriter(xmlOutputBufferPtr out)
    {
        xmlTextWriterPtr ret;
    
        ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
        if (ret == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriter : out of memory!\n");
            return NULL;
        }
        memset(ret, 0, (size_t) sizeof(xmlTextWriter));
    
        ret->nodes = xmlListCreate((xmlListDeallocator)
                                   xmlFreeTextWriterStackEntry,
                                   (xmlListDataCompare)
                                   xmlCmpTextWriterStackEntry);
        if (ret->nodes == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriter : out of memory!\n");
            xmlFree(ret);
            return NULL;
        }
    
        ret->nsstack = xmlListCreate((xmlListDeallocator)
                                     xmlFreeTextWriterNsStackEntry,
                                     (xmlListDataCompare)
                                     xmlCmpTextWriterNsStackEntry);
        if (ret->nsstack == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriter : out of memory!\n");
            xmlFree(ret->nodes);
            xmlFree(ret);
            return NULL;
        }
    
        ret->out = out;
        ret->ichar = xmlStrdup (BAD_CAST " ");
        ret->qchar = '"';
    
        if (!ret->ichar) return NULL;
      
        return ret;
    }
    
    /**
     * xmlNewTextWriterFilename:
     * @uri:  the URI of the resource for the output
     * @compression:  compress the output?
     *
     * Create a new xmlNewTextWriter structure with @uri as output
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriterFilename(const char *uri, int compression)
    {
        xmlTextWriterPtr ret;
        xmlOutputBufferPtr out;
    
        out = xmlOutputBufferCreateFilename(uri, NULL, compression);
        if (out == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterFilename : out of memory!\n");
            return NULL;
        }
    
        ret = xmlNewTextWriter(out);
        if (ret == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterFilename : out of memory!\n");
            xmlOutputBufferClose(out);
            return NULL;
        }
    
        ret->indent = 0;
        ret->doindent = 0;
        return ret;
    }
    
    /**
     * xmlNewTextWriterMemory:
     * @buf:  xmlBufferPtr
     * @compression:  compress the output?
     *
     * Create a new xmlNewTextWriter structure with @buf as output
     * TODO: handle compression
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
    {
        xmlTextWriterPtr ret;
        xmlOutputBufferPtr out;
    
    /*::todo handle compression */
        out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
                                      xmlTextWriterWriteMemCallback,
                                      (xmlOutputCloseCallback)
                                      xmlTextWriterCloseMemCallback,
                                      (void *) buf, NULL);
        if (out == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterMemory : out of memory!\n");
            return NULL;
        }
    
        ret = xmlNewTextWriter(out);
        if (ret == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterMemory : out of memory!\n");
            xmlOutputBufferClose(out);
            return NULL;
        }
    
        return ret;
    }
    
    /**
     * xmlNewTextWriterPushParser:
     * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
     * @compression:  compress the output?
     *
     * Create a new xmlNewTextWriter structure with @ctxt as output
     * TODO: handle compression
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
                               int compression ATTRIBUTE_UNUSED)
    {
        xmlTextWriterPtr ret;
        xmlOutputBufferPtr out;
    
        out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
                                      xmlTextWriterWriteDocCallback,
                                      (xmlOutputCloseCallback)
                                      xmlTextWriterCloseDocCallback,
                                      (void *) ctxt, NULL);
        if (out == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
            return NULL;
        }
    
        ret = xmlNewTextWriter(out);
        if (ret == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
            xmlOutputBufferClose(out);
            return NULL;
        }
    
        return ret;
    }
    
    /**
     * xmlNewTextWriterDoc:
     * @doc: address of a xmlDocPtr to hold the new XML document tree
     * @compression:  compress the output?
     *
     * Create a new xmlNewTextWriter structure with @*doc as output
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
    {
        xmlTextWriterPtr ret;
        xmlSAXHandler saxHandler;
        xmlParserCtxtPtr ctxt;
    
        memset(&saxHandler, '\0', sizeof(saxHandler));
        xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
        saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
        saxHandler.startElement = xmlSAX2StartElement;
        saxHandler.endElement = xmlSAX2EndElement;
    
        ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
        if (ctxt == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
            return NULL;
        }
    
        ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
        if (ctxt->myDoc == NULL) {
            xmlFreeParserCtxt(ctxt);
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
            return NULL;
        }
    
        ret = xmlNewTextWriterPushParser(ctxt, compression);
        if (ret == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
            return NULL;
        }
    
        *doc = ctxt->myDoc;
        xmlSetDocCompressMode(*doc, compression);
    
        return ret;
    }
    
    /**
     * xmlNewTextWriterTree:
     * @doc: xmlDocPtr
     * @node: xmlNodePtr or NULL for doc->children
     * @compression:  compress the output?
     *
     * Create a new xmlNewTextWriter structure with @doc as output
     * starting at @node
     *
     * Returns the new xmlTextWriterPtr or NULL in case of error
     */
    xmlTextWriterPtr
    xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
    {
        xmlTextWriterPtr ret;
        xmlSAXHandler saxHandler;
        xmlParserCtxtPtr ctxt;
    
        if (doc == NULL) {
            return NULL;
        }
    
        memset(&saxHandler, '\0', sizeof(saxHandler));
        xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
        saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
        saxHandler.startElement = xmlSAX2StartElement;
        saxHandler.endElement = xmlSAX2EndElement;
    
        ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
        if (ctxt == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
            return NULL;
        }
    
        ctxt->myDoc = doc;
        ctxt->node = node;
    
        ret = xmlNewTextWriterPushParser(ctxt, compression);
        if (ret == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
            return NULL;
        }
    
        xmlSetDocCompressMode(doc, compression);
    
        return ret;
    }
    
    /**
     * xmlFreeTextWriter:
     * @writer:  the xmlTextWriterPtr
     *
     * Deallocate all the resources associated to the writer
     */
    void
    xmlFreeTextWriter(xmlTextWriterPtr writer)
    {
        if (writer == NULL)
            return;
    
        if (writer->out != NULL)
            xmlOutputBufferClose(writer->out);
    
        if (writer->nodes != NULL)
            xmlListDelete(writer->nodes);
    
        if (writer->nsstack != NULL)
            xmlListDelete(writer->nsstack);
    
        xmlFree(writer);
    }
    
    /**
     * xmlTextWriterStartDocument:
     * @writer:  the xmlTextWriterPtr
     * @version:  the xml version ("1.0") or NULL for default ("1.0")
     * @encoding:  the encoding or NULL for default
     * @standalone: "yes" or "no" or NULL for default
     *
     * Start a new xml document
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
                               const char *encoding, const char *standalone)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlCharEncodingHandlerPtr encoder;
    
        if ((writer == NULL) || (writer->out == NULL))
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartDocument : only one prolog allowed in an XML document!\n");
            return -1;
        }
    
        encoder = NULL;
        if (encoding != NULL) {
            encoder = xmlFindCharEncodingHandler(encoding);
            if (encoder == NULL) {
                xmlGenericError(xmlGenericErrorContext,
                                "xmlTextWriterStartDocument : out of memory!\n");
                return -1;
            }
        }
    
        writer->out->encoder = encoder;
        if (encoder != NULL) {
            writer->out->conv = xmlBufferCreateSize(4000);
            xmlCharEncOutFunc(encoder, writer->out->conv, NULL);
        } else
            writer->out->conv = NULL;
    
        sum = 0;
        count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
        if (count < 0)
            return -1;
        sum += count;
        if (version != 0)
            count = xmlOutputBufferWriteString(writer->out, version);
        else
            count = xmlOutputBufferWriteString(writer->out, "1.0");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
        if (count < 0)
            return -1;
        sum += count;
        if (writer->out->encoder != 0) {
            count = xmlOutputBufferWriteString(writer->out, " encoding=");
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
            count =
                xmlOutputBufferWriteString(writer->out,
                                           writer->out->encoder->name);
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (standalone != 0) {
            count = xmlOutputBufferWriteString(writer->out, " standalone=");
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWriteString(writer->out, standalone);
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, "?>\n");
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndDocument:
     * @writer:  the xmlTextWriterPtr
     *
     * End an xml document. All open elements are closed
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndDocument(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        sum = 0;
        while ((lk = xmlListFront(writer->nodes)) != NULL) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p == 0)
                break;
            switch (p->state) {
                case XML_TEXTWRITER_NAME:
                case XML_TEXTWRITER_ATTRIBUTE:
                case XML_TEXTWRITER_TEXT:
                    count = xmlTextWriterEndElement(writer);
                    if (count < 0)
                        return -1;
                    sum += count;
                    break;
                case XML_TEXTWRITER_PI:
                case XML_TEXTWRITER_PI_TEXT:
                    count = xmlTextWriterEndPI(writer);
                    if (count < 0)
                        return -1;
                    sum += count;
                    break;
                case XML_TEXTWRITER_CDATA:
                    count = xmlTextWriterEndCDATA(writer);
                    if (count < 0)
                        return -1;
                    sum += count;
                    break;
                case XML_TEXTWRITER_DTD:
                    count = xmlTextWriterEndDTD(writer);
                    if (count < 0)
                        return -1;
                    sum += count;
                    break;
                default:
    		break;
            }
        }
    
        if (!writer->indent) {
        count = xmlOutputBufferWriteString(writer->out, "\n");
        if(count < 0)
            return -1;
        sum += count;
        }
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatComment:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write an xml comment.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
                                    const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatComment:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write an xml comment.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
                                     const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteComment(writer, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteComment:
     * @writer:  the xmlTextWriterPtr
     * @content:  comment string
     *
     * Write an xml comment.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if ((writer == NULL) || (writer->out == NULL))
            return -1;
    
        if (content == NULL)
            return 0;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                switch (p->state) {
                    case XML_TEXTWRITER_PI:
                    case XML_TEXTWRITER_PI_TEXT:
                        return -1;
                    case XML_TEXTWRITER_NONE:
                    case XML_TEXTWRITER_TEXT:
                        break;
                    case XML_TEXTWRITER_NAME:
                        count = xmlOutputBufferWriteString(writer->out, ">");
                        if (count < 0)
                            return -1;
                        sum += count;
                        p->state = XML_TEXTWRITER_TEXT;
                        break;
    		default:
    		    break;
                }
            }
        }
    
        if (writer->indent) {
          count = xmlOutputBufferWriteString (writer->out, "\n");
          sum += count;
        }
        
        count = xmlOutputBufferWriteString(writer->out, "<!--");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWriteString(writer->out,
                                           (const char *) content);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWriteString(writer->out, "-->");
        if (count < 0)
            return -1;
        sum += count;
    
        if (writer->indent) {
          count = xmlOutputBufferWriteString (writer->out, "\n");
          sum += count;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  element name
     *
     * Start an xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                switch (p->state) {
                    case XML_TEXTWRITER_PI:
                    case XML_TEXTWRITER_PI_TEXT:
                        return -1;
                    case XML_TEXTWRITER_NONE:
                        break;
                    case XML_TEXTWRITER_NAME:
                        count = xmlOutputBufferWriteString(writer->out, ">");
                        if (count < 0)
                            return -1;
                        sum += count;
    		    if (writer->indent)
    		      count = xmlOutputBufferWriteString (writer->out, "\n");
                        p->state = XML_TEXTWRITER_TEXT;
                        break;
    		default:
    		    break;
                }
            }
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartElement : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(name);
        if (p->name == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartElement : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_NAME;
    
        xmlListPushFront(writer->nodes, p);
    
        if (writer->indent) { 
          count = xmlTextWriterWriteIndent (writer);
          sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, "<");
        if (count < 0)
            return -1;
        sum += count;
        count =
            xmlOutputBufferWriteString(writer->out, (const char *) p->name);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartElementNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix or NULL
     * @name:  element local name
     * @namespaceURI:  namespace URI or NULL
     *
     * Start an xml element with namespace support.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
                                const xmlChar * prefix, const xmlChar * name,
                                const xmlChar * namespaceURI)
    {
        int count;
        int sum;
        xmlChar *buf;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        buf = 0;
        if (prefix != 0) {
            buf = xmlStrdup(prefix);
            buf = xmlStrcat(buf, BAD_CAST ":");
        }
        buf = xmlStrcat(buf, name);
    
        sum = 0;
        count = xmlTextWriterStartElement(writer, buf);
        xmlFree(buf);
        if (count < 0)
            return -1;
        sum += count;
    
        if (namespaceURI != 0) {
            buf = xmlStrdup(BAD_CAST "xmlns");
            if (prefix != 0) {
                buf = xmlStrcat(buf, BAD_CAST ":");
                buf = xmlStrcat(buf, prefix);
            }
    
            count = xmlTextWriterWriteAttribute(writer, buf, namespaceURI);
            xmlFree(buf);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndElement:
     * @writer:  the xmlTextWriterPtr
     *
     * End the current xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndElement(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_ATTRIBUTE:
                count = xmlTextWriterEndAttribute(writer);
                if (count < 0)
                    return -1;
                sum += count;
                /* fallthrough */
            case XML_TEXTWRITER_NAME:
                count = xmlOutputBufferWriteString(writer->out, "/>");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            case XML_TEXTWRITER_TEXT:
    	    if ((writer->indent) && (writer->doindent)) {
    	      count = xmlTextWriterWriteIndent (writer);
    	      sum += count;
    	      writer->doindent = 1;
    	    } else writer->doindent = 1;
                count = xmlOutputBufferWriteString(writer->out, "</");
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out,
    	                                       (const char *)p->name);
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        if (writer->indent) {
          count = xmlOutputBufferWriteString (writer->out, "\n");
          sum += count;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterFullEndElement:
     * @writer:  the xmlTextWriterPtr
     *
     * End the current xml element. Writes an end tag even if the element is empty
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_ATTRIBUTE:
                count = xmlTextWriterEndAttribute(writer);
                if (count < 0)
                    return -1;
                sum += count;
                /* fallthrough */
            case XML_TEXTWRITER_NAME:
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                /* fallthrough */
            case XML_TEXTWRITER_TEXT:
                count = xmlOutputBufferWriteString(writer->out, "</");
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out,
    	                                       (const char *) p->name);
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatRaw:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted raw xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
                                ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatRaw:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted raw xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
                                 va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteRaw(writer, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteRawLen:
     * @writer:  the xmlTextWriterPtr
     * @content:  text string
     * @len:  length of the text string
     *
     * Write an xml text.
     * TODO: what about entities and special chars??
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
                             int len)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return 0;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return 0;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_NONE:
                return -1;
            case XML_TEXTWRITER_NAME:
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_TEXT;
                break;
            case XML_TEXTWRITER_PI:
                count = xmlOutputBufferWriteString(writer->out, " ");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_PI_TEXT;
                break;
            case XML_TEXTWRITER_DTD:
                count = xmlOutputBufferWriteString(writer->out, " [");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_DTD_TEXT;
                break;
            default:
                break;
        }
    
        count = xmlOutputBufferWrite(writer->out, len, (const char *) content);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteRaw:
     * @writer:  the xmlTextWriterPtr
     * @content:  text string
     *
     * Write a raw xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
    {
        return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
    }
    
    /**
     * xmlTextWriterWriteFormatString:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
                                   ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatString(writer, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatString:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
                                    const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteString(writer, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteString:
     * @writer:  the xmlTextWriterPtr
     * @content:  text string
     *
     * Write an xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
        xmlChar *buf = NULL;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_NONE:
                return -1;
            case XML_TEXTWRITER_NAME:
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_TEXT;
                goto encode;
            case XML_TEXTWRITER_PI:
                count = xmlOutputBufferWriteString(writer->out, " ");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_PI_TEXT;
                /* fallthrough */
            case XML_TEXTWRITER_PI_TEXT:
            case XML_TEXTWRITER_TEXT:
            case XML_TEXTWRITER_ATTRIBUTE:
              encode:
                buf = xmlEncodeSpecialChars(NULL, content);
                break;
            case XML_TEXTWRITER_DTD:
                count = xmlOutputBufferWriteString(writer->out, " [");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_DTD_TEXT;
                /* fallthrough */
            case XML_TEXTWRITER_DTD_TEXT:
            case XML_TEXTWRITER_DTD_ELEM:
            case XML_TEXTWRITER_CDATA:
                buf = xmlStrdup(content);
                break;
    	default:
    	    break;
        }
    
        if (writer->indent)
          writer->doindent = 0;
    
        if (buf != 0) {
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) buf);
            xmlFree(buf);
        } else
            count = -1;
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlOutputBufferWriteBase64:
     * @out: the xmlOutputBufferPtr
     * @data:   binary data
     * @len:  the number of bytes to encode
     *
     * Write base64 encoded data to an xmlOutputBuffer.
     * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    static int
    xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
                               const unsigned char *data)
    {
        static unsigned char dtable[64] =
            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        int i;
        int linelen;
        int count;
        int sum;
    
        linelen = 0;
        sum = 0;
    
        i = 0;
        while (1) {
            unsigned char igroup[3];
            unsigned char ogroup[4];
            int c;
            int n;
    
            igroup[0] = igroup[1] = igroup[2] = 0;
            for (n = 0; n < 3 && i < len; n++, i++) {
                c = data[i];
                igroup[n] = (unsigned char) c;
            }
    
            if (n > 0) {
                ogroup[0] = dtable[igroup[0] >> 2];
                ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
                ogroup[2] =
                    dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
                ogroup[3] = dtable[igroup[2] & 0x3F];
    
                if (n < 3) {
                    ogroup[3] = '=';
                    if (n < 2) {
                        ogroup[2] = '=';
                    }
                }
    
                if (linelen >= B64LINELEN) {
                    count = xmlOutputBufferWrite(out, 2, B64CRLF);
                    if (count == -1)
                        return -1;
                    sum += count;
                    linelen = 0;
                }
                count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
                if (count == -1)
                    return -1;
                sum += count;
    
                linelen += 4;
            }
    
            if (i >= len)
                break;
        }
    
        count = xmlOutputBufferWrite(out, 2, B64CRLF);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteBase64:
     * @writer: the xmlTextWriterPtr
     * @data:   binary data
     * @start:  the position within the data of the first byte to encode
     * @len:  the number of bytes to encode
     *
     * Write an base64 encoded xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char * data,
                             int start, int len)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return 0;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return 0;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_NONE:
                return -1;
            case XML_TEXTWRITER_NAME:
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_TEXT;
                break;
            case XML_TEXTWRITER_PI:
                count = xmlOutputBufferWriteString(writer->out, " ");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_PI_TEXT;
                break;
            case XML_TEXTWRITER_DTD:
                count = xmlOutputBufferWriteString(writer->out, " [");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_DTD_TEXT;
                break;
            default:
                break;
        }
    
        count =
            xmlOutputBufferWriteBase64(writer->out, len,
                                       (unsigned char *) data + start);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlOutputBufferWriteBinHex:
     * @out: the xmlOutputBufferPtr
     * @data:   binary data
     * @len:  the number of bytes to encode
     *
     * Write hqx encoded data to an xmlOutputBuffer.
     * ::todo
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    static int
    xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out ATTRIBUTE_UNUSED,
                               int len ATTRIBUTE_UNUSED,
                               const unsigned char *data ATTRIBUTE_UNUSED)
    {
        return -1;
    }
    
    /**
     * xmlTextWriterWriteBinHex:
     * @writer: the xmlTextWriterPtr
     * @data:   binary data
     * @start:  the position within the data of the first byte to encode
     * @len:  the number of bytes to encode
     *
     * Write a BinHex encoded xml text.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char * data,
                             int start, int len)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return 0;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return 0;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_NONE:
                return -1;
            case XML_TEXTWRITER_NAME:
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_TEXT;
                break;
            case XML_TEXTWRITER_PI:
                count = xmlOutputBufferWriteString(writer->out, " ");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_PI_TEXT;
                break;
            case XML_TEXTWRITER_DTD:
                count = xmlOutputBufferWriteString(writer->out, " [");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_DTD_TEXT;
                break;
            default:
                break;
        }
    
        count =
            xmlOutputBufferWriteBinHex(writer->out, len,
                                       (unsigned char *) data + start);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartAttribute:
     * @writer:  the xmlTextWriterPtr
     * @name:  element name
     *
     * Start an xml attribute.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_ATTRIBUTE:
                count = xmlTextWriterEndAttribute(writer);
                if (count < 0)
                    return -1;
                sum += count;
                /* fallthrough */
            case XML_TEXTWRITER_NAME:
                count = xmlOutputBufferWriteString(writer->out, " ");
                if (count < 0)
                    return -1;
                sum += count;
                count =
                    xmlOutputBufferWriteString(writer->out,
                                               (const char *) name);
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWriteString(writer->out, "=");
                if (count < 0)
                    return -1;
                sum += count;
                count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_ATTRIBUTE;
                break;
            default:
                return -1;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartAttributeNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix or NULL
     * @name:  element local name
     * @namespaceURI:  namespace URI or NULL
     *
     * Start an xml attribute with namespace support.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
                                  const xmlChar * prefix, const xmlChar * name,
                                  const xmlChar * namespaceURI)
    {
        int count;
        int sum;
        xmlChar *buf;
        xmlTextWriterNsStackEntry *p;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        buf = 0;
        if (prefix != 0) {
            buf = xmlStrdup(prefix);
            buf = xmlStrcat(buf, BAD_CAST ":");
        }
        buf = xmlStrcat(buf, name);
    
        sum = 0;
        count = xmlTextWriterStartAttribute(writer, buf);
        xmlFree(buf);
        if (count < 0)
            return -1;
        sum += count;
    
        if (namespaceURI != 0) {
            buf = xmlStrdup(BAD_CAST "xmlns");
            if (prefix != 0) {
                buf = xmlStrcat(buf, BAD_CAST ":");
                buf = xmlStrcat(buf, prefix);
            }
    
            p = (xmlTextWriterNsStackEntry *)
                xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
            if (p == 0) {
                xmlGenericError(xmlGenericErrorContext,
                                "xmlTextWriterStartAttributeNS : out of memory!\n");
                return -1;
            }
    
            p->prefix = buf;
            p->uri = xmlStrdup(namespaceURI);
            if (p->uri == 0) {
                xmlGenericError(xmlGenericErrorContext,
                                "xmlTextWriterStartAttributeNS : out of memory!\n");
                xmlFree(p);
                return -1;
            }
            p->elem = xmlListFront(writer->nodes);
    
            xmlListPushFront(writer->nsstack, p);
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndAttribute:
     * @writer:  the xmlTextWriterPtr
     *
     * End the current xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
        xmlTextWriterNsStackEntry *np;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            xmlListDelete(writer->nsstack);
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0) {
            xmlListDelete(writer->nsstack);
            return -1;
        }
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_ATTRIBUTE:
                p->state = XML_TEXTWRITER_NAME;
    
                count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
                if (count < 0) {
                    xmlListDelete(writer->nsstack);
                    return -1;
                }
                sum += count;
    
                while (!xmlListEmpty(writer->nsstack)) {
                    lk = xmlListFront(writer->nsstack);
                    np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
                    if (np != 0) {
                        count =
                            xmlTextWriterWriteAttribute(writer, np->prefix,
                                                        np->uri);
                        if (count < 0) {
                            xmlListDelete(writer->nsstack);
                            return -1;
                        }
                        sum += count;
                    }
    
                    xmlListPopFront(writer->nsstack);
                }
                break;
    
            default:
                xmlListClear(writer->nsstack);
                return -1;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatAttribute:
     * @writer:  the xmlTextWriterPtr
     * @name:  attribute name
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml attribute.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
                                      const xmlChar * name, const char *format,
                                      ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatAttribute:
     * @writer:  the xmlTextWriterPtr
     * @name:  attribute name
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml attribute.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
                                       const xmlChar * name,
                                       const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteAttribute(writer, name, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteAttribute:
     * @writer:  the xmlTextWriterPtr
     * @name:  attribute name
     * @content:  attribute content
     *
     * Write an xml attribute.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
                                const xmlChar * content)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartAttribute(writer, name);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterWriteString(writer, content);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterEndAttribute(writer);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatAttributeNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  attribute local name
     * @namespaceURI:  namespace URI
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml attribute.with namespace support
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
                                        const xmlChar * prefix,
                                        const xmlChar * name,
                                        const xmlChar * namespaceURI,
                                        const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
                                                  namespaceURI, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatAttributeNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  attribute local name
     * @namespaceURI:  namespace URI
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml attribute.with namespace support
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
                                         const xmlChar * prefix,
                                         const xmlChar * name,
                                         const xmlChar * namespaceURI,
                                         const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
                                           buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteAttributeNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  attribute local name
     * @namespaceURI:  namespace URI
     * @content:  attribute content
     *
     * Write an xml attribute.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
                                  const xmlChar * prefix, const xmlChar * name,
                                  const xmlChar * namespaceURI,
                                  const xmlChar * content)
    {
        int count;
        int sum;
        xmlChar *buf;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        buf = 0;
        if (prefix != NULL) {
            buf = xmlStrdup(prefix);
            buf = xmlStrcat(buf, BAD_CAST ":");
        }
        buf = xmlStrcat(buf, name);
    
        sum = 0;
        count = xmlTextWriterWriteAttribute(writer, buf, content);
        xmlFree(buf);
        if (count < 0)
            return -1;
        sum += count;
    
        if (namespaceURI != NULL) {
            buf = 0;
            buf = xmlStrdup(BAD_CAST "xmlns");
            if (prefix != NULL) {
                buf = xmlStrcat(buf, BAD_CAST ":");
                buf = xmlStrcat(buf, prefix);
            }
            count = xmlTextWriterWriteAttribute(writer, buf, namespaceURI);
            xmlFree(buf);
            if (count < 0)
                return -1;
            sum += count;
        }
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  element name
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
                                    const xmlChar * name, const char *format,
                                    ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  element name
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
                                     const xmlChar * name, const char *format,
                                     va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteElement(writer, name, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  element name
     * @content:  element content
     *
     * Write an xml element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
                              const xmlChar * content)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartElement(writer, name);
        if (count == -1)
            return -1;
        sum += count;
        count = xmlTextWriterWriteString(writer, content);
        if (count == -1)
            return -1;
        sum += count;
        count = xmlTextWriterEndElement(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatElementNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  element local name
     * @namespaceURI:  namespace URI
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml element with namespace support.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
                                      const xmlChar * prefix,
                                      const xmlChar * name,
                                      const xmlChar * namespaceURI,
                                      const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
                                                namespaceURI, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatElementNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  element local name
     * @namespaceURI:  namespace URI
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml element with namespace support.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
                                       const xmlChar * prefix,
                                       const xmlChar * name,
                                       const xmlChar * namespaceURI,
                                       const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
                                         buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteElementNS:
     * @writer:  the xmlTextWriterPtr
     * @prefix:  namespace prefix
     * @name:  element local name
     * @namespaceURI:  namespace URI
     * @content:  element content
     *
     * Write an xml element with namespace support.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
                                const xmlChar * prefix, const xmlChar * name,
                                const xmlChar * namespaceURI,
                                const xmlChar * content)
    {
        int count;
        int sum;
    
        if ((writer == NULL) || (name == NULL) || (*name == '\0'))
            return -1;
    
        sum = 0;
        count =
            xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterWriteString(writer, content);
        if (count == -1)
            return -1;
        sum += count;
        count = xmlTextWriterEndElement(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartPI:
     * @writer:  the xmlTextWriterPtr
     * @target:  PI target
     *
     * Start an xml PI.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if ((writer == NULL) || (target == NULL) || (*target == '\0'))
            return -1;
    
        if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
            return -1;
        }
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                switch (p->state) {
                    case XML_TEXTWRITER_ATTRIBUTE:
                        count = xmlTextWriterEndAttribute(writer);
                        if (count < 0)
                            return -1;
                        sum += count;
                        /* fallthrough */
                    case XML_TEXTWRITER_NAME:
                        count = xmlOutputBufferWriteString(writer->out, ">");
                        if (count < 0)
                            return -1;
                        sum += count;
                        p->state = XML_TEXTWRITER_TEXT;
                        break;
    		case XML_TEXTWRITER_NONE:
    		case XML_TEXTWRITER_TEXT:
    		case XML_TEXTWRITER_DTD:
    		    break;
                    case XML_TEXTWRITER_PI:
                    case XML_TEXTWRITER_PI_TEXT:
                        xmlGenericError(xmlGenericErrorContext,
                                        "xmlTextWriterStartPI : nested PI!\n");
                        return -1;
                    default:
                        return -1;
                }
            }
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartPI : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(target);
        if (p->name == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartPI : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_PI;
    
        xmlListPushFront(writer->nodes, p);
    
        count = xmlOutputBufferWriteString(writer->out, "<?");
        if (count < 0)
            return -1;
        sum += count;
        count =
            xmlOutputBufferWriteString(writer->out, (const char *) p->name);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndPI:
     * @writer:  the xmlTextWriterPtr
     *
     * End the current xml PI.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndPI(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return 0;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return 0;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_PI:
            case XML_TEXTWRITER_PI_TEXT:
                count = xmlOutputBufferWriteString(writer->out, "?>");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatPI:
     * @writer:  the xmlTextWriterPtr
     * @target:  PI target
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted PI.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
                               const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatPI:
     * @writer:  the xmlTextWriterPtr
     * @target:  PI target
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml PI.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
                                const xmlChar * target, const char *format,
                                va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWritePI(writer, target, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWritePI:
     * @writer:  the xmlTextWriterPtr
     * @target:  PI target
     * @content:  PI content
     *
     * Write an xml PI.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
                         const xmlChar * content)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartPI(writer, target);
        if (count == -1)
            return -1;
        sum += count;
        if (content != 0) {
            count = xmlTextWriterWriteString(writer, content);
            if (count == -1)
                return -1;
            sum += count;
        }
        count = xmlTextWriterEndPI(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartCDATA:
     * @writer:  the xmlTextWriterPtr
     *
     * Start an xml CDATA section.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
            if (p != 0) {
                switch (p->state) {
                    case XML_TEXTWRITER_NONE:
                    case XML_TEXTWRITER_PI:
                    case XML_TEXTWRITER_PI_TEXT:
                        break;
                    case XML_TEXTWRITER_ATTRIBUTE:
                        count = xmlTextWriterEndAttribute(writer);
                        if (count < 0)
                            return -1;
                        sum += count;
                        /* fallthrough */
                    case XML_TEXTWRITER_NAME:
                        count = xmlOutputBufferWriteString(writer->out, ">");
                        if (count < 0)
                            return -1;
                        sum += count;
                        p->state = XML_TEXTWRITER_TEXT;
                        break;
                    case XML_TEXTWRITER_CDATA:
                        xmlGenericError(xmlGenericErrorContext,
                                        "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
                        return -1;
                    default:
                        return -1;
                }
            }
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartCDATA : out of memory!\n");
            return -1;
        }
    
        p->name = 0;
        p->state = XML_TEXTWRITER_CDATA;
    
        xmlListPushFront(writer->nodes, p);
    
        count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndCDATA:
     * @writer:  the xmlTextWriterPtr
     *
     * End an xml CDATA section.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        sum = 0;
        switch (p->state) {
            case XML_TEXTWRITER_CDATA:
                count = xmlOutputBufferWriteString(writer->out, "]]>");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatCDATA:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted xml CDATA.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
                                  ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatCDATA:
     * @writer:  the xmlTextWriterPtr
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted xml CDATA.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
                                   va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteCDATA(writer, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteCDATA:
     * @writer:  the xmlTextWriterPtr
     * @content:  CDATA content
     *
     * Write an xml CDATA.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartCDATA(writer);
        if (count == -1)
            return -1;
        sum += count;
        if (content != 0) {
            count = xmlTextWriterWriteString(writer, content);
            if (count == -1)
                return -1;
            sum += count;
        }
        count = xmlTextWriterEndCDATA(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartDTD:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     *
     * Start an xml DTD.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartDTD(xmlTextWriterPtr writer,
                          const xmlChar * name,
                          const xmlChar * pubid, const xmlChar * sysid)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL || name == NULL || *name == '\0')
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk != 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartDTD : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(name);
        if (p->name == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartDTD : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_DTD;
    
        xmlListPushFront(writer->nodes, p);
    
        count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWriteString(writer->out, (const char *) name);
        if (count < 0)
            return -1;
        sum += count;
    
        if (pubid != 0) {
            if (sysid == 0) {
                xmlGenericError(xmlGenericErrorContext,
                                "xmlTextWriterStartDTD : system identifier needed!\n");
                return -1;
            }
    
            count = xmlOutputBufferWriteString(writer->out, " PUBLIC \"");
            if (count < 0)
                return -1;
            sum += count;
    
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) pubid);
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWriteString(writer->out, "\"");
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (sysid != 0) {
            if (pubid == 0) {
                count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
                if (count < 0)
                    return -1;
                sum += count;
            }
    
            count = xmlOutputBufferWriteString(writer->out, " \"");
            if (count < 0)
                return -1;
            sum += count;
    
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) sysid);
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWriteString(writer->out, "\"");
            if (count < 0)
                return -1;
            sum += count;
        }
    
        return sum;
    }
    
    /**
     * xmlTextWriterEndDTD:
     * @writer:  the xmlTextWriterPtr
     *
     * End an xml DTD.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterEndDTD(xmlTextWriterPtr writer)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL)
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0)
            return -1;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_DTD_TEXT:
                count = xmlOutputBufferWriteString(writer->out, "]");
                if (count < 0)
                    return -1;
                sum += count;
                /* fallthrough */
            case XML_TEXTWRITER_DTD:
            case XML_TEXTWRITER_DTD_ELEM:
            case XML_TEXTWRITER_DTD_ATTL:
                count = xmlOutputBufferWriteString(writer->out, ">");
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        xmlListPopFront(writer->nodes);
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatDTD:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a DTD with a formatted markup declarations part.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
                                const xmlChar * name,
                                const xmlChar * pubid,
                                const xmlChar * sysid, const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
                                          ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatDTD:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a DTD with a formatted markup declarations part.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
                                 const xmlChar * name,
                                 const xmlChar * pubid,
                                 const xmlChar * sysid,
                                 const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteDTD:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @subset:  string content of the DTD
     *
     * Write a DTD.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
                          const xmlChar * name,
                          const xmlChar * pubid,
                          const xmlChar * sysid, const xmlChar * subset)
    {
        int count;
        int sum;
    
        sum = 0;
        count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
        if (count == -1)
            return -1;
        sum += count;
        if (subset != 0) {
            count = xmlTextWriterWriteString(writer, subset);
            if (count == -1)
                return -1;
            sum += count;
        }
        count = xmlTextWriterEndDTD(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartDTDElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD element
     *
     * Start an xml DTD element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL || name == NULL || *name == '\0')
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_DTD:
                count = xmlOutputBufferWriteString(writer->out, " [");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_DTD_TEXT;
                /* fallthrough */
            case XML_TEXTWRITER_DTD_TEXT:
                break;
            case XML_TEXTWRITER_DTD_ELEM:
                count = xmlTextWriterEndDTDElement(writer);
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartDTDElement : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(name);
        if (p->name == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartDTDElement : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_DTD_ELEM;
    
        xmlListPushFront(writer->nodes, p);
    
        count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWriteString(writer->out, (const char *) name);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatDTDElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD element
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted DTD element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
                                       const xmlChar * name,
                                       const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatDTDElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD element
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted DTD element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
                                        const xmlChar * name,
                                        const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteDTDElement(writer, name, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteDTDElement:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD element
     * @content:  content of the element
     *
     * Write a DTD element.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
                                 const xmlChar * name, const xmlChar * content)
    {
        int count;
        int sum;
    
        if (content == NULL)
            return -1;
    
        sum = 0;
        count = xmlTextWriterStartDTDElement(writer, name);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterWriteString(writer, BAD_CAST " ");
        if (count == -1)
            return -1;
        sum += count;
        count = xmlTextWriterWriteString(writer, content);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterEndDTDElement(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartDTDAttlist:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD ATTLIST
     *
     * Start an xml DTD ATTLIST.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL || name == NULL || *name == '\0')
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_DTD:
                count = xmlOutputBufferWriteString(writer->out, " [");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_DTD_TEXT;
                /* fallthrough */
            case XML_TEXTWRITER_DTD_TEXT:
                break;
            case XML_TEXTWRITER_DTD_ELEM:
            case XML_TEXTWRITER_DTD_ATTL:
            case XML_TEXTWRITER_DTD_ENTY:
                count = xmlTextWriterEndDTD(writer);
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartDTDAttlist : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(name);
        if (p->name == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartDTDAttlist : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_DTD_ATTL;
    
        xmlListPushFront(writer->nodes, p);
    
        count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWriteString(writer->out, (const char *)name);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatDTDAttlist:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD ATTLIST
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted DTD ATTLIST.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
                                       const xmlChar * name,
                                       const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatDTDAttlist:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD ATTLIST
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted DTD ATTLIST.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
                                        const xmlChar * name,
                                        const char *format, va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteDTDAttlist:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the DTD ATTLIST
     * @content:  content of the ATTLIST
     *
     * Write a DTD ATTLIST.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
                                 const xmlChar * name, const xmlChar * content)
    {
        int count;
        int sum;
    
        if (content == NULL)
            return -1;
    
        sum = 0;
        count = xmlTextWriterStartDTDAttlist(writer, name);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterWriteString(writer, BAD_CAST " ");
        if (count == -1)
            return -1;
        sum += count;
        count = xmlTextWriterWriteString(writer, content);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterEndDTDAttlist(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterStartDTDEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD ATTLIST
     *
     * Start an xml DTD ATTLIST.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
                                int pe, const xmlChar * name)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL || name == NULL || *name == '\0')
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_DTD:
                count = xmlOutputBufferWriteString(writer->out, " [");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_DTD_TEXT;
                /* fallthrough */
            case XML_TEXTWRITER_DTD_TEXT:
                break;
            case XML_TEXTWRITER_DTD_ELEM:
            case XML_TEXTWRITER_DTD_ATTL:
            case XML_TEXTWRITER_DTD_ENTY:
                count = xmlTextWriterEndDTD(writer);
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        p = (xmlTextWriterStackEntry *)
            xmlMalloc(sizeof(xmlTextWriterStackEntry));
        if (p == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartDTDElement : out of memory!\n");
            return -1;
        }
    
        p->name = xmlStrdup(name);
        if (p->name == 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterStartDTDElement : out of memory!\n");
            xmlFree(p);
            return -1;
        }
        p->state = XML_TEXTWRITER_DTD_ENTY;
    
        xmlListPushFront(writer->nodes, p);
    
        count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
        if (count < 0)
            return -1;
        sum += count;
    
        if (pe != 0) {
            count = xmlOutputBufferWriteString(writer->out, " % ");
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, (const char *)name);
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteFormatDTDInternalEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD entity
     * @format:  format string (see printf)
     * @...:  extra parameters for the format
     *
     * Write a formatted DTD internal entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
                                              int pe,
                                              const xmlChar * name,
                                              const char *format, ...)
    {
        int rc;
        va_list ap;
    
        va_start(ap, format);
    
        rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
                                                        format, ap);
    
        va_end(ap);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteVFormatDTDInternalEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD entity
     * @format:  format string (see printf)
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Write a formatted DTD internal entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
                                               int pe,
                                               const xmlChar * name,
                                               const char *format,
                                               va_list argptr)
    {
        int rc;
        xmlChar *buf;
    
        if (writer == NULL)
            return -1;
    
        buf = xmlTextWriterVSprintf(format, argptr);
        if (buf == 0)
            return 0;
    
        rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
    
        xmlFree(buf);
        return rc;
    }
    
    /**
     * xmlTextWriterWriteDTDEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD entity
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @ndataid:  the xml notation name.
     * @content:  content of the entity
     *
     * Write a DTD entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
                                int pe,
                                const xmlChar * name,
                                const xmlChar * pubid,
                                const xmlChar * sysid,
                                const xmlChar * ndataid,
                                const xmlChar * content)
    {
        if (((content == NULL) && (pubid == NULL) && (sysid == NULL))
            || ((content != NULL) && ((pubid != NULL) || (sysid != NULL))))
            return -1;
        if ((pe != 0) && (ndataid != NULL))
            return -1;
    
        if (content != 0)
            return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
                                                       content);
    
        return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
                                                   sysid, ndataid);
    }
    
    /**
     * xmlTextWriterWriteDTDInternalEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD entity
     * @content:  content of the entity
     *
     * Write a DTD internal entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
                                        int pe,
                                        const xmlChar * name,
                                        const xmlChar * content)
    {
        int count;
        int sum;
    
        if ((name == NULL) || (*name == '\0') || (content == NULL))
            return -1;
    
        sum = 0;
        count = xmlTextWriterStartDTDEntity(writer, pe, name);
        if (count == -1)
            return -1;
        sum += count;
    
        count = xmlTextWriterWriteString(writer, BAD_CAST " ");
        if (count == -1)
            return -1;
        sum += count;
        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
        if (count < 0)
            return -1;
        sum += count;
        count = xmlTextWriterWriteString(writer, content);
        if (count == -1)
            return -1;
        sum += count;
        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
        if (count < 0)
            return -1;
        sum += count;
    
        count = xmlTextWriterEndDTDEntity(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteDTDExternalEntity:
     * @writer:  the xmlTextWriterPtr
     * @pe:  TRUE if this is a parameter entity, FALSE if not
     * @name:  the name of the DTD entity
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     * @ndataid:  the xml notation name.
     *
     * Write a DTD internal entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
                                        int pe,
                                        const xmlChar * name,
                                        const xmlChar * pubid,
                                        const xmlChar * sysid,
                                        const xmlChar * ndataid)
    {
        int count;
        int sum;
    
        if ((name == NULL) || (*name == '\0')
            || ((pubid == NULL) && (sysid == NULL)))
            return -1;
        if ((pe != 0) && (ndataid != NULL))
            return -1;
    
        sum = 0;
        count = xmlTextWriterStartDTDEntity(writer, pe, name);
        if (count == -1)
            return -1;
        sum += count;
    
        if (pubid != 0) {
            if (sysid == 0) {
                xmlGenericError(xmlGenericErrorContext,
                                "xmlTextWriterWriteDTDEntity : system identifier needed!\n");
                return -1;
            }
    
            count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
    
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) pubid);
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (sysid != 0) {
            if (pubid == 0) {
                count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
                if (count < 0)
                    return -1;
                sum += count;
            }
    
            count = xmlOutputBufferWriteString(writer->out, " ");
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
    
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) sysid);
            if (count < 0)
                return -1;
            sum += count;
    
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (ndataid != NULL) {
            count = xmlOutputBufferWriteString(writer->out, " NDATA ");
            if (count < 0)
                return -1;
            sum += count;
    
            count =
                xmlOutputBufferWriteString(writer->out,
                                           (const char *) ndataid);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlTextWriterEndDTDEntity(writer);
        if (count == -1)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterWriteDTDNotation:
     * @writer:  the xmlTextWriterPtr
     * @name:  the name of the xml notation
     * @pubid:  the public identifier, which is an alternative to the system identifier
     * @sysid:  the system identifier, which is the URI of the DTD
     *
     * Write a DTD entity.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
                                  const xmlChar * name,
                                  const xmlChar * pubid, const xmlChar * sysid)
    {
        int count;
        int sum;
        xmlLinkPtr lk;
        xmlTextWriterStackEntry *p;
    
        if (writer == NULL || name == NULL || *name == '\0')
            return -1;
    
        sum = 0;
        lk = xmlListFront(writer->nodes);
        if (lk == 0) {
            return -1;
        }
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return -1;
    
        switch (p->state) {
            case XML_TEXTWRITER_DTD:
                count = xmlOutputBufferWriteString(writer->out, " [");
                if (count < 0)
                    return -1;
                sum += count;
                p->state = XML_TEXTWRITER_DTD_TEXT;
                /* fallthrough */
            case XML_TEXTWRITER_DTD_TEXT:
                break;
            case XML_TEXTWRITER_DTD_ELEM:
            case XML_TEXTWRITER_DTD_ATTL:
            case XML_TEXTWRITER_DTD_ENTY:
                count = xmlTextWriterEndDTD(writer);
                if (count < 0)
                    return -1;
                sum += count;
                break;
            default:
                return -1;
        }
    
        count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
        if (count < 0)
            return -1;
        sum += count;
        count = xmlOutputBufferWriteString(writer->out, (const char *) name);
        if (count < 0)
            return -1;
        sum += count;
    
        if (pubid != 0) {
            count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) pubid);
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        if (sysid != 0) {
            if (pubid == 0) {
                count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
                if (count < 0)
                    return -1;
                sum += count;
            }
            count = xmlOutputBufferWriteString(writer->out, " ");
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
            count =
                xmlOutputBufferWriteString(writer->out, (const char *) sysid);
            if (count < 0)
                return -1;
            sum += count;
            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
            if (count < 0)
                return -1;
            sum += count;
        }
    
        count = xmlOutputBufferWriteString(writer->out, ">");
        if (count < 0)
            return -1;
        sum += count;
    
        return sum;
    }
    
    /**
     * xmlTextWriterFlush:
     * @writer:  the xmlTextWriterPtr
     *
     * Flush the output buffer.
     *
     * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
     */
    int
    xmlTextWriterFlush(xmlTextWriterPtr writer)
    {
        int count;
    
        if (writer == NULL)
            return -1;
    
        if (writer->out == NULL)
            count = 0;
        else
            count = xmlOutputBufferFlush(writer->out);
    
        return count;
    }
    
    /**
     * misc
     */
    
    /**
     * xmlFreeTextWriterStackEntry:
     * @lk:  the xmlLinkPtr
     *
     * Free callback for the xmlList.
     */
    static void
    xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
    {
        xmlTextWriterStackEntry *p;
    
        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return;
    
        if (p->name != 0)
            xmlFree(p->name);
        xmlFree(p);
    }
    
    /**
     * xmlCmpTextWriterStackEntry:
     * @data0:  the first data
     * @data1:  the second data
     *
     * Compare callback for the xmlList.
     *
     * Returns -1, 0, 1
     */
    static int
    xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
    {
        xmlTextWriterStackEntry *p0;
        xmlTextWriterStackEntry *p1;
    
        if (data0 == data1)
            return 0;
    
        if (data0 == 0)
            return -1;
    
        if (data1 == 0)
            return 1;
    
        p0 = (xmlTextWriterStackEntry *) data0;
        p1 = (xmlTextWriterStackEntry *) data1;
    
        return xmlStrcmp(p0->name, p1->name);
    }
    
    /**
     * misc
     */
    
    /**
     * xmlFreeTextWriterNsStackEntry:
     * @lk:  the xmlLinkPtr
     *
     * Free callback for the xmlList.
     */
    static void
    xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
    {
        xmlTextWriterNsStackEntry *p;
    
        p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
        if (p == 0)
            return;
    
        if (p->prefix != 0)
            xmlFree(p->prefix);
        if (p->uri != 0)
            xmlFree(p->uri);
    
        xmlFree(p);
    }
    
    /**
     * xmlCmpTextWriterNsStackEntry:
     * @data0:  the first data
     * @data1:  the second data
     *
     * Compare callback for the xmlList.
     *
     * Returns -1, 0, 1
     */
    static int
    xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
    {
        xmlTextWriterNsStackEntry *p0;
        xmlTextWriterNsStackEntry *p1;
        int rc;
    
        if (data0 == data1)
            return 0;
    
        if (data0 == 0)
            return -1;
    
        if (data1 == 0)
            return 1;
    
        p0 = (xmlTextWriterNsStackEntry *) data0;
        p1 = (xmlTextWriterNsStackEntry *) data1;
    
        rc = xmlStrcmp(p0->prefix, p1->prefix);
    
        if (rc == 0)
            rc = p0->elem == p1->elem;
    
        return rc;
    }
    
    /**
     * xmlTextWriterWriteMemCallback:
     * @context:  the xmlBufferPtr
     * @str:  the data to write
     * @len:  the length of the data
     *
     * Write callback for the xmlOutputBuffer with target xmlBuffer
     *
     * Returns -1, 0, 1
     */
    static int
    xmlTextWriterWriteMemCallback(void *context, const xmlChar * str, int len)
    {
        xmlBufferPtr buf = (xmlBufferPtr) context;
    
        xmlBufferAdd(buf, str, len);
    
        return len;
    }
    
    /**
     * xmlTextWriterCloseMemCallback:
     * @context:  the xmlBufferPtr
     *
     * Close callback for the xmlOutputBuffer with target xmlBuffer
     *
     * Returns -1, 0, 1
     */
    static int
    xmlTextWriterCloseMemCallback(void *context ATTRIBUTE_UNUSED)
    {
        return 0;
    }
    
    /**
     * xmlTextWriterWriteDocCallback:
     * @context:  the xmlBufferPtr
     * @str:  the data to write
     * @len:  the length of the data
     *
     * Write callback for the xmlOutputBuffer with target xmlBuffer
     *
     * Returns -1, 0, 1
     */
    static int
    xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
    {
        xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
        int rc;
    
        if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterWriteDocCallback : XML error %d !\n",
                            rc);
            return -1;
        }
    
        return len;
    }
    
    /**
     * xmlTextWriterCloseDocCallback:
     * @context:  the xmlBufferPtr
     *
     * Close callback for the xmlOutputBuffer with target xmlBuffer
     *
     * Returns -1, 0, 1
     */
    static int
    xmlTextWriterCloseDocCallback(void *context)
    {
        xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
        int rc;
    
        if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterWriteDocCallback : XML error %d !\n",
                            rc);
            return -1;
        }
    
        return 0;
    }
    
    /**
     * xmlTextWriterVSprintf:
     * @format:  see printf
     * @argptr:  pointer to the first member of the variable argument list.
     *
     * Utility function for formatted output
     *
     * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
     */
    static xmlChar *
    xmlTextWriterVSprintf(const char *format, va_list argptr)
    {
        int size;
        int count;
        xmlChar *buf;
    
        size = BUFSIZ;
        buf = (xmlChar *) xmlMalloc(size);
        if (buf == NULL) {
            xmlGenericError(xmlGenericErrorContext,
                            "xmlTextWriterVSprintf : out of memory!\n");
            return NULL;
        }
    
        while (((count = vsnprintf((char *) buf, size, format, argptr)) < 0)
               || (count == size - 1) || (count == size) || (count > size)) {
            xmlFree(buf);
            size += BUFSIZ;
            buf = (xmlChar *) xmlMalloc(size);
            if (buf == NULL) {
                xmlGenericError(xmlGenericErrorContext,
                                "xmlTextWriterVSprintf : out of memory!\n");
                return NULL;
            }
        }
    
        return buf;
    }
    
    /**
     * xmlTextWriterStartDocumentCallback:
     * @ctx: the user data (XML parser context)
     *
     * called at the start of document processing.
     */
    static void
    xmlTextWriterStartDocumentCallback(void *ctx)
    {
        xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
        xmlDocPtr doc;
    
    #ifdef DEBUG_SAX
        xmlGenericError(xmlGenericErrorContext, "SAX.startDocument()\n");
    #endif
        if (ctxt->html) {
    #ifdef LIBXML_HTML_ENABLED
            if (ctxt->myDoc == NULL)
                ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
            if (ctxt->myDoc == NULL) {
                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    ctxt->sax->error(ctxt->userData,
                                     "SAX.startDocument(): out of memory\n");
                ctxt->errNo = XML_ERR_NO_MEMORY;
                ctxt->instate = XML_PARSER_EOF;
                ctxt->disableSAX = 1;
                return;
            }
    #else
            xmlGenericError(xmlGenericErrorContext,
                            "libxml2 built without HTML support\n");
            ctxt->errNo = XML_ERR_INTERNAL_ERROR;
            ctxt->instate = XML_PARSER_EOF;
            ctxt->disableSAX = 1;
            return;
    #endif
        } else {
            doc = ctxt->myDoc;
            if (doc == NULL)
                doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
            if (doc != NULL) {
                if (doc->children == NULL) {
                    if (ctxt->encoding != NULL)
                        doc->encoding = xmlStrdup(ctxt->encoding);
                    else
                        doc->encoding = NULL;
                    doc->standalone = ctxt->standalone;
                }
            } else {
                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    ctxt->sax->error(ctxt->userData,
                                     "SAX.startDocument(): out of memory\n");
                ctxt->errNo = XML_ERR_NO_MEMORY;
                ctxt->instate = XML_PARSER_EOF;
                ctxt->disableSAX = 1;
                return;
            }
        }
        if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
            (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
            ctxt->myDoc->URL =
                xmlCanonicPath((const xmlChar *) ctxt->input->filename);
            if (ctxt->myDoc->URL == NULL)
                ctxt->myDoc->URL =
                    xmlStrdup((const xmlChar *) ctxt->input->filename);
        }
    }
    
    /**
     * xmlTextWriterSetIndent:
     * @writer:  the xmlTextWriterPtr
     * @indent:  do indentation?
     *
     * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
     *
     * Returns -1 on error or 0 otherwise.
     */
    int
    xmlTextWriterSetIndent (xmlTextWriterPtr writer, int indent)
    {
      if (indent < 0) 
        return -1;
    
      writer->indent = indent;
      writer->doindent = 1;
    
      return 0;
    }
    
    /**
     * xmlTextWriterSetIndentString:
     * @writer:  the xmlTextWriterPtr
     * @str:  the xmlChar string
     *
     * Set string indentation.
     *
     * Returns -1 on error or 0 otherwise.
     */
    int
    xmlTextWriterSetIndentString (xmlTextWriterPtr writer, xmlChar *str)
    {
    
      if (!str)
        return -1;
    
      writer->ichar = xmlStrdup (str);
      
      if (!writer->ichar)
        return -1;
      else
        return 0;
    }
    
    /**
     * xmlTextWriterWriteIndent:
     * @writer:  the xmlTextWriterPtr
     *
     * Write indent string.
     *
     * Returns -1 on error or the number of strings written.
     */  
    static int
    xmlTextWriterWriteIndent (xmlTextWriterPtr writer)
    {
      int lksize;
      int i;
      int ret = -1;		/* just in case of an empty list */
      
      lksize = xmlListSize (writer->nodes);
      for (i = 0; i < (lksize-1); i++) {
        ret = xmlOutputBufferWriteString (writer->out, 
                (const char *)writer->ichar);
        if (ret == -1)
          break;
      }
    
      return (ret == -1)?ret:i;
    }
    
    #endif