blob: fc2b06695b45084bf5d263e1d533fe64c707b2a1 [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 Veillard500a1de2004-03-22 15:22:58 +00001329 buf = xmlEncodeSpecialChars(NULL, content);
1330 break;
1331 case XML_TEXTWRITER_ATTRIBUTE:
1332 buf = NULL;
1333 xmlAttrSerializeTxtContent(writer->out->buffer, NULL,
1334 NULL, content);
1335 break;
William M. Brack87640d52004-04-17 14:58:15 +00001336 default:
1337 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001338 }
1339 }
1340 }
1341
1342 if (buf != NULL) {
1343 count = xmlTextWriterWriteRaw(writer, buf);
1344 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001345 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001346 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001347
Daniel Veillard500a1de2004-03-22 15:22:58 +00001348 if (buf != content) /* buf was allocated by us, so free it */
1349 xmlFree(buf);
William M. Bracka9c612c2004-02-01 10:04:05 +00001350 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001351
1352 return sum;
1353}
1354
1355/**
1356 * xmlOutputBufferWriteBase64:
1357 * @out: the xmlOutputBufferPtr
1358 * @data: binary data
1359 * @len: the number of bytes to encode
1360 *
1361 * Write base64 encoded data to an xmlOutputBuffer.
1362 * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1363 *
1364 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1365 */
1366static int
1367xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1368 const unsigned char *data)
1369{
1370 static unsigned char dtable[64] =
1371 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1372 int i;
1373 int linelen;
1374 int count;
1375 int sum;
1376
1377 linelen = 0;
1378 sum = 0;
1379
1380 i = 0;
1381 while (1) {
1382 unsigned char igroup[3];
1383 unsigned char ogroup[4];
1384 int c;
1385 int n;
1386
1387 igroup[0] = igroup[1] = igroup[2] = 0;
1388 for (n = 0; n < 3 && i < len; n++, i++) {
1389 c = data[i];
1390 igroup[n] = (unsigned char) c;
1391 }
1392
1393 if (n > 0) {
1394 ogroup[0] = dtable[igroup[0] >> 2];
1395 ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1396 ogroup[2] =
1397 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1398 ogroup[3] = dtable[igroup[2] & 0x3F];
1399
1400 if (n < 3) {
1401 ogroup[3] = '=';
1402 if (n < 2) {
1403 ogroup[2] = '=';
1404 }
1405 }
1406
1407 if (linelen >= B64LINELEN) {
1408 count = xmlOutputBufferWrite(out, 2, B64CRLF);
1409 if (count == -1)
1410 return -1;
1411 sum += count;
1412 linelen = 0;
1413 }
1414 count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1415 if (count == -1)
1416 return -1;
1417 sum += count;
1418
1419 linelen += 4;
1420 }
Daniel Veillard929714b2003-10-22 12:34:36 +00001421
1422 if (i >= len)
1423 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001424 }
1425
Daniel Veillard1d211e22003-10-20 22:32:39 +00001426 return sum;
1427}
1428
1429/**
1430 * xmlTextWriterWriteBase64:
1431 * @writer: the xmlTextWriterPtr
1432 * @data: binary data
1433 * @start: the position within the data of the first byte to encode
1434 * @len: the number of bytes to encode
1435 *
1436 * Write an base64 encoded xml text.
1437 *
1438 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1439 */
1440int
Daniel Veillardab69f362004-02-17 11:40:32 +00001441xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001442 int start, int len)
1443{
1444 int count;
1445 int sum;
1446 xmlLinkPtr lk;
1447 xmlTextWriterStackEntry *p;
1448
1449 if (writer == NULL)
1450 return -1;
1451
Daniel Veillard1d211e22003-10-20 22:32:39 +00001452 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001453 lk = xmlListFront(writer->nodes);
1454 if (lk != 0) {
1455 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1456 if (p != 0) {
1457 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001458 if (count < 0)
1459 return -1;
1460 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001461 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001462 }
1463
Daniel Veillardab69f362004-02-17 11:40:32 +00001464 if (writer->indent)
1465 writer->doindent = 0;
1466
Daniel Veillard1d211e22003-10-20 22:32:39 +00001467 count =
1468 xmlOutputBufferWriteBase64(writer->out, len,
1469 (unsigned char *) data + start);
1470 if (count < 0)
1471 return -1;
1472 sum += count;
1473
1474 return sum;
1475}
1476
1477/**
1478 * xmlOutputBufferWriteBinHex:
1479 * @out: the xmlOutputBufferPtr
1480 * @data: binary data
1481 * @len: the number of bytes to encode
1482 *
1483 * Write hqx encoded data to an xmlOutputBuffer.
1484 * ::todo
1485 *
1486 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1487 */
1488static int
Daniel Veillardab69f362004-02-17 11:40:32 +00001489xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1490 int len, const unsigned char *data)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001491{
Daniel Veillardab69f362004-02-17 11:40:32 +00001492 int count;
1493 int sum;
1494 static char hex[] = "0123456789ABCDEF";
1495 int i;
1496
1497 if ((out == NULL) || ((data == 0) && (len != 0))) {
1498 return -1;
1499 }
1500
1501 sum = 0;
1502 for (i = 0; i < len; i++) {
1503 count =
1504 xmlOutputBufferWrite(out, 1,
1505 (const char *) &hex[data[i] >> 4]);
1506 if (count == -1)
1507 return -1;
1508 sum += count;
1509 count =
1510 xmlOutputBufferWrite(out, 1,
1511 (const char *) &hex[data[i] & 0xF]);
1512 if (count == -1)
1513 return -1;
1514 sum += count;
1515 }
1516
1517 return sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001518}
1519
1520/**
1521 * xmlTextWriterWriteBinHex:
1522 * @writer: the xmlTextWriterPtr
1523 * @data: binary data
1524 * @start: the position within the data of the first byte to encode
1525 * @len: the number of bytes to encode
1526 *
1527 * Write a BinHex encoded xml text.
1528 *
1529 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1530 */
1531int
Daniel Veillardab69f362004-02-17 11:40:32 +00001532xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001533 int start, int len)
1534{
1535 int count;
1536 int sum;
1537 xmlLinkPtr lk;
1538 xmlTextWriterStackEntry *p;
1539
1540 if (writer == NULL)
1541 return -1;
1542
Daniel Veillard1d211e22003-10-20 22:32:39 +00001543 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001544 lk = xmlListFront(writer->nodes);
1545 if (lk != 0) {
1546 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1547 if (p != 0) {
1548 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001549 if (count < 0)
1550 return -1;
1551 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001552 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001553 }
1554
Daniel Veillardab69f362004-02-17 11:40:32 +00001555 if (writer->indent)
1556 writer->doindent = 0;
1557
Daniel Veillard1d211e22003-10-20 22:32:39 +00001558 count =
1559 xmlOutputBufferWriteBinHex(writer->out, len,
1560 (unsigned char *) data + start);
1561 if (count < 0)
1562 return -1;
1563 sum += count;
1564
1565 return sum;
1566}
1567
1568/**
1569 * xmlTextWriterStartAttribute:
1570 * @writer: the xmlTextWriterPtr
1571 * @name: element name
1572 *
1573 * Start an xml attribute.
1574 *
1575 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1576 */
1577int
1578xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1579{
1580 int count;
1581 int sum;
1582 xmlLinkPtr lk;
1583 xmlTextWriterStackEntry *p;
1584
1585 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1586 return -1;
1587
1588 sum = 0;
1589 lk = xmlListFront(writer->nodes);
1590 if (lk == 0)
1591 return -1;
1592
1593 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1594 if (p == 0)
1595 return -1;
1596
1597 switch (p->state) {
1598 case XML_TEXTWRITER_ATTRIBUTE:
1599 count = xmlTextWriterEndAttribute(writer);
1600 if (count < 0)
1601 return -1;
1602 sum += count;
1603 /* fallthrough */
1604 case XML_TEXTWRITER_NAME:
1605 count = xmlOutputBufferWriteString(writer->out, " ");
1606 if (count < 0)
1607 return -1;
1608 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001609 count =
1610 xmlOutputBufferWriteString(writer->out,
1611 (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001612 if (count < 0)
1613 return -1;
1614 sum += count;
1615 count = xmlOutputBufferWriteString(writer->out, "=");
1616 if (count < 0)
1617 return -1;
1618 sum += count;
1619 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1620 if (count < 0)
1621 return -1;
1622 sum += count;
1623 p->state = XML_TEXTWRITER_ATTRIBUTE;
1624 break;
1625 default:
1626 return -1;
1627 }
1628
1629 return sum;
1630}
1631
1632/**
1633 * xmlTextWriterStartAttributeNS:
1634 * @writer: the xmlTextWriterPtr
1635 * @prefix: namespace prefix or NULL
1636 * @name: element local name
1637 * @namespaceURI: namespace URI or NULL
1638 *
1639 * Start an xml attribute with namespace support.
1640 *
1641 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1642 */
1643int
1644xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1645 const xmlChar * prefix, const xmlChar * name,
1646 const xmlChar * namespaceURI)
1647{
1648 int count;
1649 int sum;
1650 xmlChar *buf;
1651 xmlTextWriterNsStackEntry *p;
1652
1653 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1654 return -1;
1655
1656 buf = 0;
1657 if (prefix != 0) {
1658 buf = xmlStrdup(prefix);
1659 buf = xmlStrcat(buf, BAD_CAST ":");
1660 }
1661 buf = xmlStrcat(buf, name);
1662
1663 sum = 0;
1664 count = xmlTextWriterStartAttribute(writer, buf);
1665 xmlFree(buf);
1666 if (count < 0)
1667 return -1;
1668 sum += count;
1669
1670 if (namespaceURI != 0) {
1671 buf = xmlStrdup(BAD_CAST "xmlns");
1672 if (prefix != 0) {
1673 buf = xmlStrcat(buf, BAD_CAST ":");
1674 buf = xmlStrcat(buf, prefix);
1675 }
1676
1677 p = (xmlTextWriterNsStackEntry *)
1678 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1679 if (p == 0) {
1680 xmlGenericError(xmlGenericErrorContext,
1681 "xmlTextWriterStartAttributeNS : out of memory!\n");
1682 return -1;
1683 }
1684
1685 p->prefix = buf;
1686 p->uri = xmlStrdup(namespaceURI);
1687 if (p->uri == 0) {
1688 xmlGenericError(xmlGenericErrorContext,
1689 "xmlTextWriterStartAttributeNS : out of memory!\n");
1690 xmlFree(p);
1691 return -1;
1692 }
1693 p->elem = xmlListFront(writer->nodes);
1694
1695 xmlListPushFront(writer->nsstack, p);
1696 }
1697
1698 return sum;
1699}
1700
1701/**
1702 * xmlTextWriterEndAttribute:
1703 * @writer: the xmlTextWriterPtr
1704 *
1705 * End the current xml element.
1706 *
1707 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1708 */
1709int
1710xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1711{
1712 int count;
1713 int sum;
1714 xmlLinkPtr lk;
1715 xmlTextWriterStackEntry *p;
1716 xmlTextWriterNsStackEntry *np;
1717
1718 if (writer == NULL)
1719 return -1;
1720
1721 lk = xmlListFront(writer->nodes);
1722 if (lk == 0) {
1723 xmlListDelete(writer->nsstack);
1724 return -1;
1725 }
1726
1727 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1728 if (p == 0) {
1729 xmlListDelete(writer->nsstack);
1730 return -1;
1731 }
1732
1733 sum = 0;
1734 switch (p->state) {
1735 case XML_TEXTWRITER_ATTRIBUTE:
1736 p->state = XML_TEXTWRITER_NAME;
1737
1738 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1739 if (count < 0) {
1740 xmlListDelete(writer->nsstack);
1741 return -1;
1742 }
1743 sum += count;
1744
1745 while (!xmlListEmpty(writer->nsstack)) {
1746 lk = xmlListFront(writer->nsstack);
1747 np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
1748 if (np != 0) {
1749 count =
1750 xmlTextWriterWriteAttribute(writer, np->prefix,
1751 np->uri);
1752 if (count < 0) {
1753 xmlListDelete(writer->nsstack);
1754 return -1;
1755 }
1756 sum += count;
1757 }
1758
1759 xmlListPopFront(writer->nsstack);
1760 }
1761 break;
1762
1763 default:
1764 xmlListClear(writer->nsstack);
1765 return -1;
1766 }
1767
1768 return sum;
1769}
1770
1771/**
1772 * xmlTextWriterWriteFormatAttribute:
1773 * @writer: the xmlTextWriterPtr
1774 * @name: attribute name
1775 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001776 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001777 *
1778 * Write a formatted xml attribute.
1779 *
1780 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1781 */
1782int
1783xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1784 const xmlChar * name, const char *format,
1785 ...)
1786{
1787 int rc;
1788 va_list ap;
1789
1790 va_start(ap, format);
1791
1792 rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1793
1794 va_end(ap);
1795 return rc;
1796}
1797
1798/**
1799 * xmlTextWriterWriteVFormatAttribute:
1800 * @writer: the xmlTextWriterPtr
1801 * @name: attribute name
1802 * @format: format string (see printf)
1803 * @argptr: pointer to the first member of the variable argument list.
1804 *
1805 * Write a formatted xml attribute.
1806 *
1807 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1808 */
1809int
1810xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
1811 const xmlChar * name,
1812 const char *format, va_list argptr)
1813{
1814 int rc;
1815 xmlChar *buf;
1816
1817 if (writer == NULL)
1818 return -1;
1819
1820 buf = xmlTextWriterVSprintf(format, argptr);
1821 if (buf == 0)
1822 return 0;
1823
1824 rc = xmlTextWriterWriteAttribute(writer, name, buf);
1825
1826 xmlFree(buf);
1827 return rc;
1828}
1829
1830/**
1831 * xmlTextWriterWriteAttribute:
1832 * @writer: the xmlTextWriterPtr
1833 * @name: attribute name
1834 * @content: attribute content
1835 *
1836 * Write an xml attribute.
1837 *
1838 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1839 */
1840int
1841xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
1842 const xmlChar * content)
1843{
1844 int count;
1845 int sum;
1846
1847 sum = 0;
1848 count = xmlTextWriterStartAttribute(writer, name);
1849 if (count < 0)
1850 return -1;
1851 sum += count;
1852 count = xmlTextWriterWriteString(writer, content);
1853 if (count < 0)
1854 return -1;
1855 sum += count;
1856 count = xmlTextWriterEndAttribute(writer);
1857 if (count < 0)
1858 return -1;
1859 sum += count;
1860
1861 return sum;
1862}
1863
1864/**
1865 * xmlTextWriterWriteFormatAttributeNS:
1866 * @writer: the xmlTextWriterPtr
1867 * @prefix: namespace prefix
1868 * @name: attribute local name
1869 * @namespaceURI: namespace URI
1870 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001871 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001872 *
1873 * Write a formatted xml attribute.with namespace support
1874 *
1875 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1876 */
1877int
1878xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
1879 const xmlChar * prefix,
1880 const xmlChar * name,
1881 const xmlChar * namespaceURI,
1882 const char *format, ...)
1883{
1884 int rc;
1885 va_list ap;
1886
1887 va_start(ap, format);
1888
1889 rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
1890 namespaceURI, format, ap);
1891
1892 va_end(ap);
1893 return rc;
1894}
1895
1896/**
1897 * xmlTextWriterWriteVFormatAttributeNS:
1898 * @writer: the xmlTextWriterPtr
1899 * @prefix: namespace prefix
1900 * @name: attribute local name
1901 * @namespaceURI: namespace URI
1902 * @format: format string (see printf)
1903 * @argptr: pointer to the first member of the variable argument list.
1904 *
1905 * Write a formatted xml attribute.with namespace support
1906 *
1907 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1908 */
1909int
1910xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
1911 const xmlChar * prefix,
1912 const xmlChar * name,
1913 const xmlChar * namespaceURI,
1914 const char *format, va_list argptr)
1915{
1916 int rc;
1917 xmlChar *buf;
1918
1919 if (writer == NULL)
1920 return -1;
1921
1922 buf = xmlTextWriterVSprintf(format, argptr);
1923 if (buf == 0)
1924 return 0;
1925
1926 rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
1927 buf);
1928
1929 xmlFree(buf);
1930 return rc;
1931}
1932
1933/**
1934 * xmlTextWriterWriteAttributeNS:
1935 * @writer: the xmlTextWriterPtr
1936 * @prefix: namespace prefix
1937 * @name: attribute local name
1938 * @namespaceURI: namespace URI
1939 * @content: attribute content
1940 *
1941 * Write an xml attribute.
1942 *
1943 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1944 */
1945int
1946xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
1947 const xmlChar * prefix, const xmlChar * name,
1948 const xmlChar * namespaceURI,
1949 const xmlChar * content)
1950{
1951 int count;
1952 int sum;
1953 xmlChar *buf;
1954
1955 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1956 return -1;
1957
1958 buf = 0;
1959 if (prefix != NULL) {
1960 buf = xmlStrdup(prefix);
1961 buf = xmlStrcat(buf, BAD_CAST ":");
1962 }
1963 buf = xmlStrcat(buf, name);
1964
1965 sum = 0;
1966 count = xmlTextWriterWriteAttribute(writer, buf, content);
1967 xmlFree(buf);
1968 if (count < 0)
1969 return -1;
1970 sum += count;
1971
1972 if (namespaceURI != NULL) {
1973 buf = 0;
1974 buf = xmlStrdup(BAD_CAST "xmlns");
1975 if (prefix != NULL) {
1976 buf = xmlStrcat(buf, BAD_CAST ":");
1977 buf = xmlStrcat(buf, prefix);
1978 }
1979 count = xmlTextWriterWriteAttribute(writer, buf, namespaceURI);
1980 xmlFree(buf);
1981 if (count < 0)
1982 return -1;
1983 sum += count;
1984 }
1985 return sum;
1986}
1987
1988/**
1989 * xmlTextWriterWriteFormatElement:
1990 * @writer: the xmlTextWriterPtr
1991 * @name: element name
1992 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001993 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001994 *
1995 * Write a formatted xml element.
1996 *
1997 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1998 */
1999int
2000xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2001 const xmlChar * name, const char *format,
2002 ...)
2003{
2004 int rc;
2005 va_list ap;
2006
2007 va_start(ap, format);
2008
2009 rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2010
2011 va_end(ap);
2012 return rc;
2013}
2014
2015/**
2016 * xmlTextWriterWriteVFormatElement:
2017 * @writer: the xmlTextWriterPtr
2018 * @name: element name
2019 * @format: format string (see printf)
2020 * @argptr: pointer to the first member of the variable argument list.
2021 *
2022 * Write a formatted xml element.
2023 *
2024 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2025 */
2026int
2027xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2028 const xmlChar * name, const char *format,
2029 va_list argptr)
2030{
2031 int rc;
2032 xmlChar *buf;
2033
2034 if (writer == NULL)
2035 return -1;
2036
2037 buf = xmlTextWriterVSprintf(format, argptr);
2038 if (buf == 0)
2039 return 0;
2040
2041 rc = xmlTextWriterWriteElement(writer, name, buf);
2042
2043 xmlFree(buf);
2044 return rc;
2045}
2046
2047/**
2048 * xmlTextWriterWriteElement:
2049 * @writer: the xmlTextWriterPtr
2050 * @name: element name
2051 * @content: element content
2052 *
2053 * Write an xml element.
2054 *
2055 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2056 */
2057int
2058xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2059 const xmlChar * content)
2060{
2061 int count;
2062 int sum;
2063
2064 sum = 0;
2065 count = xmlTextWriterStartElement(writer, name);
2066 if (count == -1)
2067 return -1;
2068 sum += count;
2069 count = xmlTextWriterWriteString(writer, content);
2070 if (count == -1)
2071 return -1;
2072 sum += count;
2073 count = xmlTextWriterEndElement(writer);
2074 if (count == -1)
2075 return -1;
2076 sum += count;
2077
2078 return sum;
2079}
2080
2081/**
2082 * xmlTextWriterWriteFormatElementNS:
2083 * @writer: the xmlTextWriterPtr
2084 * @prefix: namespace prefix
2085 * @name: element local name
2086 * @namespaceURI: namespace URI
2087 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002088 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002089 *
2090 * Write a formatted xml element with namespace support.
2091 *
2092 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2093 */
2094int
2095xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2096 const xmlChar * prefix,
2097 const xmlChar * name,
2098 const xmlChar * namespaceURI,
2099 const char *format, ...)
2100{
2101 int rc;
2102 va_list ap;
2103
2104 va_start(ap, format);
2105
2106 rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2107 namespaceURI, format, ap);
2108
2109 va_end(ap);
2110 return rc;
2111}
2112
2113/**
2114 * xmlTextWriterWriteVFormatElementNS:
2115 * @writer: the xmlTextWriterPtr
2116 * @prefix: namespace prefix
2117 * @name: element local name
2118 * @namespaceURI: namespace URI
2119 * @format: format string (see printf)
2120 * @argptr: pointer to the first member of the variable argument list.
2121 *
2122 * Write a formatted xml element with namespace support.
2123 *
2124 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2125 */
2126int
2127xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2128 const xmlChar * prefix,
2129 const xmlChar * name,
2130 const xmlChar * namespaceURI,
2131 const char *format, va_list argptr)
2132{
2133 int rc;
2134 xmlChar *buf;
2135
2136 if (writer == NULL)
2137 return -1;
2138
2139 buf = xmlTextWriterVSprintf(format, argptr);
2140 if (buf == 0)
2141 return 0;
2142
2143 rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2144 buf);
2145
2146 xmlFree(buf);
2147 return rc;
2148}
2149
2150/**
2151 * xmlTextWriterWriteElementNS:
2152 * @writer: the xmlTextWriterPtr
2153 * @prefix: namespace prefix
2154 * @name: element local name
2155 * @namespaceURI: namespace URI
2156 * @content: element content
2157 *
2158 * Write an xml element with namespace support.
2159 *
2160 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2161 */
2162int
2163xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2164 const xmlChar * prefix, const xmlChar * name,
2165 const xmlChar * namespaceURI,
2166 const xmlChar * content)
2167{
2168 int count;
2169 int sum;
2170
2171 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2172 return -1;
2173
2174 sum = 0;
2175 count =
2176 xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2177 if (count < 0)
2178 return -1;
2179 sum += count;
2180 count = xmlTextWriterWriteString(writer, content);
2181 if (count == -1)
2182 return -1;
2183 sum += count;
2184 count = xmlTextWriterEndElement(writer);
2185 if (count == -1)
2186 return -1;
2187 sum += count;
2188
2189 return sum;
2190}
2191
2192/**
2193 * xmlTextWriterStartPI:
2194 * @writer: the xmlTextWriterPtr
2195 * @target: PI target
2196 *
2197 * Start an xml PI.
2198 *
2199 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2200 */
2201int
2202xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2203{
2204 int count;
2205 int sum;
2206 xmlLinkPtr lk;
2207 xmlTextWriterStackEntry *p;
2208
2209 if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2210 return -1;
2211
2212 if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
2213 xmlGenericError(xmlGenericErrorContext,
2214 "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2215 return -1;
2216 }
2217
2218 sum = 0;
2219 lk = xmlListFront(writer->nodes);
2220 if (lk != 0) {
2221 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2222 if (p != 0) {
2223 switch (p->state) {
2224 case XML_TEXTWRITER_ATTRIBUTE:
2225 count = xmlTextWriterEndAttribute(writer);
2226 if (count < 0)
2227 return -1;
2228 sum += count;
2229 /* fallthrough */
2230 case XML_TEXTWRITER_NAME:
2231 count = xmlOutputBufferWriteString(writer->out, ">");
2232 if (count < 0)
2233 return -1;
2234 sum += count;
2235 p->state = XML_TEXTWRITER_TEXT;
2236 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00002237 case XML_TEXTWRITER_NONE:
2238 case XML_TEXTWRITER_TEXT:
2239 case XML_TEXTWRITER_DTD:
2240 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002241 case XML_TEXTWRITER_PI:
2242 case XML_TEXTWRITER_PI_TEXT:
2243 xmlGenericError(xmlGenericErrorContext,
2244 "xmlTextWriterStartPI : nested PI!\n");
2245 return -1;
2246 default:
2247 return -1;
2248 }
2249 }
2250 }
2251
2252 p = (xmlTextWriterStackEntry *)
2253 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2254 if (p == 0) {
2255 xmlGenericError(xmlGenericErrorContext,
2256 "xmlTextWriterStartPI : out of memory!\n");
2257 return -1;
2258 }
2259
2260 p->name = xmlStrdup(target);
2261 if (p->name == 0) {
2262 xmlGenericError(xmlGenericErrorContext,
2263 "xmlTextWriterStartPI : out of memory!\n");
2264 xmlFree(p);
2265 return -1;
2266 }
2267 p->state = XML_TEXTWRITER_PI;
2268
2269 xmlListPushFront(writer->nodes, p);
2270
2271 count = xmlOutputBufferWriteString(writer->out, "<?");
2272 if (count < 0)
2273 return -1;
2274 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002275 count =
2276 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002277 if (count < 0)
2278 return -1;
2279 sum += count;
2280
2281 return sum;
2282}
2283
2284/**
2285 * xmlTextWriterEndPI:
2286 * @writer: the xmlTextWriterPtr
2287 *
2288 * End the current xml PI.
2289 *
2290 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2291 */
2292int
2293xmlTextWriterEndPI(xmlTextWriterPtr writer)
2294{
2295 int count;
2296 int sum;
2297 xmlLinkPtr lk;
2298 xmlTextWriterStackEntry *p;
2299
2300 if (writer == NULL)
2301 return -1;
2302
2303 lk = xmlListFront(writer->nodes);
2304 if (lk == 0)
2305 return 0;
2306
2307 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2308 if (p == 0)
2309 return 0;
2310
2311 sum = 0;
2312 switch (p->state) {
2313 case XML_TEXTWRITER_PI:
2314 case XML_TEXTWRITER_PI_TEXT:
2315 count = xmlOutputBufferWriteString(writer->out, "?>");
2316 if (count < 0)
2317 return -1;
2318 sum += count;
2319 break;
2320 default:
2321 return -1;
2322 }
2323
2324 xmlListPopFront(writer->nodes);
2325 return sum;
2326}
2327
2328/**
2329 * xmlTextWriterWriteFormatPI:
2330 * @writer: the xmlTextWriterPtr
2331 * @target: PI target
2332 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002333 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002334 *
2335 * Write a formatted PI.
2336 *
2337 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2338 */
2339int
2340xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2341 const char *format, ...)
2342{
2343 int rc;
2344 va_list ap;
2345
2346 va_start(ap, format);
2347
2348 rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2349
2350 va_end(ap);
2351 return rc;
2352}
2353
2354/**
2355 * xmlTextWriterWriteVFormatPI:
2356 * @writer: the xmlTextWriterPtr
2357 * @target: PI target
2358 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002359 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002360 *
2361 * Write a formatted xml PI.
2362 *
2363 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2364 */
2365int
2366xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2367 const xmlChar * target, const char *format,
2368 va_list argptr)
2369{
2370 int rc;
2371 xmlChar *buf;
2372
2373 if (writer == NULL)
2374 return -1;
2375
2376 buf = xmlTextWriterVSprintf(format, argptr);
2377 if (buf == 0)
2378 return 0;
2379
2380 rc = xmlTextWriterWritePI(writer, target, buf);
2381
2382 xmlFree(buf);
2383 return rc;
2384}
2385
2386/**
2387 * xmlTextWriterWritePI:
2388 * @writer: the xmlTextWriterPtr
2389 * @target: PI target
2390 * @content: PI content
2391 *
2392 * Write an xml PI.
2393 *
2394 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2395 */
2396int
2397xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2398 const xmlChar * content)
2399{
2400 int count;
2401 int sum;
2402
2403 sum = 0;
2404 count = xmlTextWriterStartPI(writer, target);
2405 if (count == -1)
2406 return -1;
2407 sum += count;
2408 if (content != 0) {
2409 count = xmlTextWriterWriteString(writer, content);
2410 if (count == -1)
2411 return -1;
2412 sum += count;
2413 }
2414 count = xmlTextWriterEndPI(writer);
2415 if (count == -1)
2416 return -1;
2417 sum += count;
2418
2419 return sum;
2420}
2421
2422/**
2423 * xmlTextWriterStartCDATA:
2424 * @writer: the xmlTextWriterPtr
2425 *
2426 * Start an xml CDATA section.
2427 *
2428 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2429 */
2430int
2431xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2432{
2433 int count;
2434 int sum;
2435 xmlLinkPtr lk;
2436 xmlTextWriterStackEntry *p;
2437
2438 if (writer == NULL)
2439 return -1;
2440
2441 sum = 0;
2442 lk = xmlListFront(writer->nodes);
2443 if (lk != 0) {
2444 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2445 if (p != 0) {
2446 switch (p->state) {
2447 case XML_TEXTWRITER_NONE:
2448 case XML_TEXTWRITER_PI:
2449 case XML_TEXTWRITER_PI_TEXT:
2450 break;
2451 case XML_TEXTWRITER_ATTRIBUTE:
2452 count = xmlTextWriterEndAttribute(writer);
2453 if (count < 0)
2454 return -1;
2455 sum += count;
2456 /* fallthrough */
2457 case XML_TEXTWRITER_NAME:
2458 count = xmlOutputBufferWriteString(writer->out, ">");
2459 if (count < 0)
2460 return -1;
2461 sum += count;
2462 p->state = XML_TEXTWRITER_TEXT;
2463 break;
2464 case XML_TEXTWRITER_CDATA:
2465 xmlGenericError(xmlGenericErrorContext,
2466 "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2467 return -1;
2468 default:
2469 return -1;
2470 }
2471 }
2472 }
2473
2474 p = (xmlTextWriterStackEntry *)
2475 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2476 if (p == 0) {
2477 xmlGenericError(xmlGenericErrorContext,
2478 "xmlTextWriterStartCDATA : out of memory!\n");
2479 return -1;
2480 }
2481
2482 p->name = 0;
2483 p->state = XML_TEXTWRITER_CDATA;
2484
2485 xmlListPushFront(writer->nodes, p);
2486
2487 count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2488 if (count < 0)
2489 return -1;
2490 sum += count;
2491
2492 return sum;
2493}
2494
2495/**
2496 * xmlTextWriterEndCDATA:
2497 * @writer: the xmlTextWriterPtr
2498 *
2499 * End an xml CDATA section.
2500 *
2501 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2502 */
2503int
2504xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2505{
2506 int count;
2507 int sum;
2508 xmlLinkPtr lk;
2509 xmlTextWriterStackEntry *p;
2510
2511 if (writer == NULL)
2512 return -1;
2513
2514 lk = xmlListFront(writer->nodes);
2515 if (lk == 0)
2516 return -1;
2517
2518 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2519 if (p == 0)
2520 return -1;
2521
2522 sum = 0;
2523 switch (p->state) {
2524 case XML_TEXTWRITER_CDATA:
2525 count = xmlOutputBufferWriteString(writer->out, "]]>");
2526 if (count < 0)
2527 return -1;
2528 sum += count;
2529 break;
2530 default:
2531 return -1;
2532 }
2533
2534 xmlListPopFront(writer->nodes);
2535 return sum;
2536}
2537
2538/**
2539 * xmlTextWriterWriteFormatCDATA:
2540 * @writer: the xmlTextWriterPtr
2541 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002542 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002543 *
2544 * Write a formatted xml CDATA.
2545 *
2546 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2547 */
2548int
2549xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2550 ...)
2551{
2552 int rc;
2553 va_list ap;
2554
2555 va_start(ap, format);
2556
2557 rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2558
2559 va_end(ap);
2560 return rc;
2561}
2562
2563/**
2564 * xmlTextWriterWriteVFormatCDATA:
2565 * @writer: the xmlTextWriterPtr
2566 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002567 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002568 *
2569 * Write a formatted xml CDATA.
2570 *
2571 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2572 */
2573int
2574xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2575 va_list argptr)
2576{
2577 int rc;
2578 xmlChar *buf;
2579
2580 if (writer == NULL)
2581 return -1;
2582
2583 buf = xmlTextWriterVSprintf(format, argptr);
2584 if (buf == 0)
2585 return 0;
2586
2587 rc = xmlTextWriterWriteCDATA(writer, buf);
2588
2589 xmlFree(buf);
2590 return rc;
2591}
2592
2593/**
2594 * xmlTextWriterWriteCDATA:
2595 * @writer: the xmlTextWriterPtr
2596 * @content: CDATA content
2597 *
2598 * Write an xml CDATA.
2599 *
2600 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2601 */
2602int
2603xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2604{
2605 int count;
2606 int sum;
2607
2608 sum = 0;
2609 count = xmlTextWriterStartCDATA(writer);
2610 if (count == -1)
2611 return -1;
2612 sum += count;
2613 if (content != 0) {
2614 count = xmlTextWriterWriteString(writer, content);
2615 if (count == -1)
2616 return -1;
2617 sum += count;
2618 }
2619 count = xmlTextWriterEndCDATA(writer);
2620 if (count == -1)
2621 return -1;
2622 sum += count;
2623
2624 return sum;
2625}
2626
2627/**
2628 * xmlTextWriterStartDTD:
2629 * @writer: the xmlTextWriterPtr
2630 * @name: the name of the DTD
2631 * @pubid: the public identifier, which is an alternative to the system identifier
2632 * @sysid: the system identifier, which is the URI of the DTD
2633 *
2634 * Start an xml DTD.
2635 *
2636 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2637 */
2638int
2639xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2640 const xmlChar * name,
2641 const xmlChar * pubid, const xmlChar * sysid)
2642{
2643 int count;
2644 int sum;
2645 xmlLinkPtr lk;
2646 xmlTextWriterStackEntry *p;
2647
2648 if (writer == NULL || name == NULL || *name == '\0')
2649 return -1;
2650
2651 sum = 0;
2652 lk = xmlListFront(writer->nodes);
Daniel Veillardab69f362004-02-17 11:40:32 +00002653 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00002654 xmlGenericError(xmlGenericErrorContext,
2655 "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2656 return -1;
2657 }
2658
2659 p = (xmlTextWriterStackEntry *)
2660 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2661 if (p == 0) {
2662 xmlGenericError(xmlGenericErrorContext,
2663 "xmlTextWriterStartDTD : out of memory!\n");
2664 return -1;
2665 }
2666
2667 p->name = xmlStrdup(name);
2668 if (p->name == 0) {
2669 xmlGenericError(xmlGenericErrorContext,
2670 "xmlTextWriterStartDTD : out of memory!\n");
2671 xmlFree(p);
2672 return -1;
2673 }
2674 p->state = XML_TEXTWRITER_DTD;
2675
2676 xmlListPushFront(writer->nodes, p);
2677
2678 count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2679 if (count < 0)
2680 return -1;
2681 sum += count;
2682 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2683 if (count < 0)
2684 return -1;
2685 sum += count;
2686
2687 if (pubid != 0) {
2688 if (sysid == 0) {
2689 xmlGenericError(xmlGenericErrorContext,
2690 "xmlTextWriterStartDTD : system identifier needed!\n");
2691 return -1;
2692 }
2693
Daniel Veillard500a1de2004-03-22 15:22:58 +00002694 if (writer->indent)
2695 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2696 else
2697 count = xmlOutputBufferWrite(writer->out, 1, " ");
2698 if (count < 0)
2699 return -1;
2700 sum += count;
2701
2702 count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2703 if (count < 0)
2704 return -1;
2705 sum += count;
2706
2707 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002708 if (count < 0)
2709 return -1;
2710 sum += count;
2711
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002712 count =
2713 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002714 if (count < 0)
2715 return -1;
2716 sum += count;
2717
Daniel Veillard500a1de2004-03-22 15:22:58 +00002718 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 }
2723
2724 if (sysid != 0) {
2725 if (pubid == 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00002726 if (writer->indent)
2727 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2728 else
2729 count = xmlOutputBufferWrite(writer->out, 1, " ");
2730 if (count < 0)
2731 return -1;
2732 sum += count;
2733 count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2734 if (count < 0)
2735 return -1;
2736 sum += count;
2737 } else if (writer->indent) {
2738 count = xmlOutputBufferWriteString(writer->out, "\n ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00002739 if (count < 0)
2740 return -1;
2741 sum += count;
2742 }
2743
Daniel Veillard500a1de2004-03-22 15:22:58 +00002744 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002745 if (count < 0)
2746 return -1;
2747 sum += count;
2748
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002749 count =
2750 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002751 if (count < 0)
2752 return -1;
2753 sum += count;
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 }
2760
2761 return sum;
2762}
2763
2764/**
2765 * xmlTextWriterEndDTD:
2766 * @writer: the xmlTextWriterPtr
2767 *
2768 * End an xml DTD.
2769 *
2770 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2771 */
2772int
2773xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2774{
Daniel Veillard500a1de2004-03-22 15:22:58 +00002775 int loop;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002776 int count;
2777 int sum;
2778 xmlLinkPtr lk;
2779 xmlTextWriterStackEntry *p;
2780
2781 if (writer == NULL)
2782 return -1;
2783
2784 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002785 loop = 1;
2786 while (loop) {
2787 lk = xmlListFront(writer->nodes);
2788 if (lk == NULL)
Daniel Veillard1d211e22003-10-20 22:32:39 +00002789 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002790 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2791 if (p == 0)
2792 break;
2793 switch (p->state) {
2794 case XML_TEXTWRITER_DTD_TEXT:
2795 count = xmlOutputBufferWriteString(writer->out, "]");
2796 if (count < 0)
2797 return -1;
2798 sum += count;
2799 /* fallthrough */
2800 case XML_TEXTWRITER_DTD:
2801 count = xmlOutputBufferWriteString(writer->out, ">");
2802
2803 if (writer->indent) {
2804 if (count < 0)
2805 return -1;
2806 sum += count;
2807 count = xmlOutputBufferWriteString(writer->out, "\n");
2808 }
2809
2810 xmlListPopFront(writer->nodes);
2811 break;
2812 case XML_TEXTWRITER_DTD_ELEM:
2813 case XML_TEXTWRITER_DTD_ELEM_TEXT:
2814 count = xmlTextWriterEndDTDElement(writer);
2815 break;
2816 case XML_TEXTWRITER_DTD_ATTL:
2817 case XML_TEXTWRITER_DTD_ATTL_TEXT:
2818 count = xmlTextWriterEndDTDAttlist(writer);
2819 break;
2820 case XML_TEXTWRITER_DTD_ENTY:
2821 case XML_TEXTWRITER_DTD_PENT:
2822 case XML_TEXTWRITER_DTD_ENTY_TEXT:
2823 count = xmlTextWriterEndDTDEntity(writer);
2824 break;
2825 case XML_TEXTWRITER_COMMENT:
2826 count = xmlTextWriterEndComment(writer);
2827 break;
2828 default:
2829 loop = 0;
2830 continue;
2831 }
2832
2833 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00002834 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002835 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002836 }
2837
Daniel Veillard1d211e22003-10-20 22:32:39 +00002838 return sum;
2839}
2840
2841/**
2842 * xmlTextWriterWriteFormatDTD:
2843 * @writer: the xmlTextWriterPtr
2844 * @name: the name of the DTD
2845 * @pubid: the public identifier, which is an alternative to the system identifier
2846 * @sysid: the system identifier, which is the URI of the DTD
2847 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002848 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002849 *
2850 * Write a DTD with a formatted markup declarations part.
2851 *
2852 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2853 */
2854int
2855xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
2856 const xmlChar * name,
2857 const xmlChar * pubid,
2858 const xmlChar * sysid, const char *format, ...)
2859{
2860 int rc;
2861 va_list ap;
2862
2863 va_start(ap, format);
2864
2865 rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
2866 ap);
2867
2868 va_end(ap);
2869 return rc;
2870}
2871
2872/**
2873 * xmlTextWriterWriteVFormatDTD:
2874 * @writer: the xmlTextWriterPtr
2875 * @name: the name of the DTD
2876 * @pubid: the public identifier, which is an alternative to the system identifier
2877 * @sysid: the system identifier, which is the URI of the DTD
2878 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002879 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002880 *
2881 * Write a DTD with a formatted markup declarations part.
2882 *
2883 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2884 */
2885int
2886xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
2887 const xmlChar * name,
2888 const xmlChar * pubid,
2889 const xmlChar * sysid,
2890 const char *format, va_list argptr)
2891{
2892 int rc;
2893 xmlChar *buf;
2894
2895 if (writer == NULL)
2896 return -1;
2897
2898 buf = xmlTextWriterVSprintf(format, argptr);
2899 if (buf == 0)
2900 return 0;
2901
2902 rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
2903
2904 xmlFree(buf);
2905 return rc;
2906}
2907
2908/**
2909 * xmlTextWriterWriteDTD:
2910 * @writer: the xmlTextWriterPtr
2911 * @name: the name of the DTD
2912 * @pubid: the public identifier, which is an alternative to the system identifier
2913 * @sysid: the system identifier, which is the URI of the DTD
William M. Brackb1d53162003-11-18 06:54:40 +00002914 * @subset: string content of the DTD
Daniel Veillard1d211e22003-10-20 22:32:39 +00002915 *
2916 * Write a DTD.
2917 *
2918 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2919 */
2920int
2921xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
2922 const xmlChar * name,
2923 const xmlChar * pubid,
2924 const xmlChar * sysid, const xmlChar * subset)
2925{
2926 int count;
2927 int sum;
2928
2929 sum = 0;
2930 count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
2931 if (count == -1)
2932 return -1;
2933 sum += count;
2934 if (subset != 0) {
2935 count = xmlTextWriterWriteString(writer, subset);
2936 if (count == -1)
2937 return -1;
2938 sum += count;
2939 }
2940 count = xmlTextWriterEndDTD(writer);
2941 if (count == -1)
2942 return -1;
2943 sum += count;
2944
2945 return sum;
2946}
2947
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002948/**
2949 * xmlTextWriterStartDTDElement:
2950 * @writer: the xmlTextWriterPtr
2951 * @name: the name of the DTD element
2952 *
2953 * Start an xml DTD element.
2954 *
2955 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2956 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00002957int
2958xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
2959{
2960 int count;
2961 int sum;
2962 xmlLinkPtr lk;
2963 xmlTextWriterStackEntry *p;
2964
2965 if (writer == NULL || name == NULL || *name == '\0')
2966 return -1;
2967
2968 sum = 0;
2969 lk = xmlListFront(writer->nodes);
2970 if (lk == 0) {
2971 return -1;
2972 }
2973
2974 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00002975 if (p != 0) {
2976 switch (p->state) {
2977 case XML_TEXTWRITER_DTD:
2978 count = xmlOutputBufferWriteString(writer->out, " [");
2979 if (count < 0)
2980 return -1;
2981 sum += count;
2982 if (writer->indent) {
2983 count = xmlOutputBufferWriteString(writer->out, "\n");
2984 if (count < 0)
2985 return -1;
2986 sum += count;
2987 }
2988 p->state = XML_TEXTWRITER_DTD_TEXT;
2989 /* fallthrough */
2990 case XML_TEXTWRITER_DTD_TEXT:
2991 case XML_TEXTWRITER_NONE:
2992 break;
2993 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00002994 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002995 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00002996 }
2997
2998 p = (xmlTextWriterStackEntry *)
2999 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3000 if (p == 0) {
3001 xmlGenericError(xmlGenericErrorContext,
3002 "xmlTextWriterStartDTDElement : out of memory!\n");
3003 return -1;
3004 }
3005
3006 p->name = xmlStrdup(name);
3007 if (p->name == 0) {
3008 xmlGenericError(xmlGenericErrorContext,
3009 "xmlTextWriterStartDTDElement : out of memory!\n");
3010 xmlFree(p);
3011 return -1;
3012 }
3013 p->state = XML_TEXTWRITER_DTD_ELEM;
3014
3015 xmlListPushFront(writer->nodes, p);
3016
Daniel Veillard500a1de2004-03-22 15:22:58 +00003017 if (writer->indent) {
3018 count = xmlTextWriterWriteIndent(writer);
3019 if (count < 0)
3020 return -1;
3021 sum += count;
3022 }
3023
Daniel Veillard1d211e22003-10-20 22:32:39 +00003024 count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3025 if (count < 0)
3026 return -1;
3027 sum += count;
3028 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3029 if (count < 0)
3030 return -1;
3031 sum += count;
3032
3033 return sum;
3034}
3035
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003036/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003037 * xmlTextWriterEndDTDElement:
3038 * @writer: the xmlTextWriterPtr
3039 *
3040 * End an xml DTD element.
3041 *
3042 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3043 */
3044int
3045xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3046{
3047 int count;
3048 int sum;
3049 xmlLinkPtr lk;
3050 xmlTextWriterStackEntry *p;
3051
3052 if (writer == NULL)
3053 return -1;
3054
3055 sum = 0;
3056 lk = xmlListFront(writer->nodes);
3057 if (lk == 0)
3058 return -1;
3059
3060 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3061 if (p == 0)
3062 return -1;
3063
3064 switch (p->state) {
3065 case XML_TEXTWRITER_DTD_ELEM:
3066 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3067 count = xmlOutputBufferWriteString(writer->out, ">");
3068 if (count < 0)
3069 return -1;
3070 sum += count;
3071 break;
3072 default:
3073 return -1;
3074 }
3075
3076 if (writer->indent) {
3077 count = xmlOutputBufferWriteString(writer->out, "\n");
3078 if (count < 0)
3079 return -1;
3080 sum += count;
3081 }
3082
3083 xmlListPopFront(writer->nodes);
3084 return sum;
3085}
3086
3087/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003088 * xmlTextWriterWriteFormatDTDElement:
3089 * @writer: the xmlTextWriterPtr
3090 * @name: the name of the DTD element
3091 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003092 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003093 *
3094 * Write a formatted DTD element.
3095 *
3096 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3097 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003098int
3099xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3100 const xmlChar * name,
3101 const char *format, ...)
3102{
3103 int rc;
3104 va_list ap;
3105
3106 va_start(ap, format);
3107
3108 rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3109
3110 va_end(ap);
3111 return rc;
3112}
3113
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003114/**
3115 * xmlTextWriterWriteVFormatDTDElement:
3116 * @writer: the xmlTextWriterPtr
3117 * @name: the name of the DTD element
3118 * @format: format string (see printf)
3119 * @argptr: pointer to the first member of the variable argument list.
3120 *
3121 * Write a formatted DTD element.
3122 *
3123 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3124 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003125int
3126xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3127 const xmlChar * name,
3128 const char *format, va_list argptr)
3129{
3130 int rc;
3131 xmlChar *buf;
3132
3133 if (writer == NULL)
3134 return -1;
3135
3136 buf = xmlTextWriterVSprintf(format, argptr);
3137 if (buf == 0)
3138 return 0;
3139
3140 rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3141
3142 xmlFree(buf);
3143 return rc;
3144}
3145
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003146/**
3147 * xmlTextWriterWriteDTDElement:
3148 * @writer: the xmlTextWriterPtr
3149 * @name: the name of the DTD element
3150 * @content: content of the element
3151 *
3152 * Write a DTD element.
3153 *
3154 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3155 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003156int
3157xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3158 const xmlChar * name, const xmlChar * content)
3159{
3160 int count;
3161 int sum;
3162
3163 if (content == NULL)
3164 return -1;
3165
3166 sum = 0;
3167 count = xmlTextWriterStartDTDElement(writer, name);
3168 if (count == -1)
3169 return -1;
3170 sum += count;
3171
Daniel Veillard1d211e22003-10-20 22:32:39 +00003172 count = xmlTextWriterWriteString(writer, content);
3173 if (count == -1)
3174 return -1;
3175 sum += count;
3176
3177 count = xmlTextWriterEndDTDElement(writer);
3178 if (count == -1)
3179 return -1;
3180 sum += count;
3181
3182 return sum;
3183}
3184
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003185/**
3186 * xmlTextWriterStartDTDAttlist:
3187 * @writer: the xmlTextWriterPtr
3188 * @name: the name of the DTD ATTLIST
3189 *
3190 * Start an xml DTD ATTLIST.
3191 *
3192 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3193 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003194int
3195xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3196{
3197 int count;
3198 int sum;
3199 xmlLinkPtr lk;
3200 xmlTextWriterStackEntry *p;
3201
3202 if (writer == NULL || name == NULL || *name == '\0')
3203 return -1;
3204
3205 sum = 0;
3206 lk = xmlListFront(writer->nodes);
3207 if (lk == 0) {
3208 return -1;
3209 }
3210
3211 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003212 if (p != 0) {
3213 switch (p->state) {
3214 case XML_TEXTWRITER_DTD:
3215 count = xmlOutputBufferWriteString(writer->out, " [");
3216 if (count < 0)
3217 return -1;
3218 sum += count;
3219 if (writer->indent) {
3220 count = xmlOutputBufferWriteString(writer->out, "\n");
3221 if (count < 0)
3222 return -1;
3223 sum += count;
3224 }
3225 p->state = XML_TEXTWRITER_DTD_TEXT;
3226 /* fallthrough */
3227 case XML_TEXTWRITER_DTD_TEXT:
3228 case XML_TEXTWRITER_NONE:
3229 break;
3230 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003231 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003232 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003233 }
3234
3235 p = (xmlTextWriterStackEntry *)
3236 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3237 if (p == 0) {
3238 xmlGenericError(xmlGenericErrorContext,
3239 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3240 return -1;
3241 }
3242
3243 p->name = xmlStrdup(name);
3244 if (p->name == 0) {
3245 xmlGenericError(xmlGenericErrorContext,
3246 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3247 xmlFree(p);
3248 return -1;
3249 }
3250 p->state = XML_TEXTWRITER_DTD_ATTL;
3251
3252 xmlListPushFront(writer->nodes, p);
3253
Daniel Veillard500a1de2004-03-22 15:22:58 +00003254 if (writer->indent) {
3255 count = xmlTextWriterWriteIndent(writer);
3256 if (count < 0)
3257 return -1;
3258 sum += count;
3259 }
3260
Daniel Veillard1d211e22003-10-20 22:32:39 +00003261 count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3262 if (count < 0)
3263 return -1;
3264 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +00003265 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003266 if (count < 0)
3267 return -1;
3268 sum += count;
3269
3270 return sum;
3271}
3272
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003273/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003274 * xmlTextWriterEndDTDAttlist:
3275 * @writer: the xmlTextWriterPtr
3276 *
3277 * End an xml DTD attribute list.
3278 *
3279 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3280 */
3281int
3282xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3283{
3284 int count;
3285 int sum;
3286 xmlLinkPtr lk;
3287 xmlTextWriterStackEntry *p;
3288
3289 if (writer == NULL)
3290 return -1;
3291
3292 sum = 0;
3293 lk = xmlListFront(writer->nodes);
3294 if (lk == 0)
3295 return -1;
3296
3297 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3298 if (p == 0)
3299 return -1;
3300
3301 switch (p->state) {
3302 case XML_TEXTWRITER_DTD_ATTL:
3303 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3304 count = xmlOutputBufferWriteString(writer->out, ">");
3305 if (count < 0)
3306 return -1;
3307 sum += count;
3308 break;
3309 default:
3310 return -1;
3311 }
3312
3313 if (writer->indent) {
3314 count = xmlOutputBufferWriteString(writer->out, "\n");
3315 if (count < 0)
3316 return -1;
3317 sum += count;
3318 }
3319
3320 xmlListPopFront(writer->nodes);
3321 return sum;
3322}
3323
3324/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003325 * xmlTextWriterWriteFormatDTDAttlist:
3326 * @writer: the xmlTextWriterPtr
3327 * @name: the name of the DTD ATTLIST
3328 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003329 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003330 *
3331 * Write a formatted DTD ATTLIST.
3332 *
3333 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3334 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003335int
3336xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3337 const xmlChar * name,
3338 const char *format, ...)
3339{
3340 int rc;
3341 va_list ap;
3342
3343 va_start(ap, format);
3344
3345 rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3346
3347 va_end(ap);
3348 return rc;
3349}
3350
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003351/**
3352 * xmlTextWriterWriteVFormatDTDAttlist:
3353 * @writer: the xmlTextWriterPtr
3354 * @name: the name of the DTD ATTLIST
3355 * @format: format string (see printf)
3356 * @argptr: pointer to the first member of the variable argument list.
3357 *
3358 * Write a formatted DTD ATTLIST.
3359 *
3360 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3361 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003362int
3363xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3364 const xmlChar * name,
3365 const char *format, va_list argptr)
3366{
3367 int rc;
3368 xmlChar *buf;
3369
3370 if (writer == NULL)
3371 return -1;
3372
3373 buf = xmlTextWriterVSprintf(format, argptr);
3374 if (buf == 0)
3375 return 0;
3376
3377 rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3378
3379 xmlFree(buf);
3380 return rc;
3381}
3382
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003383/**
3384 * xmlTextWriterWriteDTDAttlist:
3385 * @writer: the xmlTextWriterPtr
3386 * @name: the name of the DTD ATTLIST
3387 * @content: content of the ATTLIST
3388 *
3389 * Write a DTD ATTLIST.
3390 *
3391 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3392 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003393int
3394xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3395 const xmlChar * name, const xmlChar * content)
3396{
3397 int count;
3398 int sum;
3399
3400 if (content == NULL)
3401 return -1;
3402
3403 sum = 0;
3404 count = xmlTextWriterStartDTDAttlist(writer, name);
3405 if (count == -1)
3406 return -1;
3407 sum += count;
3408
Daniel Veillard1d211e22003-10-20 22:32:39 +00003409 count = xmlTextWriterWriteString(writer, content);
3410 if (count == -1)
3411 return -1;
3412 sum += count;
3413
3414 count = xmlTextWriterEndDTDAttlist(writer);
3415 if (count == -1)
3416 return -1;
3417 sum += count;
3418
3419 return sum;
3420}
3421
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003422/**
3423 * xmlTextWriterStartDTDEntity:
3424 * @writer: the xmlTextWriterPtr
3425 * @pe: TRUE if this is a parameter entity, FALSE if not
3426 * @name: the name of the DTD ATTLIST
3427 *
3428 * Start an xml DTD ATTLIST.
3429 *
3430 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3431 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003432int
3433xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3434 int pe, const xmlChar * name)
3435{
3436 int count;
3437 int sum;
3438 xmlLinkPtr lk;
3439 xmlTextWriterStackEntry *p;
3440
3441 if (writer == NULL || name == NULL || *name == '\0')
3442 return -1;
3443
3444 sum = 0;
3445 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003446 if (lk != 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00003447
Daniel Veillard500a1de2004-03-22 15:22:58 +00003448 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3449 if (p != 0) {
3450 switch (p->state) {
3451 case XML_TEXTWRITER_DTD:
3452 count = xmlOutputBufferWriteString(writer->out, " [");
3453 if (count < 0)
3454 return -1;
3455 sum += count;
3456 if (writer->indent) {
3457 count =
3458 xmlOutputBufferWriteString(writer->out, "\n");
3459 if (count < 0)
3460 return -1;
3461 sum += count;
3462 }
3463 p->state = XML_TEXTWRITER_DTD_TEXT;
3464 /* fallthrough */
3465 case XML_TEXTWRITER_DTD_TEXT:
3466 case XML_TEXTWRITER_NONE:
3467 break;
3468 default:
3469 return -1;
3470 }
3471 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003472 }
3473
3474 p = (xmlTextWriterStackEntry *)
3475 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3476 if (p == 0) {
3477 xmlGenericError(xmlGenericErrorContext,
3478 "xmlTextWriterStartDTDElement : out of memory!\n");
3479 return -1;
3480 }
3481
3482 p->name = xmlStrdup(name);
3483 if (p->name == 0) {
3484 xmlGenericError(xmlGenericErrorContext,
3485 "xmlTextWriterStartDTDElement : out of memory!\n");
3486 xmlFree(p);
3487 return -1;
3488 }
Daniel Veillard500a1de2004-03-22 15:22:58 +00003489
3490 if (pe != 0)
3491 p->state = XML_TEXTWRITER_DTD_PENT;
3492 else
3493 p->state = XML_TEXTWRITER_DTD_ENTY;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003494
3495 xmlListPushFront(writer->nodes, p);
3496
Daniel Veillard500a1de2004-03-22 15:22:58 +00003497 if (writer->indent) {
3498 count = xmlTextWriterWriteIndent(writer);
3499 if (count < 0)
3500 return -1;
3501 sum += count;
3502 }
3503
Daniel Veillard1d211e22003-10-20 22:32:39 +00003504 count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3505 if (count < 0)
3506 return -1;
3507 sum += count;
3508
3509 if (pe != 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00003510 count = xmlOutputBufferWriteString(writer->out, "% ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003511 if (count < 0)
3512 return -1;
3513 sum += count;
3514 }
3515
Daniel Veillardab69f362004-02-17 11:40:32 +00003516 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003517 if (count < 0)
3518 return -1;
3519 sum += count;
3520
3521 return sum;
3522}
3523
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003524/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003525 * xmlTextWriterEndDTDEntity:
3526 * @writer: the xmlTextWriterPtr
3527 *
3528 * End an xml DTD entity.
3529 *
3530 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3531 */
3532int
3533xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3534{
3535 int count;
3536 int sum;
3537 xmlLinkPtr lk;
3538 xmlTextWriterStackEntry *p;
3539
3540 if (writer == NULL)
3541 return -1;
3542
3543 sum = 0;
3544 lk = xmlListFront(writer->nodes);
3545 if (lk == 0)
3546 return -1;
3547
3548 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3549 if (p == 0)
3550 return -1;
3551
3552 switch (p->state) {
3553 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3554 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3555 if (count < 0)
3556 return -1;
3557 sum += count;
3558 case XML_TEXTWRITER_DTD_ENTY:
3559 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard500a1de2004-03-22 15:22:58 +00003560 count = xmlOutputBufferWriteString(writer->out, ">");
3561 if (count < 0)
3562 return -1;
3563 sum += count;
3564 break;
3565 default:
3566 return -1;
3567 }
3568
3569 if (writer->indent) {
3570 count = xmlOutputBufferWriteString(writer->out, "\n");
3571 if (count < 0)
3572 return -1;
3573 sum += count;
3574 }
3575
3576 xmlListPopFront(writer->nodes);
3577 return sum;
3578}
3579
3580/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003581 * xmlTextWriterWriteFormatDTDInternalEntity:
3582 * @writer: the xmlTextWriterPtr
3583 * @pe: TRUE if this is a parameter entity, FALSE if not
3584 * @name: the name of the DTD entity
3585 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003586 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003587 *
3588 * Write a formatted DTD internal entity.
3589 *
3590 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3591 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003592int
3593xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3594 int pe,
3595 const xmlChar * name,
3596 const char *format, ...)
3597{
3598 int rc;
3599 va_list ap;
3600
3601 va_start(ap, format);
3602
3603 rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3604 format, ap);
3605
3606 va_end(ap);
3607 return rc;
3608}
3609
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003610/**
3611 * xmlTextWriterWriteVFormatDTDInternalEntity:
3612 * @writer: the xmlTextWriterPtr
3613 * @pe: TRUE if this is a parameter entity, FALSE if not
3614 * @name: the name of the DTD entity
3615 * @format: format string (see printf)
3616 * @argptr: pointer to the first member of the variable argument list.
3617 *
3618 * Write a formatted DTD internal entity.
3619 *
3620 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3621 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003622int
3623xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3624 int pe,
3625 const xmlChar * name,
3626 const char *format,
3627 va_list argptr)
3628{
3629 int rc;
3630 xmlChar *buf;
3631
3632 if (writer == NULL)
3633 return -1;
3634
3635 buf = xmlTextWriterVSprintf(format, argptr);
3636 if (buf == 0)
3637 return 0;
3638
3639 rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3640
3641 xmlFree(buf);
3642 return rc;
3643}
3644
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003645/**
3646 * xmlTextWriterWriteDTDEntity:
3647 * @writer: the xmlTextWriterPtr
3648 * @pe: TRUE if this is a parameter entity, FALSE if not
3649 * @name: the name of the DTD entity
3650 * @pubid: the public identifier, which is an alternative to the system identifier
3651 * @sysid: the system identifier, which is the URI of the DTD
3652 * @ndataid: the xml notation name.
3653 * @content: content of the entity
3654 *
3655 * Write a DTD entity.
3656 *
3657 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3658 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003659int
3660xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3661 int pe,
3662 const xmlChar * name,
3663 const xmlChar * pubid,
3664 const xmlChar * sysid,
3665 const xmlChar * ndataid,
3666 const xmlChar * content)
3667{
Daniel Veillard500a1de2004-03-22 15:22:58 +00003668 if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003669 return -1;
3670 if ((pe != 0) && (ndataid != NULL))
3671 return -1;
3672
Daniel Veillard500a1de2004-03-22 15:22:58 +00003673 if ((pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003674 return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3675 content);
3676
3677 return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3678 sysid, ndataid);
3679}
3680
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003681/**
3682 * xmlTextWriterWriteDTDInternalEntity:
3683 * @writer: the xmlTextWriterPtr
3684 * @pe: TRUE if this is a parameter entity, FALSE if not
3685 * @name: the name of the DTD entity
3686 * @content: content of the entity
3687 *
3688 * Write a DTD internal entity.
3689 *
3690 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3691 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003692int
3693xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3694 int pe,
3695 const xmlChar * name,
3696 const xmlChar * content)
3697{
3698 int count;
3699 int sum;
3700
3701 if ((name == NULL) || (*name == '\0') || (content == NULL))
3702 return -1;
3703
3704 sum = 0;
3705 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3706 if (count == -1)
3707 return -1;
3708 sum += count;
3709
Daniel Veillard1d211e22003-10-20 22:32:39 +00003710 count = xmlTextWriterWriteString(writer, content);
3711 if (count == -1)
3712 return -1;
3713 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003714
3715 count = xmlTextWriterEndDTDEntity(writer);
3716 if (count == -1)
3717 return -1;
3718 sum += count;
3719
3720 return sum;
3721}
3722
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003723/**
3724 * xmlTextWriterWriteDTDExternalEntity:
3725 * @writer: the xmlTextWriterPtr
3726 * @pe: TRUE if this is a parameter entity, FALSE if not
3727 * @name: the name of the DTD entity
3728 * @pubid: the public identifier, which is an alternative to the system identifier
3729 * @sysid: the system identifier, which is the URI of the DTD
3730 * @ndataid: the xml notation name.
3731 *
Daniel Veillard500a1de2004-03-22 15:22:58 +00003732 * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003733 *
3734 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3735 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003736int
3737xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3738 int pe,
3739 const xmlChar * name,
3740 const xmlChar * pubid,
3741 const xmlChar * sysid,
3742 const xmlChar * ndataid)
3743{
3744 int count;
3745 int sum;
3746
Daniel Veillard500a1de2004-03-22 15:22:58 +00003747 if (((pubid == NULL) && (sysid == NULL)))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003748 return -1;
3749 if ((pe != 0) && (ndataid != NULL))
3750 return -1;
3751
3752 sum = 0;
3753 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3754 if (count == -1)
3755 return -1;
3756 sum += count;
3757
Daniel Veillard500a1de2004-03-22 15:22:58 +00003758 count =
3759 xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3760 ndataid);
3761 if (count < 0)
3762 return -1;
3763 sum += count;
3764
3765 count = xmlTextWriterEndDTDEntity(writer);
3766 if (count == -1)
3767 return -1;
3768 sum += count;
3769
3770 return sum;
3771}
3772
3773/**
3774 * xmlTextWriterWriteDTDExternalEntityContents:
3775 * @writer: the xmlTextWriterPtr
3776 * @pubid: the public identifier, which is an alternative to the system identifier
3777 * @sysid: the system identifier, which is the URI of the DTD
3778 * @ndataid: the xml notation name.
3779 *
3780 * Write the contents of a DTD external entity.
3781 *
3782 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3783 */
3784int
3785xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3786 const xmlChar * pubid,
3787 const xmlChar * sysid,
3788 const xmlChar * ndataid)
3789{
3790 int count;
3791 int sum;
3792 xmlLinkPtr lk;
3793 xmlTextWriterStackEntry *p;
3794
3795 if (writer == NULL) {
3796 xmlGenericError(xmlGenericErrorContext,
3797 "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3798 return -1;
3799 }
3800
3801 sum = 0;
3802 lk = xmlListFront(writer->nodes);
3803 if (lk == 0) {
3804 xmlGenericError(xmlGenericErrorContext,
3805 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
3806 return -1;
3807 }
3808
3809 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3810 if (p == 0)
3811 return -1;
3812
3813 switch (p->state) {
3814 case XML_TEXTWRITER_DTD_ENTY:
3815 break;
3816 case XML_TEXTWRITER_DTD_PENT:
3817 if (ndataid != NULL) {
3818 xmlGenericError(xmlGenericErrorContext,
3819 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
3820 return -1;
3821 }
3822 break;
3823 default:
3824 xmlGenericError(xmlGenericErrorContext,
3825 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
3826 return -1;
3827 }
3828
Daniel Veillard1d211e22003-10-20 22:32:39 +00003829 if (pubid != 0) {
3830 if (sysid == 0) {
3831 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003832 "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003833 return -1;
3834 }
3835
3836 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
3837 if (count < 0)
3838 return -1;
3839 sum += count;
3840
3841 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3842 if (count < 0)
3843 return -1;
3844 sum += count;
3845
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003846 count =
3847 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003848 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 }
3857
3858 if (sysid != 0) {
3859 if (pubid == 0) {
3860 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
3861 if (count < 0)
3862 return -1;
3863 sum += count;
3864 }
3865
3866 count = xmlOutputBufferWriteString(writer->out, " ");
3867 if (count < 0)
3868 return -1;
3869 sum += count;
3870
3871 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3872 if (count < 0)
3873 return -1;
3874 sum += count;
3875
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003876 count =
3877 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003878 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 }
3887
3888 if (ndataid != NULL) {
3889 count = xmlOutputBufferWriteString(writer->out, " NDATA ");
3890 if (count < 0)
3891 return -1;
3892 sum += count;
3893
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003894 count =
3895 xmlOutputBufferWriteString(writer->out,
3896 (const char *) ndataid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003897 if (count < 0)
3898 return -1;
3899 sum += count;
3900 }
3901
Daniel Veillard1d211e22003-10-20 22:32:39 +00003902 return sum;
3903}
3904
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003905/**
3906 * xmlTextWriterWriteDTDNotation:
3907 * @writer: the xmlTextWriterPtr
3908 * @name: the name of the xml notation
3909 * @pubid: the public identifier, which is an alternative to the system identifier
3910 * @sysid: the system identifier, which is the URI of the DTD
3911 *
3912 * Write a DTD entity.
3913 *
3914 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3915 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003916int
3917xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
3918 const xmlChar * name,
3919 const xmlChar * pubid, const xmlChar * sysid)
3920{
3921 int count;
3922 int sum;
3923 xmlLinkPtr lk;
3924 xmlTextWriterStackEntry *p;
3925
3926 if (writer == NULL || name == NULL || *name == '\0')
3927 return -1;
3928
3929 sum = 0;
3930 lk = xmlListFront(writer->nodes);
3931 if (lk == 0) {
3932 return -1;
3933 }
3934
3935 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003936 if (p != 0) {
3937 switch (p->state) {
3938 case XML_TEXTWRITER_DTD:
3939 count = xmlOutputBufferWriteString(writer->out, " [");
3940 if (count < 0)
3941 return -1;
3942 sum += count;
3943 if (writer->indent) {
3944 count = xmlOutputBufferWriteString(writer->out, "\n");
3945 if (count < 0)
3946 return -1;
3947 sum += count;
3948 }
3949 p->state = XML_TEXTWRITER_DTD_TEXT;
3950 /* fallthrough */
3951 case XML_TEXTWRITER_DTD_TEXT:
3952 break;
3953 default:
3954 return -1;
3955 }
3956 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003957
Daniel Veillard500a1de2004-03-22 15:22:58 +00003958 if (writer->indent) {
3959 count = xmlTextWriterWriteIndent(writer);
3960 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00003961 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003962 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003963 }
3964
3965 count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
3966 if (count < 0)
3967 return -1;
3968 sum += count;
3969 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3970 if (count < 0)
3971 return -1;
3972 sum += count;
3973
3974 if (pubid != 0) {
3975 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
3976 if (count < 0)
3977 return -1;
3978 sum += count;
3979 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3980 if (count < 0)
3981 return -1;
3982 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003983 count =
3984 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003985 if (count < 0)
3986 return -1;
3987 sum += count;
3988 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3989 if (count < 0)
3990 return -1;
3991 sum += count;
3992 }
3993
3994 if (sysid != 0) {
3995 if (pubid == 0) {
3996 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
3997 if (count < 0)
3998 return -1;
3999 sum += count;
4000 }
4001 count = xmlOutputBufferWriteString(writer->out, " ");
4002 if (count < 0)
4003 return -1;
4004 sum += count;
4005 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4006 if (count < 0)
4007 return -1;
4008 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004009 count =
4010 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004011 if (count < 0)
4012 return -1;
4013 sum += count;
4014 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4015 if (count < 0)
4016 return -1;
4017 sum += count;
4018 }
4019
4020 count = xmlOutputBufferWriteString(writer->out, ">");
4021 if (count < 0)
4022 return -1;
4023 sum += count;
4024
4025 return sum;
4026}
4027
4028/**
4029 * xmlTextWriterFlush:
4030 * @writer: the xmlTextWriterPtr
4031 *
4032 * Flush the output buffer.
4033 *
4034 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4035 */
4036int
4037xmlTextWriterFlush(xmlTextWriterPtr writer)
4038{
4039 int count;
4040
4041 if (writer == NULL)
4042 return -1;
4043
4044 if (writer->out == NULL)
4045 count = 0;
4046 else
4047 count = xmlOutputBufferFlush(writer->out);
4048
4049 return count;
4050}
4051
4052/**
4053 * misc
4054 */
4055
4056/**
4057 * xmlFreeTextWriterStackEntry:
4058 * @lk: the xmlLinkPtr
4059 *
4060 * Free callback for the xmlList.
4061 */
4062static void
4063xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4064{
4065 xmlTextWriterStackEntry *p;
4066
4067 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4068 if (p == 0)
4069 return;
4070
4071 if (p->name != 0)
4072 xmlFree(p->name);
4073 xmlFree(p);
4074}
4075
4076/**
4077 * xmlCmpTextWriterStackEntry:
4078 * @data0: the first data
4079 * @data1: the second data
4080 *
4081 * Compare callback for the xmlList.
4082 *
4083 * Returns -1, 0, 1
4084 */
4085static int
4086xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4087{
4088 xmlTextWriterStackEntry *p0;
4089 xmlTextWriterStackEntry *p1;
4090
4091 if (data0 == data1)
4092 return 0;
4093
4094 if (data0 == 0)
4095 return -1;
4096
4097 if (data1 == 0)
4098 return 1;
4099
4100 p0 = (xmlTextWriterStackEntry *) data0;
4101 p1 = (xmlTextWriterStackEntry *) data1;
4102
4103 return xmlStrcmp(p0->name, p1->name);
4104}
4105
4106/**
4107 * misc
4108 */
4109
4110/**
4111 * xmlFreeTextWriterNsStackEntry:
4112 * @lk: the xmlLinkPtr
4113 *
4114 * Free callback for the xmlList.
4115 */
4116static void
4117xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4118{
4119 xmlTextWriterNsStackEntry *p;
4120
4121 p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4122 if (p == 0)
4123 return;
4124
4125 if (p->prefix != 0)
4126 xmlFree(p->prefix);
4127 if (p->uri != 0)
4128 xmlFree(p->uri);
4129
4130 xmlFree(p);
4131}
4132
4133/**
4134 * xmlCmpTextWriterNsStackEntry:
4135 * @data0: the first data
4136 * @data1: the second data
4137 *
4138 * Compare callback for the xmlList.
4139 *
4140 * Returns -1, 0, 1
4141 */
4142static int
4143xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4144{
4145 xmlTextWriterNsStackEntry *p0;
4146 xmlTextWriterNsStackEntry *p1;
4147 int rc;
4148
4149 if (data0 == data1)
4150 return 0;
4151
4152 if (data0 == 0)
4153 return -1;
4154
4155 if (data1 == 0)
4156 return 1;
4157
4158 p0 = (xmlTextWriterNsStackEntry *) data0;
4159 p1 = (xmlTextWriterNsStackEntry *) data1;
4160
4161 rc = xmlStrcmp(p0->prefix, p1->prefix);
4162
4163 if (rc == 0)
4164 rc = p0->elem == p1->elem;
4165
4166 return rc;
4167}
4168
4169/**
4170 * xmlTextWriterWriteMemCallback:
4171 * @context: the xmlBufferPtr
4172 * @str: the data to write
4173 * @len: the length of the data
4174 *
4175 * Write callback for the xmlOutputBuffer with target xmlBuffer
4176 *
4177 * Returns -1, 0, 1
4178 */
4179static int
4180xmlTextWriterWriteMemCallback(void *context, const xmlChar * str, int len)
4181{
4182 xmlBufferPtr buf = (xmlBufferPtr) context;
4183
4184 xmlBufferAdd(buf, str, len);
4185
4186 return len;
4187}
4188
4189/**
4190 * xmlTextWriterCloseMemCallback:
4191 * @context: the xmlBufferPtr
4192 *
4193 * Close callback for the xmlOutputBuffer with target xmlBuffer
4194 *
4195 * Returns -1, 0, 1
4196 */
4197static int
4198xmlTextWriterCloseMemCallback(void *context ATTRIBUTE_UNUSED)
4199{
4200 return 0;
4201}
4202
4203/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004204 * xmlTextWriterWriteDocCallback:
4205 * @context: the xmlBufferPtr
4206 * @str: the data to write
4207 * @len: the length of the data
4208 *
4209 * Write callback for the xmlOutputBuffer with target xmlBuffer
4210 *
4211 * Returns -1, 0, 1
4212 */
4213static int
4214xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
4215{
4216 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4217 int rc;
4218
Daniel Veillard1d913862003-11-21 00:28:39 +00004219 if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004220 xmlGenericError(xmlGenericErrorContext,
4221 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4222 rc);
4223 return -1;
4224 }
4225
4226 return len;
4227}
4228
4229/**
4230 * xmlTextWriterCloseDocCallback:
4231 * @context: the xmlBufferPtr
4232 *
4233 * Close callback for the xmlOutputBuffer with target xmlBuffer
4234 *
4235 * Returns -1, 0, 1
4236 */
4237static int
4238xmlTextWriterCloseDocCallback(void *context)
4239{
4240 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4241 int rc;
4242
4243 if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
4244 xmlGenericError(xmlGenericErrorContext,
4245 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4246 rc);
4247 return -1;
4248 }
4249
4250 return 0;
4251}
4252
4253/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004254 * xmlTextWriterVSprintf:
4255 * @format: see printf
4256 * @argptr: pointer to the first member of the variable argument list.
4257 *
4258 * Utility function for formatted output
4259 *
4260 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4261 */
4262static xmlChar *
4263xmlTextWriterVSprintf(const char *format, va_list argptr)
4264{
4265 int size;
4266 int count;
4267 xmlChar *buf;
4268
4269 size = BUFSIZ;
4270 buf = (xmlChar *) xmlMalloc(size);
4271 if (buf == NULL) {
4272 xmlGenericError(xmlGenericErrorContext,
4273 "xmlTextWriterVSprintf : out of memory!\n");
4274 return NULL;
4275 }
4276
4277 while (((count = vsnprintf((char *) buf, size, format, argptr)) < 0)
4278 || (count == size - 1) || (count == size) || (count > size)) {
4279 xmlFree(buf);
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
4289 return buf;
4290}
4291
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004292/**
4293 * xmlTextWriterStartDocumentCallback:
4294 * @ctx: the user data (XML parser context)
4295 *
4296 * called at the start of document processing.
4297 */
4298static void
4299xmlTextWriterStartDocumentCallback(void *ctx)
4300{
4301 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4302 xmlDocPtr doc;
4303
4304#ifdef DEBUG_SAX
4305 xmlGenericError(xmlGenericErrorContext, "SAX.startDocument()\n");
4306#endif
4307 if (ctxt->html) {
4308#ifdef LIBXML_HTML_ENABLED
4309 if (ctxt->myDoc == NULL)
4310 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4311 if (ctxt->myDoc == NULL) {
4312 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4313 ctxt->sax->error(ctxt->userData,
4314 "SAX.startDocument(): out of memory\n");
4315 ctxt->errNo = XML_ERR_NO_MEMORY;
4316 ctxt->instate = XML_PARSER_EOF;
4317 ctxt->disableSAX = 1;
4318 return;
4319 }
4320#else
4321 xmlGenericError(xmlGenericErrorContext,
4322 "libxml2 built without HTML support\n");
4323 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4324 ctxt->instate = XML_PARSER_EOF;
4325 ctxt->disableSAX = 1;
4326 return;
4327#endif
4328 } else {
4329 doc = ctxt->myDoc;
4330 if (doc == NULL)
4331 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4332 if (doc != NULL) {
4333 if (doc->children == NULL) {
4334 if (ctxt->encoding != NULL)
4335 doc->encoding = xmlStrdup(ctxt->encoding);
4336 else
4337 doc->encoding = NULL;
4338 doc->standalone = ctxt->standalone;
4339 }
4340 } else {
4341 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4342 ctxt->sax->error(ctxt->userData,
4343 "SAX.startDocument(): out of memory\n");
4344 ctxt->errNo = XML_ERR_NO_MEMORY;
4345 ctxt->instate = XML_PARSER_EOF;
4346 ctxt->disableSAX = 1;
4347 return;
4348 }
4349 }
4350 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4351 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4352 ctxt->myDoc->URL =
4353 xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4354 if (ctxt->myDoc->URL == NULL)
4355 ctxt->myDoc->URL =
4356 xmlStrdup((const xmlChar *) ctxt->input->filename);
4357 }
4358}
4359
Daniel Veillard2cca4462004-01-02 20:04:23 +00004360/**
4361 * xmlTextWriterSetIndent:
4362 * @writer: the xmlTextWriterPtr
4363 * @indent: do indentation?
4364 *
4365 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4366 *
4367 * Returns -1 on error or 0 otherwise.
4368 */
4369int
Daniel Veillardab69f362004-02-17 11:40:32 +00004370xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004371{
Daniel Veillardab69f362004-02-17 11:40:32 +00004372 if (indent < 0)
4373 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004374
Daniel Veillardab69f362004-02-17 11:40:32 +00004375 writer->indent = indent;
4376 writer->doindent = 1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004377
Daniel Veillardab69f362004-02-17 11:40:32 +00004378 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004379}
4380
4381/**
4382 * xmlTextWriterSetIndentString:
4383 * @writer: the xmlTextWriterPtr
4384 * @str: the xmlChar string
4385 *
4386 * Set string indentation.
4387 *
4388 * Returns -1 on error or 0 otherwise.
4389 */
4390int
Daniel Veillardab69f362004-02-17 11:40:32 +00004391xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004392{
Daniel Veillardab69f362004-02-17 11:40:32 +00004393 if (!str)
4394 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004395
Daniel Veillardab69f362004-02-17 11:40:32 +00004396 if (writer->ichar != NULL)
4397 xmlFree(writer->ichar);
4398 writer->ichar = xmlStrdup(str);
4399
4400 if (!writer->ichar)
4401 return -1;
4402 else
4403 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004404}
4405
4406/**
4407 * xmlTextWriterWriteIndent:
4408 * @writer: the xmlTextWriterPtr
4409 *
4410 * Write indent string.
4411 *
4412 * Returns -1 on error or the number of strings written.
Daniel Veillardab69f362004-02-17 11:40:32 +00004413 */
Daniel Veillard2cca4462004-01-02 20:04:23 +00004414static int
Daniel Veillardab69f362004-02-17 11:40:32 +00004415xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004416{
Daniel Veillardab69f362004-02-17 11:40:32 +00004417 int lksize;
4418 int i;
4419 int ret;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004420
Daniel Veillardab69f362004-02-17 11:40:32 +00004421 lksize = xmlListSize(writer->nodes);
4422 if (lksize < 1)
4423 return (-1); /* list is empty */
4424 for (i = 0; i < (lksize - 1); i++) {
4425 ret = xmlOutputBufferWriteString(writer->out,
4426 (const char *) writer->ichar);
4427 if (ret == -1)
4428 return (-1);
4429 }
4430
4431 return (lksize - 1);
Daniel Veillard2cca4462004-01-02 20:04:23 +00004432}
4433
Daniel Veillard500a1de2004-03-22 15:22:58 +00004434/**
4435 * xmlTextWriterHandleStateDependencies:
4436 * @writer: the xmlTextWriterPtr
4437 * @p: the xmlTextWriterStackEntry
4438 *
4439 * Write state dependent strings.
4440 *
4441 * Returns -1 on error or the number of characters written.
4442 */
4443static int
4444xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4445 xmlTextWriterStackEntry * p)
4446{
4447 int count;
4448 int sum;
4449 char extra[3];
4450
4451 if (writer == NULL)
4452 return -1;
4453
4454 if (p == NULL)
4455 return 0;
4456
4457 sum = 0;
4458 extra[0] = extra[1] = extra[2] = '\0';
4459 if (p != 0) {
4460 sum = 0;
4461 switch (p->state) {
4462 case XML_TEXTWRITER_NAME:
4463 extra[0] = '>';
4464 p->state = XML_TEXTWRITER_TEXT;
4465 break;
4466 case XML_TEXTWRITER_PI:
4467 extra[0] = ' ';
4468 p->state = XML_TEXTWRITER_PI_TEXT;
4469 break;
4470 case XML_TEXTWRITER_DTD:
4471 extra[0] = ' ';
4472 extra[1] = '[';
4473 p->state = XML_TEXTWRITER_DTD_TEXT;
4474 break;
4475 case XML_TEXTWRITER_DTD_ELEM:
4476 extra[0] = ' ';
4477 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4478 break;
4479 case XML_TEXTWRITER_DTD_ATTL:
4480 extra[0] = ' ';
4481 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4482 break;
4483 case XML_TEXTWRITER_DTD_ENTY:
4484 case XML_TEXTWRITER_DTD_PENT:
4485 extra[0] = ' ';
4486 extra[1] = writer->qchar;
4487 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4488 break;
4489 default:
4490 break;
4491 }
4492 }
4493
4494 if (*extra != '\0') {
4495 count = xmlOutputBufferWriteString(writer->out, extra);
4496 if (count < 0)
4497 return -1;
4498 sum += count;
4499 }
4500
4501 return sum;
4502}
4503
Daniel Veillard1d211e22003-10-20 22:32:39 +00004504#endif