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