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