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