blob: 43e5f63dda3a3c53bd5954bd2dba16227e20597f [file] [log] [blame]
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001
Daniel Veillard1d211e22003-10-20 22:32:39 +00002/*
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
Igor Zlatkovicb23de5a2003-11-27 18:36:46 +000011#define IN_LIBXML
Daniel Veillard1d211e22003-10-20 22:32:39 +000012#include <string.h>
Daniel Veillard1d211e22003-10-20 22:32:39 +000013
14#include "libxml.h"
15#include <libxml/xmlmemory.h>
16#include <libxml/parser.h>
Daniel Veillard5841f0e2003-11-20 11:59:09 +000017#include <libxml/uri.h>
18#include <libxml/HTMLtree.h>
Daniel Veillard1d211e22003-10-20 22:32:39 +000019
20#ifdef LIBXML_WRITER_ENABLED
21
22#include <libxml/xmlwriter.h>
23
24#define B64LINELEN 72
25#define B64CRLF "\r\n"
26
27/*
28 * Types are kept private
29 */
30typedef enum {
31 XML_TEXTWRITER_NONE = 0,
32 XML_TEXTWRITER_NAME,
33 XML_TEXTWRITER_ATTRIBUTE,
34 XML_TEXTWRITER_TEXT,
35 XML_TEXTWRITER_PI,
36 XML_TEXTWRITER_PI_TEXT,
37 XML_TEXTWRITER_CDATA,
38 XML_TEXTWRITER_DTD,
39 XML_TEXTWRITER_DTD_TEXT,
40 XML_TEXTWRITER_DTD_ELEM,
41 XML_TEXTWRITER_DTD_ATTL,
Daniel Veillardab69f362004-02-17 11:40:32 +000042 XML_TEXTWRITER_DTD_ENTY,
43 XML_TEXTWRITER_COMMENT
Daniel Veillard1d211e22003-10-20 22:32:39 +000044} xmlTextWriterState;
45
46typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
47
48struct _xmlTextWriterStackEntry {
49 xmlChar *name;
50 xmlTextWriterState state;
51};
52
53typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
54struct _xmlTextWriterNsStackEntry {
55 xmlChar *prefix;
56 xmlChar *uri;
57 xmlLinkPtr elem;
58};
59
60struct _xmlTextWriter {
Daniel Veillardab69f362004-02-17 11:40:32 +000061 xmlOutputBufferPtr out; /* output buffer */
62 xmlListPtr nodes; /* element name stack */
63 xmlListPtr nsstack; /* name spaces stack */
Daniel Veillard1d211e22003-10-20 22:32:39 +000064 int level;
Daniel Veillardab69f362004-02-17 11:40:32 +000065 int indent; /* enable indent */
66 int doindent; /* internal indent flag */
67 xmlChar *ichar; /* indent character */
68 char qchar; /* character used for quoting attribute values */
Daniel Veillard20c5e782004-01-21 09:57:31 +000069 xmlParserCtxtPtr ctxt;
Daniel Veillard1d211e22003-10-20 22:32:39 +000070};
71
72static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
73static int xmlCmpTextWriterStackEntry(const void *data0,
74 const void *data1);
75static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
76static int xmlCmpTextWriterNsStackEntry(const void *data0,
77 const void *data1);
78static int xmlTextWriterWriteMemCallback(void *context,
79 const xmlChar * str, int len);
80static int xmlTextWriterCloseMemCallback(void *context);
Daniel Veillard5841f0e2003-11-20 11:59:09 +000081static int xmlTextWriterWriteDocCallback(void *context,
82 const xmlChar * str, int len);
83static int xmlTextWriterCloseDocCallback(void *context);
84
Daniel Veillard1d211e22003-10-20 22:32:39 +000085static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);
86static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
87 const unsigned char *data);
Daniel Veillard5841f0e2003-11-20 11:59:09 +000088static void xmlTextWriterStartDocumentCallback(void *ctx);
Daniel Veillardab69f362004-02-17 11:40:32 +000089static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +000090
91/**
92 * xmlNewTextWriter:
93 * @out: an xmlOutputBufferPtr
94 *
95 * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
96 *
97 * Returns the new xmlTextWriterPtr or NULL in case of error
98 */
99xmlTextWriterPtr
100xmlNewTextWriter(xmlOutputBufferPtr out)
101{
102 xmlTextWriterPtr ret;
103
104 ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
105 if (ret == NULL) {
106 xmlGenericError(xmlGenericErrorContext,
107 "xmlNewTextWriter : out of memory!\n");
108 return NULL;
109 }
110 memset(ret, 0, (size_t) sizeof(xmlTextWriter));
111
112 ret->nodes = xmlListCreate((xmlListDeallocator)
113 xmlFreeTextWriterStackEntry,
114 (xmlListDataCompare)
115 xmlCmpTextWriterStackEntry);
116 if (ret->nodes == NULL) {
117 xmlGenericError(xmlGenericErrorContext,
118 "xmlNewTextWriter : out of memory!\n");
119 xmlFree(ret);
120 return NULL;
121 }
122
123 ret->nsstack = xmlListCreate((xmlListDeallocator)
124 xmlFreeTextWriterNsStackEntry,
125 (xmlListDataCompare)
126 xmlCmpTextWriterNsStackEntry);
127 if (ret->nsstack == NULL) {
128 xmlGenericError(xmlGenericErrorContext,
129 "xmlNewTextWriter : out of memory!\n");
130 xmlFree(ret->nodes);
131 xmlFree(ret);
132 return NULL;
133 }
134
135 ret->out = out;
Daniel Veillardab69f362004-02-17 11:40:32 +0000136 ret->ichar = xmlStrdup(BAD_CAST " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000137 ret->qchar = '"';
138
Daniel Veillardab69f362004-02-17 11:40:32 +0000139 if (!ret->ichar)
140 return NULL;
141
Daniel Veillard1d211e22003-10-20 22:32:39 +0000142 return ret;
143}
144
145/**
146 * xmlNewTextWriterFilename:
147 * @uri: the URI of the resource for the output
148 * @compression: compress the output?
149 *
150 * Create a new xmlNewTextWriter structure with @uri as output
151 *
152 * Returns the new xmlTextWriterPtr or NULL in case of error
153 */
154xmlTextWriterPtr
155xmlNewTextWriterFilename(const char *uri, int compression)
156{
157 xmlTextWriterPtr ret;
158 xmlOutputBufferPtr out;
159
160 out = xmlOutputBufferCreateFilename(uri, NULL, compression);
161 if (out == NULL) {
162 xmlGenericError(xmlGenericErrorContext,
163 "xmlNewTextWriterFilename : out of memory!\n");
164 return NULL;
165 }
166
167 ret = xmlNewTextWriter(out);
168 if (ret == NULL) {
169 xmlGenericError(xmlGenericErrorContext,
170 "xmlNewTextWriterFilename : out of memory!\n");
171 xmlOutputBufferClose(out);
172 return NULL;
173 }
174
Daniel Veillard2cca4462004-01-02 20:04:23 +0000175 ret->indent = 0;
176 ret->doindent = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000177 return ret;
178}
179
180/**
181 * xmlNewTextWriterMemory:
182 * @buf: xmlBufferPtr
183 * @compression: compress the output?
184 *
185 * Create a new xmlNewTextWriter structure with @buf as output
186 * TODO: handle compression
187 *
188 * Returns the new xmlTextWriterPtr or NULL in case of error
189 */
190xmlTextWriterPtr
191xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
192{
193 xmlTextWriterPtr ret;
194 xmlOutputBufferPtr out;
195
196/*::todo handle compression */
197 out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
198 xmlTextWriterWriteMemCallback,
199 (xmlOutputCloseCallback)
200 xmlTextWriterCloseMemCallback,
201 (void *) buf, NULL);
202 if (out == NULL) {
203 xmlGenericError(xmlGenericErrorContext,
204 "xmlNewTextWriterMemory : out of memory!\n");
205 return NULL;
206 }
207
208 ret = xmlNewTextWriter(out);
209 if (ret == NULL) {
210 xmlGenericError(xmlGenericErrorContext,
211 "xmlNewTextWriterMemory : out of memory!\n");
212 xmlOutputBufferClose(out);
213 return NULL;
214 }
215
216 return ret;
217}
218
219/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000220 * xmlNewTextWriterPushParser:
221 * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
222 * @compression: compress the output?
223 *
224 * Create a new xmlNewTextWriter structure with @ctxt as output
225 * TODO: handle compression
226 *
227 * Returns the new xmlTextWriterPtr or NULL in case of error
228 */
229xmlTextWriterPtr
Daniel Veillard1d913862003-11-21 00:28:39 +0000230xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
231 int compression ATTRIBUTE_UNUSED)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000232{
233 xmlTextWriterPtr ret;
234 xmlOutputBufferPtr out;
235
236 out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
237 xmlTextWriterWriteDocCallback,
238 (xmlOutputCloseCallback)
239 xmlTextWriterCloseDocCallback,
240 (void *) ctxt, NULL);
241 if (out == NULL) {
242 xmlGenericError(xmlGenericErrorContext,
243 "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
244 return NULL;
245 }
246
247 ret = xmlNewTextWriter(out);
248 if (ret == NULL) {
249 xmlGenericError(xmlGenericErrorContext,
250 "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
251 xmlOutputBufferClose(out);
252 return NULL;
253 }
254
Daniel Veillard20c5e782004-01-21 09:57:31 +0000255 ret->ctxt = ctxt;
256
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000257 return ret;
258}
259
260/**
261 * xmlNewTextWriterDoc:
262 * @doc: address of a xmlDocPtr to hold the new XML document tree
263 * @compression: compress the output?
264 *
265 * Create a new xmlNewTextWriter structure with @*doc as output
266 *
267 * Returns the new xmlTextWriterPtr or NULL in case of error
268 */
269xmlTextWriterPtr
270xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
271{
272 xmlTextWriterPtr ret;
273 xmlSAXHandler saxHandler;
274 xmlParserCtxtPtr ctxt;
275
276 memset(&saxHandler, '\0', sizeof(saxHandler));
277 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
278 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
279 saxHandler.startElement = xmlSAX2StartElement;
280 saxHandler.endElement = xmlSAX2EndElement;
281
282 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
283 if (ctxt == NULL) {
284 xmlGenericError(xmlGenericErrorContext,
285 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
286 return NULL;
287 }
288
Daniel Veillard1d913862003-11-21 00:28:39 +0000289 ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000290 if (ctxt->myDoc == NULL) {
291 xmlFreeParserCtxt(ctxt);
292 xmlGenericError(xmlGenericErrorContext,
293 "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
294 return NULL;
295 }
296
297 ret = xmlNewTextWriterPushParser(ctxt, compression);
298 if (ret == NULL) {
299 xmlGenericError(xmlGenericErrorContext,
300 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
301 return NULL;
302 }
303
304 *doc = ctxt->myDoc;
305 xmlSetDocCompressMode(*doc, compression);
306
307 return ret;
308}
309
310/**
311 * xmlNewTextWriterTree:
312 * @doc: xmlDocPtr
313 * @node: xmlNodePtr or NULL for doc->children
314 * @compression: compress the output?
315 *
316 * Create a new xmlNewTextWriter structure with @doc as output
317 * starting at @node
318 *
319 * Returns the new xmlTextWriterPtr or NULL in case of error
320 */
321xmlTextWriterPtr
322xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
323{
324 xmlTextWriterPtr ret;
325 xmlSAXHandler saxHandler;
326 xmlParserCtxtPtr ctxt;
327
328 if (doc == NULL) {
329 return NULL;
330 }
331
332 memset(&saxHandler, '\0', sizeof(saxHandler));
333 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
334 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
335 saxHandler.startElement = xmlSAX2StartElement;
336 saxHandler.endElement = xmlSAX2EndElement;
337
338 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
339 if (ctxt == NULL) {
340 xmlGenericError(xmlGenericErrorContext,
341 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
342 return NULL;
343 }
344
345 ctxt->myDoc = doc;
346 ctxt->node = node;
347
348 ret = xmlNewTextWriterPushParser(ctxt, compression);
349 if (ret == NULL) {
350 xmlGenericError(xmlGenericErrorContext,
351 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
352 return NULL;
353 }
354
355 xmlSetDocCompressMode(doc, compression);
356
357 return ret;
358}
359
360/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000361 * xmlFreeTextWriter:
362 * @writer: the xmlTextWriterPtr
363 *
364 * Deallocate all the resources associated to the writer
365 */
366void
367xmlFreeTextWriter(xmlTextWriterPtr writer)
368{
369 if (writer == NULL)
370 return;
371
372 if (writer->out != NULL)
373 xmlOutputBufferClose(writer->out);
374
375 if (writer->nodes != NULL)
376 xmlListDelete(writer->nodes);
377
378 if (writer->nsstack != NULL)
379 xmlListDelete(writer->nsstack);
380
Daniel Veillard20c5e782004-01-21 09:57:31 +0000381 if (writer->ctxt != NULL)
382 xmlFreeParserCtxt(writer->ctxt);
383
Daniel Veillard4773df22004-01-23 13:15:13 +0000384 if (writer->ichar != NULL)
385 xmlFree(writer->ichar);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000386 xmlFree(writer);
387}
388
389/**
390 * xmlTextWriterStartDocument:
391 * @writer: the xmlTextWriterPtr
392 * @version: the xml version ("1.0") or NULL for default ("1.0")
393 * @encoding: the encoding or NULL for default
394 * @standalone: "yes" or "no" or NULL for default
395 *
396 * Start a new xml document
397 *
398 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
399 */
400int
401xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
402 const char *encoding, const char *standalone)
403{
404 int count;
405 int sum;
406 xmlLinkPtr lk;
407 xmlCharEncodingHandlerPtr encoder;
408
409 if ((writer == NULL) || (writer->out == NULL))
410 return -1;
411
412 lk = xmlListFront(writer->nodes);
413 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
414 xmlGenericError(xmlGenericErrorContext,
415 "xmlTextWriterStartDocument : only one prolog allowed in an XML document!\n");
416 return -1;
417 }
418
419 encoder = NULL;
420 if (encoding != NULL) {
421 encoder = xmlFindCharEncodingHandler(encoding);
422 if (encoder == NULL) {
423 xmlGenericError(xmlGenericErrorContext,
424 "xmlTextWriterStartDocument : out of memory!\n");
425 return -1;
426 }
427 }
428
429 writer->out->encoder = encoder;
430 if (encoder != NULL) {
431 writer->out->conv = xmlBufferCreateSize(4000);
432 xmlCharEncOutFunc(encoder, writer->out->conv, NULL);
433 } else
434 writer->out->conv = NULL;
435
436 sum = 0;
437 count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
438 if (count < 0)
439 return -1;
440 sum += count;
441 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
442 if (count < 0)
443 return -1;
444 sum += count;
445 if (version != 0)
446 count = xmlOutputBufferWriteString(writer->out, version);
447 else
448 count = xmlOutputBufferWriteString(writer->out, "1.0");
449 if (count < 0)
450 return -1;
451 sum += count;
452 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
453 if (count < 0)
454 return -1;
455 sum += count;
456 if (writer->out->encoder != 0) {
457 count = xmlOutputBufferWriteString(writer->out, " encoding=");
458 if (count < 0)
459 return -1;
460 sum += count;
461 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
462 if (count < 0)
463 return -1;
464 sum += count;
465 count =
466 xmlOutputBufferWriteString(writer->out,
467 writer->out->encoder->name);
468 if (count < 0)
469 return -1;
470 sum += count;
471 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
472 if (count < 0)
473 return -1;
474 sum += count;
475 }
476
477 if (standalone != 0) {
478 count = xmlOutputBufferWriteString(writer->out, " standalone=");
479 if (count < 0)
480 return -1;
481 sum += count;
482 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
483 if (count < 0)
484 return -1;
485 sum += count;
486 count = xmlOutputBufferWriteString(writer->out, standalone);
487 if (count < 0)
488 return -1;
489 sum += count;
490 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
491 if (count < 0)
492 return -1;
493 sum += count;
494 }
495
496 count = xmlOutputBufferWriteString(writer->out, "?>\n");
497 if (count < 0)
498 return -1;
499 sum += count;
500
501 return sum;
502}
503
504/**
505 * xmlTextWriterEndDocument:
506 * @writer: the xmlTextWriterPtr
507 *
508 * End an xml document. All open elements are closed
509 *
510 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
511 */
512int
513xmlTextWriterEndDocument(xmlTextWriterPtr writer)
514{
515 int count;
516 int sum;
517 xmlLinkPtr lk;
518 xmlTextWriterStackEntry *p;
519
520 if (writer == NULL)
521 return -1;
522
523 sum = 0;
524 while ((lk = xmlListFront(writer->nodes)) != NULL) {
525 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
526 if (p == 0)
527 break;
528 switch (p->state) {
529 case XML_TEXTWRITER_NAME:
530 case XML_TEXTWRITER_ATTRIBUTE:
531 case XML_TEXTWRITER_TEXT:
532 count = xmlTextWriterEndElement(writer);
533 if (count < 0)
534 return -1;
535 sum += count;
536 break;
537 case XML_TEXTWRITER_PI:
538 case XML_TEXTWRITER_PI_TEXT:
539 count = xmlTextWriterEndPI(writer);
540 if (count < 0)
541 return -1;
542 sum += count;
543 break;
544 case XML_TEXTWRITER_CDATA:
545 count = xmlTextWriterEndCDATA(writer);
546 if (count < 0)
547 return -1;
548 sum += count;
549 break;
550 case XML_TEXTWRITER_DTD:
551 count = xmlTextWriterEndDTD(writer);
552 if (count < 0)
553 return -1;
554 sum += count;
555 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000556 case XML_TEXTWRITER_COMMENT:
557 count = xmlTextWriterEndComment(writer);
558 if (count < 0)
559 return -1;
560 sum += count;
561 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000562 default:
Daniel Veillardab69f362004-02-17 11:40:32 +0000563 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000564 }
565 }
566
Daniel Veillard2cca4462004-01-02 20:04:23 +0000567 if (!writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000568 count = xmlOutputBufferWriteString(writer->out, "\n");
569 if (count < 0)
570 return -1;
571 sum += count;
572 }
573 return sum;
574}
575
576
577
578
579
580
581/**
582 * xmlTextWriterStartComment:
583 * @writer: the xmlTextWriterPtr
584 *
585 * Start an xml comment.
586 *
587 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
588 */
589int
590xmlTextWriterStartComment(xmlTextWriterPtr writer)
591{
592 int count;
593 int sum;
594 xmlLinkPtr lk;
595 xmlTextWriterStackEntry *p;
596
597 if (writer == NULL)
598 return -1;
599
600 sum = 0;
601 lk = xmlListFront(writer->nodes);
602 if (lk != 0) {
603 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
604 if (p != 0) {
605 switch (p->state) {
606 case XML_TEXTWRITER_TEXT:
607 case XML_TEXTWRITER_NONE:
608 break;
609 case XML_TEXTWRITER_NAME:
610 count = xmlOutputBufferWriteString(writer->out, ">");
611 if (count < 0)
612 return -1;
613 sum += count;
614 p->state = XML_TEXTWRITER_TEXT;
615 break;
616 default:
617 return -1;
618 }
619 }
620 }
621
622 p = (xmlTextWriterStackEntry *)
623 xmlMalloc(sizeof(xmlTextWriterStackEntry));
624 if (p == 0) {
625 xmlGenericError(xmlGenericErrorContext,
626 "xmlTextWriterStartElement : out of memory!\n");
627 return -1;
628 }
629
630 p->name = 0;
631 p->state = XML_TEXTWRITER_COMMENT;
632
633 xmlListPushFront(writer->nodes, p);
634
635 if (writer->indent) {
636 count = xmlOutputBufferWriteString(writer->out, "\n");
637 if (count < 0)
638 return -1;
639 sum += count;
640 count = xmlTextWriterWriteIndent(writer);
641 if (count < 0)
642 return -1;
643 sum += count;
644 }
645
646 count = xmlOutputBufferWriteString(writer->out, "<!--");
647 if (count < 0)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000648 return -1;
649 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000650
651 return sum;
652}
653
654/**
655 * xmlTextWriterEndComment:
656 * @writer: the xmlTextWriterPtr
657 *
658 * End the current xml coment.
659 *
660 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
661 */
662int
663xmlTextWriterEndComment(xmlTextWriterPtr writer)
664{
665 int count;
666 int sum;
667 xmlLinkPtr lk;
668 xmlTextWriterStackEntry *p;
669
670 if (writer == NULL)
671 return -1;
672
673 lk = xmlListFront(writer->nodes);
674 if (lk == 0)
675 return -1;
676
677 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
678 if (p == 0)
679 return -1;
680
681 sum = 0;
682 switch (p->state) {
683 case XML_TEXTWRITER_COMMENT:
684 count = xmlOutputBufferWriteString(writer->out, "-->");
685 if (count < 0)
686 return -1;
687 sum += count;
688 break;
689 default:
690 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +0000691 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000692
693 if (writer->indent) {
694 count = xmlOutputBufferWriteString(writer->out, "\n");
695 if (count < 0)
696 return -1;
697 sum += count;
698 }
699
700 xmlListPopFront(writer->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000701 return sum;
702}
703
704/**
705 * xmlTextWriterWriteFormatComment:
706 * @writer: the xmlTextWriterPtr
707 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +0000708 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +0000709 *
710 * Write an xml comment.
711 *
712 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
713 */
714int
715xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
716 const char *format, ...)
717{
718 int rc;
719 va_list ap;
720
721 va_start(ap, format);
722
723 rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
724
725 va_end(ap);
726 return rc;
727}
728
729/**
730 * xmlTextWriterWriteVFormatComment:
731 * @writer: the xmlTextWriterPtr
732 * @format: format string (see printf)
733 * @argptr: pointer to the first member of the variable argument list.
734 *
735 * Write an xml comment.
736 *
737 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
738 */
739int
740xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
741 const char *format, va_list argptr)
742{
743 int rc;
744 xmlChar *buf;
745
746 if (writer == NULL)
747 return -1;
748
749 buf = xmlTextWriterVSprintf(format, argptr);
750 if (buf == 0)
751 return 0;
752
753 rc = xmlTextWriterWriteComment(writer, buf);
754
755 xmlFree(buf);
756 return rc;
757}
758
759/**
760 * xmlTextWriterWriteComment:
761 * @writer: the xmlTextWriterPtr
762 * @content: comment string
763 *
764 * Write an xml comment.
765 *
766 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
767 */
768int
769xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
770{
771 int count;
772 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000773
774 sum = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000775 count = xmlTextWriterStartComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000776 if (count < 0)
777 return -1;
778 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000779 count = xmlTextWriterWriteString(writer, content);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000780 if (count < 0)
781 return -1;
782 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000783 count = xmlTextWriterEndComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000784 if (count < 0)
785 return -1;
786 sum += count;
787
788 return sum;
789}
790
791/**
792 * xmlTextWriterStartElement:
793 * @writer: the xmlTextWriterPtr
794 * @name: element name
795 *
796 * Start an xml element.
797 *
798 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
799 */
800int
801xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
802{
803 int count;
804 int sum;
805 xmlLinkPtr lk;
806 xmlTextWriterStackEntry *p;
807
808 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
809 return -1;
810
811 sum = 0;
812 lk = xmlListFront(writer->nodes);
813 if (lk != 0) {
814 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
815 if (p != 0) {
816 switch (p->state) {
817 case XML_TEXTWRITER_PI:
818 case XML_TEXTWRITER_PI_TEXT:
819 return -1;
820 case XML_TEXTWRITER_NONE:
821 break;
822 case XML_TEXTWRITER_NAME:
823 count = xmlOutputBufferWriteString(writer->out, ">");
824 if (count < 0)
825 return -1;
826 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000827 if (writer->indent)
828 count =
829 xmlOutputBufferWriteString(writer->out, "\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000830 p->state = XML_TEXTWRITER_TEXT;
831 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000832 default:
833 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000834 }
835 }
836 }
837
838 p = (xmlTextWriterStackEntry *)
839 xmlMalloc(sizeof(xmlTextWriterStackEntry));
840 if (p == 0) {
841 xmlGenericError(xmlGenericErrorContext,
842 "xmlTextWriterStartElement : out of memory!\n");
843 return -1;
844 }
845
846 p->name = xmlStrdup(name);
847 if (p->name == 0) {
848 xmlGenericError(xmlGenericErrorContext,
849 "xmlTextWriterStartElement : out of memory!\n");
850 xmlFree(p);
851 return -1;
852 }
853 p->state = XML_TEXTWRITER_NAME;
854
855 xmlListPushFront(writer->nodes, p);
856
Daniel Veillardab69f362004-02-17 11:40:32 +0000857 if (writer->indent) {
858 count = xmlTextWriterWriteIndent(writer);
859 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +0000860 }
861
Daniel Veillard1d211e22003-10-20 22:32:39 +0000862 count = xmlOutputBufferWriteString(writer->out, "<");
863 if (count < 0)
864 return -1;
865 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000866 count =
867 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000868 if (count < 0)
869 return -1;
870 sum += count;
871
872 return sum;
873}
874
875/**
876 * xmlTextWriterStartElementNS:
877 * @writer: the xmlTextWriterPtr
878 * @prefix: namespace prefix or NULL
879 * @name: element local name
880 * @namespaceURI: namespace URI or NULL
881 *
882 * Start an xml element with namespace support.
883 *
884 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
885 */
886int
887xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
888 const xmlChar * prefix, const xmlChar * name,
889 const xmlChar * namespaceURI)
890{
891 int count;
892 int sum;
893 xmlChar *buf;
894
895 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
896 return -1;
897
898 buf = 0;
899 if (prefix != 0) {
900 buf = xmlStrdup(prefix);
901 buf = xmlStrcat(buf, BAD_CAST ":");
902 }
903 buf = xmlStrcat(buf, name);
904
905 sum = 0;
906 count = xmlTextWriterStartElement(writer, buf);
907 xmlFree(buf);
908 if (count < 0)
909 return -1;
910 sum += count;
911
912 if (namespaceURI != 0) {
913 buf = xmlStrdup(BAD_CAST "xmlns");
914 if (prefix != 0) {
915 buf = xmlStrcat(buf, BAD_CAST ":");
916 buf = xmlStrcat(buf, prefix);
917 }
918
919 count = xmlTextWriterWriteAttribute(writer, buf, namespaceURI);
920 xmlFree(buf);
921 if (count < 0)
922 return -1;
923 sum += count;
924 }
925
926 return sum;
927}
928
929/**
930 * xmlTextWriterEndElement:
931 * @writer: the xmlTextWriterPtr
932 *
933 * End the current xml element.
934 *
935 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
936 */
937int
938xmlTextWriterEndElement(xmlTextWriterPtr writer)
939{
940 int count;
941 int sum;
942 xmlLinkPtr lk;
943 xmlTextWriterStackEntry *p;
944
945 if (writer == NULL)
946 return -1;
947
948 lk = xmlListFront(writer->nodes);
949 if (lk == 0)
950 return -1;
951
952 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
953 if (p == 0)
954 return -1;
955
956 sum = 0;
957 switch (p->state) {
958 case XML_TEXTWRITER_ATTRIBUTE:
959 count = xmlTextWriterEndAttribute(writer);
960 if (count < 0)
961 return -1;
962 sum += count;
963 /* fallthrough */
964 case XML_TEXTWRITER_NAME:
Daniel Veillardab69f362004-02-17 11:40:32 +0000965 if (writer->indent) /* next element needs indent */
966 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000967 count = xmlOutputBufferWriteString(writer->out, "/>");
968 if (count < 0)
969 return -1;
970 sum += count;
971 break;
972 case XML_TEXTWRITER_TEXT:
Daniel Veillardab69f362004-02-17 11:40:32 +0000973 if ((writer->indent) && (writer->doindent)) {
974 count = xmlTextWriterWriteIndent(writer);
975 sum += count;
976 writer->doindent = 1;
977 } else
978 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000979 count = xmlOutputBufferWriteString(writer->out, "</");
980 if (count < 0)
981 return -1;
982 sum += count;
983 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +0000984 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000985 if (count < 0)
986 return -1;
987 sum += count;
988 count = xmlOutputBufferWriteString(writer->out, ">");
989 if (count < 0)
990 return -1;
991 sum += count;
992 break;
993 default:
994 return -1;
995 }
996
Daniel Veillard2cca4462004-01-02 20:04:23 +0000997 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000998 count = xmlOutputBufferWriteString(writer->out, "\n");
999 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001000 }
1001
Daniel Veillard1d211e22003-10-20 22:32:39 +00001002 xmlListPopFront(writer->nodes);
1003 return sum;
1004}
1005
1006/**
1007 * xmlTextWriterFullEndElement:
1008 * @writer: the xmlTextWriterPtr
1009 *
1010 * End the current xml element. Writes an end tag even if the element is empty
1011 *
1012 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1013 */
1014int
1015xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1016{
1017 int count;
1018 int sum;
1019 xmlLinkPtr lk;
1020 xmlTextWriterStackEntry *p;
1021
1022 if (writer == NULL)
1023 return -1;
1024
1025 lk = xmlListFront(writer->nodes);
1026 if (lk == 0)
1027 return -1;
1028
1029 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1030 if (p == 0)
1031 return -1;
1032
1033 sum = 0;
1034 switch (p->state) {
1035 case XML_TEXTWRITER_ATTRIBUTE:
1036 count = xmlTextWriterEndAttribute(writer);
1037 if (count < 0)
1038 return -1;
1039 sum += count;
1040 /* fallthrough */
1041 case XML_TEXTWRITER_NAME:
1042 count = xmlOutputBufferWriteString(writer->out, ">");
1043 if (count < 0)
1044 return -1;
1045 sum += count;
1046 /* fallthrough */
1047 case XML_TEXTWRITER_TEXT:
1048 count = xmlOutputBufferWriteString(writer->out, "</");
1049 if (count < 0)
1050 return -1;
1051 sum += count;
1052 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001053 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001054 if (count < 0)
1055 return -1;
1056 sum += count;
1057 count = xmlOutputBufferWriteString(writer->out, ">");
1058 if (count < 0)
1059 return -1;
1060 sum += count;
1061 break;
1062 default:
1063 return -1;
1064 }
1065
1066 xmlListPopFront(writer->nodes);
1067 return sum;
1068}
1069
1070/**
1071 * xmlTextWriterWriteFormatRaw:
1072 * @writer: the xmlTextWriterPtr
1073 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001074 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001075 *
1076 * Write a formatted raw xml text.
1077 *
1078 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1079 */
1080int
1081xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1082 ...)
1083{
1084 int rc;
1085 va_list ap;
1086
1087 va_start(ap, format);
1088
1089 rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1090
1091 va_end(ap);
1092 return rc;
1093}
1094
1095/**
1096 * xmlTextWriterWriteVFormatRaw:
1097 * @writer: the xmlTextWriterPtr
1098 * @format: format string (see printf)
1099 * @argptr: pointer to the first member of the variable argument list.
1100 *
1101 * Write a formatted raw xml text.
1102 *
1103 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1104 */
1105int
1106xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1107 va_list argptr)
1108{
1109 int rc;
1110 xmlChar *buf;
1111
1112 if (writer == NULL)
1113 return -1;
1114
1115 buf = xmlTextWriterVSprintf(format, argptr);
1116 if (buf == 0)
1117 return 0;
1118
1119 rc = xmlTextWriterWriteRaw(writer, buf);
1120
1121 xmlFree(buf);
1122 return rc;
1123}
1124
1125/**
Daniel Veillard1e906612003-12-05 14:57:46 +00001126 * xmlTextWriterWriteRawLen:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001127 * @writer: the xmlTextWriterPtr
1128 * @content: text string
1129 * @len: length of the text string
1130 *
1131 * Write an xml text.
1132 * TODO: what about entities and special chars??
1133 *
1134 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1135 */
1136int
1137xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1138 int len)
1139{
1140 int count;
1141 int sum;
1142 xmlLinkPtr lk;
1143 xmlTextWriterStackEntry *p;
1144
1145 if (writer == NULL)
1146 return -1;
1147
1148 lk = xmlListFront(writer->nodes);
1149 if (lk == 0)
1150 return 0;
1151
1152 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1153 if (p == 0)
1154 return 0;
1155
1156 sum = 0;
1157 switch (p->state) {
1158 case XML_TEXTWRITER_NONE:
1159 return -1;
1160 case XML_TEXTWRITER_NAME:
1161 count = xmlOutputBufferWriteString(writer->out, ">");
1162 if (count < 0)
1163 return -1;
1164 sum += count;
1165 p->state = XML_TEXTWRITER_TEXT;
1166 break;
1167 case XML_TEXTWRITER_PI:
1168 count = xmlOutputBufferWriteString(writer->out, " ");
1169 if (count < 0)
1170 return -1;
1171 sum += count;
1172 p->state = XML_TEXTWRITER_PI_TEXT;
1173 break;
1174 case XML_TEXTWRITER_DTD:
1175 count = xmlOutputBufferWriteString(writer->out, " [");
1176 if (count < 0)
1177 return -1;
1178 sum += count;
1179 p->state = XML_TEXTWRITER_DTD_TEXT;
1180 break;
1181 default:
1182 break;
1183 }
1184
1185 count = xmlOutputBufferWrite(writer->out, len, (const char *) content);
1186 if (count < 0)
1187 return -1;
1188 sum += count;
1189
1190 return sum;
1191}
1192
1193/**
1194 * xmlTextWriterWriteRaw:
1195 * @writer: the xmlTextWriterPtr
1196 * @content: text string
1197 *
1198 * Write a raw xml text.
1199 *
1200 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1201 */
1202int
1203xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1204{
1205 return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1206}
1207
1208/**
1209 * xmlTextWriterWriteFormatString:
1210 * @writer: the xmlTextWriterPtr
1211 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001212 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001213 *
1214 * Write a formatted xml text.
1215 *
1216 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1217 */
1218int
1219xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1220 ...)
1221{
1222 int rc;
1223 va_list ap;
1224
1225 va_start(ap, format);
1226
1227 rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1228
1229 va_end(ap);
1230 return rc;
1231}
1232
1233/**
1234 * xmlTextWriterWriteVFormatString:
1235 * @writer: the xmlTextWriterPtr
1236 * @format: format string (see printf)
1237 * @argptr: pointer to the first member of the variable argument list.
1238 *
1239 * Write a formatted xml text.
1240 *
1241 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1242 */
1243int
1244xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1245 const char *format, va_list argptr)
1246{
1247 int rc;
1248 xmlChar *buf;
1249
1250 if (writer == NULL)
1251 return -1;
1252
1253 buf = xmlTextWriterVSprintf(format, argptr);
1254 if (buf == 0)
1255 return 0;
1256
1257 rc = xmlTextWriterWriteString(writer, buf);
1258
1259 xmlFree(buf);
1260 return rc;
1261}
1262
1263/**
1264 * xmlTextWriterWriteString:
1265 * @writer: the xmlTextWriterPtr
1266 * @content: text string
1267 *
1268 * Write an xml text.
1269 *
1270 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1271 */
1272int
1273xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1274{
Daniel Veillardab69f362004-02-17 11:40:32 +00001275 int count = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001276 int sum;
1277 xmlLinkPtr lk;
1278 xmlTextWriterStackEntry *p;
Daniel Veillardab69f362004-02-17 11:40:32 +00001279 xmlChar *buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001280
1281 if (writer == NULL)
1282 return -1;
1283
1284 lk = xmlListFront(writer->nodes);
1285 if (lk == 0)
1286 return -1;
1287
1288 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1289 if (p == 0)
1290 return -1;
1291
1292 sum = 0;
1293 switch (p->state) {
1294 case XML_TEXTWRITER_NONE:
1295 return -1;
1296 case XML_TEXTWRITER_NAME:
1297 count = xmlOutputBufferWriteString(writer->out, ">");
1298 if (count < 0)
1299 return -1;
1300 sum += count;
1301 p->state = XML_TEXTWRITER_TEXT;
1302 goto encode;
1303 case XML_TEXTWRITER_PI:
1304 count = xmlOutputBufferWriteString(writer->out, " ");
1305 if (count < 0)
1306 return -1;
1307 sum += count;
1308 p->state = XML_TEXTWRITER_PI_TEXT;
1309 /* fallthrough */
1310 case XML_TEXTWRITER_PI_TEXT:
1311 case XML_TEXTWRITER_TEXT:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001312 encode:
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001313 buf = xmlEncodeSpecialChars(NULL, content);
Daniel Veillardab69f362004-02-17 11:40:32 +00001314 if (buf == NULL)
1315 count = -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001316 break;
William M. Bracka9c612c2004-02-01 10:04:05 +00001317 case XML_TEXTWRITER_ATTRIBUTE:
Daniel Veillardab69f362004-02-17 11:40:32 +00001318 xmlAttrSerializeTxtContent(writer->out->buffer, NULL,
1319 NULL, content);
1320 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001321 case XML_TEXTWRITER_DTD:
1322 count = xmlOutputBufferWriteString(writer->out, " [");
1323 if (count < 0)
1324 return -1;
1325 sum += count;
1326 p->state = XML_TEXTWRITER_DTD_TEXT;
1327 /* fallthrough */
1328 case XML_TEXTWRITER_DTD_TEXT:
1329 case XML_TEXTWRITER_DTD_ELEM:
1330 case XML_TEXTWRITER_CDATA:
Daniel Veillardab69f362004-02-17 11:40:32 +00001331 case XML_TEXTWRITER_COMMENT:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001332 buf = xmlStrdup(content);
Daniel Veillardab69f362004-02-17 11:40:32 +00001333 if (buf == NULL)
1334 count = -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001335 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00001336 default:
1337 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001338 }
1339
Daniel Veillard751c9ec2004-01-05 13:05:58 +00001340 if (writer->indent)
Daniel Veillardab69f362004-02-17 11:40:32 +00001341 writer->doindent = 0;
Daniel Veillard751c9ec2004-01-05 13:05:58 +00001342
Daniel Veillard1d211e22003-10-20 22:32:39 +00001343 if (buf != 0) {
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001344 count =
1345 xmlOutputBufferWriteString(writer->out, (const char *) buf);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001346 xmlFree(buf);
William M. Bracka9c612c2004-02-01 10:04:05 +00001347 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001348 if (count < 0)
1349 return -1;
1350 sum += count;
1351
1352 return sum;
1353}
1354
1355/**
1356 * xmlOutputBufferWriteBase64:
1357 * @out: the xmlOutputBufferPtr
1358 * @data: binary data
1359 * @len: the number of bytes to encode
1360 *
1361 * Write base64 encoded data to an xmlOutputBuffer.
1362 * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1363 *
1364 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1365 */
1366static int
1367xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1368 const unsigned char *data)
1369{
1370 static unsigned char dtable[64] =
1371 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1372 int i;
1373 int linelen;
1374 int count;
1375 int sum;
1376
1377 linelen = 0;
1378 sum = 0;
1379
1380 i = 0;
1381 while (1) {
1382 unsigned char igroup[3];
1383 unsigned char ogroup[4];
1384 int c;
1385 int n;
1386
1387 igroup[0] = igroup[1] = igroup[2] = 0;
1388 for (n = 0; n < 3 && i < len; n++, i++) {
1389 c = data[i];
1390 igroup[n] = (unsigned char) c;
1391 }
1392
1393 if (n > 0) {
1394 ogroup[0] = dtable[igroup[0] >> 2];
1395 ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1396 ogroup[2] =
1397 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1398 ogroup[3] = dtable[igroup[2] & 0x3F];
1399
1400 if (n < 3) {
1401 ogroup[3] = '=';
1402 if (n < 2) {
1403 ogroup[2] = '=';
1404 }
1405 }
1406
1407 if (linelen >= B64LINELEN) {
1408 count = xmlOutputBufferWrite(out, 2, B64CRLF);
1409 if (count == -1)
1410 return -1;
1411 sum += count;
1412 linelen = 0;
1413 }
1414 count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1415 if (count == -1)
1416 return -1;
1417 sum += count;
1418
1419 linelen += 4;
1420 }
Daniel Veillard929714b2003-10-22 12:34:36 +00001421
1422 if (i >= len)
1423 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001424 }
1425
Daniel Veillard1d211e22003-10-20 22:32:39 +00001426 return sum;
1427}
1428
1429/**
1430 * xmlTextWriterWriteBase64:
1431 * @writer: the xmlTextWriterPtr
1432 * @data: binary data
1433 * @start: the position within the data of the first byte to encode
1434 * @len: the number of bytes to encode
1435 *
1436 * Write an base64 encoded xml text.
1437 *
1438 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1439 */
1440int
Daniel Veillardab69f362004-02-17 11:40:32 +00001441xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001442 int start, int len)
1443{
1444 int count;
1445 int sum;
1446 xmlLinkPtr lk;
1447 xmlTextWriterStackEntry *p;
1448
1449 if (writer == NULL)
1450 return -1;
1451
1452 lk = xmlListFront(writer->nodes);
1453 if (lk == 0)
1454 return 0;
1455
1456 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1457 if (p == 0)
1458 return 0;
1459
1460 sum = 0;
1461 switch (p->state) {
1462 case XML_TEXTWRITER_NONE:
1463 return -1;
1464 case XML_TEXTWRITER_NAME:
1465 count = xmlOutputBufferWriteString(writer->out, ">");
1466 if (count < 0)
1467 return -1;
1468 sum += count;
1469 p->state = XML_TEXTWRITER_TEXT;
1470 break;
1471 case XML_TEXTWRITER_PI:
1472 count = xmlOutputBufferWriteString(writer->out, " ");
1473 if (count < 0)
1474 return -1;
1475 sum += count;
1476 p->state = XML_TEXTWRITER_PI_TEXT;
1477 break;
1478 case XML_TEXTWRITER_DTD:
1479 count = xmlOutputBufferWriteString(writer->out, " [");
1480 if (count < 0)
1481 return -1;
1482 sum += count;
1483 p->state = XML_TEXTWRITER_DTD_TEXT;
1484 break;
1485 default:
1486 break;
1487 }
1488
Daniel Veillardab69f362004-02-17 11:40:32 +00001489 if (writer->indent)
1490 writer->doindent = 0;
1491
Daniel Veillard1d211e22003-10-20 22:32:39 +00001492 count =
1493 xmlOutputBufferWriteBase64(writer->out, len,
1494 (unsigned char *) data + start);
1495 if (count < 0)
1496 return -1;
1497 sum += count;
1498
1499 return sum;
1500}
1501
1502/**
1503 * xmlOutputBufferWriteBinHex:
1504 * @out: the xmlOutputBufferPtr
1505 * @data: binary data
1506 * @len: the number of bytes to encode
1507 *
1508 * Write hqx encoded data to an xmlOutputBuffer.
1509 * ::todo
1510 *
1511 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1512 */
1513static int
Daniel Veillardab69f362004-02-17 11:40:32 +00001514xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1515 int len, const unsigned char *data)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001516{
Daniel Veillardab69f362004-02-17 11:40:32 +00001517 int count;
1518 int sum;
1519 static char hex[] = "0123456789ABCDEF";
1520 int i;
1521
1522 if ((out == NULL) || ((data == 0) && (len != 0))) {
1523 return -1;
1524 }
1525
1526 sum = 0;
1527 for (i = 0; i < len; i++) {
1528 count =
1529 xmlOutputBufferWrite(out, 1,
1530 (const char *) &hex[data[i] >> 4]);
1531 if (count == -1)
1532 return -1;
1533 sum += count;
1534 count =
1535 xmlOutputBufferWrite(out, 1,
1536 (const char *) &hex[data[i] & 0xF]);
1537 if (count == -1)
1538 return -1;
1539 sum += count;
1540 }
1541
1542 return sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001543}
1544
1545/**
1546 * xmlTextWriterWriteBinHex:
1547 * @writer: the xmlTextWriterPtr
1548 * @data: binary data
1549 * @start: the position within the data of the first byte to encode
1550 * @len: the number of bytes to encode
1551 *
1552 * Write a BinHex encoded xml text.
1553 *
1554 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1555 */
1556int
Daniel Veillardab69f362004-02-17 11:40:32 +00001557xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001558 int start, int len)
1559{
1560 int count;
1561 int sum;
1562 xmlLinkPtr lk;
1563 xmlTextWriterStackEntry *p;
1564
1565 if (writer == NULL)
1566 return -1;
1567
1568 lk = xmlListFront(writer->nodes);
1569 if (lk == 0)
1570 return 0;
1571
1572 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1573 if (p == 0)
1574 return 0;
1575
1576 sum = 0;
1577 switch (p->state) {
1578 case XML_TEXTWRITER_NONE:
1579 return -1;
1580 case XML_TEXTWRITER_NAME:
1581 count = xmlOutputBufferWriteString(writer->out, ">");
1582 if (count < 0)
1583 return -1;
1584 sum += count;
1585 p->state = XML_TEXTWRITER_TEXT;
1586 break;
1587 case XML_TEXTWRITER_PI:
1588 count = xmlOutputBufferWriteString(writer->out, " ");
1589 if (count < 0)
1590 return -1;
1591 sum += count;
1592 p->state = XML_TEXTWRITER_PI_TEXT;
1593 break;
1594 case XML_TEXTWRITER_DTD:
1595 count = xmlOutputBufferWriteString(writer->out, " [");
1596 if (count < 0)
1597 return -1;
1598 sum += count;
1599 p->state = XML_TEXTWRITER_DTD_TEXT;
1600 break;
1601 default:
1602 break;
1603 }
1604
Daniel Veillardab69f362004-02-17 11:40:32 +00001605 if (writer->indent)
1606 writer->doindent = 0;
1607
Daniel Veillard1d211e22003-10-20 22:32:39 +00001608 count =
1609 xmlOutputBufferWriteBinHex(writer->out, len,
1610 (unsigned char *) data + start);
1611 if (count < 0)
1612 return -1;
1613 sum += count;
1614
1615 return sum;
1616}
1617
1618/**
1619 * xmlTextWriterStartAttribute:
1620 * @writer: the xmlTextWriterPtr
1621 * @name: element name
1622 *
1623 * Start an xml attribute.
1624 *
1625 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1626 */
1627int
1628xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1629{
1630 int count;
1631 int sum;
1632 xmlLinkPtr lk;
1633 xmlTextWriterStackEntry *p;
1634
1635 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1636 return -1;
1637
1638 sum = 0;
1639 lk = xmlListFront(writer->nodes);
1640 if (lk == 0)
1641 return -1;
1642
1643 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1644 if (p == 0)
1645 return -1;
1646
1647 switch (p->state) {
1648 case XML_TEXTWRITER_ATTRIBUTE:
1649 count = xmlTextWriterEndAttribute(writer);
1650 if (count < 0)
1651 return -1;
1652 sum += count;
1653 /* fallthrough */
1654 case XML_TEXTWRITER_NAME:
1655 count = xmlOutputBufferWriteString(writer->out, " ");
1656 if (count < 0)
1657 return -1;
1658 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001659 count =
1660 xmlOutputBufferWriteString(writer->out,
1661 (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001662 if (count < 0)
1663 return -1;
1664 sum += count;
1665 count = xmlOutputBufferWriteString(writer->out, "=");
1666 if (count < 0)
1667 return -1;
1668 sum += count;
1669 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1670 if (count < 0)
1671 return -1;
1672 sum += count;
1673 p->state = XML_TEXTWRITER_ATTRIBUTE;
1674 break;
1675 default:
1676 return -1;
1677 }
1678
1679 return sum;
1680}
1681
1682/**
1683 * xmlTextWriterStartAttributeNS:
1684 * @writer: the xmlTextWriterPtr
1685 * @prefix: namespace prefix or NULL
1686 * @name: element local name
1687 * @namespaceURI: namespace URI or NULL
1688 *
1689 * Start an xml attribute with namespace support.
1690 *
1691 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1692 */
1693int
1694xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1695 const xmlChar * prefix, const xmlChar * name,
1696 const xmlChar * namespaceURI)
1697{
1698 int count;
1699 int sum;
1700 xmlChar *buf;
1701 xmlTextWriterNsStackEntry *p;
1702
1703 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1704 return -1;
1705
1706 buf = 0;
1707 if (prefix != 0) {
1708 buf = xmlStrdup(prefix);
1709 buf = xmlStrcat(buf, BAD_CAST ":");
1710 }
1711 buf = xmlStrcat(buf, name);
1712
1713 sum = 0;
1714 count = xmlTextWriterStartAttribute(writer, buf);
1715 xmlFree(buf);
1716 if (count < 0)
1717 return -1;
1718 sum += count;
1719
1720 if (namespaceURI != 0) {
1721 buf = xmlStrdup(BAD_CAST "xmlns");
1722 if (prefix != 0) {
1723 buf = xmlStrcat(buf, BAD_CAST ":");
1724 buf = xmlStrcat(buf, prefix);
1725 }
1726
1727 p = (xmlTextWriterNsStackEntry *)
1728 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1729 if (p == 0) {
1730 xmlGenericError(xmlGenericErrorContext,
1731 "xmlTextWriterStartAttributeNS : out of memory!\n");
1732 return -1;
1733 }
1734
1735 p->prefix = buf;
1736 p->uri = xmlStrdup(namespaceURI);
1737 if (p->uri == 0) {
1738 xmlGenericError(xmlGenericErrorContext,
1739 "xmlTextWriterStartAttributeNS : out of memory!\n");
1740 xmlFree(p);
1741 return -1;
1742 }
1743 p->elem = xmlListFront(writer->nodes);
1744
1745 xmlListPushFront(writer->nsstack, p);
1746 }
1747
1748 return sum;
1749}
1750
1751/**
1752 * xmlTextWriterEndAttribute:
1753 * @writer: the xmlTextWriterPtr
1754 *
1755 * End the current xml element.
1756 *
1757 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1758 */
1759int
1760xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1761{
1762 int count;
1763 int sum;
1764 xmlLinkPtr lk;
1765 xmlTextWriterStackEntry *p;
1766 xmlTextWriterNsStackEntry *np;
1767
1768 if (writer == NULL)
1769 return -1;
1770
1771 lk = xmlListFront(writer->nodes);
1772 if (lk == 0) {
1773 xmlListDelete(writer->nsstack);
1774 return -1;
1775 }
1776
1777 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1778 if (p == 0) {
1779 xmlListDelete(writer->nsstack);
1780 return -1;
1781 }
1782
1783 sum = 0;
1784 switch (p->state) {
1785 case XML_TEXTWRITER_ATTRIBUTE:
1786 p->state = XML_TEXTWRITER_NAME;
1787
1788 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1789 if (count < 0) {
1790 xmlListDelete(writer->nsstack);
1791 return -1;
1792 }
1793 sum += count;
1794
1795 while (!xmlListEmpty(writer->nsstack)) {
1796 lk = xmlListFront(writer->nsstack);
1797 np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
1798 if (np != 0) {
1799 count =
1800 xmlTextWriterWriteAttribute(writer, np->prefix,
1801 np->uri);
1802 if (count < 0) {
1803 xmlListDelete(writer->nsstack);
1804 return -1;
1805 }
1806 sum += count;
1807 }
1808
1809 xmlListPopFront(writer->nsstack);
1810 }
1811 break;
1812
1813 default:
1814 xmlListClear(writer->nsstack);
1815 return -1;
1816 }
1817
1818 return sum;
1819}
1820
1821/**
1822 * xmlTextWriterWriteFormatAttribute:
1823 * @writer: the xmlTextWriterPtr
1824 * @name: attribute name
1825 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001826 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001827 *
1828 * Write a formatted xml attribute.
1829 *
1830 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1831 */
1832int
1833xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1834 const xmlChar * name, const char *format,
1835 ...)
1836{
1837 int rc;
1838 va_list ap;
1839
1840 va_start(ap, format);
1841
1842 rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1843
1844 va_end(ap);
1845 return rc;
1846}
1847
1848/**
1849 * xmlTextWriterWriteVFormatAttribute:
1850 * @writer: the xmlTextWriterPtr
1851 * @name: attribute name
1852 * @format: format string (see printf)
1853 * @argptr: pointer to the first member of the variable argument list.
1854 *
1855 * Write a formatted xml attribute.
1856 *
1857 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1858 */
1859int
1860xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
1861 const xmlChar * name,
1862 const char *format, va_list argptr)
1863{
1864 int rc;
1865 xmlChar *buf;
1866
1867 if (writer == NULL)
1868 return -1;
1869
1870 buf = xmlTextWriterVSprintf(format, argptr);
1871 if (buf == 0)
1872 return 0;
1873
1874 rc = xmlTextWriterWriteAttribute(writer, name, buf);
1875
1876 xmlFree(buf);
1877 return rc;
1878}
1879
1880/**
1881 * xmlTextWriterWriteAttribute:
1882 * @writer: the xmlTextWriterPtr
1883 * @name: attribute name
1884 * @content: attribute content
1885 *
1886 * Write an xml attribute.
1887 *
1888 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1889 */
1890int
1891xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
1892 const xmlChar * content)
1893{
1894 int count;
1895 int sum;
1896
1897 sum = 0;
1898 count = xmlTextWriterStartAttribute(writer, name);
1899 if (count < 0)
1900 return -1;
1901 sum += count;
1902 count = xmlTextWriterWriteString(writer, content);
1903 if (count < 0)
1904 return -1;
1905 sum += count;
1906 count = xmlTextWriterEndAttribute(writer);
1907 if (count < 0)
1908 return -1;
1909 sum += count;
1910
1911 return sum;
1912}
1913
1914/**
1915 * xmlTextWriterWriteFormatAttributeNS:
1916 * @writer: the xmlTextWriterPtr
1917 * @prefix: namespace prefix
1918 * @name: attribute local name
1919 * @namespaceURI: namespace URI
1920 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001921 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001922 *
1923 * Write a formatted xml attribute.with namespace support
1924 *
1925 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1926 */
1927int
1928xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
1929 const xmlChar * prefix,
1930 const xmlChar * name,
1931 const xmlChar * namespaceURI,
1932 const char *format, ...)
1933{
1934 int rc;
1935 va_list ap;
1936
1937 va_start(ap, format);
1938
1939 rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
1940 namespaceURI, format, ap);
1941
1942 va_end(ap);
1943 return rc;
1944}
1945
1946/**
1947 * xmlTextWriterWriteVFormatAttributeNS:
1948 * @writer: the xmlTextWriterPtr
1949 * @prefix: namespace prefix
1950 * @name: attribute local name
1951 * @namespaceURI: namespace URI
1952 * @format: format string (see printf)
1953 * @argptr: pointer to the first member of the variable argument list.
1954 *
1955 * Write a formatted xml attribute.with namespace support
1956 *
1957 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1958 */
1959int
1960xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
1961 const xmlChar * prefix,
1962 const xmlChar * name,
1963 const xmlChar * namespaceURI,
1964 const char *format, va_list argptr)
1965{
1966 int rc;
1967 xmlChar *buf;
1968
1969 if (writer == NULL)
1970 return -1;
1971
1972 buf = xmlTextWriterVSprintf(format, argptr);
1973 if (buf == 0)
1974 return 0;
1975
1976 rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
1977 buf);
1978
1979 xmlFree(buf);
1980 return rc;
1981}
1982
1983/**
1984 * xmlTextWriterWriteAttributeNS:
1985 * @writer: the xmlTextWriterPtr
1986 * @prefix: namespace prefix
1987 * @name: attribute local name
1988 * @namespaceURI: namespace URI
1989 * @content: attribute content
1990 *
1991 * Write an xml attribute.
1992 *
1993 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1994 */
1995int
1996xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
1997 const xmlChar * prefix, const xmlChar * name,
1998 const xmlChar * namespaceURI,
1999 const xmlChar * content)
2000{
2001 int count;
2002 int sum;
2003 xmlChar *buf;
2004
2005 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2006 return -1;
2007
2008 buf = 0;
2009 if (prefix != NULL) {
2010 buf = xmlStrdup(prefix);
2011 buf = xmlStrcat(buf, BAD_CAST ":");
2012 }
2013 buf = xmlStrcat(buf, name);
2014
2015 sum = 0;
2016 count = xmlTextWriterWriteAttribute(writer, buf, content);
2017 xmlFree(buf);
2018 if (count < 0)
2019 return -1;
2020 sum += count;
2021
2022 if (namespaceURI != NULL) {
2023 buf = 0;
2024 buf = xmlStrdup(BAD_CAST "xmlns");
2025 if (prefix != NULL) {
2026 buf = xmlStrcat(buf, BAD_CAST ":");
2027 buf = xmlStrcat(buf, prefix);
2028 }
2029 count = xmlTextWriterWriteAttribute(writer, buf, namespaceURI);
2030 xmlFree(buf);
2031 if (count < 0)
2032 return -1;
2033 sum += count;
2034 }
2035 return sum;
2036}
2037
2038/**
2039 * xmlTextWriterWriteFormatElement:
2040 * @writer: the xmlTextWriterPtr
2041 * @name: element name
2042 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002043 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002044 *
2045 * Write a formatted xml element.
2046 *
2047 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2048 */
2049int
2050xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2051 const xmlChar * name, const char *format,
2052 ...)
2053{
2054 int rc;
2055 va_list ap;
2056
2057 va_start(ap, format);
2058
2059 rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2060
2061 va_end(ap);
2062 return rc;
2063}
2064
2065/**
2066 * xmlTextWriterWriteVFormatElement:
2067 * @writer: the xmlTextWriterPtr
2068 * @name: element name
2069 * @format: format string (see printf)
2070 * @argptr: pointer to the first member of the variable argument list.
2071 *
2072 * Write a formatted xml element.
2073 *
2074 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2075 */
2076int
2077xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2078 const xmlChar * name, const char *format,
2079 va_list argptr)
2080{
2081 int rc;
2082 xmlChar *buf;
2083
2084 if (writer == NULL)
2085 return -1;
2086
2087 buf = xmlTextWriterVSprintf(format, argptr);
2088 if (buf == 0)
2089 return 0;
2090
2091 rc = xmlTextWriterWriteElement(writer, name, buf);
2092
2093 xmlFree(buf);
2094 return rc;
2095}
2096
2097/**
2098 * xmlTextWriterWriteElement:
2099 * @writer: the xmlTextWriterPtr
2100 * @name: element name
2101 * @content: element content
2102 *
2103 * Write an xml element.
2104 *
2105 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2106 */
2107int
2108xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2109 const xmlChar * content)
2110{
2111 int count;
2112 int sum;
2113
2114 sum = 0;
2115 count = xmlTextWriterStartElement(writer, name);
2116 if (count == -1)
2117 return -1;
2118 sum += count;
2119 count = xmlTextWriterWriteString(writer, content);
2120 if (count == -1)
2121 return -1;
2122 sum += count;
2123 count = xmlTextWriterEndElement(writer);
2124 if (count == -1)
2125 return -1;
2126 sum += count;
2127
2128 return sum;
2129}
2130
2131/**
2132 * xmlTextWriterWriteFormatElementNS:
2133 * @writer: the xmlTextWriterPtr
2134 * @prefix: namespace prefix
2135 * @name: element local name
2136 * @namespaceURI: namespace URI
2137 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002138 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002139 *
2140 * Write a formatted xml element with namespace support.
2141 *
2142 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2143 */
2144int
2145xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2146 const xmlChar * prefix,
2147 const xmlChar * name,
2148 const xmlChar * namespaceURI,
2149 const char *format, ...)
2150{
2151 int rc;
2152 va_list ap;
2153
2154 va_start(ap, format);
2155
2156 rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2157 namespaceURI, format, ap);
2158
2159 va_end(ap);
2160 return rc;
2161}
2162
2163/**
2164 * xmlTextWriterWriteVFormatElementNS:
2165 * @writer: the xmlTextWriterPtr
2166 * @prefix: namespace prefix
2167 * @name: element local name
2168 * @namespaceURI: namespace URI
2169 * @format: format string (see printf)
2170 * @argptr: pointer to the first member of the variable argument list.
2171 *
2172 * Write a formatted xml element with namespace support.
2173 *
2174 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2175 */
2176int
2177xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2178 const xmlChar * prefix,
2179 const xmlChar * name,
2180 const xmlChar * namespaceURI,
2181 const char *format, va_list argptr)
2182{
2183 int rc;
2184 xmlChar *buf;
2185
2186 if (writer == NULL)
2187 return -1;
2188
2189 buf = xmlTextWriterVSprintf(format, argptr);
2190 if (buf == 0)
2191 return 0;
2192
2193 rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2194 buf);
2195
2196 xmlFree(buf);
2197 return rc;
2198}
2199
2200/**
2201 * xmlTextWriterWriteElementNS:
2202 * @writer: the xmlTextWriterPtr
2203 * @prefix: namespace prefix
2204 * @name: element local name
2205 * @namespaceURI: namespace URI
2206 * @content: element content
2207 *
2208 * Write an xml element with namespace support.
2209 *
2210 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2211 */
2212int
2213xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2214 const xmlChar * prefix, const xmlChar * name,
2215 const xmlChar * namespaceURI,
2216 const xmlChar * content)
2217{
2218 int count;
2219 int sum;
2220
2221 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2222 return -1;
2223
2224 sum = 0;
2225 count =
2226 xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2227 if (count < 0)
2228 return -1;
2229 sum += count;
2230 count = xmlTextWriterWriteString(writer, content);
2231 if (count == -1)
2232 return -1;
2233 sum += count;
2234 count = xmlTextWriterEndElement(writer);
2235 if (count == -1)
2236 return -1;
2237 sum += count;
2238
2239 return sum;
2240}
2241
2242/**
2243 * xmlTextWriterStartPI:
2244 * @writer: the xmlTextWriterPtr
2245 * @target: PI target
2246 *
2247 * Start an xml PI.
2248 *
2249 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2250 */
2251int
2252xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2253{
2254 int count;
2255 int sum;
2256 xmlLinkPtr lk;
2257 xmlTextWriterStackEntry *p;
2258
2259 if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2260 return -1;
2261
2262 if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
2263 xmlGenericError(xmlGenericErrorContext,
2264 "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2265 return -1;
2266 }
2267
2268 sum = 0;
2269 lk = xmlListFront(writer->nodes);
2270 if (lk != 0) {
2271 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2272 if (p != 0) {
2273 switch (p->state) {
2274 case XML_TEXTWRITER_ATTRIBUTE:
2275 count = xmlTextWriterEndAttribute(writer);
2276 if (count < 0)
2277 return -1;
2278 sum += count;
2279 /* fallthrough */
2280 case XML_TEXTWRITER_NAME:
2281 count = xmlOutputBufferWriteString(writer->out, ">");
2282 if (count < 0)
2283 return -1;
2284 sum += count;
2285 p->state = XML_TEXTWRITER_TEXT;
2286 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00002287 case XML_TEXTWRITER_NONE:
2288 case XML_TEXTWRITER_TEXT:
2289 case XML_TEXTWRITER_DTD:
2290 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002291 case XML_TEXTWRITER_PI:
2292 case XML_TEXTWRITER_PI_TEXT:
2293 xmlGenericError(xmlGenericErrorContext,
2294 "xmlTextWriterStartPI : nested PI!\n");
2295 return -1;
2296 default:
2297 return -1;
2298 }
2299 }
2300 }
2301
2302 p = (xmlTextWriterStackEntry *)
2303 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2304 if (p == 0) {
2305 xmlGenericError(xmlGenericErrorContext,
2306 "xmlTextWriterStartPI : out of memory!\n");
2307 return -1;
2308 }
2309
2310 p->name = xmlStrdup(target);
2311 if (p->name == 0) {
2312 xmlGenericError(xmlGenericErrorContext,
2313 "xmlTextWriterStartPI : out of memory!\n");
2314 xmlFree(p);
2315 return -1;
2316 }
2317 p->state = XML_TEXTWRITER_PI;
2318
2319 xmlListPushFront(writer->nodes, p);
2320
2321 count = xmlOutputBufferWriteString(writer->out, "<?");
2322 if (count < 0)
2323 return -1;
2324 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002325 count =
2326 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002327 if (count < 0)
2328 return -1;
2329 sum += count;
2330
2331 return sum;
2332}
2333
2334/**
2335 * xmlTextWriterEndPI:
2336 * @writer: the xmlTextWriterPtr
2337 *
2338 * End the current xml PI.
2339 *
2340 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2341 */
2342int
2343xmlTextWriterEndPI(xmlTextWriterPtr writer)
2344{
2345 int count;
2346 int sum;
2347 xmlLinkPtr lk;
2348 xmlTextWriterStackEntry *p;
2349
2350 if (writer == NULL)
2351 return -1;
2352
2353 lk = xmlListFront(writer->nodes);
2354 if (lk == 0)
2355 return 0;
2356
2357 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2358 if (p == 0)
2359 return 0;
2360
2361 sum = 0;
2362 switch (p->state) {
2363 case XML_TEXTWRITER_PI:
2364 case XML_TEXTWRITER_PI_TEXT:
2365 count = xmlOutputBufferWriteString(writer->out, "?>");
2366 if (count < 0)
2367 return -1;
2368 sum += count;
2369 break;
2370 default:
2371 return -1;
2372 }
2373
2374 xmlListPopFront(writer->nodes);
2375 return sum;
2376}
2377
2378/**
2379 * xmlTextWriterWriteFormatPI:
2380 * @writer: the xmlTextWriterPtr
2381 * @target: PI target
2382 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002383 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002384 *
2385 * Write a formatted PI.
2386 *
2387 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2388 */
2389int
2390xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2391 const char *format, ...)
2392{
2393 int rc;
2394 va_list ap;
2395
2396 va_start(ap, format);
2397
2398 rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2399
2400 va_end(ap);
2401 return rc;
2402}
2403
2404/**
2405 * xmlTextWriterWriteVFormatPI:
2406 * @writer: the xmlTextWriterPtr
2407 * @target: PI target
2408 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002409 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002410 *
2411 * Write a formatted xml PI.
2412 *
2413 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2414 */
2415int
2416xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2417 const xmlChar * target, const char *format,
2418 va_list argptr)
2419{
2420 int rc;
2421 xmlChar *buf;
2422
2423 if (writer == NULL)
2424 return -1;
2425
2426 buf = xmlTextWriterVSprintf(format, argptr);
2427 if (buf == 0)
2428 return 0;
2429
2430 rc = xmlTextWriterWritePI(writer, target, buf);
2431
2432 xmlFree(buf);
2433 return rc;
2434}
2435
2436/**
2437 * xmlTextWriterWritePI:
2438 * @writer: the xmlTextWriterPtr
2439 * @target: PI target
2440 * @content: PI content
2441 *
2442 * Write an xml PI.
2443 *
2444 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2445 */
2446int
2447xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2448 const xmlChar * content)
2449{
2450 int count;
2451 int sum;
2452
2453 sum = 0;
2454 count = xmlTextWriterStartPI(writer, target);
2455 if (count == -1)
2456 return -1;
2457 sum += count;
2458 if (content != 0) {
2459 count = xmlTextWriterWriteString(writer, content);
2460 if (count == -1)
2461 return -1;
2462 sum += count;
2463 }
2464 count = xmlTextWriterEndPI(writer);
2465 if (count == -1)
2466 return -1;
2467 sum += count;
2468
2469 return sum;
2470}
2471
2472/**
2473 * xmlTextWriterStartCDATA:
2474 * @writer: the xmlTextWriterPtr
2475 *
2476 * Start an xml CDATA section.
2477 *
2478 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2479 */
2480int
2481xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2482{
2483 int count;
2484 int sum;
2485 xmlLinkPtr lk;
2486 xmlTextWriterStackEntry *p;
2487
2488 if (writer == NULL)
2489 return -1;
2490
2491 sum = 0;
2492 lk = xmlListFront(writer->nodes);
2493 if (lk != 0) {
2494 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2495 if (p != 0) {
2496 switch (p->state) {
2497 case XML_TEXTWRITER_NONE:
2498 case XML_TEXTWRITER_PI:
2499 case XML_TEXTWRITER_PI_TEXT:
2500 break;
2501 case XML_TEXTWRITER_ATTRIBUTE:
2502 count = xmlTextWriterEndAttribute(writer);
2503 if (count < 0)
2504 return -1;
2505 sum += count;
2506 /* fallthrough */
2507 case XML_TEXTWRITER_NAME:
2508 count = xmlOutputBufferWriteString(writer->out, ">");
2509 if (count < 0)
2510 return -1;
2511 sum += count;
2512 p->state = XML_TEXTWRITER_TEXT;
2513 break;
2514 case XML_TEXTWRITER_CDATA:
2515 xmlGenericError(xmlGenericErrorContext,
2516 "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2517 return -1;
2518 default:
2519 return -1;
2520 }
2521 }
2522 }
2523
2524 p = (xmlTextWriterStackEntry *)
2525 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2526 if (p == 0) {
2527 xmlGenericError(xmlGenericErrorContext,
2528 "xmlTextWriterStartCDATA : out of memory!\n");
2529 return -1;
2530 }
2531
2532 p->name = 0;
2533 p->state = XML_TEXTWRITER_CDATA;
2534
2535 xmlListPushFront(writer->nodes, p);
2536
2537 count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2538 if (count < 0)
2539 return -1;
2540 sum += count;
2541
2542 return sum;
2543}
2544
2545/**
2546 * xmlTextWriterEndCDATA:
2547 * @writer: the xmlTextWriterPtr
2548 *
2549 * End an xml CDATA section.
2550 *
2551 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2552 */
2553int
2554xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2555{
2556 int count;
2557 int sum;
2558 xmlLinkPtr lk;
2559 xmlTextWriterStackEntry *p;
2560
2561 if (writer == NULL)
2562 return -1;
2563
2564 lk = xmlListFront(writer->nodes);
2565 if (lk == 0)
2566 return -1;
2567
2568 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2569 if (p == 0)
2570 return -1;
2571
2572 sum = 0;
2573 switch (p->state) {
2574 case XML_TEXTWRITER_CDATA:
2575 count = xmlOutputBufferWriteString(writer->out, "]]>");
2576 if (count < 0)
2577 return -1;
2578 sum += count;
2579 break;
2580 default:
2581 return -1;
2582 }
2583
2584 xmlListPopFront(writer->nodes);
2585 return sum;
2586}
2587
2588/**
2589 * xmlTextWriterWriteFormatCDATA:
2590 * @writer: the xmlTextWriterPtr
2591 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002592 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002593 *
2594 * Write a formatted xml CDATA.
2595 *
2596 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2597 */
2598int
2599xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2600 ...)
2601{
2602 int rc;
2603 va_list ap;
2604
2605 va_start(ap, format);
2606
2607 rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2608
2609 va_end(ap);
2610 return rc;
2611}
2612
2613/**
2614 * xmlTextWriterWriteVFormatCDATA:
2615 * @writer: the xmlTextWriterPtr
2616 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002617 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002618 *
2619 * Write a formatted xml CDATA.
2620 *
2621 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2622 */
2623int
2624xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2625 va_list argptr)
2626{
2627 int rc;
2628 xmlChar *buf;
2629
2630 if (writer == NULL)
2631 return -1;
2632
2633 buf = xmlTextWriterVSprintf(format, argptr);
2634 if (buf == 0)
2635 return 0;
2636
2637 rc = xmlTextWriterWriteCDATA(writer, buf);
2638
2639 xmlFree(buf);
2640 return rc;
2641}
2642
2643/**
2644 * xmlTextWriterWriteCDATA:
2645 * @writer: the xmlTextWriterPtr
2646 * @content: CDATA content
2647 *
2648 * Write an xml CDATA.
2649 *
2650 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2651 */
2652int
2653xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2654{
2655 int count;
2656 int sum;
2657
2658 sum = 0;
2659 count = xmlTextWriterStartCDATA(writer);
2660 if (count == -1)
2661 return -1;
2662 sum += count;
2663 if (content != 0) {
2664 count = xmlTextWriterWriteString(writer, content);
2665 if (count == -1)
2666 return -1;
2667 sum += count;
2668 }
2669 count = xmlTextWriterEndCDATA(writer);
2670 if (count == -1)
2671 return -1;
2672 sum += count;
2673
2674 return sum;
2675}
2676
2677/**
2678 * xmlTextWriterStartDTD:
2679 * @writer: the xmlTextWriterPtr
2680 * @name: the name of the DTD
2681 * @pubid: the public identifier, which is an alternative to the system identifier
2682 * @sysid: the system identifier, which is the URI of the DTD
2683 *
2684 * Start an xml DTD.
2685 *
2686 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2687 */
2688int
2689xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2690 const xmlChar * name,
2691 const xmlChar * pubid, const xmlChar * sysid)
2692{
2693 int count;
2694 int sum;
2695 xmlLinkPtr lk;
2696 xmlTextWriterStackEntry *p;
2697
2698 if (writer == NULL || name == NULL || *name == '\0')
2699 return -1;
2700
2701 sum = 0;
2702 lk = xmlListFront(writer->nodes);
Daniel Veillardab69f362004-02-17 11:40:32 +00002703 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00002704 xmlGenericError(xmlGenericErrorContext,
2705 "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2706 return -1;
2707 }
2708
2709 p = (xmlTextWriterStackEntry *)
2710 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2711 if (p == 0) {
2712 xmlGenericError(xmlGenericErrorContext,
2713 "xmlTextWriterStartDTD : out of memory!\n");
2714 return -1;
2715 }
2716
2717 p->name = xmlStrdup(name);
2718 if (p->name == 0) {
2719 xmlGenericError(xmlGenericErrorContext,
2720 "xmlTextWriterStartDTD : out of memory!\n");
2721 xmlFree(p);
2722 return -1;
2723 }
2724 p->state = XML_TEXTWRITER_DTD;
2725
2726 xmlListPushFront(writer->nodes, p);
2727
2728 count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2729 if (count < 0)
2730 return -1;
2731 sum += count;
2732 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2733 if (count < 0)
2734 return -1;
2735 sum += count;
2736
2737 if (pubid != 0) {
2738 if (sysid == 0) {
2739 xmlGenericError(xmlGenericErrorContext,
2740 "xmlTextWriterStartDTD : system identifier needed!\n");
2741 return -1;
2742 }
2743
2744 count = xmlOutputBufferWriteString(writer->out, " PUBLIC \"");
2745 if (count < 0)
2746 return -1;
2747 sum += count;
2748
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002749 count =
2750 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002751 if (count < 0)
2752 return -1;
2753 sum += count;
2754
2755 count = xmlOutputBufferWriteString(writer->out, "\"");
2756 if (count < 0)
2757 return -1;
2758 sum += count;
2759 }
2760
2761 if (sysid != 0) {
2762 if (pubid == 0) {
2763 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
2764 if (count < 0)
2765 return -1;
2766 sum += count;
2767 }
2768
2769 count = xmlOutputBufferWriteString(writer->out, " \"");
2770 if (count < 0)
2771 return -1;
2772 sum += count;
2773
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002774 count =
2775 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002776 if (count < 0)
2777 return -1;
2778 sum += count;
2779
2780 count = xmlOutputBufferWriteString(writer->out, "\"");
2781 if (count < 0)
2782 return -1;
2783 sum += count;
2784 }
2785
2786 return sum;
2787}
2788
2789/**
2790 * xmlTextWriterEndDTD:
2791 * @writer: the xmlTextWriterPtr
2792 *
2793 * End an xml DTD.
2794 *
2795 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2796 */
2797int
2798xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2799{
2800 int count;
2801 int sum;
2802 xmlLinkPtr lk;
2803 xmlTextWriterStackEntry *p;
2804
2805 if (writer == NULL)
2806 return -1;
2807
2808 sum = 0;
2809 lk = xmlListFront(writer->nodes);
2810 if (lk == 0)
2811 return -1;
2812
2813 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2814 if (p == 0)
2815 return -1;
2816
2817 switch (p->state) {
2818 case XML_TEXTWRITER_DTD_TEXT:
2819 count = xmlOutputBufferWriteString(writer->out, "]");
2820 if (count < 0)
2821 return -1;
2822 sum += count;
2823 /* fallthrough */
2824 case XML_TEXTWRITER_DTD:
2825 case XML_TEXTWRITER_DTD_ELEM:
2826 case XML_TEXTWRITER_DTD_ATTL:
2827 count = xmlOutputBufferWriteString(writer->out, ">");
2828 if (count < 0)
2829 return -1;
2830 sum += count;
2831 break;
2832 default:
2833 return -1;
2834 }
2835
2836 xmlListPopFront(writer->nodes);
2837 return sum;
2838}
2839
2840/**
2841 * xmlTextWriterWriteFormatDTD:
2842 * @writer: the xmlTextWriterPtr
2843 * @name: the name of the DTD
2844 * @pubid: the public identifier, which is an alternative to the system identifier
2845 * @sysid: the system identifier, which is the URI of the DTD
2846 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002847 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002848 *
2849 * Write a DTD with a formatted markup declarations part.
2850 *
2851 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2852 */
2853int
2854xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
2855 const xmlChar * name,
2856 const xmlChar * pubid,
2857 const xmlChar * sysid, const char *format, ...)
2858{
2859 int rc;
2860 va_list ap;
2861
2862 va_start(ap, format);
2863
2864 rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
2865 ap);
2866
2867 va_end(ap);
2868 return rc;
2869}
2870
2871/**
2872 * xmlTextWriterWriteVFormatDTD:
2873 * @writer: the xmlTextWriterPtr
2874 * @name: the name of the DTD
2875 * @pubid: the public identifier, which is an alternative to the system identifier
2876 * @sysid: the system identifier, which is the URI of the DTD
2877 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002878 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002879 *
2880 * Write a DTD with a formatted markup declarations part.
2881 *
2882 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2883 */
2884int
2885xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
2886 const xmlChar * name,
2887 const xmlChar * pubid,
2888 const xmlChar * sysid,
2889 const char *format, va_list argptr)
2890{
2891 int rc;
2892 xmlChar *buf;
2893
2894 if (writer == NULL)
2895 return -1;
2896
2897 buf = xmlTextWriterVSprintf(format, argptr);
2898 if (buf == 0)
2899 return 0;
2900
2901 rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
2902
2903 xmlFree(buf);
2904 return rc;
2905}
2906
2907/**
2908 * xmlTextWriterWriteDTD:
2909 * @writer: the xmlTextWriterPtr
2910 * @name: the name of the DTD
2911 * @pubid: the public identifier, which is an alternative to the system identifier
2912 * @sysid: the system identifier, which is the URI of the DTD
William M. Brackb1d53162003-11-18 06:54:40 +00002913 * @subset: string content of the DTD
Daniel Veillard1d211e22003-10-20 22:32:39 +00002914 *
2915 * Write a DTD.
2916 *
2917 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2918 */
2919int
2920xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
2921 const xmlChar * name,
2922 const xmlChar * pubid,
2923 const xmlChar * sysid, const xmlChar * subset)
2924{
2925 int count;
2926 int sum;
2927
2928 sum = 0;
2929 count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
2930 if (count == -1)
2931 return -1;
2932 sum += count;
2933 if (subset != 0) {
2934 count = xmlTextWriterWriteString(writer, subset);
2935 if (count == -1)
2936 return -1;
2937 sum += count;
2938 }
2939 count = xmlTextWriterEndDTD(writer);
2940 if (count == -1)
2941 return -1;
2942 sum += count;
2943
2944 return sum;
2945}
2946
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002947/**
2948 * xmlTextWriterStartDTDElement:
2949 * @writer: the xmlTextWriterPtr
2950 * @name: the name of the DTD element
2951 *
2952 * Start an xml DTD element.
2953 *
2954 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2955 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00002956int
2957xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
2958{
2959 int count;
2960 int sum;
2961 xmlLinkPtr lk;
2962 xmlTextWriterStackEntry *p;
2963
2964 if (writer == NULL || name == NULL || *name == '\0')
2965 return -1;
2966
2967 sum = 0;
2968 lk = xmlListFront(writer->nodes);
2969 if (lk == 0) {
2970 return -1;
2971 }
2972
2973 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2974 if (p == 0)
2975 return -1;
2976
2977 switch (p->state) {
2978 case XML_TEXTWRITER_DTD:
2979 count = xmlOutputBufferWriteString(writer->out, " [");
2980 if (count < 0)
2981 return -1;
2982 sum += count;
2983 p->state = XML_TEXTWRITER_DTD_TEXT;
2984 /* fallthrough */
2985 case XML_TEXTWRITER_DTD_TEXT:
2986 break;
2987 case XML_TEXTWRITER_DTD_ELEM:
2988 count = xmlTextWriterEndDTDElement(writer);
2989 if (count < 0)
2990 return -1;
2991 sum += count;
2992 break;
2993 default:
2994 return -1;
2995 }
2996
2997 p = (xmlTextWriterStackEntry *)
2998 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2999 if (p == 0) {
3000 xmlGenericError(xmlGenericErrorContext,
3001 "xmlTextWriterStartDTDElement : out of memory!\n");
3002 return -1;
3003 }
3004
3005 p->name = xmlStrdup(name);
3006 if (p->name == 0) {
3007 xmlGenericError(xmlGenericErrorContext,
3008 "xmlTextWriterStartDTDElement : out of memory!\n");
3009 xmlFree(p);
3010 return -1;
3011 }
3012 p->state = XML_TEXTWRITER_DTD_ELEM;
3013
3014 xmlListPushFront(writer->nodes, p);
3015
3016 count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3017 if (count < 0)
3018 return -1;
3019 sum += count;
3020 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3021 if (count < 0)
3022 return -1;
3023 sum += count;
3024
3025 return sum;
3026}
3027
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003028/**
3029 * xmlTextWriterWriteFormatDTDElement:
3030 * @writer: the xmlTextWriterPtr
3031 * @name: the name of the DTD element
3032 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003033 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003034 *
3035 * Write a formatted DTD element.
3036 *
3037 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3038 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003039int
3040xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3041 const xmlChar * name,
3042 const char *format, ...)
3043{
3044 int rc;
3045 va_list ap;
3046
3047 va_start(ap, format);
3048
3049 rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3050
3051 va_end(ap);
3052 return rc;
3053}
3054
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003055/**
3056 * xmlTextWriterWriteVFormatDTDElement:
3057 * @writer: the xmlTextWriterPtr
3058 * @name: the name of the DTD element
3059 * @format: format string (see printf)
3060 * @argptr: pointer to the first member of the variable argument list.
3061 *
3062 * Write a formatted DTD element.
3063 *
3064 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3065 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003066int
3067xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3068 const xmlChar * name,
3069 const char *format, va_list argptr)
3070{
3071 int rc;
3072 xmlChar *buf;
3073
3074 if (writer == NULL)
3075 return -1;
3076
3077 buf = xmlTextWriterVSprintf(format, argptr);
3078 if (buf == 0)
3079 return 0;
3080
3081 rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3082
3083 xmlFree(buf);
3084 return rc;
3085}
3086
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003087/**
3088 * xmlTextWriterWriteDTDElement:
3089 * @writer: the xmlTextWriterPtr
3090 * @name: the name of the DTD element
3091 * @content: content of the element
3092 *
3093 * Write a DTD element.
3094 *
3095 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3096 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003097int
3098xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3099 const xmlChar * name, const xmlChar * content)
3100{
3101 int count;
3102 int sum;
3103
3104 if (content == NULL)
3105 return -1;
3106
3107 sum = 0;
3108 count = xmlTextWriterStartDTDElement(writer, name);
3109 if (count == -1)
3110 return -1;
3111 sum += count;
3112
3113 count = xmlTextWriterWriteString(writer, BAD_CAST " ");
3114 if (count == -1)
3115 return -1;
3116 sum += count;
3117 count = xmlTextWriterWriteString(writer, content);
3118 if (count == -1)
3119 return -1;
3120 sum += count;
3121
3122 count = xmlTextWriterEndDTDElement(writer);
3123 if (count == -1)
3124 return -1;
3125 sum += count;
3126
3127 return sum;
3128}
3129
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003130/**
3131 * xmlTextWriterStartDTDAttlist:
3132 * @writer: the xmlTextWriterPtr
3133 * @name: the name of the DTD ATTLIST
3134 *
3135 * Start an xml DTD ATTLIST.
3136 *
3137 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3138 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003139int
3140xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3141{
3142 int count;
3143 int sum;
3144 xmlLinkPtr lk;
3145 xmlTextWriterStackEntry *p;
3146
3147 if (writer == NULL || name == NULL || *name == '\0')
3148 return -1;
3149
3150 sum = 0;
3151 lk = xmlListFront(writer->nodes);
3152 if (lk == 0) {
3153 return -1;
3154 }
3155
3156 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3157 if (p == 0)
3158 return -1;
3159
3160 switch (p->state) {
3161 case XML_TEXTWRITER_DTD:
3162 count = xmlOutputBufferWriteString(writer->out, " [");
3163 if (count < 0)
3164 return -1;
3165 sum += count;
3166 p->state = XML_TEXTWRITER_DTD_TEXT;
3167 /* fallthrough */
3168 case XML_TEXTWRITER_DTD_TEXT:
3169 break;
3170 case XML_TEXTWRITER_DTD_ELEM:
3171 case XML_TEXTWRITER_DTD_ATTL:
3172 case XML_TEXTWRITER_DTD_ENTY:
3173 count = xmlTextWriterEndDTD(writer);
3174 if (count < 0)
3175 return -1;
3176 sum += count;
3177 break;
3178 default:
3179 return -1;
3180 }
3181
3182 p = (xmlTextWriterStackEntry *)
3183 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3184 if (p == 0) {
3185 xmlGenericError(xmlGenericErrorContext,
3186 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3187 return -1;
3188 }
3189
3190 p->name = xmlStrdup(name);
3191 if (p->name == 0) {
3192 xmlGenericError(xmlGenericErrorContext,
3193 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3194 xmlFree(p);
3195 return -1;
3196 }
3197 p->state = XML_TEXTWRITER_DTD_ATTL;
3198
3199 xmlListPushFront(writer->nodes, p);
3200
3201 count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3202 if (count < 0)
3203 return -1;
3204 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +00003205 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003206 if (count < 0)
3207 return -1;
3208 sum += count;
3209
3210 return sum;
3211}
3212
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003213/**
3214 * xmlTextWriterWriteFormatDTDAttlist:
3215 * @writer: the xmlTextWriterPtr
3216 * @name: the name of the DTD ATTLIST
3217 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003218 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003219 *
3220 * Write a formatted DTD ATTLIST.
3221 *
3222 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3223 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003224int
3225xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3226 const xmlChar * name,
3227 const char *format, ...)
3228{
3229 int rc;
3230 va_list ap;
3231
3232 va_start(ap, format);
3233
3234 rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3235
3236 va_end(ap);
3237 return rc;
3238}
3239
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003240/**
3241 * xmlTextWriterWriteVFormatDTDAttlist:
3242 * @writer: the xmlTextWriterPtr
3243 * @name: the name of the DTD ATTLIST
3244 * @format: format string (see printf)
3245 * @argptr: pointer to the first member of the variable argument list.
3246 *
3247 * Write a formatted DTD ATTLIST.
3248 *
3249 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3250 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003251int
3252xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3253 const xmlChar * name,
3254 const char *format, va_list argptr)
3255{
3256 int rc;
3257 xmlChar *buf;
3258
3259 if (writer == NULL)
3260 return -1;
3261
3262 buf = xmlTextWriterVSprintf(format, argptr);
3263 if (buf == 0)
3264 return 0;
3265
3266 rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3267
3268 xmlFree(buf);
3269 return rc;
3270}
3271
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003272/**
3273 * xmlTextWriterWriteDTDAttlist:
3274 * @writer: the xmlTextWriterPtr
3275 * @name: the name of the DTD ATTLIST
3276 * @content: content of the ATTLIST
3277 *
3278 * Write a DTD ATTLIST.
3279 *
3280 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3281 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003282int
3283xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3284 const xmlChar * name, const xmlChar * content)
3285{
3286 int count;
3287 int sum;
3288
3289 if (content == NULL)
3290 return -1;
3291
3292 sum = 0;
3293 count = xmlTextWriterStartDTDAttlist(writer, name);
3294 if (count == -1)
3295 return -1;
3296 sum += count;
3297
3298 count = xmlTextWriterWriteString(writer, BAD_CAST " ");
3299 if (count == -1)
3300 return -1;
3301 sum += count;
3302 count = xmlTextWriterWriteString(writer, content);
3303 if (count == -1)
3304 return -1;
3305 sum += count;
3306
3307 count = xmlTextWriterEndDTDAttlist(writer);
3308 if (count == -1)
3309 return -1;
3310 sum += count;
3311
3312 return sum;
3313}
3314
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003315/**
3316 * xmlTextWriterStartDTDEntity:
3317 * @writer: the xmlTextWriterPtr
3318 * @pe: TRUE if this is a parameter entity, FALSE if not
3319 * @name: the name of the DTD ATTLIST
3320 *
3321 * Start an xml DTD ATTLIST.
3322 *
3323 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3324 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003325int
3326xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3327 int pe, const xmlChar * name)
3328{
3329 int count;
3330 int sum;
3331 xmlLinkPtr lk;
3332 xmlTextWriterStackEntry *p;
3333
3334 if (writer == NULL || name == NULL || *name == '\0')
3335 return -1;
3336
3337 sum = 0;
3338 lk = xmlListFront(writer->nodes);
3339 if (lk == 0) {
3340 return -1;
3341 }
3342
3343 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3344 if (p == 0)
3345 return -1;
3346
3347 switch (p->state) {
3348 case XML_TEXTWRITER_DTD:
3349 count = xmlOutputBufferWriteString(writer->out, " [");
3350 if (count < 0)
3351 return -1;
3352 sum += count;
3353 p->state = XML_TEXTWRITER_DTD_TEXT;
3354 /* fallthrough */
3355 case XML_TEXTWRITER_DTD_TEXT:
3356 break;
3357 case XML_TEXTWRITER_DTD_ELEM:
3358 case XML_TEXTWRITER_DTD_ATTL:
3359 case XML_TEXTWRITER_DTD_ENTY:
3360 count = xmlTextWriterEndDTD(writer);
3361 if (count < 0)
3362 return -1;
3363 sum += count;
3364 break;
3365 default:
3366 return -1;
3367 }
3368
3369 p = (xmlTextWriterStackEntry *)
3370 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3371 if (p == 0) {
3372 xmlGenericError(xmlGenericErrorContext,
3373 "xmlTextWriterStartDTDElement : out of memory!\n");
3374 return -1;
3375 }
3376
3377 p->name = xmlStrdup(name);
3378 if (p->name == 0) {
3379 xmlGenericError(xmlGenericErrorContext,
3380 "xmlTextWriterStartDTDElement : out of memory!\n");
3381 xmlFree(p);
3382 return -1;
3383 }
3384 p->state = XML_TEXTWRITER_DTD_ENTY;
3385
3386 xmlListPushFront(writer->nodes, p);
3387
3388 count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3389 if (count < 0)
3390 return -1;
3391 sum += count;
3392
3393 if (pe != 0) {
3394 count = xmlOutputBufferWriteString(writer->out, " % ");
3395 if (count < 0)
3396 return -1;
3397 sum += count;
3398 }
3399
Daniel Veillardab69f362004-02-17 11:40:32 +00003400 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003401 if (count < 0)
3402 return -1;
3403 sum += count;
3404
3405 return sum;
3406}
3407
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003408/**
3409 * xmlTextWriterWriteFormatDTDInternalEntity:
3410 * @writer: the xmlTextWriterPtr
3411 * @pe: TRUE if this is a parameter entity, FALSE if not
3412 * @name: the name of the DTD entity
3413 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003414 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003415 *
3416 * Write a formatted DTD internal entity.
3417 *
3418 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3419 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003420int
3421xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3422 int pe,
3423 const xmlChar * name,
3424 const char *format, ...)
3425{
3426 int rc;
3427 va_list ap;
3428
3429 va_start(ap, format);
3430
3431 rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3432 format, ap);
3433
3434 va_end(ap);
3435 return rc;
3436}
3437
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003438/**
3439 * xmlTextWriterWriteVFormatDTDInternalEntity:
3440 * @writer: the xmlTextWriterPtr
3441 * @pe: TRUE if this is a parameter entity, FALSE if not
3442 * @name: the name of the DTD entity
3443 * @format: format string (see printf)
3444 * @argptr: pointer to the first member of the variable argument list.
3445 *
3446 * Write a formatted DTD internal entity.
3447 *
3448 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3449 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003450int
3451xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3452 int pe,
3453 const xmlChar * name,
3454 const char *format,
3455 va_list argptr)
3456{
3457 int rc;
3458 xmlChar *buf;
3459
3460 if (writer == NULL)
3461 return -1;
3462
3463 buf = xmlTextWriterVSprintf(format, argptr);
3464 if (buf == 0)
3465 return 0;
3466
3467 rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3468
3469 xmlFree(buf);
3470 return rc;
3471}
3472
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003473/**
3474 * xmlTextWriterWriteDTDEntity:
3475 * @writer: the xmlTextWriterPtr
3476 * @pe: TRUE if this is a parameter entity, FALSE if not
3477 * @name: the name of the DTD entity
3478 * @pubid: the public identifier, which is an alternative to the system identifier
3479 * @sysid: the system identifier, which is the URI of the DTD
3480 * @ndataid: the xml notation name.
3481 * @content: content of the entity
3482 *
3483 * Write a DTD entity.
3484 *
3485 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3486 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003487int
3488xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3489 int pe,
3490 const xmlChar * name,
3491 const xmlChar * pubid,
3492 const xmlChar * sysid,
3493 const xmlChar * ndataid,
3494 const xmlChar * content)
3495{
3496 if (((content == NULL) && (pubid == NULL) && (sysid == NULL))
3497 || ((content != NULL) && ((pubid != NULL) || (sysid != NULL))))
3498 return -1;
3499 if ((pe != 0) && (ndataid != NULL))
3500 return -1;
3501
3502 if (content != 0)
3503 return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3504 content);
3505
3506 return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3507 sysid, ndataid);
3508}
3509
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003510/**
3511 * xmlTextWriterWriteDTDInternalEntity:
3512 * @writer: the xmlTextWriterPtr
3513 * @pe: TRUE if this is a parameter entity, FALSE if not
3514 * @name: the name of the DTD entity
3515 * @content: content of the entity
3516 *
3517 * Write a DTD internal entity.
3518 *
3519 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3520 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003521int
3522xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3523 int pe,
3524 const xmlChar * name,
3525 const xmlChar * content)
3526{
3527 int count;
3528 int sum;
3529
3530 if ((name == NULL) || (*name == '\0') || (content == NULL))
3531 return -1;
3532
3533 sum = 0;
3534 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3535 if (count == -1)
3536 return -1;
3537 sum += count;
3538
3539 count = xmlTextWriterWriteString(writer, BAD_CAST " ");
3540 if (count == -1)
3541 return -1;
3542 sum += count;
3543 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3544 if (count < 0)
3545 return -1;
3546 sum += count;
3547 count = xmlTextWriterWriteString(writer, content);
3548 if (count == -1)
3549 return -1;
3550 sum += count;
3551 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3552 if (count < 0)
3553 return -1;
3554 sum += count;
3555
3556 count = xmlTextWriterEndDTDEntity(writer);
3557 if (count == -1)
3558 return -1;
3559 sum += count;
3560
3561 return sum;
3562}
3563
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003564/**
3565 * xmlTextWriterWriteDTDExternalEntity:
3566 * @writer: the xmlTextWriterPtr
3567 * @pe: TRUE if this is a parameter entity, FALSE if not
3568 * @name: the name of the DTD entity
3569 * @pubid: the public identifier, which is an alternative to the system identifier
3570 * @sysid: the system identifier, which is the URI of the DTD
3571 * @ndataid: the xml notation name.
3572 *
3573 * Write a DTD internal entity.
3574 *
3575 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3576 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003577int
3578xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3579 int pe,
3580 const xmlChar * name,
3581 const xmlChar * pubid,
3582 const xmlChar * sysid,
3583 const xmlChar * ndataid)
3584{
3585 int count;
3586 int sum;
3587
3588 if ((name == NULL) || (*name == '\0')
3589 || ((pubid == NULL) && (sysid == NULL)))
3590 return -1;
3591 if ((pe != 0) && (ndataid != NULL))
3592 return -1;
3593
3594 sum = 0;
3595 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3596 if (count == -1)
3597 return -1;
3598 sum += count;
3599
3600 if (pubid != 0) {
3601 if (sysid == 0) {
3602 xmlGenericError(xmlGenericErrorContext,
3603 "xmlTextWriterWriteDTDEntity : system identifier needed!\n");
3604 return -1;
3605 }
3606
3607 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
3608 if (count < 0)
3609 return -1;
3610 sum += count;
3611
3612 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3613 if (count < 0)
3614 return -1;
3615 sum += count;
3616
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003617 count =
3618 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003619 if (count < 0)
3620 return -1;
3621 sum += count;
3622
3623 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3624 if (count < 0)
3625 return -1;
3626 sum += count;
3627 }
3628
3629 if (sysid != 0) {
3630 if (pubid == 0) {
3631 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
3632 if (count < 0)
3633 return -1;
3634 sum += count;
3635 }
3636
3637 count = xmlOutputBufferWriteString(writer->out, " ");
3638 if (count < 0)
3639 return -1;
3640 sum += count;
3641
3642 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3643 if (count < 0)
3644 return -1;
3645 sum += count;
3646
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003647 count =
3648 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003649 if (count < 0)
3650 return -1;
3651 sum += count;
3652
3653 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3654 if (count < 0)
3655 return -1;
3656 sum += count;
3657 }
3658
3659 if (ndataid != NULL) {
3660 count = xmlOutputBufferWriteString(writer->out, " NDATA ");
3661 if (count < 0)
3662 return -1;
3663 sum += count;
3664
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003665 count =
3666 xmlOutputBufferWriteString(writer->out,
3667 (const char *) ndataid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003668 if (count < 0)
3669 return -1;
3670 sum += count;
3671 }
3672
3673 count = xmlTextWriterEndDTDEntity(writer);
3674 if (count == -1)
3675 return -1;
3676 sum += count;
3677
3678 return sum;
3679}
3680
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003681/**
3682 * xmlTextWriterWriteDTDNotation:
3683 * @writer: the xmlTextWriterPtr
3684 * @name: the name of the xml notation
3685 * @pubid: the public identifier, which is an alternative to the system identifier
3686 * @sysid: the system identifier, which is the URI of the DTD
3687 *
3688 * Write a DTD entity.
3689 *
3690 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3691 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003692int
3693xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
3694 const xmlChar * name,
3695 const xmlChar * pubid, const xmlChar * sysid)
3696{
3697 int count;
3698 int sum;
3699 xmlLinkPtr lk;
3700 xmlTextWriterStackEntry *p;
3701
3702 if (writer == NULL || name == NULL || *name == '\0')
3703 return -1;
3704
3705 sum = 0;
3706 lk = xmlListFront(writer->nodes);
3707 if (lk == 0) {
3708 return -1;
3709 }
3710
3711 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3712 if (p == 0)
3713 return -1;
3714
3715 switch (p->state) {
3716 case XML_TEXTWRITER_DTD:
3717 count = xmlOutputBufferWriteString(writer->out, " [");
3718 if (count < 0)
3719 return -1;
3720 sum += count;
3721 p->state = XML_TEXTWRITER_DTD_TEXT;
3722 /* fallthrough */
3723 case XML_TEXTWRITER_DTD_TEXT:
3724 break;
3725 case XML_TEXTWRITER_DTD_ELEM:
3726 case XML_TEXTWRITER_DTD_ATTL:
3727 case XML_TEXTWRITER_DTD_ENTY:
3728 count = xmlTextWriterEndDTD(writer);
3729 if (count < 0)
3730 return -1;
3731 sum += count;
3732 break;
3733 default:
3734 return -1;
3735 }
3736
3737 count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
3738 if (count < 0)
3739 return -1;
3740 sum += count;
3741 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3742 if (count < 0)
3743 return -1;
3744 sum += count;
3745
3746 if (pubid != 0) {
3747 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
3748 if (count < 0)
3749 return -1;
3750 sum += count;
3751 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3752 if (count < 0)
3753 return -1;
3754 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003755 count =
3756 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003757 if (count < 0)
3758 return -1;
3759 sum += count;
3760 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3761 if (count < 0)
3762 return -1;
3763 sum += count;
3764 }
3765
3766 if (sysid != 0) {
3767 if (pubid == 0) {
3768 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
3769 if (count < 0)
3770 return -1;
3771 sum += count;
3772 }
3773 count = xmlOutputBufferWriteString(writer->out, " ");
3774 if (count < 0)
3775 return -1;
3776 sum += count;
3777 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3778 if (count < 0)
3779 return -1;
3780 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003781 count =
3782 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003783 if (count < 0)
3784 return -1;
3785 sum += count;
3786 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3787 if (count < 0)
3788 return -1;
3789 sum += count;
3790 }
3791
3792 count = xmlOutputBufferWriteString(writer->out, ">");
3793 if (count < 0)
3794 return -1;
3795 sum += count;
3796
3797 return sum;
3798}
3799
3800/**
3801 * xmlTextWriterFlush:
3802 * @writer: the xmlTextWriterPtr
3803 *
3804 * Flush the output buffer.
3805 *
3806 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3807 */
3808int
3809xmlTextWriterFlush(xmlTextWriterPtr writer)
3810{
3811 int count;
3812
3813 if (writer == NULL)
3814 return -1;
3815
3816 if (writer->out == NULL)
3817 count = 0;
3818 else
3819 count = xmlOutputBufferFlush(writer->out);
3820
3821 return count;
3822}
3823
3824/**
3825 * misc
3826 */
3827
3828/**
3829 * xmlFreeTextWriterStackEntry:
3830 * @lk: the xmlLinkPtr
3831 *
3832 * Free callback for the xmlList.
3833 */
3834static void
3835xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
3836{
3837 xmlTextWriterStackEntry *p;
3838
3839 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3840 if (p == 0)
3841 return;
3842
3843 if (p->name != 0)
3844 xmlFree(p->name);
3845 xmlFree(p);
3846}
3847
3848/**
3849 * xmlCmpTextWriterStackEntry:
3850 * @data0: the first data
3851 * @data1: the second data
3852 *
3853 * Compare callback for the xmlList.
3854 *
3855 * Returns -1, 0, 1
3856 */
3857static int
3858xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
3859{
3860 xmlTextWriterStackEntry *p0;
3861 xmlTextWriterStackEntry *p1;
3862
3863 if (data0 == data1)
3864 return 0;
3865
3866 if (data0 == 0)
3867 return -1;
3868
3869 if (data1 == 0)
3870 return 1;
3871
3872 p0 = (xmlTextWriterStackEntry *) data0;
3873 p1 = (xmlTextWriterStackEntry *) data1;
3874
3875 return xmlStrcmp(p0->name, p1->name);
3876}
3877
3878/**
3879 * misc
3880 */
3881
3882/**
3883 * xmlFreeTextWriterNsStackEntry:
3884 * @lk: the xmlLinkPtr
3885 *
3886 * Free callback for the xmlList.
3887 */
3888static void
3889xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
3890{
3891 xmlTextWriterNsStackEntry *p;
3892
3893 p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
3894 if (p == 0)
3895 return;
3896
3897 if (p->prefix != 0)
3898 xmlFree(p->prefix);
3899 if (p->uri != 0)
3900 xmlFree(p->uri);
3901
3902 xmlFree(p);
3903}
3904
3905/**
3906 * xmlCmpTextWriterNsStackEntry:
3907 * @data0: the first data
3908 * @data1: the second data
3909 *
3910 * Compare callback for the xmlList.
3911 *
3912 * Returns -1, 0, 1
3913 */
3914static int
3915xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
3916{
3917 xmlTextWriterNsStackEntry *p0;
3918 xmlTextWriterNsStackEntry *p1;
3919 int rc;
3920
3921 if (data0 == data1)
3922 return 0;
3923
3924 if (data0 == 0)
3925 return -1;
3926
3927 if (data1 == 0)
3928 return 1;
3929
3930 p0 = (xmlTextWriterNsStackEntry *) data0;
3931 p1 = (xmlTextWriterNsStackEntry *) data1;
3932
3933 rc = xmlStrcmp(p0->prefix, p1->prefix);
3934
3935 if (rc == 0)
3936 rc = p0->elem == p1->elem;
3937
3938 return rc;
3939}
3940
3941/**
3942 * xmlTextWriterWriteMemCallback:
3943 * @context: the xmlBufferPtr
3944 * @str: the data to write
3945 * @len: the length of the data
3946 *
3947 * Write callback for the xmlOutputBuffer with target xmlBuffer
3948 *
3949 * Returns -1, 0, 1
3950 */
3951static int
3952xmlTextWriterWriteMemCallback(void *context, const xmlChar * str, int len)
3953{
3954 xmlBufferPtr buf = (xmlBufferPtr) context;
3955
3956 xmlBufferAdd(buf, str, len);
3957
3958 return len;
3959}
3960
3961/**
3962 * xmlTextWriterCloseMemCallback:
3963 * @context: the xmlBufferPtr
3964 *
3965 * Close callback for the xmlOutputBuffer with target xmlBuffer
3966 *
3967 * Returns -1, 0, 1
3968 */
3969static int
3970xmlTextWriterCloseMemCallback(void *context ATTRIBUTE_UNUSED)
3971{
3972 return 0;
3973}
3974
3975/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003976 * xmlTextWriterWriteDocCallback:
3977 * @context: the xmlBufferPtr
3978 * @str: the data to write
3979 * @len: the length of the data
3980 *
3981 * Write callback for the xmlOutputBuffer with target xmlBuffer
3982 *
3983 * Returns -1, 0, 1
3984 */
3985static int
3986xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
3987{
3988 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
3989 int rc;
3990
Daniel Veillard1d913862003-11-21 00:28:39 +00003991 if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003992 xmlGenericError(xmlGenericErrorContext,
3993 "xmlTextWriterWriteDocCallback : XML error %d !\n",
3994 rc);
3995 return -1;
3996 }
3997
3998 return len;
3999}
4000
4001/**
4002 * xmlTextWriterCloseDocCallback:
4003 * @context: the xmlBufferPtr
4004 *
4005 * Close callback for the xmlOutputBuffer with target xmlBuffer
4006 *
4007 * Returns -1, 0, 1
4008 */
4009static int
4010xmlTextWriterCloseDocCallback(void *context)
4011{
4012 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4013 int rc;
4014
4015 if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
4016 xmlGenericError(xmlGenericErrorContext,
4017 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4018 rc);
4019 return -1;
4020 }
4021
4022 return 0;
4023}
4024
4025/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004026 * xmlTextWriterVSprintf:
4027 * @format: see printf
4028 * @argptr: pointer to the first member of the variable argument list.
4029 *
4030 * Utility function for formatted output
4031 *
4032 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4033 */
4034static xmlChar *
4035xmlTextWriterVSprintf(const char *format, va_list argptr)
4036{
4037 int size;
4038 int count;
4039 xmlChar *buf;
4040
4041 size = BUFSIZ;
4042 buf = (xmlChar *) xmlMalloc(size);
4043 if (buf == NULL) {
4044 xmlGenericError(xmlGenericErrorContext,
4045 "xmlTextWriterVSprintf : out of memory!\n");
4046 return NULL;
4047 }
4048
4049 while (((count = vsnprintf((char *) buf, size, format, argptr)) < 0)
4050 || (count == size - 1) || (count == size) || (count > size)) {
4051 xmlFree(buf);
4052 size += BUFSIZ;
4053 buf = (xmlChar *) xmlMalloc(size);
4054 if (buf == NULL) {
4055 xmlGenericError(xmlGenericErrorContext,
4056 "xmlTextWriterVSprintf : out of memory!\n");
4057 return NULL;
4058 }
4059 }
4060
4061 return buf;
4062}
4063
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004064/**
4065 * xmlTextWriterStartDocumentCallback:
4066 * @ctx: the user data (XML parser context)
4067 *
4068 * called at the start of document processing.
4069 */
4070static void
4071xmlTextWriterStartDocumentCallback(void *ctx)
4072{
4073 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4074 xmlDocPtr doc;
4075
4076#ifdef DEBUG_SAX
4077 xmlGenericError(xmlGenericErrorContext, "SAX.startDocument()\n");
4078#endif
4079 if (ctxt->html) {
4080#ifdef LIBXML_HTML_ENABLED
4081 if (ctxt->myDoc == NULL)
4082 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4083 if (ctxt->myDoc == NULL) {
4084 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4085 ctxt->sax->error(ctxt->userData,
4086 "SAX.startDocument(): out of memory\n");
4087 ctxt->errNo = XML_ERR_NO_MEMORY;
4088 ctxt->instate = XML_PARSER_EOF;
4089 ctxt->disableSAX = 1;
4090 return;
4091 }
4092#else
4093 xmlGenericError(xmlGenericErrorContext,
4094 "libxml2 built without HTML support\n");
4095 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4096 ctxt->instate = XML_PARSER_EOF;
4097 ctxt->disableSAX = 1;
4098 return;
4099#endif
4100 } else {
4101 doc = ctxt->myDoc;
4102 if (doc == NULL)
4103 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4104 if (doc != NULL) {
4105 if (doc->children == NULL) {
4106 if (ctxt->encoding != NULL)
4107 doc->encoding = xmlStrdup(ctxt->encoding);
4108 else
4109 doc->encoding = NULL;
4110 doc->standalone = ctxt->standalone;
4111 }
4112 } else {
4113 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4114 ctxt->sax->error(ctxt->userData,
4115 "SAX.startDocument(): out of memory\n");
4116 ctxt->errNo = XML_ERR_NO_MEMORY;
4117 ctxt->instate = XML_PARSER_EOF;
4118 ctxt->disableSAX = 1;
4119 return;
4120 }
4121 }
4122 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4123 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4124 ctxt->myDoc->URL =
4125 xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4126 if (ctxt->myDoc->URL == NULL)
4127 ctxt->myDoc->URL =
4128 xmlStrdup((const xmlChar *) ctxt->input->filename);
4129 }
4130}
4131
Daniel Veillard2cca4462004-01-02 20:04:23 +00004132/**
4133 * xmlTextWriterSetIndent:
4134 * @writer: the xmlTextWriterPtr
4135 * @indent: do indentation?
4136 *
4137 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4138 *
4139 * Returns -1 on error or 0 otherwise.
4140 */
4141int
Daniel Veillardab69f362004-02-17 11:40:32 +00004142xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004143{
Daniel Veillardab69f362004-02-17 11:40:32 +00004144 if (indent < 0)
4145 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004146
Daniel Veillardab69f362004-02-17 11:40:32 +00004147 writer->indent = indent;
4148 writer->doindent = 1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004149
Daniel Veillardab69f362004-02-17 11:40:32 +00004150 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004151}
4152
4153/**
4154 * xmlTextWriterSetIndentString:
4155 * @writer: the xmlTextWriterPtr
4156 * @str: the xmlChar string
4157 *
4158 * Set string indentation.
4159 *
4160 * Returns -1 on error or 0 otherwise.
4161 */
4162int
Daniel Veillardab69f362004-02-17 11:40:32 +00004163xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004164{
4165
Daniel Veillardab69f362004-02-17 11:40:32 +00004166 if (!str)
4167 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004168
Daniel Veillardab69f362004-02-17 11:40:32 +00004169 if (writer->ichar != NULL)
4170 xmlFree(writer->ichar);
4171 writer->ichar = xmlStrdup(str);
4172
4173 if (!writer->ichar)
4174 return -1;
4175 else
4176 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004177}
4178
4179/**
4180 * xmlTextWriterWriteIndent:
4181 * @writer: the xmlTextWriterPtr
4182 *
4183 * Write indent string.
4184 *
4185 * Returns -1 on error or the number of strings written.
Daniel Veillardab69f362004-02-17 11:40:32 +00004186 */
Daniel Veillard2cca4462004-01-02 20:04:23 +00004187static int
Daniel Veillardab69f362004-02-17 11:40:32 +00004188xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004189{
Daniel Veillardab69f362004-02-17 11:40:32 +00004190 int lksize;
4191 int i;
4192 int ret;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004193
Daniel Veillardab69f362004-02-17 11:40:32 +00004194 lksize = xmlListSize(writer->nodes);
4195 if (lksize < 1)
4196 return (-1); /* list is empty */
4197 for (i = 0; i < (lksize - 1); i++) {
4198 ret = xmlOutputBufferWriteString(writer->out,
4199 (const char *) writer->ichar);
4200 if (ret == -1)
4201 return (-1);
4202 }
4203
4204 return (lksize - 1);
Daniel Veillard2cca4462004-01-02 20:04:23 +00004205}
4206
Daniel Veillard1d211e22003-10-20 22:32:39 +00004207#endif