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