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