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