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