1
2/*
3 * xmlwriter.c: XML text writer implementation
4 *
5 * For license and disclaimer see the license and disclaimer of
6 * libxml2.
7 *
8 * alfred@mickautsch.de
9 */
10
11#define IN_LIBXML
12#include "libxml.h"
13#include <string.h>
14
15#include <libxml/xmlmemory.h>
16#include <libxml/parser.h>
17#include <libxml/uri.h>
18#include <libxml/HTMLtree.h>
19
20#ifdef LIBXML_WRITER_ENABLED
21
22#include <libxml/xmlwriter.h>
23
24#include "buf.h"
25#include "enc.h"
26#include "save.h"
27
28#define B64LINELEN 72
29#define B64CRLF "\r\n"
30
31/*
32 * The following VA_COPY was coded following an example in
33 * the Samba project.  It may not be sufficient for some
34 * esoteric implementations of va_list (i.e. it may need
35 * something involving a memcpy) but (hopefully) will be
36 * sufficient for libxml2.
37 */
38#ifndef VA_COPY
39  #ifdef HAVE_VA_COPY
40    #define VA_COPY(dest, src) va_copy(dest, src)
41  #else
42    #ifdef HAVE___VA_COPY
43      #define VA_COPY(dest,src) __va_copy(dest, src)
44    #else
45      #define VA_COPY(dest,src) (dest) = (src)
46    #endif
47  #endif
48#endif
49
50/*
51 * Types are kept private
52 */
53typedef enum {
54    XML_TEXTWRITER_NONE = 0,
55    XML_TEXTWRITER_NAME,
56    XML_TEXTWRITER_ATTRIBUTE,
57    XML_TEXTWRITER_TEXT,
58    XML_TEXTWRITER_PI,
59    XML_TEXTWRITER_PI_TEXT,
60    XML_TEXTWRITER_CDATA,
61    XML_TEXTWRITER_DTD,
62    XML_TEXTWRITER_DTD_TEXT,
63    XML_TEXTWRITER_DTD_ELEM,
64    XML_TEXTWRITER_DTD_ELEM_TEXT,
65    XML_TEXTWRITER_DTD_ATTL,
66    XML_TEXTWRITER_DTD_ATTL_TEXT,
67    XML_TEXTWRITER_DTD_ENTY,    /* entity */
68    XML_TEXTWRITER_DTD_ENTY_TEXT,
69    XML_TEXTWRITER_DTD_PENT,    /* parameter entity */
70    XML_TEXTWRITER_COMMENT
71} xmlTextWriterState;
72
73typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
74
75struct _xmlTextWriterStackEntry {
76    xmlChar *name;
77    xmlTextWriterState state;
78};
79
80typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
81struct _xmlTextWriterNsStackEntry {
82    xmlChar *prefix;
83    xmlChar *uri;
84    xmlLinkPtr elem;
85};
86
87struct _xmlTextWriter {
88    xmlOutputBufferPtr out;     /* output buffer */
89    xmlListPtr nodes;           /* element name stack */
90    xmlListPtr nsstack;         /* name spaces stack */
91    int level;
92    int indent;                 /* enable indent */
93    int doindent;               /* internal indent flag */
94    xmlChar *ichar;             /* indent character */
95    char qchar;                 /* character used for quoting attribute values */
96    xmlParserCtxtPtr ctxt;
97    int no_doc_free;
98    xmlDocPtr doc;
99};
100
101static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
102static int xmlCmpTextWriterStackEntry(const void *data0,
103                                      const void *data1);
104static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer);
105static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
106static int xmlCmpTextWriterNsStackEntry(const void *data0,
107                                        const void *data1);
108static int xmlTextWriterWriteDocCallback(void *context,
109                                         const xmlChar * str, int len);
110static int xmlTextWriterCloseDocCallback(void *context);
111
112static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);
113static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
114                                      const unsigned char *data);
115static void xmlTextWriterStartDocumentCallback(void *ctx);
116static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);
117static int
118  xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
119                                       xmlTextWriterStackEntry * p);
120
121/**
122 * xmlWriterErrMsg:
123 * @ctxt:  a writer context
124 * @error:  the error number
125 * @msg:  the error message
126 *
127 * Handle a writer error
128 */
129static void
130xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,
131               const char *msg)
132{
133    if (ctxt != NULL) {
134	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
135	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
136		    NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
137    } else {
138	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
139                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
140    }
141}
142
143/**
144 * xmlWriterErrMsgInt:
145 * @ctxt:  a writer context
146 * @error:  the error number
147 * @msg:  the error message
148 * @val:  an int
149 *
150 * Handle a writer error
151 */
152static void
153xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,
154               const char *msg, int val)
155{
156    if (ctxt != NULL) {
157	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
158	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
159		    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
160    } else {
161	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
162                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
163    }
164}
165
166/**
167 * xmlNewTextWriter:
168 * @out:  an xmlOutputBufferPtr
169 *
170 * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
171 * NOTE: the @out parameter will be deallocated when the writer is closed
172 *       (if the call succeed.)
173 *
174 * Returns the new xmlTextWriterPtr or NULL in case of error
175 */
176xmlTextWriterPtr
177xmlNewTextWriter(xmlOutputBufferPtr out)
178{
179    xmlTextWriterPtr ret;
180
181    ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
182    if (ret == NULL) {
183        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
184                        "xmlNewTextWriter : out of memory!\n");
185        return NULL;
186    }
187    memset(ret, 0, (size_t) sizeof(xmlTextWriter));
188
189    ret->nodes = xmlListCreate((xmlListDeallocator)
190                               xmlFreeTextWriterStackEntry,
191                               (xmlListDataCompare)
192                               xmlCmpTextWriterStackEntry);
193    if (ret->nodes == NULL) {
194        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
195                        "xmlNewTextWriter : out of memory!\n");
196        xmlFree(ret);
197        return NULL;
198    }
199
200    ret->nsstack = xmlListCreate((xmlListDeallocator)
201                                 xmlFreeTextWriterNsStackEntry,
202                                 (xmlListDataCompare)
203                                 xmlCmpTextWriterNsStackEntry);
204    if (ret->nsstack == NULL) {
205        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
206                        "xmlNewTextWriter : out of memory!\n");
207        xmlListDelete(ret->nodes);
208        xmlFree(ret);
209        return NULL;
210    }
211
212    ret->out = out;
213    ret->ichar = xmlStrdup(BAD_CAST " ");
214    ret->qchar = '"';
215
216    if (!ret->ichar) {
217        xmlListDelete(ret->nodes);
218        xmlListDelete(ret->nsstack);
219        xmlFree(ret);
220        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
221                        "xmlNewTextWriter : out of memory!\n");
222        return NULL;
223    }
224
225    ret->doc = xmlNewDoc(NULL);
226
227    ret->no_doc_free = 0;
228
229    return ret;
230}
231
232/**
233 * xmlNewTextWriterFilename:
234 * @uri:  the URI of the resource for the output
235 * @compression:  compress the output?
236 *
237 * Create a new xmlNewTextWriter structure with @uri as output
238 *
239 * Returns the new xmlTextWriterPtr or NULL in case of error
240 */
241xmlTextWriterPtr
242xmlNewTextWriterFilename(const char *uri, int compression)
243{
244    xmlTextWriterPtr ret;
245    xmlOutputBufferPtr out;
246
247    out = xmlOutputBufferCreateFilename(uri, NULL, compression);
248    if (out == NULL) {
249        xmlWriterErrMsg(NULL, XML_IO_EIO,
250                        "xmlNewTextWriterFilename : cannot open uri\n");
251        return NULL;
252    }
253
254    ret = xmlNewTextWriter(out);
255    if (ret == NULL) {
256        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
257                        "xmlNewTextWriterFilename : out of memory!\n");
258        xmlOutputBufferClose(out);
259        return NULL;
260    }
261
262    ret->indent = 0;
263    ret->doindent = 0;
264    return ret;
265}
266
267/**
268 * xmlNewTextWriterMemory:
269 * @buf:  xmlBufferPtr
270 * @compression:  compress the output?
271 *
272 * Create a new xmlNewTextWriter structure with @buf as output
273 * TODO: handle compression
274 *
275 * Returns the new xmlTextWriterPtr or NULL in case of error
276 */
277xmlTextWriterPtr
278xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
279{
280    xmlTextWriterPtr ret;
281    xmlOutputBufferPtr out;
282
283/*::todo handle compression */
284    out = xmlOutputBufferCreateBuffer(buf, NULL);
285
286    if (out == NULL) {
287        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
288                        "xmlNewTextWriterMemory : out of memory!\n");
289        return NULL;
290    }
291
292    ret = xmlNewTextWriter(out);
293    if (ret == NULL) {
294        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
295                        "xmlNewTextWriterMemory : out of memory!\n");
296        xmlOutputBufferClose(out);
297        return NULL;
298    }
299
300    return ret;
301}
302
303/**
304 * xmlNewTextWriterPushParser:
305 * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
306 * @compression:  compress the output?
307 *
308 * Create a new xmlNewTextWriter structure with @ctxt as output
309 * NOTE: the @ctxt context will be freed with the resulting writer
310 *       (if the call succeeds).
311 * TODO: handle compression
312 *
313 * Returns the new xmlTextWriterPtr or NULL in case of error
314 */
315xmlTextWriterPtr
316xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
317                           int compression ATTRIBUTE_UNUSED)
318{
319    xmlTextWriterPtr ret;
320    xmlOutputBufferPtr out;
321
322    if (ctxt == NULL) {
323        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
324                        "xmlNewTextWriterPushParser : invalid context!\n");
325        return NULL;
326    }
327
328    out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
329                                  xmlTextWriterWriteDocCallback,
330                                  (xmlOutputCloseCallback)
331                                  xmlTextWriterCloseDocCallback,
332                                  (void *) ctxt, NULL);
333    if (out == NULL) {
334        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
335                        "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
336        return NULL;
337    }
338
339    ret = xmlNewTextWriter(out);
340    if (ret == NULL) {
341        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
342                        "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
343        xmlOutputBufferClose(out);
344        return NULL;
345    }
346
347    ret->ctxt = ctxt;
348
349    return ret;
350}
351
352/**
353 * xmlNewTextWriterDoc:
354 * @doc: address of a xmlDocPtr to hold the new XML document tree
355 * @compression:  compress the output?
356 *
357 * Create a new xmlNewTextWriter structure with @*doc as output
358 *
359 * Returns the new xmlTextWriterPtr or NULL in case of error
360 */
361xmlTextWriterPtr
362xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
363{
364    xmlTextWriterPtr ret;
365    xmlSAXHandler saxHandler;
366    xmlParserCtxtPtr ctxt;
367
368    memset(&saxHandler, '\0', sizeof(saxHandler));
369    xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
370    saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
371    saxHandler.startElement = xmlSAX2StartElement;
372    saxHandler.endElement = xmlSAX2EndElement;
373
374    ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
375    if (ctxt == NULL) {
376        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
377                "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
378        return NULL;
379    }
380    /*
381     * For some reason this seems to completely break if node names
382     * are interned.
383     */
384    ctxt->dictNames = 0;
385
386    ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
387    if (ctxt->myDoc == NULL) {
388        xmlFreeParserCtxt(ctxt);
389        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
390                        "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
391        return NULL;
392    }
393
394    ret = xmlNewTextWriterPushParser(ctxt, compression);
395    if (ret == NULL) {
396        xmlFreeDoc(ctxt->myDoc);
397        xmlFreeParserCtxt(ctxt);
398        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
399                "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
400        return NULL;
401    }
402
403    xmlSetDocCompressMode(ctxt->myDoc, compression);
404
405    if (doc != NULL) {
406        *doc = ctxt->myDoc;
407	ret->no_doc_free = 1;
408    }
409
410    return ret;
411}
412
413/**
414 * xmlNewTextWriterTree:
415 * @doc: xmlDocPtr
416 * @node: xmlNodePtr or NULL for doc->children
417 * @compression:  compress the output?
418 *
419 * Create a new xmlNewTextWriter structure with @doc as output
420 * starting at @node
421 *
422 * Returns the new xmlTextWriterPtr or NULL in case of error
423 */
424xmlTextWriterPtr
425xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
426{
427    xmlTextWriterPtr ret;
428    xmlSAXHandler saxHandler;
429    xmlParserCtxtPtr ctxt;
430
431    if (doc == NULL) {
432        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
433                        "xmlNewTextWriterTree : invalid document tree!\n");
434        return NULL;
435    }
436
437    memset(&saxHandler, '\0', sizeof(saxHandler));
438    xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
439    saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
440    saxHandler.startElement = xmlSAX2StartElement;
441    saxHandler.endElement = xmlSAX2EndElement;
442
443    ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
444    if (ctxt == NULL) {
445        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
446                        "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
447        return NULL;
448    }
449    /*
450     * For some reason this seems to completely break if node names
451     * are interned.
452     */
453    ctxt->dictNames = 0;
454
455    ret = xmlNewTextWriterPushParser(ctxt, compression);
456    if (ret == NULL) {
457        xmlFreeParserCtxt(ctxt);
458        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
459                        "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
460        return NULL;
461    }
462
463    ctxt->myDoc = doc;
464    ctxt->node = node;
465    ret->no_doc_free = 1;
466
467    xmlSetDocCompressMode(doc, compression);
468
469    return ret;
470}
471
472/**
473 * xmlFreeTextWriter:
474 * @writer:  the xmlTextWriterPtr
475 *
476 * Deallocate all the resources associated to the writer
477 */
478void
479xmlFreeTextWriter(xmlTextWriterPtr writer)
480{
481    if (writer == NULL)
482        return;
483
484    if (writer->out != NULL)
485        xmlOutputBufferClose(writer->out);
486
487    if (writer->nodes != NULL)
488        xmlListDelete(writer->nodes);
489
490    if (writer->nsstack != NULL)
491        xmlListDelete(writer->nsstack);
492
493    if (writer->ctxt != NULL) {
494        if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
495	    xmlFreeDoc(writer->ctxt->myDoc);
496	    writer->ctxt->myDoc = NULL;
497	}
498        xmlFreeParserCtxt(writer->ctxt);
499    }
500
501    if (writer->doc != NULL)
502        xmlFreeDoc(writer->doc);
503
504    if (writer->ichar != NULL)
505        xmlFree(writer->ichar);
506    xmlFree(writer);
507}
508
509/**
510 * xmlTextWriterStartDocument:
511 * @writer:  the xmlTextWriterPtr
512 * @version:  the xml version ("1.0") or NULL for default ("1.0")
513 * @encoding:  the encoding or NULL for default
514 * @standalone: "yes" or "no" or NULL for default
515 *
516 * Start a new xml document
517 *
518 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
519 */
520int
521xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
522                           const char *encoding, const char *standalone)
523{
524    int count;
525    int sum;
526    xmlLinkPtr lk;
527    xmlCharEncodingHandlerPtr encoder;
528
529    if ((writer == NULL) || (writer->out == NULL)) {
530        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
531                        "xmlTextWriterStartDocument : invalid writer!\n");
532        return -1;
533    }
534
535    lk = xmlListFront(writer->nodes);
536    if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
537        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
538                        "xmlTextWriterStartDocument : not allowed in this context!\n");
539        return -1;
540    }
541
542    encoder = NULL;
543    if (encoding != NULL) {
544        encoder = xmlFindCharEncodingHandler(encoding);
545        if (encoder == NULL) {
546            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
547                            "xmlTextWriterStartDocument : out of memory!\n");
548            return -1;
549        }
550    }
551
552    writer->out->encoder = encoder;
553    if (encoder != NULL) {
554	if (writer->out->conv == NULL) {
555	    writer->out->conv = xmlBufCreateSize(4000);
556	}
557        xmlCharEncOutput(writer->out, 1);
558        if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
559            writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
560    } else
561        writer->out->conv = NULL;
562
563    sum = 0;
564    count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
565    if (count < 0)
566        return -1;
567    sum += count;
568    count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
569    if (count < 0)
570        return -1;
571    sum += count;
572    if (version != 0)
573        count = xmlOutputBufferWriteString(writer->out, version);
574    else
575        count = xmlOutputBufferWriteString(writer->out, "1.0");
576    if (count < 0)
577        return -1;
578    sum += count;
579    count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
580    if (count < 0)
581        return -1;
582    sum += count;
583    if (writer->out->encoder != 0) {
584        count = xmlOutputBufferWriteString(writer->out, " encoding=");
585        if (count < 0)
586            return -1;
587        sum += count;
588        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
589        if (count < 0)
590            return -1;
591        sum += count;
592        count =
593            xmlOutputBufferWriteString(writer->out,
594                                       writer->out->encoder->name);
595        if (count < 0)
596            return -1;
597        sum += count;
598        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
599        if (count < 0)
600            return -1;
601        sum += count;
602    }
603
604    if (standalone != 0) {
605        count = xmlOutputBufferWriteString(writer->out, " standalone=");
606        if (count < 0)
607            return -1;
608        sum += count;
609        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
610        if (count < 0)
611            return -1;
612        sum += count;
613        count = xmlOutputBufferWriteString(writer->out, standalone);
614        if (count < 0)
615            return -1;
616        sum += count;
617        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
618        if (count < 0)
619            return -1;
620        sum += count;
621    }
622
623    count = xmlOutputBufferWriteString(writer->out, "?>\n");
624    if (count < 0)
625        return -1;
626    sum += count;
627
628    return sum;
629}
630
631/**
632 * xmlTextWriterEndDocument:
633 * @writer:  the xmlTextWriterPtr
634 *
635 * End an xml document. All open elements are closed, and
636 * the content is flushed to the output.
637 *
638 * Returns the bytes written or -1 in case of error
639 */
640int
641xmlTextWriterEndDocument(xmlTextWriterPtr writer)
642{
643    int count;
644    int sum;
645    xmlLinkPtr lk;
646    xmlTextWriterStackEntry *p;
647
648    if (writer == NULL) {
649        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
650                        "xmlTextWriterEndDocument : invalid writer!\n");
651        return -1;
652    }
653
654    sum = 0;
655    while ((lk = xmlListFront(writer->nodes)) != NULL) {
656        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
657        if (p == 0)
658            break;
659        switch (p->state) {
660            case XML_TEXTWRITER_NAME:
661            case XML_TEXTWRITER_ATTRIBUTE:
662            case XML_TEXTWRITER_TEXT:
663                count = xmlTextWriterEndElement(writer);
664                if (count < 0)
665                    return -1;
666                sum += count;
667                break;
668            case XML_TEXTWRITER_PI:
669            case XML_TEXTWRITER_PI_TEXT:
670                count = xmlTextWriterEndPI(writer);
671                if (count < 0)
672                    return -1;
673                sum += count;
674                break;
675            case XML_TEXTWRITER_CDATA:
676                count = xmlTextWriterEndCDATA(writer);
677                if (count < 0)
678                    return -1;
679                sum += count;
680                break;
681            case XML_TEXTWRITER_DTD:
682            case XML_TEXTWRITER_DTD_TEXT:
683            case XML_TEXTWRITER_DTD_ELEM:
684            case XML_TEXTWRITER_DTD_ELEM_TEXT:
685            case XML_TEXTWRITER_DTD_ATTL:
686            case XML_TEXTWRITER_DTD_ATTL_TEXT:
687            case XML_TEXTWRITER_DTD_ENTY:
688            case XML_TEXTWRITER_DTD_ENTY_TEXT:
689            case XML_TEXTWRITER_DTD_PENT:
690                count = xmlTextWriterEndDTD(writer);
691                if (count < 0)
692                    return -1;
693                sum += count;
694                break;
695            case XML_TEXTWRITER_COMMENT:
696                count = xmlTextWriterEndComment(writer);
697                if (count < 0)
698                    return -1;
699                sum += count;
700                break;
701            default:
702                break;
703        }
704    }
705
706    if (!writer->indent) {
707        count = xmlOutputBufferWriteString(writer->out, "\n");
708        if (count < 0)
709            return -1;
710        sum += count;
711    }
712
713    sum += xmlTextWriterFlush(writer);
714
715    return sum;
716}
717
718/**
719 * xmlTextWriterStartComment:
720 * @writer:  the xmlTextWriterPtr
721 *
722 * Start an xml comment.
723 *
724 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
725 */
726int
727xmlTextWriterStartComment(xmlTextWriterPtr writer)
728{
729    int count;
730    int sum;
731    xmlLinkPtr lk;
732    xmlTextWriterStackEntry *p;
733
734    if (writer == NULL) {
735        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
736                        "xmlTextWriterStartComment : invalid writer!\n");
737        return -1;
738    }
739
740    sum = 0;
741    lk = xmlListFront(writer->nodes);
742    if (lk != 0) {
743        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
744        if (p != 0) {
745            switch (p->state) {
746                case XML_TEXTWRITER_TEXT:
747                case XML_TEXTWRITER_NONE:
748                    break;
749                case XML_TEXTWRITER_NAME:
750                    /* Output namespace declarations */
751                    count = xmlTextWriterOutputNSDecl(writer);
752                    if (count < 0)
753                        return -1;
754                    sum += count;
755                    count = xmlOutputBufferWriteString(writer->out, ">");
756                    if (count < 0)
757                        return -1;
758                    sum += count;
759                    if (writer->indent) {
760                        count =
761                            xmlOutputBufferWriteString(writer->out, "\n");
762                        if (count < 0)
763                            return -1;
764                        sum += count;
765                    }
766                    p->state = XML_TEXTWRITER_TEXT;
767                    break;
768                default:
769                    return -1;
770            }
771        }
772    }
773
774    p = (xmlTextWriterStackEntry *)
775        xmlMalloc(sizeof(xmlTextWriterStackEntry));
776    if (p == 0) {
777        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
778                        "xmlTextWriterStartElement : out of memory!\n");
779        return -1;
780    }
781
782    p->name = NULL;
783    p->state = XML_TEXTWRITER_COMMENT;
784
785    xmlListPushFront(writer->nodes, p);
786
787    if (writer->indent) {
788        count = xmlTextWriterWriteIndent(writer);
789        if (count < 0)
790            return -1;
791        sum += count;
792    }
793
794    count = xmlOutputBufferWriteString(writer->out, "<!--");
795    if (count < 0)
796        return -1;
797    sum += count;
798
799    return sum;
800}
801
802/**
803 * xmlTextWriterEndComment:
804 * @writer:  the xmlTextWriterPtr
805 *
806 * End the current xml coment.
807 *
808 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
809 */
810int
811xmlTextWriterEndComment(xmlTextWriterPtr writer)
812{
813    int count;
814    int sum;
815    xmlLinkPtr lk;
816    xmlTextWriterStackEntry *p;
817
818    if (writer == NULL) {
819        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
820                        "xmlTextWriterEndComment : invalid writer!\n");
821        return -1;
822    }
823
824    lk = xmlListFront(writer->nodes);
825    if (lk == 0) {
826        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
827                        "xmlTextWriterEndComment : not allowed in this context!\n");
828        return -1;
829    }
830
831    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
832    if (p == 0)
833        return -1;
834
835    sum = 0;
836    switch (p->state) {
837        case XML_TEXTWRITER_COMMENT:
838            count = xmlOutputBufferWriteString(writer->out, "-->");
839            if (count < 0)
840                return -1;
841            sum += count;
842            break;
843        default:
844            return -1;
845    }
846
847    if (writer->indent) {
848        count = xmlOutputBufferWriteString(writer->out, "\n");
849        if (count < 0)
850            return -1;
851        sum += count;
852    }
853
854    xmlListPopFront(writer->nodes);
855    return sum;
856}
857
858/**
859 * xmlTextWriterWriteFormatComment:
860 * @writer:  the xmlTextWriterPtr
861 * @format:  format string (see printf)
862 * @...:  extra parameters for the format
863 *
864 * Write an xml comment.
865 *
866 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
867 */
868int XMLCDECL
869xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
870                                const char *format, ...)
871{
872    int rc;
873    va_list ap;
874
875    va_start(ap, format);
876
877    rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
878
879    va_end(ap);
880    return rc;
881}
882
883/**
884 * xmlTextWriterWriteVFormatComment:
885 * @writer:  the xmlTextWriterPtr
886 * @format:  format string (see printf)
887 * @argptr:  pointer to the first member of the variable argument list.
888 *
889 * Write an xml comment.
890 *
891 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
892 */
893int
894xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
895                                 const char *format, va_list argptr)
896{
897    int rc;
898    xmlChar *buf;
899
900    if (writer == NULL) {
901        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
902                        "xmlTextWriterWriteVFormatComment : invalid writer!\n");
903        return -1;
904    }
905
906    buf = xmlTextWriterVSprintf(format, argptr);
907    if (buf == NULL)
908        return -1;
909
910    rc = xmlTextWriterWriteComment(writer, buf);
911
912    xmlFree(buf);
913    return rc;
914}
915
916/**
917 * xmlTextWriterWriteComment:
918 * @writer:  the xmlTextWriterPtr
919 * @content:  comment string
920 *
921 * Write an xml comment.
922 *
923 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
924 */
925int
926xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
927{
928    int count;
929    int sum;
930
931    sum = 0;
932    count = xmlTextWriterStartComment(writer);
933    if (count < 0)
934        return -1;
935    sum += count;
936    count = xmlTextWriterWriteString(writer, content);
937    if (count < 0)
938        return -1;
939    sum += count;
940    count = xmlTextWriterEndComment(writer);
941    if (count < 0)
942        return -1;
943    sum += count;
944
945    return sum;
946}
947
948/**
949 * xmlTextWriterStartElement:
950 * @writer:  the xmlTextWriterPtr
951 * @name:  element name
952 *
953 * Start an xml element.
954 *
955 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
956 */
957int
958xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
959{
960    int count;
961    int sum;
962    xmlLinkPtr lk;
963    xmlTextWriterStackEntry *p;
964
965    if ((writer == NULL) || (name == NULL) || (*name == '\0'))
966        return -1;
967
968    sum = 0;
969    lk = xmlListFront(writer->nodes);
970    if (lk != 0) {
971        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
972        if (p != 0) {
973            switch (p->state) {
974                case XML_TEXTWRITER_PI:
975                case XML_TEXTWRITER_PI_TEXT:
976                    return -1;
977                case XML_TEXTWRITER_NONE:
978                    break;
979				case XML_TEXTWRITER_ATTRIBUTE:
980					count = xmlTextWriterEndAttribute(writer);
981					if (count < 0)
982						return -1;
983					sum += count;
984					/* fallthrough */
985                case XML_TEXTWRITER_NAME:
986                    /* Output namespace declarations */
987                    count = xmlTextWriterOutputNSDecl(writer);
988                    if (count < 0)
989                        return -1;
990                    sum += count;
991                    count = xmlOutputBufferWriteString(writer->out, ">");
992                    if (count < 0)
993                        return -1;
994                    sum += count;
995                    if (writer->indent)
996                        count =
997                            xmlOutputBufferWriteString(writer->out, "\n");
998                    p->state = XML_TEXTWRITER_TEXT;
999                    break;
1000                default:
1001                    break;
1002            }
1003        }
1004    }
1005
1006    p = (xmlTextWriterStackEntry *)
1007        xmlMalloc(sizeof(xmlTextWriterStackEntry));
1008    if (p == 0) {
1009        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1010                        "xmlTextWriterStartElement : out of memory!\n");
1011        return -1;
1012    }
1013
1014    p->name = xmlStrdup(name);
1015    if (p->name == 0) {
1016        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1017                        "xmlTextWriterStartElement : out of memory!\n");
1018        xmlFree(p);
1019        return -1;
1020    }
1021    p->state = XML_TEXTWRITER_NAME;
1022
1023    xmlListPushFront(writer->nodes, p);
1024
1025    if (writer->indent) {
1026        count = xmlTextWriterWriteIndent(writer);
1027        sum += count;
1028    }
1029
1030    count = xmlOutputBufferWriteString(writer->out, "<");
1031    if (count < 0)
1032        return -1;
1033    sum += count;
1034    count =
1035        xmlOutputBufferWriteString(writer->out, (const char *) p->name);
1036    if (count < 0)
1037        return -1;
1038    sum += count;
1039
1040    return sum;
1041}
1042
1043/**
1044 * xmlTextWriterStartElementNS:
1045 * @writer:  the xmlTextWriterPtr
1046 * @prefix:  namespace prefix or NULL
1047 * @name:  element local name
1048 * @namespaceURI:  namespace URI or NULL
1049 *
1050 * Start an xml element with namespace support.
1051 *
1052 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1053 */
1054int
1055xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
1056                            const xmlChar * prefix, const xmlChar * name,
1057                            const xmlChar * namespaceURI)
1058{
1059    int count;
1060    int sum;
1061    xmlChar *buf;
1062
1063    if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1064        return -1;
1065
1066    buf = NULL;
1067    if (prefix != 0) {
1068        buf = xmlStrdup(prefix);
1069        buf = xmlStrcat(buf, BAD_CAST ":");
1070    }
1071    buf = xmlStrcat(buf, name);
1072
1073    sum = 0;
1074    count = xmlTextWriterStartElement(writer, buf);
1075    xmlFree(buf);
1076    if (count < 0)
1077        return -1;
1078    sum += count;
1079
1080    if (namespaceURI != 0) {
1081        xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
1082        xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1083        if (p == 0) {
1084            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1085                            "xmlTextWriterStartElementNS : out of memory!\n");
1086            return -1;
1087        }
1088
1089        buf = xmlStrdup(BAD_CAST "xmlns");
1090        if (prefix != 0) {
1091            buf = xmlStrcat(buf, BAD_CAST ":");
1092            buf = xmlStrcat(buf, prefix);
1093        }
1094
1095        p->prefix = buf;
1096        p->uri = xmlStrdup(namespaceURI);
1097        if (p->uri == 0) {
1098            xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1099                            "xmlTextWriterStartElementNS : out of memory!\n");
1100            xmlFree(p);
1101            return -1;
1102        }
1103        p->elem = xmlListFront(writer->nodes);
1104
1105        xmlListPushFront(writer->nsstack, p);
1106    }
1107
1108    return sum;
1109}
1110
1111/**
1112 * xmlTextWriterEndElement:
1113 * @writer:  the xmlTextWriterPtr
1114 *
1115 * End the current xml element.
1116 *
1117 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1118 */
1119int
1120xmlTextWriterEndElement(xmlTextWriterPtr writer)
1121{
1122    int count;
1123    int sum;
1124    xmlLinkPtr lk;
1125    xmlTextWriterStackEntry *p;
1126
1127    if (writer == NULL)
1128        return -1;
1129
1130    lk = xmlListFront(writer->nodes);
1131    if (lk == 0) {
1132        xmlListDelete(writer->nsstack);
1133        writer->nsstack = NULL;
1134        return -1;
1135    }
1136
1137    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1138    if (p == 0) {
1139        xmlListDelete(writer->nsstack);
1140        writer->nsstack = NULL;
1141        return -1;
1142    }
1143
1144    sum = 0;
1145    switch (p->state) {
1146        case XML_TEXTWRITER_ATTRIBUTE:
1147            count = xmlTextWriterEndAttribute(writer);
1148            if (count < 0) {
1149                xmlListDelete(writer->nsstack);
1150                writer->nsstack = NULL;
1151                return -1;
1152            }
1153            sum += count;
1154            /* fallthrough */
1155        case XML_TEXTWRITER_NAME:
1156            /* Output namespace declarations */
1157            count = xmlTextWriterOutputNSDecl(writer);
1158            if (count < 0)
1159                return -1;
1160            sum += count;
1161
1162            if (writer->indent) /* next element needs indent */
1163                writer->doindent = 1;
1164            count = xmlOutputBufferWriteString(writer->out, "/>");
1165            if (count < 0)
1166                return -1;
1167            sum += count;
1168            break;
1169        case XML_TEXTWRITER_TEXT:
1170            if ((writer->indent) && (writer->doindent)) {
1171                count = xmlTextWriterWriteIndent(writer);
1172                sum += count;
1173                writer->doindent = 1;
1174            } else
1175                writer->doindent = 1;
1176            count = xmlOutputBufferWriteString(writer->out, "</");
1177            if (count < 0)
1178                return -1;
1179            sum += count;
1180            count = xmlOutputBufferWriteString(writer->out,
1181                                               (const char *) p->name);
1182            if (count < 0)
1183                return -1;
1184            sum += count;
1185            count = xmlOutputBufferWriteString(writer->out, ">");
1186            if (count < 0)
1187                return -1;
1188            sum += count;
1189            break;
1190        default:
1191            return -1;
1192    }
1193
1194    if (writer->indent) {
1195        count = xmlOutputBufferWriteString(writer->out, "\n");
1196        sum += count;
1197    }
1198
1199    xmlListPopFront(writer->nodes);
1200    return sum;
1201}
1202
1203/**
1204 * xmlTextWriterFullEndElement:
1205 * @writer:  the xmlTextWriterPtr
1206 *
1207 * End the current xml element. Writes an end tag even if the element is empty
1208 *
1209 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1210 */
1211int
1212xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1213{
1214    int count;
1215    int sum;
1216    xmlLinkPtr lk;
1217    xmlTextWriterStackEntry *p;
1218
1219    if (writer == NULL)
1220        return -1;
1221
1222    lk = xmlListFront(writer->nodes);
1223    if (lk == 0)
1224        return -1;
1225
1226    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1227    if (p == 0)
1228        return -1;
1229
1230    sum = 0;
1231    switch (p->state) {
1232        case XML_TEXTWRITER_ATTRIBUTE:
1233            count = xmlTextWriterEndAttribute(writer);
1234            if (count < 0)
1235                return -1;
1236            sum += count;
1237            /* fallthrough */
1238        case XML_TEXTWRITER_NAME:
1239            /* Output namespace declarations */
1240            count = xmlTextWriterOutputNSDecl(writer);
1241            if (count < 0)
1242                return -1;
1243            sum += count;
1244
1245            count = xmlOutputBufferWriteString(writer->out, ">");
1246            if (count < 0)
1247                return -1;
1248            sum += count;
1249            if (writer->indent)
1250                writer->doindent = 0;
1251            /* fallthrough */
1252        case XML_TEXTWRITER_TEXT:
1253            if ((writer->indent) && (writer->doindent)) {
1254                count = xmlTextWriterWriteIndent(writer);
1255                sum += count;
1256                writer->doindent = 1;
1257            } else
1258                writer->doindent = 1;
1259            count = xmlOutputBufferWriteString(writer->out, "</");
1260            if (count < 0)
1261                return -1;
1262            sum += count;
1263            count = xmlOutputBufferWriteString(writer->out,
1264                                               (const char *) p->name);
1265            if (count < 0)
1266                return -1;
1267            sum += count;
1268            count = xmlOutputBufferWriteString(writer->out, ">");
1269            if (count < 0)
1270                return -1;
1271            sum += count;
1272            break;
1273        default:
1274            return -1;
1275    }
1276
1277    if (writer->indent) {
1278        count = xmlOutputBufferWriteString(writer->out, "\n");
1279        sum += count;
1280    }
1281
1282    xmlListPopFront(writer->nodes);
1283    return sum;
1284}
1285
1286/**
1287 * xmlTextWriterWriteFormatRaw:
1288 * @writer:  the xmlTextWriterPtr
1289 * @format:  format string (see printf)
1290 * @...:  extra parameters for the format
1291 *
1292 * Write a formatted raw xml text.
1293 *
1294 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1295 */
1296int XMLCDECL
1297xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1298                            ...)
1299{
1300    int rc;
1301    va_list ap;
1302
1303    va_start(ap, format);
1304
1305    rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1306
1307    va_end(ap);
1308    return rc;
1309}
1310
1311/**
1312 * xmlTextWriterWriteVFormatRaw:
1313 * @writer:  the xmlTextWriterPtr
1314 * @format:  format string (see printf)
1315 * @argptr:  pointer to the first member of the variable argument list.
1316 *
1317 * Write a formatted raw xml text.
1318 *
1319 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1320 */
1321int
1322xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1323                             va_list argptr)
1324{
1325    int rc;
1326    xmlChar *buf;
1327
1328    if (writer == NULL)
1329        return -1;
1330
1331    buf = xmlTextWriterVSprintf(format, argptr);
1332    if (buf == NULL)
1333        return -1;
1334
1335    rc = xmlTextWriterWriteRaw(writer, buf);
1336
1337    xmlFree(buf);
1338    return rc;
1339}
1340
1341/**
1342 * xmlTextWriterWriteRawLen:
1343 * @writer:  the xmlTextWriterPtr
1344 * @content:  text string
1345 * @len:  length of the text string
1346 *
1347 * Write an xml text.
1348 * TODO: what about entities and special chars??
1349 *
1350 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1351 */
1352int
1353xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1354                         int len)
1355{
1356    int count;
1357    int sum;
1358    xmlLinkPtr lk;
1359    xmlTextWriterStackEntry *p;
1360
1361    if (writer == NULL) {
1362        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
1363                        "xmlTextWriterWriteRawLen : invalid writer!\n");
1364        return -1;
1365    }
1366
1367    if ((content == NULL) || (len < 0)) {
1368        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
1369                        "xmlTextWriterWriteRawLen : invalid content!\n");
1370        return -1;
1371    }
1372
1373    sum = 0;
1374    lk = xmlListFront(writer->nodes);
1375    if (lk != 0) {
1376        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1377        count = xmlTextWriterHandleStateDependencies(writer, p);
1378        if (count < 0)
1379            return -1;
1380        sum += count;
1381    }
1382
1383    if (writer->indent)
1384        writer->doindent = 0;
1385
1386    if (content != NULL) {
1387        count =
1388            xmlOutputBufferWrite(writer->out, len, (const char *) content);
1389        if (count < 0)
1390            return -1;
1391        sum += count;
1392    }
1393
1394    return sum;
1395}
1396
1397/**
1398 * xmlTextWriterWriteRaw:
1399 * @writer:  the xmlTextWriterPtr
1400 * @content:  text string
1401 *
1402 * Write a raw xml text.
1403 *
1404 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1405 */
1406int
1407xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1408{
1409    return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1410}
1411
1412/**
1413 * xmlTextWriterWriteFormatString:
1414 * @writer:  the xmlTextWriterPtr
1415 * @format:  format string (see printf)
1416 * @...:  extra parameters for the format
1417 *
1418 * Write a formatted xml text.
1419 *
1420 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1421 */
1422int XMLCDECL
1423xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1424                               ...)
1425{
1426    int rc;
1427    va_list ap;
1428
1429    if ((writer == NULL) || (format == NULL))
1430        return -1;
1431
1432    va_start(ap, format);
1433
1434    rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1435
1436    va_end(ap);
1437    return rc;
1438}
1439
1440/**
1441 * xmlTextWriterWriteVFormatString:
1442 * @writer:  the xmlTextWriterPtr
1443 * @format:  format string (see printf)
1444 * @argptr:  pointer to the first member of the variable argument list.
1445 *
1446 * Write a formatted xml text.
1447 *
1448 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1449 */
1450int
1451xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1452                                const char *format, va_list argptr)
1453{
1454    int rc;
1455    xmlChar *buf;
1456
1457    if ((writer == NULL) || (format == NULL))
1458        return -1;
1459
1460    buf = xmlTextWriterVSprintf(format, argptr);
1461    if (buf == NULL)
1462        return -1;
1463
1464    rc = xmlTextWriterWriteString(writer, buf);
1465
1466    xmlFree(buf);
1467    return rc;
1468}
1469
1470/**
1471 * xmlTextWriterWriteString:
1472 * @writer:  the xmlTextWriterPtr
1473 * @content:  text string
1474 *
1475 * Write an xml text.
1476 *
1477 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1478 */
1479int
1480xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1481{
1482    int count;
1483    int sum;
1484    xmlLinkPtr lk;
1485    xmlTextWriterStackEntry *p;
1486    xmlChar *buf;
1487
1488    if ((writer == NULL) || (content == NULL))
1489        return -1;
1490
1491    sum = 0;
1492    buf = (xmlChar *) content;
1493    lk = xmlListFront(writer->nodes);
1494    if (lk != 0) {
1495        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1496        if (p != 0) {
1497            switch (p->state) {
1498                case XML_TEXTWRITER_NAME:
1499                case XML_TEXTWRITER_TEXT:
1500#if 0
1501                    buf = NULL;
1502		    xmlOutputBufferWriteEscape(writer->out, content, NULL);
1503#endif
1504                    buf = xmlEncodeSpecialChars(NULL, content);
1505                    break;
1506                case XML_TEXTWRITER_ATTRIBUTE:
1507                    buf = NULL;
1508                    xmlBufAttrSerializeTxtContent(writer->out->buffer,
1509                                                  writer->doc, NULL, content);
1510                    break;
1511		default:
1512		    break;
1513            }
1514        }
1515    }
1516
1517    if (buf != NULL) {
1518        count = xmlTextWriterWriteRaw(writer, buf);
1519
1520        if (buf != content)     /* buf was allocated by us, so free it */
1521            xmlFree(buf);
1522
1523        if (count < 0)
1524            return -1;
1525        sum += count;
1526    }
1527
1528    return sum;
1529}
1530
1531/**
1532 * xmlOutputBufferWriteBase64:
1533 * @out: the xmlOutputBufferPtr
1534 * @data:   binary data
1535 * @len:  the number of bytes to encode
1536 *
1537 * Write base64 encoded data to an xmlOutputBuffer.
1538 * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1539 *
1540 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1541 */
1542static int
1543xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1544                           const unsigned char *data)
1545{
1546    static unsigned char dtable[64] =
1547            {'A','B','C','D','E','F','G','H','I','J','K','L','M',
1548	     'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1549	     'a','b','c','d','e','f','g','h','i','j','k','l','m',
1550	     'n','o','p','q','r','s','t','u','v','w','x','y','z',
1551	     '0','1','2','3','4','5','6','7','8','9','+','/'};
1552
1553    int i;
1554    int linelen;
1555    int count;
1556    int sum;
1557
1558    if ((out == NULL) || (len < 0) || (data == NULL))
1559        return(-1);
1560
1561    linelen = 0;
1562    sum = 0;
1563
1564    i = 0;
1565    while (1) {
1566        unsigned char igroup[3];
1567        unsigned char ogroup[4];
1568        int c;
1569        int n;
1570
1571        igroup[0] = igroup[1] = igroup[2] = 0;
1572        for (n = 0; n < 3 && i < len; n++, i++) {
1573            c = data[i];
1574            igroup[n] = (unsigned char) c;
1575        }
1576
1577        if (n > 0) {
1578            ogroup[0] = dtable[igroup[0] >> 2];
1579            ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1580            ogroup[2] =
1581                dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1582            ogroup[3] = dtable[igroup[2] & 0x3F];
1583
1584            if (n < 3) {
1585                ogroup[3] = '=';
1586                if (n < 2) {
1587                    ogroup[2] = '=';
1588                }
1589            }
1590
1591            if (linelen >= B64LINELEN) {
1592                count = xmlOutputBufferWrite(out, 2, B64CRLF);
1593                if (count == -1)
1594                    return -1;
1595                sum += count;
1596                linelen = 0;
1597            }
1598            count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1599            if (count == -1)
1600                return -1;
1601            sum += count;
1602
1603            linelen += 4;
1604        }
1605
1606        if (i >= len)
1607            break;
1608    }
1609
1610    return sum;
1611}
1612
1613/**
1614 * xmlTextWriterWriteBase64:
1615 * @writer: the xmlTextWriterPtr
1616 * @data:   binary data
1617 * @start:  the position within the data of the first byte to encode
1618 * @len:  the number of bytes to encode
1619 *
1620 * Write an base64 encoded xml text.
1621 *
1622 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1623 */
1624int
1625xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
1626                         int start, int len)
1627{
1628    int count;
1629    int sum;
1630    xmlLinkPtr lk;
1631    xmlTextWriterStackEntry *p;
1632
1633    if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
1634        return -1;
1635
1636    sum = 0;
1637    lk = xmlListFront(writer->nodes);
1638    if (lk != 0) {
1639        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1640        if (p != 0) {
1641            count = xmlTextWriterHandleStateDependencies(writer, p);
1642            if (count < 0)
1643                return -1;
1644            sum += count;
1645        }
1646    }
1647
1648    if (writer->indent)
1649        writer->doindent = 0;
1650
1651    count =
1652        xmlOutputBufferWriteBase64(writer->out, len,
1653                                   (unsigned char *) data + start);
1654    if (count < 0)
1655        return -1;
1656    sum += count;
1657
1658    return sum;
1659}
1660
1661/**
1662 * xmlOutputBufferWriteBinHex:
1663 * @out: the xmlOutputBufferPtr
1664 * @data:   binary data
1665 * @len:  the number of bytes to encode
1666 *
1667 * Write hqx encoded data to an xmlOutputBuffer.
1668 * ::todo
1669 *
1670 * Returns the bytes written (may be 0 because of buffering)
1671 * or -1 in case of error
1672 */
1673static int
1674xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1675                           int len, const unsigned char *data)
1676{
1677    int count;
1678    int sum;
1679    static char hex[16] =
1680	{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
1681    int i;
1682
1683    if ((out == NULL) || (data == NULL) || (len < 0)) {
1684        return -1;
1685    }
1686
1687    sum = 0;
1688    for (i = 0; i < len; i++) {
1689        count =
1690            xmlOutputBufferWrite(out, 1,
1691                                 (const char *) &hex[data[i] >> 4]);
1692        if (count == -1)
1693            return -1;
1694        sum += count;
1695        count =
1696            xmlOutputBufferWrite(out, 1,
1697                                 (const char *) &hex[data[i] & 0xF]);
1698        if (count == -1)
1699            return -1;
1700        sum += count;
1701    }
1702
1703    return sum;
1704}
1705
1706/**
1707 * xmlTextWriterWriteBinHex:
1708 * @writer: the xmlTextWriterPtr
1709 * @data:   binary data
1710 * @start:  the position within the data of the first byte to encode
1711 * @len:  the number of bytes to encode
1712 *
1713 * Write a BinHex encoded xml text.
1714 *
1715 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1716 */
1717int
1718xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
1719                         int start, int len)
1720{
1721    int count;
1722    int sum;
1723    xmlLinkPtr lk;
1724    xmlTextWriterStackEntry *p;
1725
1726    if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
1727        return -1;
1728
1729    sum = 0;
1730    lk = xmlListFront(writer->nodes);
1731    if (lk != 0) {
1732        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1733        if (p != 0) {
1734            count = xmlTextWriterHandleStateDependencies(writer, p);
1735            if (count < 0)
1736                return -1;
1737            sum += count;
1738        }
1739    }
1740
1741    if (writer->indent)
1742        writer->doindent = 0;
1743
1744    count =
1745        xmlOutputBufferWriteBinHex(writer->out, len,
1746                                   (unsigned char *) data + start);
1747    if (count < 0)
1748        return -1;
1749    sum += count;
1750
1751    return sum;
1752}
1753
1754/**
1755 * xmlTextWriterStartAttribute:
1756 * @writer:  the xmlTextWriterPtr
1757 * @name:  element name
1758 *
1759 * Start an xml attribute.
1760 *
1761 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1762 */
1763int
1764xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1765{
1766    int count;
1767    int sum;
1768    xmlLinkPtr lk;
1769    xmlTextWriterStackEntry *p;
1770
1771    if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1772        return -1;
1773
1774    sum = 0;
1775    lk = xmlListFront(writer->nodes);
1776    if (lk == 0)
1777        return -1;
1778
1779    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1780    if (p == 0)
1781        return -1;
1782
1783    switch (p->state) {
1784        case XML_TEXTWRITER_ATTRIBUTE:
1785            count = xmlTextWriterEndAttribute(writer);
1786            if (count < 0)
1787                return -1;
1788            sum += count;
1789            /* fallthrough */
1790        case XML_TEXTWRITER_NAME:
1791            count = xmlOutputBufferWriteString(writer->out, " ");
1792            if (count < 0)
1793                return -1;
1794            sum += count;
1795            count =
1796                xmlOutputBufferWriteString(writer->out,
1797                                           (const char *) name);
1798            if (count < 0)
1799                return -1;
1800            sum += count;
1801            count = xmlOutputBufferWriteString(writer->out, "=");
1802            if (count < 0)
1803                return -1;
1804            sum += count;
1805            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1806            if (count < 0)
1807                return -1;
1808            sum += count;
1809            p->state = XML_TEXTWRITER_ATTRIBUTE;
1810            break;
1811        default:
1812            return -1;
1813    }
1814
1815    return sum;
1816}
1817
1818/**
1819 * xmlTextWriterStartAttributeNS:
1820 * @writer:  the xmlTextWriterPtr
1821 * @prefix:  namespace prefix or NULL
1822 * @name:  element local name
1823 * @namespaceURI:  namespace URI or NULL
1824 *
1825 * Start an xml attribute with namespace support.
1826 *
1827 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1828 */
1829int
1830xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1831                              const xmlChar * prefix, const xmlChar * name,
1832                              const xmlChar * namespaceURI)
1833{
1834    int count;
1835    int sum;
1836    xmlChar *buf;
1837    xmlTextWriterNsStackEntry *p;
1838
1839    if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1840        return -1;
1841
1842    /* Handle namespace first in case of error */
1843    if (namespaceURI != 0) {
1844        xmlTextWriterNsStackEntry nsentry, *curns;
1845
1846        buf = xmlStrdup(BAD_CAST "xmlns");
1847        if (prefix != 0) {
1848            buf = xmlStrcat(buf, BAD_CAST ":");
1849            buf = xmlStrcat(buf, prefix);
1850        }
1851
1852        nsentry.prefix = buf;
1853        nsentry.uri = (xmlChar *)namespaceURI;
1854        nsentry.elem = xmlListFront(writer->nodes);
1855
1856        curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
1857                                                           (void *)&nsentry);
1858        if ((curns != NULL)) {
1859            xmlFree(buf);
1860            if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
1861                /* Namespace already defined on element skip */
1862                buf = NULL;
1863            } else {
1864                /* Prefix mismatch so error out */
1865                return -1;
1866            }
1867        }
1868
1869        /* Do not add namespace decl to list - it is already there */
1870        if (buf != NULL) {
1871            p = (xmlTextWriterNsStackEntry *)
1872                xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1873            if (p == 0) {
1874                xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1875								        "xmlTextWriterStartAttributeNS : out of memory!\n");
1876                return -1;
1877            }
1878
1879            p->prefix = buf;
1880            p->uri = xmlStrdup(namespaceURI);
1881            if (p->uri == 0) {
1882                xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1883                        "xmlTextWriterStartAttributeNS : out of memory!\n");
1884                xmlFree(p);
1885                return -1;
1886            }
1887            p->elem = xmlListFront(writer->nodes);
1888
1889            xmlListPushFront(writer->nsstack, p);
1890        }
1891    }
1892
1893    buf = NULL;
1894    if (prefix != 0) {
1895        buf = xmlStrdup(prefix);
1896        buf = xmlStrcat(buf, BAD_CAST ":");
1897    }
1898    buf = xmlStrcat(buf, name);
1899
1900    sum = 0;
1901    count = xmlTextWriterStartAttribute(writer, buf);
1902    xmlFree(buf);
1903    if (count < 0)
1904        return -1;
1905    sum += count;
1906
1907    return sum;
1908}
1909
1910/**
1911 * xmlTextWriterEndAttribute:
1912 * @writer:  the xmlTextWriterPtr
1913 *
1914 * End the current xml element.
1915 *
1916 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1917 */
1918int
1919xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1920{
1921    int count;
1922    int sum;
1923    xmlLinkPtr lk;
1924    xmlTextWriterStackEntry *p;
1925
1926    if (writer == NULL)
1927        return -1;
1928
1929    lk = xmlListFront(writer->nodes);
1930    if (lk == 0) {
1931        return -1;
1932    }
1933
1934    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1935    if (p == 0) {
1936        return -1;
1937    }
1938
1939    sum = 0;
1940    switch (p->state) {
1941        case XML_TEXTWRITER_ATTRIBUTE:
1942            p->state = XML_TEXTWRITER_NAME;
1943
1944            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1945            if (count < 0) {
1946                return -1;
1947            }
1948            sum += count;
1949            break;
1950        default:
1951            return -1;
1952    }
1953
1954    return sum;
1955}
1956
1957/**
1958 * xmlTextWriterWriteFormatAttribute:
1959 * @writer:  the xmlTextWriterPtr
1960 * @name:  attribute name
1961 * @format:  format string (see printf)
1962 * @...:  extra parameters for the format
1963 *
1964 * Write a formatted xml attribute.
1965 *
1966 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1967 */
1968int XMLCDECL
1969xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1970                                  const xmlChar * name, const char *format,
1971                                  ...)
1972{
1973    int rc;
1974    va_list ap;
1975
1976    va_start(ap, format);
1977
1978    rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1979
1980    va_end(ap);
1981    return rc;
1982}
1983
1984/**
1985 * xmlTextWriterWriteVFormatAttribute:
1986 * @writer:  the xmlTextWriterPtr
1987 * @name:  attribute name
1988 * @format:  format string (see printf)
1989 * @argptr:  pointer to the first member of the variable argument list.
1990 *
1991 * Write a formatted xml attribute.
1992 *
1993 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1994 */
1995int
1996xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
1997                                   const xmlChar * name,
1998                                   const char *format, va_list argptr)
1999{
2000    int rc;
2001    xmlChar *buf;
2002
2003    if (writer == NULL)
2004        return -1;
2005
2006    buf = xmlTextWriterVSprintf(format, argptr);
2007    if (buf == NULL)
2008        return -1;
2009
2010    rc = xmlTextWriterWriteAttribute(writer, name, buf);
2011
2012    xmlFree(buf);
2013    return rc;
2014}
2015
2016/**
2017 * xmlTextWriterWriteAttribute:
2018 * @writer:  the xmlTextWriterPtr
2019 * @name:  attribute name
2020 * @content:  attribute content
2021 *
2022 * Write an xml attribute.
2023 *
2024 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2025 */
2026int
2027xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
2028                            const xmlChar * content)
2029{
2030    int count;
2031    int sum;
2032
2033    sum = 0;
2034    count = xmlTextWriterStartAttribute(writer, name);
2035    if (count < 0)
2036        return -1;
2037    sum += count;
2038    count = xmlTextWriterWriteString(writer, content);
2039    if (count < 0)
2040        return -1;
2041    sum += count;
2042    count = xmlTextWriterEndAttribute(writer);
2043    if (count < 0)
2044        return -1;
2045    sum += count;
2046
2047    return sum;
2048}
2049
2050/**
2051 * xmlTextWriterWriteFormatAttributeNS:
2052 * @writer:  the xmlTextWriterPtr
2053 * @prefix:  namespace prefix
2054 * @name:  attribute local name
2055 * @namespaceURI:  namespace URI
2056 * @format:  format string (see printf)
2057 * @...:  extra parameters for the format
2058 *
2059 * Write a formatted xml attribute.with namespace support
2060 *
2061 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2062 */
2063int XMLCDECL
2064xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
2065                                    const xmlChar * prefix,
2066                                    const xmlChar * name,
2067                                    const xmlChar * namespaceURI,
2068                                    const char *format, ...)
2069{
2070    int rc;
2071    va_list ap;
2072
2073    va_start(ap, format);
2074
2075    rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
2076                                              namespaceURI, format, ap);
2077
2078    va_end(ap);
2079    return rc;
2080}
2081
2082/**
2083 * xmlTextWriterWriteVFormatAttributeNS:
2084 * @writer:  the xmlTextWriterPtr
2085 * @prefix:  namespace prefix
2086 * @name:  attribute local name
2087 * @namespaceURI:  namespace URI
2088 * @format:  format string (see printf)
2089 * @argptr:  pointer to the first member of the variable argument list.
2090 *
2091 * Write a formatted xml attribute.with namespace support
2092 *
2093 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2094 */
2095int
2096xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
2097                                     const xmlChar * prefix,
2098                                     const xmlChar * name,
2099                                     const xmlChar * namespaceURI,
2100                                     const char *format, va_list argptr)
2101{
2102    int rc;
2103    xmlChar *buf;
2104
2105    if (writer == NULL)
2106        return -1;
2107
2108    buf = xmlTextWriterVSprintf(format, argptr);
2109    if (buf == NULL)
2110        return -1;
2111
2112    rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
2113                                       buf);
2114
2115    xmlFree(buf);
2116    return rc;
2117}
2118
2119/**
2120 * xmlTextWriterWriteAttributeNS:
2121 * @writer:  the xmlTextWriterPtr
2122 * @prefix:  namespace prefix
2123 * @name:  attribute local name
2124 * @namespaceURI:  namespace URI
2125 * @content:  attribute content
2126 *
2127 * Write an xml attribute.
2128 *
2129 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2130 */
2131int
2132xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
2133                              const xmlChar * prefix, const xmlChar * name,
2134                              const xmlChar * namespaceURI,
2135                              const xmlChar * content)
2136{
2137    int count;
2138    int sum;
2139
2140    if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2141        return -1;
2142
2143    sum = 0;
2144    count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
2145    if (count < 0)
2146        return -1;
2147    sum += count;
2148    count = xmlTextWriterWriteString(writer, content);
2149    if (count < 0)
2150        return -1;
2151    sum += count;
2152    count = xmlTextWriterEndAttribute(writer);
2153    if (count < 0)
2154        return -1;
2155    sum += count;
2156
2157    return sum;
2158}
2159
2160/**
2161 * xmlTextWriterWriteFormatElement:
2162 * @writer:  the xmlTextWriterPtr
2163 * @name:  element name
2164 * @format:  format string (see printf)
2165 * @...:  extra parameters for the format
2166 *
2167 * Write a formatted xml element.
2168 *
2169 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2170 */
2171int XMLCDECL
2172xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2173                                const xmlChar * name, const char *format,
2174                                ...)
2175{
2176    int rc;
2177    va_list ap;
2178
2179    va_start(ap, format);
2180
2181    rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2182
2183    va_end(ap);
2184    return rc;
2185}
2186
2187/**
2188 * xmlTextWriterWriteVFormatElement:
2189 * @writer:  the xmlTextWriterPtr
2190 * @name:  element name
2191 * @format:  format string (see printf)
2192 * @argptr:  pointer to the first member of the variable argument list.
2193 *
2194 * Write a formatted xml element.
2195 *
2196 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2197 */
2198int
2199xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2200                                 const xmlChar * name, const char *format,
2201                                 va_list argptr)
2202{
2203    int rc;
2204    xmlChar *buf;
2205
2206    if (writer == NULL)
2207        return -1;
2208
2209    buf = xmlTextWriterVSprintf(format, argptr);
2210    if (buf == NULL)
2211        return -1;
2212
2213    rc = xmlTextWriterWriteElement(writer, name, buf);
2214
2215    xmlFree(buf);
2216    return rc;
2217}
2218
2219/**
2220 * xmlTextWriterWriteElement:
2221 * @writer:  the xmlTextWriterPtr
2222 * @name:  element name
2223 * @content:  element content
2224 *
2225 * Write an xml element.
2226 *
2227 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2228 */
2229int
2230xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2231                          const xmlChar * content)
2232{
2233    int count;
2234    int sum;
2235
2236    sum = 0;
2237    count = xmlTextWriterStartElement(writer, name);
2238    if (count == -1)
2239        return -1;
2240    sum += count;
2241    count = xmlTextWriterWriteString(writer, content);
2242    if (count == -1)
2243        return -1;
2244    sum += count;
2245    count = xmlTextWriterEndElement(writer);
2246    if (count == -1)
2247        return -1;
2248    sum += count;
2249
2250    return sum;
2251}
2252
2253/**
2254 * xmlTextWriterWriteFormatElementNS:
2255 * @writer:  the xmlTextWriterPtr
2256 * @prefix:  namespace prefix
2257 * @name:  element local name
2258 * @namespaceURI:  namespace URI
2259 * @format:  format string (see printf)
2260 * @...:  extra parameters for the format
2261 *
2262 * Write a formatted xml element with namespace support.
2263 *
2264 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2265 */
2266int XMLCDECL
2267xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2268                                  const xmlChar * prefix,
2269                                  const xmlChar * name,
2270                                  const xmlChar * namespaceURI,
2271                                  const char *format, ...)
2272{
2273    int rc;
2274    va_list ap;
2275
2276    va_start(ap, format);
2277
2278    rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2279                                            namespaceURI, format, ap);
2280
2281    va_end(ap);
2282    return rc;
2283}
2284
2285/**
2286 * xmlTextWriterWriteVFormatElementNS:
2287 * @writer:  the xmlTextWriterPtr
2288 * @prefix:  namespace prefix
2289 * @name:  element local name
2290 * @namespaceURI:  namespace URI
2291 * @format:  format string (see printf)
2292 * @argptr:  pointer to the first member of the variable argument list.
2293 *
2294 * Write a formatted xml element with namespace support.
2295 *
2296 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2297 */
2298int
2299xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2300                                   const xmlChar * prefix,
2301                                   const xmlChar * name,
2302                                   const xmlChar * namespaceURI,
2303                                   const char *format, va_list argptr)
2304{
2305    int rc;
2306    xmlChar *buf;
2307
2308    if (writer == NULL)
2309        return -1;
2310
2311    buf = xmlTextWriterVSprintf(format, argptr);
2312    if (buf == NULL)
2313        return -1;
2314
2315    rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2316                                     buf);
2317
2318    xmlFree(buf);
2319    return rc;
2320}
2321
2322/**
2323 * xmlTextWriterWriteElementNS:
2324 * @writer:  the xmlTextWriterPtr
2325 * @prefix:  namespace prefix
2326 * @name:  element local name
2327 * @namespaceURI:  namespace URI
2328 * @content:  element content
2329 *
2330 * Write an xml element with namespace support.
2331 *
2332 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2333 */
2334int
2335xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2336                            const xmlChar * prefix, const xmlChar * name,
2337                            const xmlChar * namespaceURI,
2338                            const xmlChar * content)
2339{
2340    int count;
2341    int sum;
2342
2343    if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2344        return -1;
2345
2346    sum = 0;
2347    count =
2348        xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2349    if (count < 0)
2350        return -1;
2351    sum += count;
2352    count = xmlTextWriterWriteString(writer, content);
2353    if (count == -1)
2354        return -1;
2355    sum += count;
2356    count = xmlTextWriterEndElement(writer);
2357    if (count == -1)
2358        return -1;
2359    sum += count;
2360
2361    return sum;
2362}
2363
2364/**
2365 * xmlTextWriterStartPI:
2366 * @writer:  the xmlTextWriterPtr
2367 * @target:  PI target
2368 *
2369 * Start an xml PI.
2370 *
2371 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2372 */
2373int
2374xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2375{
2376    int count;
2377    int sum;
2378    xmlLinkPtr lk;
2379    xmlTextWriterStackEntry *p;
2380
2381    if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2382        return -1;
2383
2384    if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
2385        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2386                        "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2387        return -1;
2388    }
2389
2390    sum = 0;
2391    lk = xmlListFront(writer->nodes);
2392    if (lk != 0) {
2393        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2394        if (p != 0) {
2395            switch (p->state) {
2396                case XML_TEXTWRITER_ATTRIBUTE:
2397                    count = xmlTextWriterEndAttribute(writer);
2398                    if (count < 0)
2399                        return -1;
2400                    sum += count;
2401                    /* fallthrough */
2402                case XML_TEXTWRITER_NAME:
2403                    /* Output namespace declarations */
2404                    count = xmlTextWriterOutputNSDecl(writer);
2405                    if (count < 0)
2406                        return -1;
2407                    sum += count;
2408                    count = xmlOutputBufferWriteString(writer->out, ">");
2409                    if (count < 0)
2410                        return -1;
2411                    sum += count;
2412                    p->state = XML_TEXTWRITER_TEXT;
2413                    break;
2414                case XML_TEXTWRITER_NONE:
2415                case XML_TEXTWRITER_TEXT:
2416                case XML_TEXTWRITER_DTD:
2417                    break;
2418                case XML_TEXTWRITER_PI:
2419                case XML_TEXTWRITER_PI_TEXT:
2420                    xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2421                                    "xmlTextWriterStartPI : nested PI!\n");
2422                    return -1;
2423                default:
2424                    return -1;
2425            }
2426        }
2427    }
2428
2429    p = (xmlTextWriterStackEntry *)
2430        xmlMalloc(sizeof(xmlTextWriterStackEntry));
2431    if (p == 0) {
2432        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2433                        "xmlTextWriterStartPI : out of memory!\n");
2434        return -1;
2435    }
2436
2437    p->name = xmlStrdup(target);
2438    if (p->name == 0) {
2439        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2440                        "xmlTextWriterStartPI : out of memory!\n");
2441        xmlFree(p);
2442        return -1;
2443    }
2444    p->state = XML_TEXTWRITER_PI;
2445
2446    xmlListPushFront(writer->nodes, p);
2447
2448    count = xmlOutputBufferWriteString(writer->out, "<?");
2449    if (count < 0)
2450        return -1;
2451    sum += count;
2452    count =
2453        xmlOutputBufferWriteString(writer->out, (const char *) p->name);
2454    if (count < 0)
2455        return -1;
2456    sum += count;
2457
2458    return sum;
2459}
2460
2461/**
2462 * xmlTextWriterEndPI:
2463 * @writer:  the xmlTextWriterPtr
2464 *
2465 * End the current xml PI.
2466 *
2467 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2468 */
2469int
2470xmlTextWriterEndPI(xmlTextWriterPtr writer)
2471{
2472    int count;
2473    int sum;
2474    xmlLinkPtr lk;
2475    xmlTextWriterStackEntry *p;
2476
2477    if (writer == NULL)
2478        return -1;
2479
2480    lk = xmlListFront(writer->nodes);
2481    if (lk == 0)
2482        return 0;
2483
2484    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2485    if (p == 0)
2486        return 0;
2487
2488    sum = 0;
2489    switch (p->state) {
2490        case XML_TEXTWRITER_PI:
2491        case XML_TEXTWRITER_PI_TEXT:
2492            count = xmlOutputBufferWriteString(writer->out, "?>");
2493            if (count < 0)
2494                return -1;
2495            sum += count;
2496            break;
2497        default:
2498            return -1;
2499    }
2500
2501    if (writer->indent) {
2502        count = xmlOutputBufferWriteString(writer->out, "\n");
2503	if (count < 0)
2504	return -1;
2505        sum += count;
2506    }
2507
2508    xmlListPopFront(writer->nodes);
2509    return sum;
2510}
2511
2512/**
2513 * xmlTextWriterWriteFormatPI:
2514 * @writer:  the xmlTextWriterPtr
2515 * @target:  PI target
2516 * @format:  format string (see printf)
2517 * @...:  extra parameters for the format
2518 *
2519 * Write a formatted PI.
2520 *
2521 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2522 */
2523int XMLCDECL
2524xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2525                           const char *format, ...)
2526{
2527    int rc;
2528    va_list ap;
2529
2530    va_start(ap, format);
2531
2532    rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2533
2534    va_end(ap);
2535    return rc;
2536}
2537
2538/**
2539 * xmlTextWriterWriteVFormatPI:
2540 * @writer:  the xmlTextWriterPtr
2541 * @target:  PI target
2542 * @format:  format string (see printf)
2543 * @argptr:  pointer to the first member of the variable argument list.
2544 *
2545 * Write a formatted xml PI.
2546 *
2547 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2548 */
2549int
2550xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2551                            const xmlChar * target, const char *format,
2552                            va_list argptr)
2553{
2554    int rc;
2555    xmlChar *buf;
2556
2557    if (writer == NULL)
2558        return -1;
2559
2560    buf = xmlTextWriterVSprintf(format, argptr);
2561    if (buf == NULL)
2562        return -1;
2563
2564    rc = xmlTextWriterWritePI(writer, target, buf);
2565
2566    xmlFree(buf);
2567    return rc;
2568}
2569
2570/**
2571 * xmlTextWriterWritePI:
2572 * @writer:  the xmlTextWriterPtr
2573 * @target:  PI target
2574 * @content:  PI content
2575 *
2576 * Write an xml PI.
2577 *
2578 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2579 */
2580int
2581xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2582                     const xmlChar * content)
2583{
2584    int count;
2585    int sum;
2586
2587    sum = 0;
2588    count = xmlTextWriterStartPI(writer, target);
2589    if (count == -1)
2590        return -1;
2591    sum += count;
2592    if (content != 0) {
2593        count = xmlTextWriterWriteString(writer, content);
2594        if (count == -1)
2595            return -1;
2596        sum += count;
2597    }
2598    count = xmlTextWriterEndPI(writer);
2599    if (count == -1)
2600        return -1;
2601    sum += count;
2602
2603    return sum;
2604}
2605
2606/**
2607 * xmlTextWriterStartCDATA:
2608 * @writer:  the xmlTextWriterPtr
2609 *
2610 * Start an xml CDATA section.
2611 *
2612 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2613 */
2614int
2615xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2616{
2617    int count;
2618    int sum;
2619    xmlLinkPtr lk;
2620    xmlTextWriterStackEntry *p;
2621
2622    if (writer == NULL)
2623        return -1;
2624
2625    sum = 0;
2626    lk = xmlListFront(writer->nodes);
2627    if (lk != 0) {
2628        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2629        if (p != 0) {
2630            switch (p->state) {
2631                case XML_TEXTWRITER_NONE:
2632		case XML_TEXTWRITER_TEXT:
2633                case XML_TEXTWRITER_PI:
2634                case XML_TEXTWRITER_PI_TEXT:
2635                    break;
2636                case XML_TEXTWRITER_ATTRIBUTE:
2637                    count = xmlTextWriterEndAttribute(writer);
2638                    if (count < 0)
2639                        return -1;
2640                    sum += count;
2641                    /* fallthrough */
2642                case XML_TEXTWRITER_NAME:
2643                    /* Output namespace declarations */
2644                    count = xmlTextWriterOutputNSDecl(writer);
2645                    if (count < 0)
2646                        return -1;
2647                    sum += count;
2648                    count = xmlOutputBufferWriteString(writer->out, ">");
2649                    if (count < 0)
2650                        return -1;
2651                    sum += count;
2652                    p->state = XML_TEXTWRITER_TEXT;
2653                    break;
2654                case XML_TEXTWRITER_CDATA:
2655                    xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2656                                    "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2657                    return -1;
2658                default:
2659                    return -1;
2660            }
2661        }
2662    }
2663
2664    p = (xmlTextWriterStackEntry *)
2665        xmlMalloc(sizeof(xmlTextWriterStackEntry));
2666    if (p == 0) {
2667        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2668                        "xmlTextWriterStartCDATA : out of memory!\n");
2669        return -1;
2670    }
2671
2672    p->name = NULL;
2673    p->state = XML_TEXTWRITER_CDATA;
2674
2675    xmlListPushFront(writer->nodes, p);
2676
2677    count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2678    if (count < 0)
2679        return -1;
2680    sum += count;
2681
2682    return sum;
2683}
2684
2685/**
2686 * xmlTextWriterEndCDATA:
2687 * @writer:  the xmlTextWriterPtr
2688 *
2689 * End an xml CDATA section.
2690 *
2691 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2692 */
2693int
2694xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2695{
2696    int count;
2697    int sum;
2698    xmlLinkPtr lk;
2699    xmlTextWriterStackEntry *p;
2700
2701    if (writer == NULL)
2702        return -1;
2703
2704    lk = xmlListFront(writer->nodes);
2705    if (lk == 0)
2706        return -1;
2707
2708    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2709    if (p == 0)
2710        return -1;
2711
2712    sum = 0;
2713    switch (p->state) {
2714        case XML_TEXTWRITER_CDATA:
2715            count = xmlOutputBufferWriteString(writer->out, "]]>");
2716            if (count < 0)
2717                return -1;
2718            sum += count;
2719            break;
2720        default:
2721            return -1;
2722    }
2723
2724    xmlListPopFront(writer->nodes);
2725    return sum;
2726}
2727
2728/**
2729 * xmlTextWriterWriteFormatCDATA:
2730 * @writer:  the xmlTextWriterPtr
2731 * @format:  format string (see printf)
2732 * @...:  extra parameters for the format
2733 *
2734 * Write a formatted xml CDATA.
2735 *
2736 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2737 */
2738int XMLCDECL
2739xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2740                              ...)
2741{
2742    int rc;
2743    va_list ap;
2744
2745    va_start(ap, format);
2746
2747    rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2748
2749    va_end(ap);
2750    return rc;
2751}
2752
2753/**
2754 * xmlTextWriterWriteVFormatCDATA:
2755 * @writer:  the xmlTextWriterPtr
2756 * @format:  format string (see printf)
2757 * @argptr:  pointer to the first member of the variable argument list.
2758 *
2759 * Write a formatted xml CDATA.
2760 *
2761 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2762 */
2763int
2764xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2765                               va_list argptr)
2766{
2767    int rc;
2768    xmlChar *buf;
2769
2770    if (writer == NULL)
2771        return -1;
2772
2773    buf = xmlTextWriterVSprintf(format, argptr);
2774    if (buf == NULL)
2775        return -1;
2776
2777    rc = xmlTextWriterWriteCDATA(writer, buf);
2778
2779    xmlFree(buf);
2780    return rc;
2781}
2782
2783/**
2784 * xmlTextWriterWriteCDATA:
2785 * @writer:  the xmlTextWriterPtr
2786 * @content:  CDATA content
2787 *
2788 * Write an xml CDATA.
2789 *
2790 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2791 */
2792int
2793xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2794{
2795    int count;
2796    int sum;
2797
2798    sum = 0;
2799    count = xmlTextWriterStartCDATA(writer);
2800    if (count == -1)
2801        return -1;
2802    sum += count;
2803    if (content != 0) {
2804        count = xmlTextWriterWriteString(writer, content);
2805        if (count == -1)
2806            return -1;
2807        sum += count;
2808    }
2809    count = xmlTextWriterEndCDATA(writer);
2810    if (count == -1)
2811        return -1;
2812    sum += count;
2813
2814    return sum;
2815}
2816
2817/**
2818 * xmlTextWriterStartDTD:
2819 * @writer:  the xmlTextWriterPtr
2820 * @name:  the name of the DTD
2821 * @pubid:  the public identifier, which is an alternative to the system identifier
2822 * @sysid:  the system identifier, which is the URI of the DTD
2823 *
2824 * Start an xml DTD.
2825 *
2826 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2827 */
2828int
2829xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2830                      const xmlChar * name,
2831                      const xmlChar * pubid, const xmlChar * sysid)
2832{
2833    int count;
2834    int sum;
2835    xmlLinkPtr lk;
2836    xmlTextWriterStackEntry *p;
2837
2838    if (writer == NULL || name == NULL || *name == '\0')
2839        return -1;
2840
2841    sum = 0;
2842    lk = xmlListFront(writer->nodes);
2843    if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
2844        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2845                        "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2846        return -1;
2847    }
2848
2849    p = (xmlTextWriterStackEntry *)
2850        xmlMalloc(sizeof(xmlTextWriterStackEntry));
2851    if (p == 0) {
2852        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2853                        "xmlTextWriterStartDTD : out of memory!\n");
2854        return -1;
2855    }
2856
2857    p->name = xmlStrdup(name);
2858    if (p->name == 0) {
2859        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2860                        "xmlTextWriterStartDTD : out of memory!\n");
2861        xmlFree(p);
2862        return -1;
2863    }
2864    p->state = XML_TEXTWRITER_DTD;
2865
2866    xmlListPushFront(writer->nodes, p);
2867
2868    count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2869    if (count < 0)
2870        return -1;
2871    sum += count;
2872    count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2873    if (count < 0)
2874        return -1;
2875    sum += count;
2876
2877    if (pubid != 0) {
2878        if (sysid == 0) {
2879            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2880                            "xmlTextWriterStartDTD : system identifier needed!\n");
2881            return -1;
2882        }
2883
2884        if (writer->indent)
2885            count = xmlOutputBufferWrite(writer->out, 1, "\n");
2886        else
2887            count = xmlOutputBufferWrite(writer->out, 1, " ");
2888        if (count < 0)
2889            return -1;
2890        sum += count;
2891
2892        count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2893        if (count < 0)
2894            return -1;
2895        sum += count;
2896
2897        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2898        if (count < 0)
2899            return -1;
2900        sum += count;
2901
2902        count =
2903            xmlOutputBufferWriteString(writer->out, (const char *) pubid);
2904        if (count < 0)
2905            return -1;
2906        sum += count;
2907
2908        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2909        if (count < 0)
2910            return -1;
2911        sum += count;
2912    }
2913
2914    if (sysid != 0) {
2915        if (pubid == 0) {
2916            if (writer->indent)
2917                count = xmlOutputBufferWrite(writer->out, 1, "\n");
2918            else
2919                count = xmlOutputBufferWrite(writer->out, 1, " ");
2920            if (count < 0)
2921                return -1;
2922            sum += count;
2923            count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2924            if (count < 0)
2925                return -1;
2926            sum += count;
2927        } else {
2928			if (writer->indent)
2929            count = xmlOutputBufferWriteString(writer->out, "\n       ");
2930            else
2931                count = xmlOutputBufferWrite(writer->out, 1, " ");
2932            if (count < 0)
2933                return -1;
2934            sum += count;
2935        }
2936
2937        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2938        if (count < 0)
2939            return -1;
2940        sum += count;
2941
2942        count =
2943            xmlOutputBufferWriteString(writer->out, (const char *) sysid);
2944        if (count < 0)
2945            return -1;
2946        sum += count;
2947
2948        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2949        if (count < 0)
2950            return -1;
2951        sum += count;
2952    }
2953
2954    return sum;
2955}
2956
2957/**
2958 * xmlTextWriterEndDTD:
2959 * @writer:  the xmlTextWriterPtr
2960 *
2961 * End an xml DTD.
2962 *
2963 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2964 */
2965int
2966xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2967{
2968    int loop;
2969    int count;
2970    int sum;
2971    xmlLinkPtr lk;
2972    xmlTextWriterStackEntry *p;
2973
2974    if (writer == NULL)
2975        return -1;
2976
2977    sum = 0;
2978    loop = 1;
2979    while (loop) {
2980        lk = xmlListFront(writer->nodes);
2981        if (lk == NULL)
2982            break;
2983        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2984        if (p == 0)
2985            break;
2986        switch (p->state) {
2987            case XML_TEXTWRITER_DTD_TEXT:
2988                count = xmlOutputBufferWriteString(writer->out, "]");
2989                if (count < 0)
2990                    return -1;
2991                sum += count;
2992                /* fallthrough */
2993            case XML_TEXTWRITER_DTD:
2994                count = xmlOutputBufferWriteString(writer->out, ">");
2995
2996                if (writer->indent) {
2997                    if (count < 0)
2998                        return -1;
2999                    sum += count;
3000                    count = xmlOutputBufferWriteString(writer->out, "\n");
3001                }
3002
3003                xmlListPopFront(writer->nodes);
3004                break;
3005            case XML_TEXTWRITER_DTD_ELEM:
3006            case XML_TEXTWRITER_DTD_ELEM_TEXT:
3007                count = xmlTextWriterEndDTDElement(writer);
3008                break;
3009            case XML_TEXTWRITER_DTD_ATTL:
3010            case XML_TEXTWRITER_DTD_ATTL_TEXT:
3011                count = xmlTextWriterEndDTDAttlist(writer);
3012                break;
3013            case XML_TEXTWRITER_DTD_ENTY:
3014            case XML_TEXTWRITER_DTD_PENT:
3015            case XML_TEXTWRITER_DTD_ENTY_TEXT:
3016                count = xmlTextWriterEndDTDEntity(writer);
3017                break;
3018            case XML_TEXTWRITER_COMMENT:
3019                count = xmlTextWriterEndComment(writer);
3020                break;
3021            default:
3022                loop = 0;
3023                continue;
3024        }
3025
3026        if (count < 0)
3027            return -1;
3028        sum += count;
3029    }
3030
3031    return sum;
3032}
3033
3034/**
3035 * xmlTextWriterWriteFormatDTD:
3036 * @writer:  the xmlTextWriterPtr
3037 * @name:  the name of the DTD
3038 * @pubid:  the public identifier, which is an alternative to the system identifier
3039 * @sysid:  the system identifier, which is the URI of the DTD
3040 * @format:  format string (see printf)
3041 * @...:  extra parameters for the format
3042 *
3043 * Write a DTD with a formatted markup declarations part.
3044 *
3045 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3046 */
3047int XMLCDECL
3048xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3049                            const xmlChar * name,
3050                            const xmlChar * pubid,
3051                            const xmlChar * sysid, const char *format, ...)
3052{
3053    int rc;
3054    va_list ap;
3055
3056    va_start(ap, format);
3057
3058    rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3059                                      ap);
3060
3061    va_end(ap);
3062    return rc;
3063}
3064
3065/**
3066 * xmlTextWriterWriteVFormatDTD:
3067 * @writer:  the xmlTextWriterPtr
3068 * @name:  the name of the DTD
3069 * @pubid:  the public identifier, which is an alternative to the system identifier
3070 * @sysid:  the system identifier, which is the URI of the DTD
3071 * @format:  format string (see printf)
3072 * @argptr:  pointer to the first member of the variable argument list.
3073 *
3074 * Write a DTD with a formatted markup declarations part.
3075 *
3076 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3077 */
3078int
3079xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3080                             const xmlChar * name,
3081                             const xmlChar * pubid,
3082                             const xmlChar * sysid,
3083                             const char *format, va_list argptr)
3084{
3085    int rc;
3086    xmlChar *buf;
3087
3088    if (writer == NULL)
3089        return -1;
3090
3091    buf = xmlTextWriterVSprintf(format, argptr);
3092    if (buf == NULL)
3093        return -1;
3094
3095    rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3096
3097    xmlFree(buf);
3098    return rc;
3099}
3100
3101/**
3102 * xmlTextWriterWriteDTD:
3103 * @writer:  the xmlTextWriterPtr
3104 * @name:  the name of the DTD
3105 * @pubid:  the public identifier, which is an alternative to the system identifier
3106 * @sysid:  the system identifier, which is the URI of the DTD
3107 * @subset:  string content of the DTD
3108 *
3109 * Write a DTD.
3110 *
3111 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3112 */
3113int
3114xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3115                      const xmlChar * name,
3116                      const xmlChar * pubid,
3117                      const xmlChar * sysid, const xmlChar * subset)
3118{
3119    int count;
3120    int sum;
3121
3122    sum = 0;
3123    count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3124    if (count == -1)
3125        return -1;
3126    sum += count;
3127    if (subset != 0) {
3128        count = xmlTextWriterWriteString(writer, subset);
3129        if (count == -1)
3130            return -1;
3131        sum += count;
3132    }
3133    count = xmlTextWriterEndDTD(writer);
3134    if (count == -1)
3135        return -1;
3136    sum += count;
3137
3138    return sum;
3139}
3140
3141/**
3142 * xmlTextWriterStartDTDElement:
3143 * @writer:  the xmlTextWriterPtr
3144 * @name:  the name of the DTD element
3145 *
3146 * Start an xml DTD element.
3147 *
3148 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3149 */
3150int
3151xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3152{
3153    int count;
3154    int sum;
3155    xmlLinkPtr lk;
3156    xmlTextWriterStackEntry *p;
3157
3158    if (writer == NULL || name == NULL || *name == '\0')
3159        return -1;
3160
3161    sum = 0;
3162    lk = xmlListFront(writer->nodes);
3163    if (lk == 0) {
3164        return -1;
3165    }
3166
3167    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3168    if (p != 0) {
3169        switch (p->state) {
3170            case XML_TEXTWRITER_DTD:
3171                count = xmlOutputBufferWriteString(writer->out, " [");
3172                if (count < 0)
3173                    return -1;
3174                sum += count;
3175                if (writer->indent) {
3176                    count = xmlOutputBufferWriteString(writer->out, "\n");
3177                    if (count < 0)
3178                        return -1;
3179                    sum += count;
3180                }
3181                p->state = XML_TEXTWRITER_DTD_TEXT;
3182                /* fallthrough */
3183            case XML_TEXTWRITER_DTD_TEXT:
3184            case XML_TEXTWRITER_NONE:
3185                break;
3186            default:
3187                return -1;
3188        }
3189    }
3190
3191    p = (xmlTextWriterStackEntry *)
3192        xmlMalloc(sizeof(xmlTextWriterStackEntry));
3193    if (p == 0) {
3194        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3195                        "xmlTextWriterStartDTDElement : out of memory!\n");
3196        return -1;
3197    }
3198
3199    p->name = xmlStrdup(name);
3200    if (p->name == 0) {
3201        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3202                        "xmlTextWriterStartDTDElement : out of memory!\n");
3203        xmlFree(p);
3204        return -1;
3205    }
3206    p->state = XML_TEXTWRITER_DTD_ELEM;
3207
3208    xmlListPushFront(writer->nodes, p);
3209
3210    if (writer->indent) {
3211        count = xmlTextWriterWriteIndent(writer);
3212        if (count < 0)
3213            return -1;
3214        sum += count;
3215    }
3216
3217    count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3218    if (count < 0)
3219        return -1;
3220    sum += count;
3221    count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3222    if (count < 0)
3223        return -1;
3224    sum += count;
3225
3226    return sum;
3227}
3228
3229/**
3230 * xmlTextWriterEndDTDElement:
3231 * @writer:  the xmlTextWriterPtr
3232 *
3233 * End an xml DTD element.
3234 *
3235 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3236 */
3237int
3238xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3239{
3240    int count;
3241    int sum;
3242    xmlLinkPtr lk;
3243    xmlTextWriterStackEntry *p;
3244
3245    if (writer == NULL)
3246        return -1;
3247
3248    sum = 0;
3249    lk = xmlListFront(writer->nodes);
3250    if (lk == 0)
3251        return -1;
3252
3253    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3254    if (p == 0)
3255        return -1;
3256
3257    switch (p->state) {
3258        case XML_TEXTWRITER_DTD_ELEM:
3259        case XML_TEXTWRITER_DTD_ELEM_TEXT:
3260            count = xmlOutputBufferWriteString(writer->out, ">");
3261            if (count < 0)
3262                return -1;
3263            sum += count;
3264            break;
3265        default:
3266            return -1;
3267    }
3268
3269    if (writer->indent) {
3270        count = xmlOutputBufferWriteString(writer->out, "\n");
3271        if (count < 0)
3272            return -1;
3273        sum += count;
3274    }
3275
3276    xmlListPopFront(writer->nodes);
3277    return sum;
3278}
3279
3280/**
3281 * xmlTextWriterWriteFormatDTDElement:
3282 * @writer:  the xmlTextWriterPtr
3283 * @name:  the name of the DTD element
3284 * @format:  format string (see printf)
3285 * @...:  extra parameters for the format
3286 *
3287 * Write a formatted DTD element.
3288 *
3289 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3290 */
3291int XMLCDECL
3292xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3293                                   const xmlChar * name,
3294                                   const char *format, ...)
3295{
3296    int rc;
3297    va_list ap;
3298
3299    va_start(ap, format);
3300
3301    rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3302
3303    va_end(ap);
3304    return rc;
3305}
3306
3307/**
3308 * xmlTextWriterWriteVFormatDTDElement:
3309 * @writer:  the xmlTextWriterPtr
3310 * @name:  the name of the DTD element
3311 * @format:  format string (see printf)
3312 * @argptr:  pointer to the first member of the variable argument list.
3313 *
3314 * Write a formatted DTD element.
3315 *
3316 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3317 */
3318int
3319xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3320                                    const xmlChar * name,
3321                                    const char *format, va_list argptr)
3322{
3323    int rc;
3324    xmlChar *buf;
3325
3326    if (writer == NULL)
3327        return -1;
3328
3329    buf = xmlTextWriterVSprintf(format, argptr);
3330    if (buf == NULL)
3331        return -1;
3332
3333    rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3334
3335    xmlFree(buf);
3336    return rc;
3337}
3338
3339/**
3340 * xmlTextWriterWriteDTDElement:
3341 * @writer:  the xmlTextWriterPtr
3342 * @name:  the name of the DTD element
3343 * @content:  content of the element
3344 *
3345 * Write a DTD element.
3346 *
3347 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3348 */
3349int
3350xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3351                             const xmlChar * name, const xmlChar * content)
3352{
3353    int count;
3354    int sum;
3355
3356    if (content == NULL)
3357        return -1;
3358
3359    sum = 0;
3360    count = xmlTextWriterStartDTDElement(writer, name);
3361    if (count == -1)
3362        return -1;
3363    sum += count;
3364
3365    count = xmlTextWriterWriteString(writer, content);
3366    if (count == -1)
3367        return -1;
3368    sum += count;
3369
3370    count = xmlTextWriterEndDTDElement(writer);
3371    if (count == -1)
3372        return -1;
3373    sum += count;
3374
3375    return sum;
3376}
3377
3378/**
3379 * xmlTextWriterStartDTDAttlist:
3380 * @writer:  the xmlTextWriterPtr
3381 * @name:  the name of the DTD ATTLIST
3382 *
3383 * Start an xml DTD ATTLIST.
3384 *
3385 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3386 */
3387int
3388xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3389{
3390    int count;
3391    int sum;
3392    xmlLinkPtr lk;
3393    xmlTextWriterStackEntry *p;
3394
3395    if (writer == NULL || name == NULL || *name == '\0')
3396        return -1;
3397
3398    sum = 0;
3399    lk = xmlListFront(writer->nodes);
3400    if (lk == 0) {
3401        return -1;
3402    }
3403
3404    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3405    if (p != 0) {
3406        switch (p->state) {
3407            case XML_TEXTWRITER_DTD:
3408                count = xmlOutputBufferWriteString(writer->out, " [");
3409                if (count < 0)
3410                    return -1;
3411                sum += count;
3412                if (writer->indent) {
3413                    count = xmlOutputBufferWriteString(writer->out, "\n");
3414                    if (count < 0)
3415                        return -1;
3416                    sum += count;
3417                }
3418                p->state = XML_TEXTWRITER_DTD_TEXT;
3419                /* fallthrough */
3420            case XML_TEXTWRITER_DTD_TEXT:
3421            case XML_TEXTWRITER_NONE:
3422                break;
3423            default:
3424                return -1;
3425        }
3426    }
3427
3428    p = (xmlTextWriterStackEntry *)
3429        xmlMalloc(sizeof(xmlTextWriterStackEntry));
3430    if (p == 0) {
3431        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3432                        "xmlTextWriterStartDTDAttlist : out of memory!\n");
3433        return -1;
3434    }
3435
3436    p->name = xmlStrdup(name);
3437    if (p->name == 0) {
3438        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3439                        "xmlTextWriterStartDTDAttlist : out of memory!\n");
3440        xmlFree(p);
3441        return -1;
3442    }
3443    p->state = XML_TEXTWRITER_DTD_ATTL;
3444
3445    xmlListPushFront(writer->nodes, p);
3446
3447    if (writer->indent) {
3448        count = xmlTextWriterWriteIndent(writer);
3449        if (count < 0)
3450            return -1;
3451        sum += count;
3452    }
3453
3454    count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3455    if (count < 0)
3456        return -1;
3457    sum += count;
3458    count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3459    if (count < 0)
3460        return -1;
3461    sum += count;
3462
3463    return sum;
3464}
3465
3466/**
3467 * xmlTextWriterEndDTDAttlist:
3468 * @writer:  the xmlTextWriterPtr
3469 *
3470 * End an xml DTD attribute list.
3471 *
3472 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3473 */
3474int
3475xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3476{
3477    int count;
3478    int sum;
3479    xmlLinkPtr lk;
3480    xmlTextWriterStackEntry *p;
3481
3482    if (writer == NULL)
3483        return -1;
3484
3485    sum = 0;
3486    lk = xmlListFront(writer->nodes);
3487    if (lk == 0)
3488        return -1;
3489
3490    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3491    if (p == 0)
3492        return -1;
3493
3494    switch (p->state) {
3495        case XML_TEXTWRITER_DTD_ATTL:
3496        case XML_TEXTWRITER_DTD_ATTL_TEXT:
3497            count = xmlOutputBufferWriteString(writer->out, ">");
3498            if (count < 0)
3499                return -1;
3500            sum += count;
3501            break;
3502        default:
3503            return -1;
3504    }
3505
3506    if (writer->indent) {
3507        count = xmlOutputBufferWriteString(writer->out, "\n");
3508        if (count < 0)
3509            return -1;
3510        sum += count;
3511    }
3512
3513    xmlListPopFront(writer->nodes);
3514    return sum;
3515}
3516
3517/**
3518 * xmlTextWriterWriteFormatDTDAttlist:
3519 * @writer:  the xmlTextWriterPtr
3520 * @name:  the name of the DTD ATTLIST
3521 * @format:  format string (see printf)
3522 * @...:  extra parameters for the format
3523 *
3524 * Write a formatted DTD ATTLIST.
3525 *
3526 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3527 */
3528int XMLCDECL
3529xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3530                                   const xmlChar * name,
3531                                   const char *format, ...)
3532{
3533    int rc;
3534    va_list ap;
3535
3536    va_start(ap, format);
3537
3538    rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3539
3540    va_end(ap);
3541    return rc;
3542}
3543
3544/**
3545 * xmlTextWriterWriteVFormatDTDAttlist:
3546 * @writer:  the xmlTextWriterPtr
3547 * @name:  the name of the DTD ATTLIST
3548 * @format:  format string (see printf)
3549 * @argptr:  pointer to the first member of the variable argument list.
3550 *
3551 * Write a formatted DTD ATTLIST.
3552 *
3553 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3554 */
3555int
3556xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3557                                    const xmlChar * name,
3558                                    const char *format, va_list argptr)
3559{
3560    int rc;
3561    xmlChar *buf;
3562
3563    if (writer == NULL)
3564        return -1;
3565
3566    buf = xmlTextWriterVSprintf(format, argptr);
3567    if (buf == NULL)
3568        return -1;
3569
3570    rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3571
3572    xmlFree(buf);
3573    return rc;
3574}
3575
3576/**
3577 * xmlTextWriterWriteDTDAttlist:
3578 * @writer:  the xmlTextWriterPtr
3579 * @name:  the name of the DTD ATTLIST
3580 * @content:  content of the ATTLIST
3581 *
3582 * Write a DTD ATTLIST.
3583 *
3584 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3585 */
3586int
3587xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3588                             const xmlChar * name, const xmlChar * content)
3589{
3590    int count;
3591    int sum;
3592
3593    if (content == NULL)
3594        return -1;
3595
3596    sum = 0;
3597    count = xmlTextWriterStartDTDAttlist(writer, name);
3598    if (count == -1)
3599        return -1;
3600    sum += count;
3601
3602    count = xmlTextWriterWriteString(writer, content);
3603    if (count == -1)
3604        return -1;
3605    sum += count;
3606
3607    count = xmlTextWriterEndDTDAttlist(writer);
3608    if (count == -1)
3609        return -1;
3610    sum += count;
3611
3612    return sum;
3613}
3614
3615/**
3616 * xmlTextWriterStartDTDEntity:
3617 * @writer:  the xmlTextWriterPtr
3618 * @pe:  TRUE if this is a parameter entity, FALSE if not
3619 * @name:  the name of the DTD ATTLIST
3620 *
3621 * Start an xml DTD ATTLIST.
3622 *
3623 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3624 */
3625int
3626xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3627                            int pe, const xmlChar * name)
3628{
3629    int count;
3630    int sum;
3631    xmlLinkPtr lk;
3632    xmlTextWriterStackEntry *p;
3633
3634    if (writer == NULL || name == NULL || *name == '\0')
3635        return -1;
3636
3637    sum = 0;
3638    lk = xmlListFront(writer->nodes);
3639    if (lk != 0) {
3640
3641        p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3642        if (p != 0) {
3643            switch (p->state) {
3644                case XML_TEXTWRITER_DTD:
3645                    count = xmlOutputBufferWriteString(writer->out, " [");
3646                    if (count < 0)
3647                        return -1;
3648                    sum += count;
3649                    if (writer->indent) {
3650                        count =
3651                            xmlOutputBufferWriteString(writer->out, "\n");
3652                        if (count < 0)
3653                            return -1;
3654                        sum += count;
3655                    }
3656                    p->state = XML_TEXTWRITER_DTD_TEXT;
3657                    /* fallthrough */
3658                case XML_TEXTWRITER_DTD_TEXT:
3659                case XML_TEXTWRITER_NONE:
3660                    break;
3661                default:
3662                    return -1;
3663            }
3664        }
3665    }
3666
3667    p = (xmlTextWriterStackEntry *)
3668        xmlMalloc(sizeof(xmlTextWriterStackEntry));
3669    if (p == 0) {
3670        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3671                        "xmlTextWriterStartDTDElement : out of memory!\n");
3672        return -1;
3673    }
3674
3675    p->name = xmlStrdup(name);
3676    if (p->name == 0) {
3677        xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3678                        "xmlTextWriterStartDTDElement : out of memory!\n");
3679        xmlFree(p);
3680        return -1;
3681    }
3682
3683    if (pe != 0)
3684        p->state = XML_TEXTWRITER_DTD_PENT;
3685    else
3686        p->state = XML_TEXTWRITER_DTD_ENTY;
3687
3688    xmlListPushFront(writer->nodes, p);
3689
3690    if (writer->indent) {
3691        count = xmlTextWriterWriteIndent(writer);
3692        if (count < 0)
3693            return -1;
3694        sum += count;
3695    }
3696
3697    count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3698    if (count < 0)
3699        return -1;
3700    sum += count;
3701
3702    if (pe != 0) {
3703        count = xmlOutputBufferWriteString(writer->out, "% ");
3704        if (count < 0)
3705            return -1;
3706        sum += count;
3707    }
3708
3709    count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3710    if (count < 0)
3711        return -1;
3712    sum += count;
3713
3714    return sum;
3715}
3716
3717/**
3718 * xmlTextWriterEndDTDEntity:
3719 * @writer:  the xmlTextWriterPtr
3720 *
3721 * End an xml DTD entity.
3722 *
3723 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3724 */
3725int
3726xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3727{
3728    int count;
3729    int sum;
3730    xmlLinkPtr lk;
3731    xmlTextWriterStackEntry *p;
3732
3733    if (writer == NULL)
3734        return -1;
3735
3736    sum = 0;
3737    lk = xmlListFront(writer->nodes);
3738    if (lk == 0)
3739        return -1;
3740
3741    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3742    if (p == 0)
3743        return -1;
3744
3745    switch (p->state) {
3746        case XML_TEXTWRITER_DTD_ENTY_TEXT:
3747            count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3748            if (count < 0)
3749                return -1;
3750            sum += count;
3751        case XML_TEXTWRITER_DTD_ENTY:
3752        case XML_TEXTWRITER_DTD_PENT:
3753            count = xmlOutputBufferWriteString(writer->out, ">");
3754            if (count < 0)
3755                return -1;
3756            sum += count;
3757            break;
3758        default:
3759            return -1;
3760    }
3761
3762    if (writer->indent) {
3763        count = xmlOutputBufferWriteString(writer->out, "\n");
3764        if (count < 0)
3765            return -1;
3766        sum += count;
3767    }
3768
3769    xmlListPopFront(writer->nodes);
3770    return sum;
3771}
3772
3773/**
3774 * xmlTextWriterWriteFormatDTDInternalEntity:
3775 * @writer:  the xmlTextWriterPtr
3776 * @pe:  TRUE if this is a parameter entity, FALSE if not
3777 * @name:  the name of the DTD entity
3778 * @format:  format string (see printf)
3779 * @...:  extra parameters for the format
3780 *
3781 * Write a formatted DTD internal entity.
3782 *
3783 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3784 */
3785int XMLCDECL
3786xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3787                                          int pe,
3788                                          const xmlChar * name,
3789                                          const char *format, ...)
3790{
3791    int rc;
3792    va_list ap;
3793
3794    va_start(ap, format);
3795
3796    rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3797                                                    format, ap);
3798
3799    va_end(ap);
3800    return rc;
3801}
3802
3803/**
3804 * xmlTextWriterWriteVFormatDTDInternalEntity:
3805 * @writer:  the xmlTextWriterPtr
3806 * @pe:  TRUE if this is a parameter entity, FALSE if not
3807 * @name:  the name of the DTD entity
3808 * @format:  format string (see printf)
3809 * @argptr:  pointer to the first member of the variable argument list.
3810 *
3811 * Write a formatted DTD internal entity.
3812 *
3813 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3814 */
3815int
3816xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3817                                           int pe,
3818                                           const xmlChar * name,
3819                                           const char *format,
3820                                           va_list argptr)
3821{
3822    int rc;
3823    xmlChar *buf;
3824
3825    if (writer == NULL)
3826        return -1;
3827
3828    buf = xmlTextWriterVSprintf(format, argptr);
3829    if (buf == NULL)
3830        return -1;
3831
3832    rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3833
3834    xmlFree(buf);
3835    return rc;
3836}
3837
3838/**
3839 * xmlTextWriterWriteDTDEntity:
3840 * @writer:  the xmlTextWriterPtr
3841 * @pe:  TRUE if this is a parameter entity, FALSE if not
3842 * @name:  the name of the DTD entity
3843 * @pubid:  the public identifier, which is an alternative to the system identifier
3844 * @sysid:  the system identifier, which is the URI of the DTD
3845 * @ndataid:  the xml notation name.
3846 * @content:  content of the entity
3847 *
3848 * Write a DTD entity.
3849 *
3850 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3851 */
3852int
3853xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3854                            int pe,
3855                            const xmlChar * name,
3856                            const xmlChar * pubid,
3857                            const xmlChar * sysid,
3858                            const xmlChar * ndataid,
3859                            const xmlChar * content)
3860{
3861    if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
3862        return -1;
3863    if ((pe != 0) && (ndataid != NULL))
3864        return -1;
3865
3866    if ((pubid == NULL) && (sysid == NULL))
3867        return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3868                                                   content);
3869
3870    return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3871                                               sysid, ndataid);
3872}
3873
3874/**
3875 * xmlTextWriterWriteDTDInternalEntity:
3876 * @writer:  the xmlTextWriterPtr
3877 * @pe:  TRUE if this is a parameter entity, FALSE if not
3878 * @name:  the name of the DTD entity
3879 * @content:  content of the entity
3880 *
3881 * Write a DTD internal entity.
3882 *
3883 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3884 */
3885int
3886xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3887                                    int pe,
3888                                    const xmlChar * name,
3889                                    const xmlChar * content)
3890{
3891    int count;
3892    int sum;
3893
3894    if ((name == NULL) || (*name == '\0') || (content == NULL))
3895        return -1;
3896
3897    sum = 0;
3898    count = xmlTextWriterStartDTDEntity(writer, pe, name);
3899    if (count == -1)
3900        return -1;
3901    sum += count;
3902
3903    count = xmlTextWriterWriteString(writer, content);
3904    if (count == -1)
3905        return -1;
3906    sum += count;
3907
3908    count = xmlTextWriterEndDTDEntity(writer);
3909    if (count == -1)
3910        return -1;
3911    sum += count;
3912
3913    return sum;
3914}
3915
3916/**
3917 * xmlTextWriterWriteDTDExternalEntity:
3918 * @writer:  the xmlTextWriterPtr
3919 * @pe:  TRUE if this is a parameter entity, FALSE if not
3920 * @name:  the name of the DTD entity
3921 * @pubid:  the public identifier, which is an alternative to the system identifier
3922 * @sysid:  the system identifier, which is the URI of the DTD
3923 * @ndataid:  the xml notation name.
3924 *
3925 * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
3926 *
3927 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3928 */
3929int
3930xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3931                                    int pe,
3932                                    const xmlChar * name,
3933                                    const xmlChar * pubid,
3934                                    const xmlChar * sysid,
3935                                    const xmlChar * ndataid)
3936{
3937    int count;
3938    int sum;
3939
3940    if (((pubid == NULL) && (sysid == NULL)))
3941        return -1;
3942    if ((pe != 0) && (ndataid != NULL))
3943        return -1;
3944
3945    sum = 0;
3946    count = xmlTextWriterStartDTDEntity(writer, pe, name);
3947    if (count == -1)
3948        return -1;
3949    sum += count;
3950
3951    count =
3952        xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3953                                                    ndataid);
3954    if (count < 0)
3955        return -1;
3956    sum += count;
3957
3958    count = xmlTextWriterEndDTDEntity(writer);
3959    if (count == -1)
3960        return -1;
3961    sum += count;
3962
3963    return sum;
3964}
3965
3966/**
3967 * xmlTextWriterWriteDTDExternalEntityContents:
3968 * @writer:  the xmlTextWriterPtr
3969 * @pubid:  the public identifier, which is an alternative to the system identifier
3970 * @sysid:  the system identifier, which is the URI of the DTD
3971 * @ndataid:  the xml notation name.
3972 *
3973 * Write the contents of a DTD external entity.
3974 *
3975 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3976 */
3977int
3978xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3979                                            const xmlChar * pubid,
3980                                            const xmlChar * sysid,
3981                                            const xmlChar * ndataid)
3982{
3983    int count;
3984    int sum;
3985    xmlLinkPtr lk;
3986    xmlTextWriterStackEntry *p;
3987
3988    if (writer == NULL) {
3989        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
3990                        "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3991        return -1;
3992    }
3993
3994    sum = 0;
3995    lk = xmlListFront(writer->nodes);
3996    if (lk == 0) {
3997        xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
3998                        "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
3999        return -1;
4000    }
4001
4002    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4003    if (p == 0)
4004        return -1;
4005
4006    switch (p->state) {
4007        case XML_TEXTWRITER_DTD_ENTY:
4008            break;
4009        case XML_TEXTWRITER_DTD_PENT:
4010            if (ndataid != NULL) {
4011                xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4012                                "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
4013                return -1;
4014            }
4015            break;
4016        default:
4017            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4018                            "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4019            return -1;
4020    }
4021
4022    if (pubid != 0) {
4023        if (sysid == 0) {
4024            xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4025                            "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
4026            return -1;
4027        }
4028
4029        count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4030        if (count < 0)
4031            return -1;
4032        sum += count;
4033
4034        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4035        if (count < 0)
4036            return -1;
4037        sum += count;
4038
4039        count =
4040            xmlOutputBufferWriteString(writer->out, (const char *) pubid);
4041        if (count < 0)
4042            return -1;
4043        sum += count;
4044
4045        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4046        if (count < 0)
4047            return -1;
4048        sum += count;
4049    }
4050
4051    if (sysid != 0) {
4052        if (pubid == 0) {
4053            count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4054            if (count < 0)
4055                return -1;
4056            sum += count;
4057        }
4058
4059        count = xmlOutputBufferWriteString(writer->out, " ");
4060        if (count < 0)
4061            return -1;
4062        sum += count;
4063
4064        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4065        if (count < 0)
4066            return -1;
4067        sum += count;
4068
4069        count =
4070            xmlOutputBufferWriteString(writer->out, (const char *) sysid);
4071        if (count < 0)
4072            return -1;
4073        sum += count;
4074
4075        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4076        if (count < 0)
4077            return -1;
4078        sum += count;
4079    }
4080
4081    if (ndataid != NULL) {
4082        count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4083        if (count < 0)
4084            return -1;
4085        sum += count;
4086
4087        count =
4088            xmlOutputBufferWriteString(writer->out,
4089                                       (const char *) ndataid);
4090        if (count < 0)
4091            return -1;
4092        sum += count;
4093    }
4094
4095    return sum;
4096}
4097
4098/**
4099 * xmlTextWriterWriteDTDNotation:
4100 * @writer:  the xmlTextWriterPtr
4101 * @name:  the name of the xml notation
4102 * @pubid:  the public identifier, which is an alternative to the system identifier
4103 * @sysid:  the system identifier, which is the URI of the DTD
4104 *
4105 * Write a DTD entity.
4106 *
4107 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4108 */
4109int
4110xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4111                              const xmlChar * name,
4112                              const xmlChar * pubid, const xmlChar * sysid)
4113{
4114    int count;
4115    int sum;
4116    xmlLinkPtr lk;
4117    xmlTextWriterStackEntry *p;
4118
4119    if (writer == NULL || name == NULL || *name == '\0')
4120        return -1;
4121
4122    sum = 0;
4123    lk = xmlListFront(writer->nodes);
4124    if (lk == 0) {
4125        return -1;
4126    }
4127
4128    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4129    if (p != 0) {
4130        switch (p->state) {
4131            case XML_TEXTWRITER_DTD:
4132                count = xmlOutputBufferWriteString(writer->out, " [");
4133                if (count < 0)
4134                    return -1;
4135                sum += count;
4136                if (writer->indent) {
4137                    count = xmlOutputBufferWriteString(writer->out, "\n");
4138                    if (count < 0)
4139                        return -1;
4140                    sum += count;
4141                }
4142                p->state = XML_TEXTWRITER_DTD_TEXT;
4143                /* fallthrough */
4144            case XML_TEXTWRITER_DTD_TEXT:
4145                break;
4146            default:
4147                return -1;
4148        }
4149    }
4150
4151    if (writer->indent) {
4152        count = xmlTextWriterWriteIndent(writer);
4153        if (count < 0)
4154            return -1;
4155        sum += count;
4156    }
4157
4158    count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4159    if (count < 0)
4160        return -1;
4161    sum += count;
4162    count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4163    if (count < 0)
4164        return -1;
4165    sum += count;
4166
4167    if (pubid != 0) {
4168        count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4169        if (count < 0)
4170            return -1;
4171        sum += count;
4172        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4173        if (count < 0)
4174            return -1;
4175        sum += count;
4176        count =
4177            xmlOutputBufferWriteString(writer->out, (const char *) pubid);
4178        if (count < 0)
4179            return -1;
4180        sum += count;
4181        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4182        if (count < 0)
4183            return -1;
4184        sum += count;
4185    }
4186
4187    if (sysid != 0) {
4188        if (pubid == 0) {
4189            count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4190            if (count < 0)
4191                return -1;
4192            sum += count;
4193        }
4194        count = xmlOutputBufferWriteString(writer->out, " ");
4195        if (count < 0)
4196            return -1;
4197        sum += count;
4198        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4199        if (count < 0)
4200            return -1;
4201        sum += count;
4202        count =
4203            xmlOutputBufferWriteString(writer->out, (const char *) sysid);
4204        if (count < 0)
4205            return -1;
4206        sum += count;
4207        count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4208        if (count < 0)
4209            return -1;
4210        sum += count;
4211    }
4212
4213    count = xmlOutputBufferWriteString(writer->out, ">");
4214    if (count < 0)
4215        return -1;
4216    sum += count;
4217
4218    return sum;
4219}
4220
4221/**
4222 * xmlTextWriterFlush:
4223 * @writer:  the xmlTextWriterPtr
4224 *
4225 * Flush the output buffer.
4226 *
4227 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4228 */
4229int
4230xmlTextWriterFlush(xmlTextWriterPtr writer)
4231{
4232    int count;
4233
4234    if (writer == NULL)
4235        return -1;
4236
4237    if (writer->out == NULL)
4238        count = 0;
4239    else
4240        count = xmlOutputBufferFlush(writer->out);
4241
4242    return count;
4243}
4244
4245/**
4246 * misc
4247 */
4248
4249/**
4250 * xmlFreeTextWriterStackEntry:
4251 * @lk:  the xmlLinkPtr
4252 *
4253 * Free callback for the xmlList.
4254 */
4255static void
4256xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4257{
4258    xmlTextWriterStackEntry *p;
4259
4260    p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4261    if (p == 0)
4262        return;
4263
4264    if (p->name != 0)
4265        xmlFree(p->name);
4266    xmlFree(p);
4267}
4268
4269/**
4270 * xmlCmpTextWriterStackEntry:
4271 * @data0:  the first data
4272 * @data1:  the second data
4273 *
4274 * Compare callback for the xmlList.
4275 *
4276 * Returns -1, 0, 1
4277 */
4278static int
4279xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4280{
4281    xmlTextWriterStackEntry *p0;
4282    xmlTextWriterStackEntry *p1;
4283
4284    if (data0 == data1)
4285        return 0;
4286
4287    if (data0 == 0)
4288        return -1;
4289
4290    if (data1 == 0)
4291        return 1;
4292
4293    p0 = (xmlTextWriterStackEntry *) data0;
4294    p1 = (xmlTextWriterStackEntry *) data1;
4295
4296    return xmlStrcmp(p0->name, p1->name);
4297}
4298
4299/**
4300 * misc
4301 */
4302
4303/**
4304 * xmlTextWriterOutputNSDecl:
4305 * @writer:  the xmlTextWriterPtr
4306 *
4307 * Output the current namespace declarations.
4308 */
4309static int
4310xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4311{
4312    xmlLinkPtr lk;
4313    xmlTextWriterNsStackEntry *np;
4314    int count;
4315    int sum;
4316
4317    sum = 0;
4318    while (!xmlListEmpty(writer->nsstack)) {
4319        xmlChar *namespaceURI = NULL;
4320        xmlChar *prefix = NULL;
4321
4322        lk = xmlListFront(writer->nsstack);
4323        np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4324
4325        if (np != 0) {
4326            namespaceURI = xmlStrdup(np->uri);
4327            prefix = xmlStrdup(np->prefix);
4328        }
4329
4330        xmlListPopFront(writer->nsstack);
4331
4332        if (np != 0) {
4333            count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4334            xmlFree(namespaceURI);
4335            xmlFree(prefix);
4336
4337            if (count < 0) {
4338                xmlListDelete(writer->nsstack);
4339                writer->nsstack = NULL;
4340                return -1;
4341            }
4342            sum += count;
4343        }
4344    }
4345    return sum;
4346}
4347
4348/**
4349 * xmlFreeTextWriterNsStackEntry:
4350 * @lk:  the xmlLinkPtr
4351 *
4352 * Free callback for the xmlList.
4353 */
4354static void
4355xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4356{
4357    xmlTextWriterNsStackEntry *p;
4358
4359    p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4360    if (p == 0)
4361        return;
4362
4363    if (p->prefix != 0)
4364        xmlFree(p->prefix);
4365    if (p->uri != 0)
4366        xmlFree(p->uri);
4367
4368    xmlFree(p);
4369}
4370
4371/**
4372 * xmlCmpTextWriterNsStackEntry:
4373 * @data0:  the first data
4374 * @data1:  the second data
4375 *
4376 * Compare callback for the xmlList.
4377 *
4378 * Returns -1, 0, 1
4379 */
4380static int
4381xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4382{
4383    xmlTextWriterNsStackEntry *p0;
4384    xmlTextWriterNsStackEntry *p1;
4385    int rc;
4386
4387    if (data0 == data1)
4388        return 0;
4389
4390    if (data0 == 0)
4391        return -1;
4392
4393    if (data1 == 0)
4394        return 1;
4395
4396    p0 = (xmlTextWriterNsStackEntry *) data0;
4397    p1 = (xmlTextWriterNsStackEntry *) data1;
4398
4399    rc = xmlStrcmp(p0->prefix, p1->prefix);
4400
4401    if ((rc != 0) || (p0->elem != p1->elem))
4402        rc = -1;
4403
4404    return rc;
4405}
4406
4407/**
4408 * xmlTextWriterWriteDocCallback:
4409 * @context:  the xmlBufferPtr
4410 * @str:  the data to write
4411 * @len:  the length of the data
4412 *
4413 * Write callback for the xmlOutputBuffer with target xmlBuffer
4414 *
4415 * Returns -1, 0, 1
4416 */
4417static int
4418xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
4419{
4420    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4421    int rc;
4422
4423    if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
4424        xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
4425                        "xmlTextWriterWriteDocCallback : XML error %d !\n",
4426                        rc);
4427        return -1;
4428    }
4429
4430    return len;
4431}
4432
4433/**
4434 * xmlTextWriterCloseDocCallback:
4435 * @context:  the xmlBufferPtr
4436 *
4437 * Close callback for the xmlOutputBuffer with target xmlBuffer
4438 *
4439 * Returns -1, 0, 1
4440 */
4441static int
4442xmlTextWriterCloseDocCallback(void *context)
4443{
4444    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4445    int rc;
4446
4447    if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
4448        xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
4449                        "xmlTextWriterWriteDocCallback : XML error %d !\n",
4450                        rc);
4451        return -1;
4452    }
4453
4454    return 0;
4455}
4456
4457/**
4458 * xmlTextWriterVSprintf:
4459 * @format:  see printf
4460 * @argptr:  pointer to the first member of the variable argument list.
4461 *
4462 * Utility function for formatted output
4463 *
4464 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4465 */
4466static xmlChar *
4467xmlTextWriterVSprintf(const char *format, va_list argptr)
4468{
4469    int size;
4470    int count;
4471    xmlChar *buf;
4472    va_list locarg;
4473
4474    size = BUFSIZ;
4475    buf = (xmlChar *) xmlMalloc(size);
4476    if (buf == NULL) {
4477        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
4478                        "xmlTextWriterVSprintf : out of memory!\n");
4479        return NULL;
4480    }
4481
4482    VA_COPY(locarg, argptr);
4483    while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
4484           || (count == size - 1) || (count == size) || (count > size)) {
4485	va_end(locarg);
4486        xmlFree(buf);
4487        size += BUFSIZ;
4488        buf = (xmlChar *) xmlMalloc(size);
4489        if (buf == NULL) {
4490            xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
4491                            "xmlTextWriterVSprintf : out of memory!\n");
4492            return NULL;
4493        }
4494	VA_COPY(locarg, argptr);
4495    }
4496    va_end(locarg);
4497
4498    return buf;
4499}
4500
4501/**
4502 * xmlTextWriterStartDocumentCallback:
4503 * @ctx: the user data (XML parser context)
4504 *
4505 * called at the start of document processing.
4506 */
4507static void
4508xmlTextWriterStartDocumentCallback(void *ctx)
4509{
4510    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4511    xmlDocPtr doc;
4512
4513    if (ctxt->html) {
4514#ifdef LIBXML_HTML_ENABLED
4515        if (ctxt->myDoc == NULL)
4516            ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4517        if (ctxt->myDoc == NULL) {
4518            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4519                ctxt->sax->error(ctxt->userData,
4520                                 "SAX.startDocument(): out of memory\n");
4521            ctxt->errNo = XML_ERR_NO_MEMORY;
4522            ctxt->instate = XML_PARSER_EOF;
4523            ctxt->disableSAX = 1;
4524            return;
4525        }
4526#else
4527        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
4528                        "libxml2 built without HTML support\n");
4529        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4530        ctxt->instate = XML_PARSER_EOF;
4531        ctxt->disableSAX = 1;
4532        return;
4533#endif
4534    } else {
4535        doc = ctxt->myDoc;
4536        if (doc == NULL)
4537            doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4538        if (doc != NULL) {
4539            if (doc->children == NULL) {
4540                if (ctxt->encoding != NULL)
4541                    doc->encoding = xmlStrdup(ctxt->encoding);
4542                else
4543                    doc->encoding = NULL;
4544                doc->standalone = ctxt->standalone;
4545            }
4546        } else {
4547            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4548                ctxt->sax->error(ctxt->userData,
4549                                 "SAX.startDocument(): out of memory\n");
4550            ctxt->errNo = XML_ERR_NO_MEMORY;
4551            ctxt->instate = XML_PARSER_EOF;
4552            ctxt->disableSAX = 1;
4553            return;
4554        }
4555    }
4556    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4557        (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4558        ctxt->myDoc->URL =
4559            xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4560        if (ctxt->myDoc->URL == NULL)
4561            ctxt->myDoc->URL =
4562                xmlStrdup((const xmlChar *) ctxt->input->filename);
4563    }
4564}
4565
4566/**
4567 * xmlTextWriterSetIndent:
4568 * @writer:  the xmlTextWriterPtr
4569 * @indent:  do indentation?
4570 *
4571 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4572 *
4573 * Returns -1 on error or 0 otherwise.
4574 */
4575int
4576xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
4577{
4578    if ((writer == NULL) || (indent < 0))
4579        return -1;
4580
4581    writer->indent = indent;
4582    writer->doindent = 1;
4583
4584    return 0;
4585}
4586
4587/**
4588 * xmlTextWriterSetIndentString:
4589 * @writer:  the xmlTextWriterPtr
4590 * @str:  the xmlChar string
4591 *
4592 * Set string indentation.
4593 *
4594 * Returns -1 on error or 0 otherwise.
4595 */
4596int
4597xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
4598{
4599    if ((writer == NULL) || (!str))
4600        return -1;
4601
4602    if (writer->ichar != NULL)
4603        xmlFree(writer->ichar);
4604    writer->ichar = xmlStrdup(str);
4605
4606    if (!writer->ichar)
4607        return -1;
4608    else
4609        return 0;
4610}
4611
4612/**
4613 * xmlTextWriterSetQuoteChar:
4614 * @writer:  the xmlTextWriterPtr
4615 * @quotechar:  the quote character
4616 *
4617 * Set the character used for quoting attributes.
4618 *
4619 * Returns -1 on error or 0 otherwise.
4620 */
4621int
4622xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar)
4623{
4624    if ((writer == NULL) || ((quotechar != '\'') && (quotechar != '"')))
4625        return -1;
4626
4627    writer->qchar = quotechar;
4628
4629    return 0;
4630}
4631
4632/**
4633 * xmlTextWriterWriteIndent:
4634 * @writer:  the xmlTextWriterPtr
4635 *
4636 * Write indent string.
4637 *
4638 * Returns -1 on error or the number of strings written.
4639 */
4640static int
4641xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
4642{
4643    int lksize;
4644    int i;
4645    int ret;
4646
4647    lksize = xmlListSize(writer->nodes);
4648    if (lksize < 1)
4649        return (-1);            /* list is empty */
4650    for (i = 0; i < (lksize - 1); i++) {
4651        ret = xmlOutputBufferWriteString(writer->out,
4652                                         (const char *) writer->ichar);
4653        if (ret == -1)
4654            return (-1);
4655    }
4656
4657    return (lksize - 1);
4658}
4659
4660/**
4661 * xmlTextWriterHandleStateDependencies:
4662 * @writer:  the xmlTextWriterPtr
4663 * @p:  the xmlTextWriterStackEntry
4664 *
4665 * Write state dependent strings.
4666 *
4667 * Returns -1 on error or the number of characters written.
4668 */
4669static int
4670xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4671                                     xmlTextWriterStackEntry * p)
4672{
4673    int count;
4674    int sum;
4675    char extra[3];
4676
4677    if (writer == NULL)
4678        return -1;
4679
4680    if (p == NULL)
4681        return 0;
4682
4683    sum = 0;
4684    extra[0] = extra[1] = extra[2] = '\0';
4685    if (p != 0) {
4686        sum = 0;
4687        switch (p->state) {
4688            case XML_TEXTWRITER_NAME:
4689                /* Output namespace declarations */
4690                count = xmlTextWriterOutputNSDecl(writer);
4691                if (count < 0)
4692                    return -1;
4693                sum += count;
4694                extra[0] = '>';
4695                p->state = XML_TEXTWRITER_TEXT;
4696                break;
4697            case XML_TEXTWRITER_PI:
4698                extra[0] = ' ';
4699                p->state = XML_TEXTWRITER_PI_TEXT;
4700                break;
4701            case XML_TEXTWRITER_DTD:
4702                extra[0] = ' ';
4703                extra[1] = '[';
4704                p->state = XML_TEXTWRITER_DTD_TEXT;
4705                break;
4706            case XML_TEXTWRITER_DTD_ELEM:
4707                extra[0] = ' ';
4708                p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4709                break;
4710            case XML_TEXTWRITER_DTD_ATTL:
4711                extra[0] = ' ';
4712                p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4713                break;
4714            case XML_TEXTWRITER_DTD_ENTY:
4715            case XML_TEXTWRITER_DTD_PENT:
4716                extra[0] = ' ';
4717                extra[1] = writer->qchar;
4718                p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4719                break;
4720            default:
4721                break;
4722        }
4723    }
4724
4725    if (*extra != '\0') {
4726        count = xmlOutputBufferWriteString(writer->out, extra);
4727        if (count < 0)
4728            return -1;
4729        sum += count;
4730    }
4731
4732    return sum;
4733}
4734
4735#define bottom_xmlwriter
4736#include "elfgcchack.h"
4737#endif
4738