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