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