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