blob: c6959b85a4441153bd73a2a258adbd72a776d0f4 [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
William M. Brackc1099be2007-01-31 18:38:56 +000012#include "libxml.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +000013#include <string.h>
Daniel Veillard1d211e22003-10-20 22:32:39 +000014
Daniel Veillard1d211e22003-10-20 22:32:39 +000015#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/*
William M. Brackf4caa5e2005-10-20 09:04:05 +000028 * The following VA_COPY was coded following an example in
29 * the Samba project. It may not be sufficient for some
30 * esoteric implementations of va_list (i.e. it may need
31 * something involving a memcpy) but (hopefully) will be
32 * sufficient for libxml2.
33 */
34#ifndef VA_COPY
35 #ifdef HAVE_VA_COPY
36 #define VA_COPY(dest, src) va_copy(dest, src)
37 #else
38 #ifdef HAVE___VA_COPY
39 #define VA_COPY(dest,src) __va_copy(dest, src)
40 #else
41 #define VA_COPY(dest,src) (dest) = (src)
42 #endif
43 #endif
44#endif
45
46/*
Daniel Veillard1d211e22003-10-20 22:32:39 +000047 * Types are kept private
48 */
49typedef enum {
50 XML_TEXTWRITER_NONE = 0,
51 XML_TEXTWRITER_NAME,
52 XML_TEXTWRITER_ATTRIBUTE,
53 XML_TEXTWRITER_TEXT,
54 XML_TEXTWRITER_PI,
55 XML_TEXTWRITER_PI_TEXT,
56 XML_TEXTWRITER_CDATA,
57 XML_TEXTWRITER_DTD,
58 XML_TEXTWRITER_DTD_TEXT,
59 XML_TEXTWRITER_DTD_ELEM,
Daniel Veillard500a1de2004-03-22 15:22:58 +000060 XML_TEXTWRITER_DTD_ELEM_TEXT,
Daniel Veillard1d211e22003-10-20 22:32:39 +000061 XML_TEXTWRITER_DTD_ATTL,
Daniel Veillard500a1de2004-03-22 15:22:58 +000062 XML_TEXTWRITER_DTD_ATTL_TEXT,
63 XML_TEXTWRITER_DTD_ENTY, /* entity */
64 XML_TEXTWRITER_DTD_ENTY_TEXT,
65 XML_TEXTWRITER_DTD_PENT, /* parameter entity */
William M. Brack87640d52004-04-17 14:58:15 +000066 XML_TEXTWRITER_COMMENT
Daniel Veillard1d211e22003-10-20 22:32:39 +000067} xmlTextWriterState;
68
69typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
70
71struct _xmlTextWriterStackEntry {
72 xmlChar *name;
73 xmlTextWriterState state;
74};
75
76typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
77struct _xmlTextWriterNsStackEntry {
78 xmlChar *prefix;
79 xmlChar *uri;
80 xmlLinkPtr elem;
81};
82
83struct _xmlTextWriter {
Daniel Veillardab69f362004-02-17 11:40:32 +000084 xmlOutputBufferPtr out; /* output buffer */
85 xmlListPtr nodes; /* element name stack */
86 xmlListPtr nsstack; /* name spaces stack */
Daniel Veillard1d211e22003-10-20 22:32:39 +000087 int level;
Daniel Veillardab69f362004-02-17 11:40:32 +000088 int indent; /* enable indent */
89 int doindent; /* internal indent flag */
90 xmlChar *ichar; /* indent character */
91 char qchar; /* character used for quoting attribute values */
Daniel Veillard20c5e782004-01-21 09:57:31 +000092 xmlParserCtxtPtr ctxt;
Daniel Veillarda521d282004-11-09 14:59:59 +000093 int no_doc_free;
Rob Richards9db68f02006-08-16 22:48:51 +000094 xmlDocPtr doc;
Daniel Veillard1d211e22003-10-20 22:32:39 +000095};
96
97static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
98static int xmlCmpTextWriterStackEntry(const void *data0,
99 const void *data1);
Rob Richardsb8769d62007-06-08 08:50:47 +0000100static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000101static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
102static int xmlCmpTextWriterNsStackEntry(const void *data0,
103 const void *data1);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000104static int xmlTextWriterWriteDocCallback(void *context,
105 const xmlChar * str, int len);
106static int xmlTextWriterCloseDocCallback(void *context);
107
Daniel Veillard1d211e22003-10-20 22:32:39 +0000108static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);
109static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
110 const unsigned char *data);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000111static void xmlTextWriterStartDocumentCallback(void *ctx);
Daniel Veillardab69f362004-02-17 11:40:32 +0000112static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000113static int
114 xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
115 xmlTextWriterStackEntry * p);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000116
117/**
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000118 * xmlWriterErrMsg:
119 * @ctxt: a writer context
120 * @error: the error number
121 * @msg: the error message
122 *
123 * Handle a writer error
124 */
125static void
126xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,
127 const char *msg)
128{
129 if (ctxt != NULL) {
130 __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
131 NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
132 NULL, 0, NULL, NULL, NULL, 0, 0, msg);
133 } else {
134 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
135 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, msg);
136 }
137}
138
139/**
140 * xmlWriterErrMsgInt:
141 * @ctxt: a writer context
142 * @error: the error number
143 * @msg: the error message
144 * @val: an int
145 *
146 * Handle a writer error
147 */
148static void
149xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,
150 const char *msg, int val)
151{
152 if (ctxt != NULL) {
153 __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
154 NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
155 NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
156 } else {
157 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
158 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
159 }
160}
161
162/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000163 * xmlNewTextWriter:
164 * @out: an xmlOutputBufferPtr
165 *
166 * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
Daniel Veillardd5cc0f72004-11-06 19:24:28 +0000167 * NOTE: the @out parameter will be deallocated when the writer is closed
168 * (if the call succeed.)
Daniel Veillard1d211e22003-10-20 22:32:39 +0000169 *
170 * Returns the new xmlTextWriterPtr or NULL in case of error
171 */
172xmlTextWriterPtr
173xmlNewTextWriter(xmlOutputBufferPtr out)
174{
175 xmlTextWriterPtr ret;
176
177 ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
178 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000179 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000180 "xmlNewTextWriter : out of memory!\n");
181 return NULL;
182 }
183 memset(ret, 0, (size_t) sizeof(xmlTextWriter));
184
185 ret->nodes = xmlListCreate((xmlListDeallocator)
186 xmlFreeTextWriterStackEntry,
187 (xmlListDataCompare)
188 xmlCmpTextWriterStackEntry);
189 if (ret->nodes == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000190 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000191 "xmlNewTextWriter : out of memory!\n");
192 xmlFree(ret);
193 return NULL;
194 }
195
196 ret->nsstack = xmlListCreate((xmlListDeallocator)
197 xmlFreeTextWriterNsStackEntry,
198 (xmlListDataCompare)
199 xmlCmpTextWriterNsStackEntry);
200 if (ret->nsstack == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000201 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000202 "xmlNewTextWriter : out of memory!\n");
Daniel Veillard500a1de2004-03-22 15:22:58 +0000203 xmlListDelete(ret->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000204 xmlFree(ret);
205 return NULL;
206 }
207
208 ret->out = out;
Daniel Veillardab69f362004-02-17 11:40:32 +0000209 ret->ichar = xmlStrdup(BAD_CAST " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000210 ret->qchar = '"';
211
Daniel Veillard500a1de2004-03-22 15:22:58 +0000212 if (!ret->ichar) {
213 xmlListDelete(ret->nodes);
214 xmlListDelete(ret->nsstack);
215 xmlFree(ret);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000216 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000217 "xmlNewTextWriter : out of memory!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000218 return NULL;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000219 }
Rob Richards9db68f02006-08-16 22:48:51 +0000220
221 ret->doc = xmlNewDoc(NULL);
222
Daniel Veillarda521d282004-11-09 14:59:59 +0000223 ret->no_doc_free = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000224
Daniel Veillard1d211e22003-10-20 22:32:39 +0000225 return ret;
226}
227
228/**
229 * xmlNewTextWriterFilename:
230 * @uri: the URI of the resource for the output
231 * @compression: compress the output?
232 *
233 * Create a new xmlNewTextWriter structure with @uri as output
234 *
235 * Returns the new xmlTextWriterPtr or NULL in case of error
236 */
237xmlTextWriterPtr
238xmlNewTextWriterFilename(const char *uri, int compression)
239{
240 xmlTextWriterPtr ret;
241 xmlOutputBufferPtr out;
242
243 out = xmlOutputBufferCreateFilename(uri, NULL, compression);
244 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000245 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000246 "xmlNewTextWriterFilename : out of memory!\n");
247 return NULL;
248 }
249
250 ret = xmlNewTextWriter(out);
251 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000252 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000253 "xmlNewTextWriterFilename : out of memory!\n");
254 xmlOutputBufferClose(out);
255 return NULL;
256 }
257
Daniel Veillard2cca4462004-01-02 20:04:23 +0000258 ret->indent = 0;
259 ret->doindent = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000260 return ret;
261}
262
263/**
264 * xmlNewTextWriterMemory:
265 * @buf: xmlBufferPtr
266 * @compression: compress the output?
267 *
268 * Create a new xmlNewTextWriter structure with @buf as output
269 * TODO: handle compression
270 *
271 * Returns the new xmlTextWriterPtr or NULL in case of error
272 */
273xmlTextWriterPtr
274xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
275{
276 xmlTextWriterPtr ret;
277 xmlOutputBufferPtr out;
278
279/*::todo handle compression */
Rob Richardsa44f2342005-11-09 18:03:45 +0000280 out = xmlOutputBufferCreateBuffer(buf, NULL);
281
Daniel Veillard1d211e22003-10-20 22:32:39 +0000282 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000283 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000284 "xmlNewTextWriterMemory : out of memory!\n");
285 return NULL;
286 }
287
288 ret = xmlNewTextWriter(out);
289 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000290 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000291 "xmlNewTextWriterMemory : out of memory!\n");
292 xmlOutputBufferClose(out);
293 return NULL;
294 }
295
296 return ret;
297}
298
299/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000300 * xmlNewTextWriterPushParser:
301 * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
302 * @compression: compress the output?
303 *
304 * Create a new xmlNewTextWriter structure with @ctxt as output
Daniel Veillardd5cc0f72004-11-06 19:24:28 +0000305 * NOTE: the @ctxt context will be freed with the resulting writer
306 * (if the call succeeds).
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000307 * TODO: handle compression
308 *
309 * Returns the new xmlTextWriterPtr or NULL in case of error
310 */
311xmlTextWriterPtr
Daniel Veillard1d913862003-11-21 00:28:39 +0000312xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
313 int compression ATTRIBUTE_UNUSED)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000314{
315 xmlTextWriterPtr ret;
316 xmlOutputBufferPtr out;
317
Daniel Veillard500a1de2004-03-22 15:22:58 +0000318 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000319 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000320 "xmlNewTextWriterPushParser : invalid context!\n");
321 return NULL;
322 }
323
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000324 out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
325 xmlTextWriterWriteDocCallback,
326 (xmlOutputCloseCallback)
327 xmlTextWriterCloseDocCallback,
328 (void *) ctxt, NULL);
329 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000330 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000331 "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
332 return NULL;
333 }
334
335 ret = xmlNewTextWriter(out);
336 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000337 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000338 "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
339 xmlOutputBufferClose(out);
340 return NULL;
341 }
342
Daniel Veillard20c5e782004-01-21 09:57:31 +0000343 ret->ctxt = ctxt;
344
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000345 return ret;
346}
347
348/**
349 * xmlNewTextWriterDoc:
350 * @doc: address of a xmlDocPtr to hold the new XML document tree
351 * @compression: compress the output?
352 *
353 * Create a new xmlNewTextWriter structure with @*doc as output
354 *
355 * Returns the new xmlTextWriterPtr or NULL in case of error
356 */
357xmlTextWriterPtr
358xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
359{
360 xmlTextWriterPtr ret;
361 xmlSAXHandler saxHandler;
362 xmlParserCtxtPtr ctxt;
363
364 memset(&saxHandler, '\0', sizeof(saxHandler));
365 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
366 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
367 saxHandler.startElement = xmlSAX2StartElement;
368 saxHandler.endElement = xmlSAX2EndElement;
369
370 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
371 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000372 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000373 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
374 return NULL;
375 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000376 /*
377 * For some reason this seems to completely break if node names
378 * are interned.
379 */
380 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000381
Daniel Veillard1d913862003-11-21 00:28:39 +0000382 ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000383 if (ctxt->myDoc == NULL) {
384 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000385 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000386 "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
387 return NULL;
388 }
389
390 ret = xmlNewTextWriterPushParser(ctxt, compression);
391 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000392 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000393 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
394 return NULL;
395 }
396
Daniel Veillard500a1de2004-03-22 15:22:58 +0000397 xmlSetDocCompressMode(ctxt->myDoc, compression);
398
Daniel Veillarda521d282004-11-09 14:59:59 +0000399 if (doc != NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000400 *doc = ctxt->myDoc;
Daniel Veillarda521d282004-11-09 14:59:59 +0000401 ret->no_doc_free = 1;
402 }
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000403
404 return ret;
405}
406
407/**
408 * xmlNewTextWriterTree:
409 * @doc: xmlDocPtr
410 * @node: xmlNodePtr or NULL for doc->children
411 * @compression: compress the output?
412 *
413 * Create a new xmlNewTextWriter structure with @doc as output
414 * starting at @node
415 *
416 * Returns the new xmlTextWriterPtr or NULL in case of error
417 */
418xmlTextWriterPtr
419xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
420{
421 xmlTextWriterPtr ret;
422 xmlSAXHandler saxHandler;
423 xmlParserCtxtPtr ctxt;
424
425 if (doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000426 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000427 "xmlNewTextWriterTree : invalid document tree!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000428 return NULL;
429 }
430
431 memset(&saxHandler, '\0', sizeof(saxHandler));
432 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
433 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
434 saxHandler.startElement = xmlSAX2StartElement;
435 saxHandler.endElement = xmlSAX2EndElement;
436
437 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
438 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000439 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000440 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
441 return NULL;
442 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000443 /*
444 * For some reason this seems to completely break if node names
445 * are interned.
446 */
447 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000448
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000449 ret = xmlNewTextWriterPushParser(ctxt, compression);
450 if (ret == NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000451 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000452 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000453 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
454 return NULL;
455 }
456
Daniel Veillard500a1de2004-03-22 15:22:58 +0000457 ctxt->myDoc = doc;
458 ctxt->node = node;
Daniel Veillarda521d282004-11-09 14:59:59 +0000459 ret->no_doc_free = 1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000460
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000461 xmlSetDocCompressMode(doc, compression);
462
463 return ret;
464}
465
466/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000467 * xmlFreeTextWriter:
468 * @writer: the xmlTextWriterPtr
469 *
470 * Deallocate all the resources associated to the writer
471 */
472void
473xmlFreeTextWriter(xmlTextWriterPtr writer)
474{
475 if (writer == NULL)
476 return;
477
478 if (writer->out != NULL)
479 xmlOutputBufferClose(writer->out);
480
481 if (writer->nodes != NULL)
482 xmlListDelete(writer->nodes);
483
484 if (writer->nsstack != NULL)
485 xmlListDelete(writer->nsstack);
486
Daniel Veillarda521d282004-11-09 14:59:59 +0000487 if (writer->ctxt != NULL) {
488 if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
489 xmlFreeDoc(writer->ctxt->myDoc);
490 writer->ctxt->myDoc = NULL;
491 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000492 xmlFreeParserCtxt(writer->ctxt);
Daniel Veillarda521d282004-11-09 14:59:59 +0000493 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000494
Rob Richards9db68f02006-08-16 22:48:51 +0000495 if (writer->doc != NULL)
496 xmlFreeDoc(writer->doc);
497
Daniel Veillard4773df22004-01-23 13:15:13 +0000498 if (writer->ichar != NULL)
499 xmlFree(writer->ichar);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000500 xmlFree(writer);
501}
502
503/**
504 * xmlTextWriterStartDocument:
505 * @writer: the xmlTextWriterPtr
506 * @version: the xml version ("1.0") or NULL for default ("1.0")
507 * @encoding: the encoding or NULL for default
508 * @standalone: "yes" or "no" or NULL for default
509 *
510 * Start a new xml document
511 *
512 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
513 */
514int
515xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
516 const char *encoding, const char *standalone)
517{
518 int count;
519 int sum;
520 xmlLinkPtr lk;
521 xmlCharEncodingHandlerPtr encoder;
522
Daniel Veillard500a1de2004-03-22 15:22:58 +0000523 if ((writer == NULL) || (writer->out == NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000524 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000525 "xmlTextWriterStartDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000526 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000527 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000528
529 lk = xmlListFront(writer->nodes);
530 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000531 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000532 "xmlTextWriterStartDocument : not allowed in this context!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000533 return -1;
534 }
535
536 encoder = NULL;
537 if (encoding != NULL) {
538 encoder = xmlFindCharEncodingHandler(encoding);
539 if (encoder == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000540 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000541 "xmlTextWriterStartDocument : out of memory!\n");
542 return -1;
543 }
544 }
545
546 writer->out->encoder = encoder;
547 if (encoder != NULL) {
Daniel Veillardcaa19512007-07-04 15:42:46 +0000548 if (writer->out->conv == NULL) {
549 writer->out->conv = xmlBufferCreateSize(4000);
550 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000551 xmlCharEncOutFunc(encoder, writer->out->conv, NULL);
Rob Richards9db68f02006-08-16 22:48:51 +0000552 if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
553 writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000554 } else
555 writer->out->conv = NULL;
556
557 sum = 0;
558 count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
559 if (count < 0)
560 return -1;
561 sum += count;
562 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
563 if (count < 0)
564 return -1;
565 sum += count;
566 if (version != 0)
567 count = xmlOutputBufferWriteString(writer->out, version);
568 else
569 count = xmlOutputBufferWriteString(writer->out, "1.0");
570 if (count < 0)
571 return -1;
572 sum += count;
573 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
574 if (count < 0)
575 return -1;
576 sum += count;
577 if (writer->out->encoder != 0) {
578 count = xmlOutputBufferWriteString(writer->out, " encoding=");
579 if (count < 0)
580 return -1;
581 sum += count;
582 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
583 if (count < 0)
584 return -1;
585 sum += count;
586 count =
587 xmlOutputBufferWriteString(writer->out,
588 writer->out->encoder->name);
589 if (count < 0)
590 return -1;
591 sum += count;
592 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
593 if (count < 0)
594 return -1;
595 sum += count;
596 }
597
598 if (standalone != 0) {
599 count = xmlOutputBufferWriteString(writer->out, " standalone=");
600 if (count < 0)
601 return -1;
602 sum += count;
603 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
604 if (count < 0)
605 return -1;
606 sum += count;
607 count = xmlOutputBufferWriteString(writer->out, standalone);
608 if (count < 0)
609 return -1;
610 sum += count;
611 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
612 if (count < 0)
613 return -1;
614 sum += count;
615 }
616
617 count = xmlOutputBufferWriteString(writer->out, "?>\n");
618 if (count < 0)
619 return -1;
620 sum += count;
621
622 return sum;
623}
624
625/**
626 * xmlTextWriterEndDocument:
627 * @writer: the xmlTextWriterPtr
628 *
Daniel Veillard3ff24112008-02-13 10:17:41 +0000629 * End an xml document. All open elements are closed, and
630 * the content is flushed to the output.
Daniel Veillard1d211e22003-10-20 22:32:39 +0000631 *
Daniel Veillard3ff24112008-02-13 10:17:41 +0000632 * Returns the bytes written or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +0000633 */
634int
635xmlTextWriterEndDocument(xmlTextWriterPtr writer)
636{
637 int count;
638 int sum;
639 xmlLinkPtr lk;
640 xmlTextWriterStackEntry *p;
641
Daniel Veillard500a1de2004-03-22 15:22:58 +0000642 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000643 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000644 "xmlTextWriterEndDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000645 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000646 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000647
648 sum = 0;
649 while ((lk = xmlListFront(writer->nodes)) != NULL) {
650 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
651 if (p == 0)
652 break;
653 switch (p->state) {
654 case XML_TEXTWRITER_NAME:
655 case XML_TEXTWRITER_ATTRIBUTE:
656 case XML_TEXTWRITER_TEXT:
657 count = xmlTextWriterEndElement(writer);
658 if (count < 0)
659 return -1;
660 sum += count;
661 break;
662 case XML_TEXTWRITER_PI:
663 case XML_TEXTWRITER_PI_TEXT:
664 count = xmlTextWriterEndPI(writer);
665 if (count < 0)
666 return -1;
667 sum += count;
668 break;
669 case XML_TEXTWRITER_CDATA:
670 count = xmlTextWriterEndCDATA(writer);
671 if (count < 0)
672 return -1;
673 sum += count;
674 break;
675 case XML_TEXTWRITER_DTD:
Daniel Veillard500a1de2004-03-22 15:22:58 +0000676 case XML_TEXTWRITER_DTD_TEXT:
677 case XML_TEXTWRITER_DTD_ELEM:
678 case XML_TEXTWRITER_DTD_ELEM_TEXT:
679 case XML_TEXTWRITER_DTD_ATTL:
680 case XML_TEXTWRITER_DTD_ATTL_TEXT:
681 case XML_TEXTWRITER_DTD_ENTY:
682 case XML_TEXTWRITER_DTD_ENTY_TEXT:
683 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard1d211e22003-10-20 22:32:39 +0000684 count = xmlTextWriterEndDTD(writer);
685 if (count < 0)
686 return -1;
687 sum += count;
688 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000689 case XML_TEXTWRITER_COMMENT:
690 count = xmlTextWriterEndComment(writer);
691 if (count < 0)
692 return -1;
693 sum += count;
694 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000695 default:
Daniel Veillardab69f362004-02-17 11:40:32 +0000696 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000697 }
698 }
699
Daniel Veillard2cca4462004-01-02 20:04:23 +0000700 if (!writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000701 count = xmlOutputBufferWriteString(writer->out, "\n");
702 if (count < 0)
703 return -1;
704 sum += count;
705 }
Daniel Veillard3ff24112008-02-13 10:17:41 +0000706
707 sum += xmlTextWriterFlush(writer);
708
Daniel Veillardab69f362004-02-17 11:40:32 +0000709 return sum;
710}
711
Daniel Veillardab69f362004-02-17 11:40:32 +0000712/**
713 * xmlTextWriterStartComment:
714 * @writer: the xmlTextWriterPtr
715 *
716 * Start an xml comment.
717 *
718 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
719 */
720int
721xmlTextWriterStartComment(xmlTextWriterPtr writer)
722{
723 int count;
724 int sum;
725 xmlLinkPtr lk;
726 xmlTextWriterStackEntry *p;
727
Daniel Veillard500a1de2004-03-22 15:22:58 +0000728 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000729 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000730 "xmlTextWriterStartComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000731 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000732 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000733
734 sum = 0;
735 lk = xmlListFront(writer->nodes);
736 if (lk != 0) {
737 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
738 if (p != 0) {
739 switch (p->state) {
740 case XML_TEXTWRITER_TEXT:
741 case XML_TEXTWRITER_NONE:
742 break;
743 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000744 /* Output namespace declarations */
745 count = xmlTextWriterOutputNSDecl(writer);
746 if (count < 0)
747 return -1;
748 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000749 count = xmlOutputBufferWriteString(writer->out, ">");
750 if (count < 0)
751 return -1;
752 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000753 if (writer->indent) {
754 count =
755 xmlOutputBufferWriteString(writer->out, "\n");
756 if (count < 0)
757 return -1;
758 sum += count;
759 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000760 p->state = XML_TEXTWRITER_TEXT;
761 break;
762 default:
763 return -1;
764 }
765 }
766 }
767
768 p = (xmlTextWriterStackEntry *)
769 xmlMalloc(sizeof(xmlTextWriterStackEntry));
770 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000771 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillardab69f362004-02-17 11:40:32 +0000772 "xmlTextWriterStartElement : out of memory!\n");
773 return -1;
774 }
775
Daniel Veillard75e389d2005-07-29 22:02:24 +0000776 p->name = NULL;
Daniel Veillardab69f362004-02-17 11:40:32 +0000777 p->state = XML_TEXTWRITER_COMMENT;
778
779 xmlListPushFront(writer->nodes, p);
780
781 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000782 count = xmlTextWriterWriteIndent(writer);
783 if (count < 0)
784 return -1;
785 sum += count;
786 }
787
788 count = xmlOutputBufferWriteString(writer->out, "<!--");
789 if (count < 0)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000790 return -1;
791 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000792
793 return sum;
794}
795
796/**
797 * xmlTextWriterEndComment:
798 * @writer: the xmlTextWriterPtr
799 *
800 * End the current xml coment.
801 *
802 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
803 */
804int
805xmlTextWriterEndComment(xmlTextWriterPtr writer)
806{
807 int count;
808 int sum;
809 xmlLinkPtr lk;
810 xmlTextWriterStackEntry *p;
811
Daniel Veillard500a1de2004-03-22 15:22:58 +0000812 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000813 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000814 "xmlTextWriterEndComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000815 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000816 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000817
818 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000819 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000820 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000821 "xmlTextWriterEndComment : not allowed in this context!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000822 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000823 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000824
825 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
826 if (p == 0)
827 return -1;
828
829 sum = 0;
830 switch (p->state) {
831 case XML_TEXTWRITER_COMMENT:
832 count = xmlOutputBufferWriteString(writer->out, "-->");
833 if (count < 0)
834 return -1;
835 sum += count;
836 break;
837 default:
838 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +0000839 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000840
841 if (writer->indent) {
842 count = xmlOutputBufferWriteString(writer->out, "\n");
843 if (count < 0)
844 return -1;
845 sum += count;
846 }
847
848 xmlListPopFront(writer->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000849 return sum;
850}
851
852/**
853 * xmlTextWriterWriteFormatComment:
854 * @writer: the xmlTextWriterPtr
855 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +0000856 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +0000857 *
858 * Write an xml comment.
859 *
860 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
861 */
Daniel Veillardffa3c742005-07-21 13:24:09 +0000862int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +0000863xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
864 const char *format, ...)
865{
866 int rc;
867 va_list ap;
868
869 va_start(ap, format);
870
871 rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
872
873 va_end(ap);
874 return rc;
875}
876
877/**
878 * xmlTextWriterWriteVFormatComment:
879 * @writer: the xmlTextWriterPtr
880 * @format: format string (see printf)
881 * @argptr: pointer to the first member of the variable argument list.
882 *
883 * Write an xml comment.
884 *
885 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
886 */
887int
888xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
889 const char *format, va_list argptr)
890{
891 int rc;
892 xmlChar *buf;
893
Daniel Veillard500a1de2004-03-22 15:22:58 +0000894 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000895 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000896 "xmlTextWriterWriteVFormatComment : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000897 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000898 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000899
900 buf = xmlTextWriterVSprintf(format, argptr);
901 if (buf == 0)
902 return 0;
903
904 rc = xmlTextWriterWriteComment(writer, buf);
905
906 xmlFree(buf);
907 return rc;
908}
909
910/**
911 * xmlTextWriterWriteComment:
912 * @writer: the xmlTextWriterPtr
913 * @content: comment string
914 *
915 * Write an xml comment.
916 *
917 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
918 */
919int
920xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
921{
922 int count;
923 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000924
925 sum = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000926 count = xmlTextWriterStartComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000927 if (count < 0)
928 return -1;
929 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000930 count = xmlTextWriterWriteString(writer, content);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000931 if (count < 0)
932 return -1;
933 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000934 count = xmlTextWriterEndComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000935 if (count < 0)
936 return -1;
937 sum += count;
938
939 return sum;
940}
941
942/**
943 * xmlTextWriterStartElement:
944 * @writer: the xmlTextWriterPtr
945 * @name: element name
946 *
947 * Start an xml element.
948 *
949 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
950 */
951int
952xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
953{
954 int count;
955 int sum;
956 xmlLinkPtr lk;
957 xmlTextWriterStackEntry *p;
958
959 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
960 return -1;
961
962 sum = 0;
963 lk = xmlListFront(writer->nodes);
964 if (lk != 0) {
965 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
966 if (p != 0) {
967 switch (p->state) {
968 case XML_TEXTWRITER_PI:
969 case XML_TEXTWRITER_PI_TEXT:
970 return -1;
971 case XML_TEXTWRITER_NONE:
972 break;
Daniel Veillard614fdc12005-02-23 14:05:37 +0000973 case XML_TEXTWRITER_ATTRIBUTE:
974 count = xmlTextWriterEndAttribute(writer);
975 if (count < 0)
976 return -1;
977 sum += count;
978 /* fallthrough */
Daniel Veillard1d211e22003-10-20 22:32:39 +0000979 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000980 /* Output namespace declarations */
981 count = xmlTextWriterOutputNSDecl(writer);
982 if (count < 0)
983 return -1;
984 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000985 count = xmlOutputBufferWriteString(writer->out, ">");
986 if (count < 0)
987 return -1;
988 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000989 if (writer->indent)
990 count =
991 xmlOutputBufferWriteString(writer->out, "\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000992 p->state = XML_TEXTWRITER_TEXT;
993 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000994 default:
995 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000996 }
997 }
998 }
999
1000 p = (xmlTextWriterStackEntry *)
1001 xmlMalloc(sizeof(xmlTextWriterStackEntry));
1002 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001003 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001004 "xmlTextWriterStartElement : out of memory!\n");
1005 return -1;
1006 }
1007
1008 p->name = xmlStrdup(name);
1009 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001010 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001011 "xmlTextWriterStartElement : out of memory!\n");
1012 xmlFree(p);
1013 return -1;
1014 }
1015 p->state = XML_TEXTWRITER_NAME;
1016
1017 xmlListPushFront(writer->nodes, p);
1018
Daniel Veillardab69f362004-02-17 11:40:32 +00001019 if (writer->indent) {
1020 count = xmlTextWriterWriteIndent(writer);
1021 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001022 }
1023
Daniel Veillard1d211e22003-10-20 22:32:39 +00001024 count = xmlOutputBufferWriteString(writer->out, "<");
1025 if (count < 0)
1026 return -1;
1027 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001028 count =
1029 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001030 if (count < 0)
1031 return -1;
1032 sum += count;
1033
1034 return sum;
1035}
1036
1037/**
1038 * xmlTextWriterStartElementNS:
1039 * @writer: the xmlTextWriterPtr
1040 * @prefix: namespace prefix or NULL
1041 * @name: element local name
1042 * @namespaceURI: namespace URI or NULL
1043 *
1044 * Start an xml element with namespace support.
1045 *
1046 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1047 */
1048int
1049xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
1050 const xmlChar * prefix, const xmlChar * name,
1051 const xmlChar * namespaceURI)
1052{
1053 int count;
1054 int sum;
1055 xmlChar *buf;
1056
1057 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1058 return -1;
1059
Daniel Veillard75e389d2005-07-29 22:02:24 +00001060 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001061 if (prefix != 0) {
1062 buf = xmlStrdup(prefix);
1063 buf = xmlStrcat(buf, BAD_CAST ":");
1064 }
1065 buf = xmlStrcat(buf, name);
1066
1067 sum = 0;
1068 count = xmlTextWriterStartElement(writer, buf);
1069 xmlFree(buf);
1070 if (count < 0)
1071 return -1;
1072 sum += count;
1073
1074 if (namespaceURI != 0) {
Rob Richardsb8769d62007-06-08 08:50:47 +00001075 xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
1076 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1077 if (p == 0) {
1078 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1079 "xmlTextWriterStartElementNS : out of memory!\n");
1080 return -1;
1081 }
1082
Daniel Veillard1d211e22003-10-20 22:32:39 +00001083 buf = xmlStrdup(BAD_CAST "xmlns");
1084 if (prefix != 0) {
1085 buf = xmlStrcat(buf, BAD_CAST ":");
1086 buf = xmlStrcat(buf, prefix);
1087 }
1088
Rob Richardsb8769d62007-06-08 08:50:47 +00001089 p->prefix = buf;
1090 p->uri = xmlStrdup(namespaceURI);
1091 if (p->uri == 0) {
1092 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1093 "xmlTextWriterStartElementNS : out of memory!\n");
1094 xmlFree(p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001095 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001096 }
1097 p->elem = xmlListFront(writer->nodes);
1098
1099 xmlListPushFront(writer->nsstack, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001100 }
1101
1102 return sum;
1103}
1104
1105/**
1106 * xmlTextWriterEndElement:
1107 * @writer: the xmlTextWriterPtr
1108 *
1109 * End the current xml element.
1110 *
1111 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1112 */
1113int
1114xmlTextWriterEndElement(xmlTextWriterPtr writer)
1115{
1116 int count;
1117 int sum;
1118 xmlLinkPtr lk;
1119 xmlTextWriterStackEntry *p;
1120
1121 if (writer == NULL)
1122 return -1;
1123
1124 lk = xmlListFront(writer->nodes);
Rob Richardsb8769d62007-06-08 08:50:47 +00001125 if (lk == 0) {
1126 xmlListDelete(writer->nsstack);
1127 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001128 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001129 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001130
1131 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Rob Richardsb8769d62007-06-08 08:50:47 +00001132 if (p == 0) {
1133 xmlListDelete(writer->nsstack);
1134 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001135 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001136 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001137
1138 sum = 0;
1139 switch (p->state) {
1140 case XML_TEXTWRITER_ATTRIBUTE:
1141 count = xmlTextWriterEndAttribute(writer);
Rob Richardsb8769d62007-06-08 08:50:47 +00001142 if (count < 0) {
1143 xmlListDelete(writer->nsstack);
1144 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001145 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001146 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001147 sum += count;
1148 /* fallthrough */
1149 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001150 /* Output namespace declarations */
1151 count = xmlTextWriterOutputNSDecl(writer);
1152 if (count < 0)
1153 return -1;
1154 sum += count;
1155
Daniel Veillardab69f362004-02-17 11:40:32 +00001156 if (writer->indent) /* next element needs indent */
1157 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001158 count = xmlOutputBufferWriteString(writer->out, "/>");
1159 if (count < 0)
1160 return -1;
1161 sum += count;
1162 break;
1163 case XML_TEXTWRITER_TEXT:
Daniel Veillardab69f362004-02-17 11:40:32 +00001164 if ((writer->indent) && (writer->doindent)) {
1165 count = xmlTextWriterWriteIndent(writer);
1166 sum += count;
1167 writer->doindent = 1;
1168 } else
1169 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001170 count = xmlOutputBufferWriteString(writer->out, "</");
1171 if (count < 0)
1172 return -1;
1173 sum += count;
1174 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001175 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001176 if (count < 0)
1177 return -1;
1178 sum += count;
1179 count = xmlOutputBufferWriteString(writer->out, ">");
1180 if (count < 0)
1181 return -1;
1182 sum += count;
1183 break;
1184 default:
1185 return -1;
1186 }
1187
Daniel Veillard2cca4462004-01-02 20:04:23 +00001188 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001189 count = xmlOutputBufferWriteString(writer->out, "\n");
1190 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001191 }
1192
Daniel Veillard1d211e22003-10-20 22:32:39 +00001193 xmlListPopFront(writer->nodes);
1194 return sum;
1195}
1196
1197/**
1198 * xmlTextWriterFullEndElement:
1199 * @writer: the xmlTextWriterPtr
1200 *
1201 * End the current xml element. Writes an end tag even if the element is empty
1202 *
1203 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1204 */
1205int
1206xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1207{
1208 int count;
1209 int sum;
1210 xmlLinkPtr lk;
1211 xmlTextWriterStackEntry *p;
1212
1213 if (writer == NULL)
1214 return -1;
1215
1216 lk = xmlListFront(writer->nodes);
1217 if (lk == 0)
1218 return -1;
1219
1220 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1221 if (p == 0)
1222 return -1;
1223
1224 sum = 0;
1225 switch (p->state) {
1226 case XML_TEXTWRITER_ATTRIBUTE:
1227 count = xmlTextWriterEndAttribute(writer);
1228 if (count < 0)
1229 return -1;
1230 sum += count;
1231 /* fallthrough */
1232 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001233 /* Output namespace declarations */
1234 count = xmlTextWriterOutputNSDecl(writer);
1235 if (count < 0)
1236 return -1;
1237 sum += count;
1238
Daniel Veillard1d211e22003-10-20 22:32:39 +00001239 count = xmlOutputBufferWriteString(writer->out, ">");
1240 if (count < 0)
1241 return -1;
1242 sum += count;
1243 /* fallthrough */
1244 case XML_TEXTWRITER_TEXT:
1245 count = xmlOutputBufferWriteString(writer->out, "</");
1246 if (count < 0)
1247 return -1;
1248 sum += count;
1249 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001250 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001251 if (count < 0)
1252 return -1;
1253 sum += count;
1254 count = xmlOutputBufferWriteString(writer->out, ">");
1255 if (count < 0)
1256 return -1;
1257 sum += count;
1258 break;
1259 default:
1260 return -1;
1261 }
1262
Daniel Veillard7e26fb42008-01-09 02:19:50 +00001263 if (writer->indent) {
1264 count = xmlOutputBufferWriteString(writer->out, "\n");
1265 sum += count;
1266 }
1267
Daniel Veillard1d211e22003-10-20 22:32:39 +00001268 xmlListPopFront(writer->nodes);
1269 return sum;
1270}
1271
1272/**
1273 * xmlTextWriterWriteFormatRaw:
1274 * @writer: the xmlTextWriterPtr
1275 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001276 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001277 *
1278 * Write a formatted raw xml text.
1279 *
1280 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1281 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001282int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001283xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1284 ...)
1285{
1286 int rc;
1287 va_list ap;
1288
1289 va_start(ap, format);
1290
1291 rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1292
1293 va_end(ap);
1294 return rc;
1295}
1296
1297/**
1298 * xmlTextWriterWriteVFormatRaw:
1299 * @writer: the xmlTextWriterPtr
1300 * @format: format string (see printf)
1301 * @argptr: pointer to the first member of the variable argument list.
1302 *
1303 * Write a formatted raw xml text.
1304 *
1305 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1306 */
1307int
1308xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1309 va_list argptr)
1310{
1311 int rc;
1312 xmlChar *buf;
1313
1314 if (writer == NULL)
1315 return -1;
1316
1317 buf = xmlTextWriterVSprintf(format, argptr);
1318 if (buf == 0)
1319 return 0;
1320
1321 rc = xmlTextWriterWriteRaw(writer, buf);
1322
1323 xmlFree(buf);
1324 return rc;
1325}
1326
1327/**
Daniel Veillard1e906612003-12-05 14:57:46 +00001328 * xmlTextWriterWriteRawLen:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001329 * @writer: the xmlTextWriterPtr
1330 * @content: text string
1331 * @len: length of the text string
1332 *
1333 * Write an xml text.
1334 * TODO: what about entities and special chars??
1335 *
1336 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1337 */
1338int
1339xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1340 int len)
1341{
1342 int count;
1343 int sum;
1344 xmlLinkPtr lk;
1345 xmlTextWriterStackEntry *p;
1346
Daniel Veillard500a1de2004-03-22 15:22:58 +00001347 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001348 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001349 "xmlTextWriterWriteRawLen : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001350 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001351 }
1352
Daniel Veillarde43cc572004-11-03 11:50:29 +00001353 if ((content == NULL) || (len < 0)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001354 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001355 "xmlTextWriterWriteRawLen : invalid content!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001356 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001357 }
1358
1359 sum = 0;
1360 lk = xmlListFront(writer->nodes);
1361 if (lk != 0) {
1362 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1363 count = xmlTextWriterHandleStateDependencies(writer, p);
1364 if (count < 0)
1365 return -1;
1366 sum += count;
1367 }
1368
1369 if (writer->indent)
1370 writer->doindent = 0;
1371
1372 if (content != NULL) {
1373 count =
1374 xmlOutputBufferWrite(writer->out, len, (const char *) content);
1375 if (count < 0)
1376 return -1;
1377 sum += count;
1378 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001379
1380 return sum;
1381}
1382
1383/**
1384 * xmlTextWriterWriteRaw:
1385 * @writer: the xmlTextWriterPtr
1386 * @content: text string
1387 *
1388 * Write a raw xml text.
1389 *
1390 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1391 */
1392int
1393xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1394{
1395 return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1396}
1397
1398/**
1399 * xmlTextWriterWriteFormatString:
1400 * @writer: the xmlTextWriterPtr
1401 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001402 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001403 *
1404 * Write a formatted xml text.
1405 *
1406 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1407 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001408int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001409xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1410 ...)
1411{
1412 int rc;
1413 va_list ap;
1414
Daniel Veillarde43cc572004-11-03 11:50:29 +00001415 if ((writer == NULL) || (format == NULL))
1416 return -1;
1417
Daniel Veillard1d211e22003-10-20 22:32:39 +00001418 va_start(ap, format);
1419
1420 rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1421
1422 va_end(ap);
1423 return rc;
1424}
1425
1426/**
1427 * xmlTextWriterWriteVFormatString:
1428 * @writer: the xmlTextWriterPtr
1429 * @format: format string (see printf)
1430 * @argptr: pointer to the first member of the variable argument list.
1431 *
1432 * Write a formatted xml text.
1433 *
1434 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1435 */
1436int
1437xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1438 const char *format, va_list argptr)
1439{
1440 int rc;
1441 xmlChar *buf;
1442
Daniel Veillarde43cc572004-11-03 11:50:29 +00001443 if ((writer == NULL) || (format == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001444 return -1;
1445
1446 buf = xmlTextWriterVSprintf(format, argptr);
1447 if (buf == 0)
1448 return 0;
1449
1450 rc = xmlTextWriterWriteString(writer, buf);
1451
1452 xmlFree(buf);
1453 return rc;
1454}
1455
1456/**
1457 * xmlTextWriterWriteString:
1458 * @writer: the xmlTextWriterPtr
1459 * @content: text string
1460 *
1461 * Write an xml text.
1462 *
1463 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1464 */
1465int
1466xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1467{
Daniel Veillard500a1de2004-03-22 15:22:58 +00001468 int count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001469 int sum;
1470 xmlLinkPtr lk;
1471 xmlTextWriterStackEntry *p;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001472 xmlChar *buf;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001473
Daniel Veillarde43cc572004-11-03 11:50:29 +00001474 if ((writer == NULL) || (content == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001475 return -1;
1476
Daniel Veillard1d211e22003-10-20 22:32:39 +00001477 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001478 buf = (xmlChar *) content;
1479 lk = xmlListFront(writer->nodes);
1480 if (lk != 0) {
1481 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1482 if (p != 0) {
1483 switch (p->state) {
1484 case XML_TEXTWRITER_NAME:
1485 case XML_TEXTWRITER_TEXT:
Daniel Veillard62040be2004-05-17 03:17:26 +00001486#if 0
1487 buf = NULL;
1488 xmlOutputBufferWriteEscape(writer->out, content, NULL);
1489#endif
Daniel Veillard500a1de2004-03-22 15:22:58 +00001490 buf = xmlEncodeSpecialChars(NULL, content);
1491 break;
1492 case XML_TEXTWRITER_ATTRIBUTE:
1493 buf = NULL;
Rob Richards9db68f02006-08-16 22:48:51 +00001494 xmlAttrSerializeTxtContent(writer->out->buffer, writer->doc,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001495 NULL, content);
1496 break;
William M. Brack87640d52004-04-17 14:58:15 +00001497 default:
1498 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001499 }
1500 }
1501 }
1502
1503 if (buf != NULL) {
1504 count = xmlTextWriterWriteRaw(writer, buf);
1505 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001506 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001507 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001508
Daniel Veillard500a1de2004-03-22 15:22:58 +00001509 if (buf != content) /* buf was allocated by us, so free it */
1510 xmlFree(buf);
William M. Bracka9c612c2004-02-01 10:04:05 +00001511 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001512
1513 return sum;
1514}
1515
1516/**
1517 * xmlOutputBufferWriteBase64:
1518 * @out: the xmlOutputBufferPtr
1519 * @data: binary data
1520 * @len: the number of bytes to encode
1521 *
1522 * Write base64 encoded data to an xmlOutputBuffer.
1523 * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1524 *
1525 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1526 */
1527static int
1528xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1529 const unsigned char *data)
1530{
1531 static unsigned char dtable[64] =
William M. Brack47a31882004-09-11 16:09:09 +00001532 {'A','B','C','D','E','F','G','H','I','J','K','L','M',
1533 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1534 'a','b','c','d','e','f','g','h','i','j','k','l','m',
1535 'n','o','p','q','r','s','t','u','v','w','x','y','z',
1536 '0','1','2','3','4','5','6','7','8','9','+','/'};
1537
Daniel Veillard1d211e22003-10-20 22:32:39 +00001538 int i;
1539 int linelen;
1540 int count;
1541 int sum;
1542
Daniel Veillarde43cc572004-11-03 11:50:29 +00001543 if ((out == NULL) || (len < 0) || (data == NULL))
1544 return(-1);
1545
Daniel Veillard1d211e22003-10-20 22:32:39 +00001546 linelen = 0;
1547 sum = 0;
1548
1549 i = 0;
1550 while (1) {
1551 unsigned char igroup[3];
1552 unsigned char ogroup[4];
1553 int c;
1554 int n;
1555
1556 igroup[0] = igroup[1] = igroup[2] = 0;
1557 for (n = 0; n < 3 && i < len; n++, i++) {
1558 c = data[i];
1559 igroup[n] = (unsigned char) c;
1560 }
1561
1562 if (n > 0) {
1563 ogroup[0] = dtable[igroup[0] >> 2];
1564 ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1565 ogroup[2] =
1566 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1567 ogroup[3] = dtable[igroup[2] & 0x3F];
1568
1569 if (n < 3) {
1570 ogroup[3] = '=';
1571 if (n < 2) {
1572 ogroup[2] = '=';
1573 }
1574 }
1575
1576 if (linelen >= B64LINELEN) {
1577 count = xmlOutputBufferWrite(out, 2, B64CRLF);
1578 if (count == -1)
1579 return -1;
1580 sum += count;
1581 linelen = 0;
1582 }
1583 count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1584 if (count == -1)
1585 return -1;
1586 sum += count;
1587
1588 linelen += 4;
1589 }
Daniel Veillard929714b2003-10-22 12:34:36 +00001590
1591 if (i >= len)
1592 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001593 }
1594
Daniel Veillard1d211e22003-10-20 22:32:39 +00001595 return sum;
1596}
1597
1598/**
1599 * xmlTextWriterWriteBase64:
1600 * @writer: the xmlTextWriterPtr
1601 * @data: binary data
1602 * @start: the position within the data of the first byte to encode
1603 * @len: the number of bytes to encode
1604 *
1605 * Write an base64 encoded xml text.
1606 *
1607 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1608 */
1609int
Daniel Veillardab69f362004-02-17 11:40:32 +00001610xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001611 int start, int len)
1612{
1613 int count;
1614 int sum;
1615 xmlLinkPtr lk;
1616 xmlTextWriterStackEntry *p;
1617
Daniel Veillarde43cc572004-11-03 11:50:29 +00001618 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001619 return -1;
1620
Daniel Veillard1d211e22003-10-20 22:32:39 +00001621 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001622 lk = xmlListFront(writer->nodes);
1623 if (lk != 0) {
1624 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1625 if (p != 0) {
1626 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001627 if (count < 0)
1628 return -1;
1629 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001630 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001631 }
1632
Daniel Veillardab69f362004-02-17 11:40:32 +00001633 if (writer->indent)
1634 writer->doindent = 0;
1635
Daniel Veillard1d211e22003-10-20 22:32:39 +00001636 count =
1637 xmlOutputBufferWriteBase64(writer->out, len,
1638 (unsigned char *) data + start);
1639 if (count < 0)
1640 return -1;
1641 sum += count;
1642
1643 return sum;
1644}
1645
1646/**
1647 * xmlOutputBufferWriteBinHex:
1648 * @out: the xmlOutputBufferPtr
1649 * @data: binary data
1650 * @len: the number of bytes to encode
1651 *
1652 * Write hqx encoded data to an xmlOutputBuffer.
1653 * ::todo
1654 *
William M. Brack47a31882004-09-11 16:09:09 +00001655 * Returns the bytes written (may be 0 because of buffering)
1656 * or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +00001657 */
1658static int
Daniel Veillardab69f362004-02-17 11:40:32 +00001659xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1660 int len, const unsigned char *data)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001661{
Daniel Veillardab69f362004-02-17 11:40:32 +00001662 int count;
1663 int sum;
William M. Brack47a31882004-09-11 16:09:09 +00001664 static char hex[16] =
1665 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
Daniel Veillardab69f362004-02-17 11:40:32 +00001666 int i;
1667
Daniel Veillarde43cc572004-11-03 11:50:29 +00001668 if ((out == NULL) || (data == NULL) || (len < 0)) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001669 return -1;
1670 }
1671
1672 sum = 0;
1673 for (i = 0; i < len; i++) {
1674 count =
1675 xmlOutputBufferWrite(out, 1,
1676 (const char *) &hex[data[i] >> 4]);
1677 if (count == -1)
1678 return -1;
1679 sum += count;
1680 count =
1681 xmlOutputBufferWrite(out, 1,
1682 (const char *) &hex[data[i] & 0xF]);
1683 if (count == -1)
1684 return -1;
1685 sum += count;
1686 }
1687
1688 return sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001689}
1690
1691/**
1692 * xmlTextWriterWriteBinHex:
1693 * @writer: the xmlTextWriterPtr
1694 * @data: binary data
1695 * @start: the position within the data of the first byte to encode
1696 * @len: the number of bytes to encode
1697 *
1698 * Write a BinHex encoded xml text.
1699 *
1700 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1701 */
1702int
Daniel Veillardab69f362004-02-17 11:40:32 +00001703xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001704 int start, int len)
1705{
1706 int count;
1707 int sum;
1708 xmlLinkPtr lk;
1709 xmlTextWriterStackEntry *p;
1710
Daniel Veillarde43cc572004-11-03 11:50:29 +00001711 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001712 return -1;
1713
Daniel Veillard1d211e22003-10-20 22:32:39 +00001714 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001715 lk = xmlListFront(writer->nodes);
1716 if (lk != 0) {
1717 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1718 if (p != 0) {
1719 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001720 if (count < 0)
1721 return -1;
1722 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001723 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001724 }
1725
Daniel Veillardab69f362004-02-17 11:40:32 +00001726 if (writer->indent)
1727 writer->doindent = 0;
1728
Daniel Veillard1d211e22003-10-20 22:32:39 +00001729 count =
1730 xmlOutputBufferWriteBinHex(writer->out, len,
1731 (unsigned char *) data + start);
1732 if (count < 0)
1733 return -1;
1734 sum += count;
1735
1736 return sum;
1737}
1738
1739/**
1740 * xmlTextWriterStartAttribute:
1741 * @writer: the xmlTextWriterPtr
1742 * @name: element name
1743 *
1744 * Start an xml attribute.
1745 *
1746 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1747 */
1748int
1749xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1750{
1751 int count;
1752 int sum;
1753 xmlLinkPtr lk;
1754 xmlTextWriterStackEntry *p;
1755
1756 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1757 return -1;
1758
1759 sum = 0;
1760 lk = xmlListFront(writer->nodes);
1761 if (lk == 0)
1762 return -1;
1763
1764 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1765 if (p == 0)
1766 return -1;
1767
1768 switch (p->state) {
1769 case XML_TEXTWRITER_ATTRIBUTE:
1770 count = xmlTextWriterEndAttribute(writer);
1771 if (count < 0)
1772 return -1;
1773 sum += count;
1774 /* fallthrough */
1775 case XML_TEXTWRITER_NAME:
1776 count = xmlOutputBufferWriteString(writer->out, " ");
1777 if (count < 0)
1778 return -1;
1779 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001780 count =
1781 xmlOutputBufferWriteString(writer->out,
1782 (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001783 if (count < 0)
1784 return -1;
1785 sum += count;
1786 count = xmlOutputBufferWriteString(writer->out, "=");
1787 if (count < 0)
1788 return -1;
1789 sum += count;
1790 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1791 if (count < 0)
1792 return -1;
1793 sum += count;
1794 p->state = XML_TEXTWRITER_ATTRIBUTE;
1795 break;
1796 default:
1797 return -1;
1798 }
1799
1800 return sum;
1801}
1802
1803/**
1804 * xmlTextWriterStartAttributeNS:
1805 * @writer: the xmlTextWriterPtr
1806 * @prefix: namespace prefix or NULL
1807 * @name: element local name
1808 * @namespaceURI: namespace URI or NULL
1809 *
1810 * Start an xml attribute with namespace support.
1811 *
1812 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1813 */
1814int
1815xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1816 const xmlChar * prefix, const xmlChar * name,
1817 const xmlChar * namespaceURI)
1818{
1819 int count;
1820 int sum;
1821 xmlChar *buf;
1822 xmlTextWriterNsStackEntry *p;
1823
1824 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1825 return -1;
1826
Rob Richardsb8769d62007-06-08 08:50:47 +00001827 /* Handle namespace first in case of error */
1828 if (namespaceURI != 0) {
1829 xmlTextWriterNsStackEntry nsentry, *curns;
1830
1831 buf = xmlStrdup(BAD_CAST "xmlns");
1832 if (prefix != 0) {
1833 buf = xmlStrcat(buf, BAD_CAST ":");
1834 buf = xmlStrcat(buf, prefix);
1835 }
1836
1837 nsentry.prefix = buf;
1838 nsentry.uri = (xmlChar *)namespaceURI;
1839 nsentry.elem = xmlListFront(writer->nodes);
1840
1841 curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
1842 (void *)&nsentry);
1843 if ((curns != NULL)) {
1844 xmlFree(buf);
1845 if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
1846 /* Namespace already defined on element skip */
1847 buf = NULL;
1848 } else {
1849 /* Prefix mismatch so error out */
1850 return -1;
1851 }
1852 }
1853
1854 /* Do not add namespace decl to list - it is already there */
1855 if (buf != NULL) {
1856 p = (xmlTextWriterNsStackEntry *)
1857 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1858 if (p == 0) {
1859 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1860 "xmlTextWriterStartAttributeNS : out of memory!\n");
1861 return -1;
1862 }
1863
1864 p->prefix = buf;
1865 p->uri = xmlStrdup(namespaceURI);
1866 if (p->uri == 0) {
1867 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1868 "xmlTextWriterStartAttributeNS : out of memory!\n");
1869 xmlFree(p);
1870 return -1;
1871 }
1872 p->elem = xmlListFront(writer->nodes);
1873
1874 xmlListPushFront(writer->nsstack, p);
1875 }
1876 }
1877
Daniel Veillard75e389d2005-07-29 22:02:24 +00001878 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001879 if (prefix != 0) {
1880 buf = xmlStrdup(prefix);
1881 buf = xmlStrcat(buf, BAD_CAST ":");
1882 }
1883 buf = xmlStrcat(buf, name);
1884
1885 sum = 0;
1886 count = xmlTextWriterStartAttribute(writer, buf);
1887 xmlFree(buf);
1888 if (count < 0)
1889 return -1;
1890 sum += count;
1891
Daniel Veillard1d211e22003-10-20 22:32:39 +00001892 return sum;
1893}
1894
1895/**
1896 * xmlTextWriterEndAttribute:
1897 * @writer: the xmlTextWriterPtr
1898 *
1899 * End the current xml element.
1900 *
1901 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1902 */
1903int
1904xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1905{
1906 int count;
1907 int sum;
1908 xmlLinkPtr lk;
1909 xmlTextWriterStackEntry *p;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001910
1911 if (writer == NULL)
1912 return -1;
1913
1914 lk = xmlListFront(writer->nodes);
1915 if (lk == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001916 return -1;
1917 }
1918
1919 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1920 if (p == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001921 return -1;
1922 }
1923
1924 sum = 0;
1925 switch (p->state) {
1926 case XML_TEXTWRITER_ATTRIBUTE:
1927 p->state = XML_TEXTWRITER_NAME;
1928
1929 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1930 if (count < 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001931 return -1;
1932 }
1933 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001934 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001935 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001936 return -1;
1937 }
1938
1939 return sum;
1940}
1941
1942/**
1943 * xmlTextWriterWriteFormatAttribute:
1944 * @writer: the xmlTextWriterPtr
1945 * @name: attribute name
1946 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001947 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001948 *
1949 * Write a formatted xml attribute.
1950 *
1951 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1952 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001953int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001954xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1955 const xmlChar * name, const char *format,
1956 ...)
1957{
1958 int rc;
1959 va_list ap;
1960
1961 va_start(ap, format);
1962
1963 rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1964
1965 va_end(ap);
1966 return rc;
1967}
1968
1969/**
1970 * xmlTextWriterWriteVFormatAttribute:
1971 * @writer: the xmlTextWriterPtr
1972 * @name: attribute name
1973 * @format: format string (see printf)
1974 * @argptr: pointer to the first member of the variable argument list.
1975 *
1976 * Write a formatted xml attribute.
1977 *
1978 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1979 */
1980int
1981xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
1982 const xmlChar * name,
1983 const char *format, va_list argptr)
1984{
1985 int rc;
1986 xmlChar *buf;
1987
1988 if (writer == NULL)
1989 return -1;
1990
1991 buf = xmlTextWriterVSprintf(format, argptr);
1992 if (buf == 0)
1993 return 0;
1994
1995 rc = xmlTextWriterWriteAttribute(writer, name, buf);
1996
1997 xmlFree(buf);
1998 return rc;
1999}
2000
2001/**
2002 * xmlTextWriterWriteAttribute:
2003 * @writer: the xmlTextWriterPtr
2004 * @name: attribute name
2005 * @content: attribute content
2006 *
2007 * Write an xml attribute.
2008 *
2009 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2010 */
2011int
2012xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
2013 const xmlChar * content)
2014{
2015 int count;
2016 int sum;
2017
2018 sum = 0;
2019 count = xmlTextWriterStartAttribute(writer, name);
2020 if (count < 0)
2021 return -1;
2022 sum += count;
2023 count = xmlTextWriterWriteString(writer, content);
2024 if (count < 0)
2025 return -1;
2026 sum += count;
2027 count = xmlTextWriterEndAttribute(writer);
2028 if (count < 0)
2029 return -1;
2030 sum += count;
2031
2032 return sum;
2033}
2034
2035/**
2036 * xmlTextWriterWriteFormatAttributeNS:
2037 * @writer: the xmlTextWriterPtr
2038 * @prefix: namespace prefix
2039 * @name: attribute local name
2040 * @namespaceURI: namespace URI
2041 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002042 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002043 *
2044 * Write a formatted xml attribute.with namespace support
2045 *
2046 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2047 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002048int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002049xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
2050 const xmlChar * prefix,
2051 const xmlChar * name,
2052 const xmlChar * namespaceURI,
2053 const char *format, ...)
2054{
2055 int rc;
2056 va_list ap;
2057
2058 va_start(ap, format);
2059
2060 rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
2061 namespaceURI, format, ap);
2062
2063 va_end(ap);
2064 return rc;
2065}
2066
2067/**
2068 * xmlTextWriterWriteVFormatAttributeNS:
2069 * @writer: the xmlTextWriterPtr
2070 * @prefix: namespace prefix
2071 * @name: attribute local name
2072 * @namespaceURI: namespace URI
2073 * @format: format string (see printf)
2074 * @argptr: pointer to the first member of the variable argument list.
2075 *
2076 * Write a formatted xml attribute.with namespace support
2077 *
2078 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2079 */
2080int
2081xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
2082 const xmlChar * prefix,
2083 const xmlChar * name,
2084 const xmlChar * namespaceURI,
2085 const char *format, va_list argptr)
2086{
2087 int rc;
2088 xmlChar *buf;
2089
2090 if (writer == NULL)
2091 return -1;
2092
2093 buf = xmlTextWriterVSprintf(format, argptr);
2094 if (buf == 0)
2095 return 0;
2096
2097 rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
2098 buf);
2099
2100 xmlFree(buf);
2101 return rc;
2102}
2103
2104/**
2105 * xmlTextWriterWriteAttributeNS:
2106 * @writer: the xmlTextWriterPtr
2107 * @prefix: namespace prefix
2108 * @name: attribute local name
2109 * @namespaceURI: namespace URI
2110 * @content: attribute content
2111 *
2112 * Write an xml attribute.
2113 *
2114 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2115 */
2116int
2117xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
2118 const xmlChar * prefix, const xmlChar * name,
2119 const xmlChar * namespaceURI,
2120 const xmlChar * content)
2121{
2122 int count;
2123 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002124
2125 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2126 return -1;
2127
Daniel Veillard1d211e22003-10-20 22:32:39 +00002128 sum = 0;
Rob Richardsb8769d62007-06-08 08:50:47 +00002129 count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
2130 if (count < 0)
2131 return -1;
2132 sum += count;
2133 count = xmlTextWriterWriteString(writer, content);
2134 if (count < 0)
2135 return -1;
2136 sum += count;
2137 count = xmlTextWriterEndAttribute(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002138 if (count < 0)
2139 return -1;
2140 sum += count;
2141
Daniel Veillard1d211e22003-10-20 22:32:39 +00002142 return sum;
2143}
2144
2145/**
2146 * xmlTextWriterWriteFormatElement:
2147 * @writer: the xmlTextWriterPtr
2148 * @name: element name
2149 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002150 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002151 *
2152 * Write a formatted xml element.
2153 *
2154 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2155 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002156int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002157xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2158 const xmlChar * name, const char *format,
2159 ...)
2160{
2161 int rc;
2162 va_list ap;
2163
2164 va_start(ap, format);
2165
2166 rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2167
2168 va_end(ap);
2169 return rc;
2170}
2171
2172/**
2173 * xmlTextWriterWriteVFormatElement:
2174 * @writer: the xmlTextWriterPtr
2175 * @name: element name
2176 * @format: format string (see printf)
2177 * @argptr: pointer to the first member of the variable argument list.
2178 *
2179 * Write a formatted xml element.
2180 *
2181 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2182 */
2183int
2184xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2185 const xmlChar * name, const char *format,
2186 va_list argptr)
2187{
2188 int rc;
2189 xmlChar *buf;
2190
2191 if (writer == NULL)
2192 return -1;
2193
2194 buf = xmlTextWriterVSprintf(format, argptr);
2195 if (buf == 0)
2196 return 0;
2197
2198 rc = xmlTextWriterWriteElement(writer, name, buf);
2199
2200 xmlFree(buf);
2201 return rc;
2202}
2203
2204/**
2205 * xmlTextWriterWriteElement:
2206 * @writer: the xmlTextWriterPtr
2207 * @name: element name
2208 * @content: element content
2209 *
2210 * Write an xml element.
2211 *
2212 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2213 */
2214int
2215xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2216 const xmlChar * content)
2217{
2218 int count;
2219 int sum;
2220
2221 sum = 0;
2222 count = xmlTextWriterStartElement(writer, name);
2223 if (count == -1)
2224 return -1;
2225 sum += count;
2226 count = xmlTextWriterWriteString(writer, content);
2227 if (count == -1)
2228 return -1;
2229 sum += count;
2230 count = xmlTextWriterEndElement(writer);
2231 if (count == -1)
2232 return -1;
2233 sum += count;
2234
2235 return sum;
2236}
2237
2238/**
2239 * xmlTextWriterWriteFormatElementNS:
2240 * @writer: the xmlTextWriterPtr
2241 * @prefix: namespace prefix
2242 * @name: element local name
2243 * @namespaceURI: namespace URI
2244 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002245 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002246 *
2247 * Write a formatted xml element with namespace support.
2248 *
2249 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2250 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002251int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002252xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2253 const xmlChar * prefix,
2254 const xmlChar * name,
2255 const xmlChar * namespaceURI,
2256 const char *format, ...)
2257{
2258 int rc;
2259 va_list ap;
2260
2261 va_start(ap, format);
2262
2263 rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2264 namespaceURI, format, ap);
2265
2266 va_end(ap);
2267 return rc;
2268}
2269
2270/**
2271 * xmlTextWriterWriteVFormatElementNS:
2272 * @writer: the xmlTextWriterPtr
2273 * @prefix: namespace prefix
2274 * @name: element local name
2275 * @namespaceURI: namespace URI
2276 * @format: format string (see printf)
2277 * @argptr: pointer to the first member of the variable argument list.
2278 *
2279 * Write a formatted xml element with namespace support.
2280 *
2281 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2282 */
2283int
2284xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2285 const xmlChar * prefix,
2286 const xmlChar * name,
2287 const xmlChar * namespaceURI,
2288 const char *format, va_list argptr)
2289{
2290 int rc;
2291 xmlChar *buf;
2292
2293 if (writer == NULL)
2294 return -1;
2295
2296 buf = xmlTextWriterVSprintf(format, argptr);
2297 if (buf == 0)
2298 return 0;
2299
2300 rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2301 buf);
2302
2303 xmlFree(buf);
2304 return rc;
2305}
2306
2307/**
2308 * xmlTextWriterWriteElementNS:
2309 * @writer: the xmlTextWriterPtr
2310 * @prefix: namespace prefix
2311 * @name: element local name
2312 * @namespaceURI: namespace URI
2313 * @content: element content
2314 *
2315 * Write an xml element with namespace support.
2316 *
2317 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2318 */
2319int
2320xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2321 const xmlChar * prefix, const xmlChar * name,
2322 const xmlChar * namespaceURI,
2323 const xmlChar * content)
2324{
2325 int count;
2326 int sum;
2327
2328 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2329 return -1;
2330
2331 sum = 0;
2332 count =
2333 xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2334 if (count < 0)
2335 return -1;
2336 sum += count;
2337 count = xmlTextWriterWriteString(writer, content);
2338 if (count == -1)
2339 return -1;
2340 sum += count;
2341 count = xmlTextWriterEndElement(writer);
2342 if (count == -1)
2343 return -1;
2344 sum += count;
2345
2346 return sum;
2347}
2348
2349/**
2350 * xmlTextWriterStartPI:
2351 * @writer: the xmlTextWriterPtr
2352 * @target: PI target
2353 *
2354 * Start an xml PI.
2355 *
2356 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2357 */
2358int
2359xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2360{
2361 int count;
2362 int sum;
2363 xmlLinkPtr lk;
2364 xmlTextWriterStackEntry *p;
2365
2366 if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2367 return -1;
2368
2369 if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002370 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002371 "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2372 return -1;
2373 }
2374
2375 sum = 0;
2376 lk = xmlListFront(writer->nodes);
2377 if (lk != 0) {
2378 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2379 if (p != 0) {
2380 switch (p->state) {
2381 case XML_TEXTWRITER_ATTRIBUTE:
2382 count = xmlTextWriterEndAttribute(writer);
2383 if (count < 0)
2384 return -1;
2385 sum += count;
2386 /* fallthrough */
2387 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002388 /* Output namespace declarations */
2389 count = xmlTextWriterOutputNSDecl(writer);
2390 if (count < 0)
2391 return -1;
2392 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002393 count = xmlOutputBufferWriteString(writer->out, ">");
2394 if (count < 0)
2395 return -1;
2396 sum += count;
2397 p->state = XML_TEXTWRITER_TEXT;
2398 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00002399 case XML_TEXTWRITER_NONE:
2400 case XML_TEXTWRITER_TEXT:
2401 case XML_TEXTWRITER_DTD:
2402 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002403 case XML_TEXTWRITER_PI:
2404 case XML_TEXTWRITER_PI_TEXT:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002405 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002406 "xmlTextWriterStartPI : nested PI!\n");
2407 return -1;
2408 default:
2409 return -1;
2410 }
2411 }
2412 }
2413
2414 p = (xmlTextWriterStackEntry *)
2415 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2416 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002417 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002418 "xmlTextWriterStartPI : out of memory!\n");
2419 return -1;
2420 }
2421
2422 p->name = xmlStrdup(target);
2423 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002424 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002425 "xmlTextWriterStartPI : out of memory!\n");
2426 xmlFree(p);
2427 return -1;
2428 }
2429 p->state = XML_TEXTWRITER_PI;
2430
2431 xmlListPushFront(writer->nodes, p);
2432
2433 count = xmlOutputBufferWriteString(writer->out, "<?");
2434 if (count < 0)
2435 return -1;
2436 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002437 count =
2438 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002439 if (count < 0)
2440 return -1;
2441 sum += count;
2442
2443 return sum;
2444}
2445
2446/**
2447 * xmlTextWriterEndPI:
2448 * @writer: the xmlTextWriterPtr
2449 *
2450 * End the current xml PI.
2451 *
2452 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2453 */
2454int
2455xmlTextWriterEndPI(xmlTextWriterPtr writer)
2456{
2457 int count;
2458 int sum;
2459 xmlLinkPtr lk;
2460 xmlTextWriterStackEntry *p;
2461
2462 if (writer == NULL)
2463 return -1;
2464
2465 lk = xmlListFront(writer->nodes);
2466 if (lk == 0)
2467 return 0;
2468
2469 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2470 if (p == 0)
2471 return 0;
2472
2473 sum = 0;
2474 switch (p->state) {
2475 case XML_TEXTWRITER_PI:
2476 case XML_TEXTWRITER_PI_TEXT:
2477 count = xmlOutputBufferWriteString(writer->out, "?>");
2478 if (count < 0)
2479 return -1;
2480 sum += count;
2481 break;
2482 default:
2483 return -1;
2484 }
2485
Daniel Veillard02c1f232006-04-27 08:10:25 +00002486 if (writer->indent) {
2487 count = xmlOutputBufferWriteString(writer->out, "\n");
2488 if (count < 0)
2489 return -1;
2490 sum += count;
2491 }
2492
Daniel Veillard1d211e22003-10-20 22:32:39 +00002493 xmlListPopFront(writer->nodes);
2494 return sum;
2495}
2496
2497/**
2498 * xmlTextWriterWriteFormatPI:
2499 * @writer: the xmlTextWriterPtr
2500 * @target: PI target
2501 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002502 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002503 *
2504 * Write a formatted PI.
2505 *
2506 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2507 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002508int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002509xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2510 const char *format, ...)
2511{
2512 int rc;
2513 va_list ap;
2514
2515 va_start(ap, format);
2516
2517 rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2518
2519 va_end(ap);
2520 return rc;
2521}
2522
2523/**
2524 * xmlTextWriterWriteVFormatPI:
2525 * @writer: the xmlTextWriterPtr
2526 * @target: PI target
2527 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002528 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002529 *
2530 * Write a formatted xml PI.
2531 *
2532 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2533 */
2534int
2535xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2536 const xmlChar * target, const char *format,
2537 va_list argptr)
2538{
2539 int rc;
2540 xmlChar *buf;
2541
2542 if (writer == NULL)
2543 return -1;
2544
2545 buf = xmlTextWriterVSprintf(format, argptr);
2546 if (buf == 0)
2547 return 0;
2548
2549 rc = xmlTextWriterWritePI(writer, target, buf);
2550
2551 xmlFree(buf);
2552 return rc;
2553}
2554
2555/**
2556 * xmlTextWriterWritePI:
2557 * @writer: the xmlTextWriterPtr
2558 * @target: PI target
2559 * @content: PI content
2560 *
2561 * Write an xml PI.
2562 *
2563 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2564 */
2565int
2566xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2567 const xmlChar * content)
2568{
2569 int count;
2570 int sum;
2571
2572 sum = 0;
2573 count = xmlTextWriterStartPI(writer, target);
2574 if (count == -1)
2575 return -1;
2576 sum += count;
2577 if (content != 0) {
2578 count = xmlTextWriterWriteString(writer, content);
2579 if (count == -1)
2580 return -1;
2581 sum += count;
2582 }
2583 count = xmlTextWriterEndPI(writer);
2584 if (count == -1)
2585 return -1;
2586 sum += count;
2587
2588 return sum;
2589}
2590
2591/**
2592 * xmlTextWriterStartCDATA:
2593 * @writer: the xmlTextWriterPtr
2594 *
2595 * Start an xml CDATA section.
2596 *
2597 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2598 */
2599int
2600xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2601{
2602 int count;
2603 int sum;
2604 xmlLinkPtr lk;
2605 xmlTextWriterStackEntry *p;
2606
2607 if (writer == NULL)
2608 return -1;
2609
2610 sum = 0;
2611 lk = xmlListFront(writer->nodes);
2612 if (lk != 0) {
2613 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2614 if (p != 0) {
2615 switch (p->state) {
2616 case XML_TEXTWRITER_NONE:
2617 case XML_TEXTWRITER_PI:
2618 case XML_TEXTWRITER_PI_TEXT:
2619 break;
2620 case XML_TEXTWRITER_ATTRIBUTE:
2621 count = xmlTextWriterEndAttribute(writer);
2622 if (count < 0)
2623 return -1;
2624 sum += count;
2625 /* fallthrough */
2626 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002627 /* Output namespace declarations */
2628 count = xmlTextWriterOutputNSDecl(writer);
2629 if (count < 0)
2630 return -1;
2631 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002632 count = xmlOutputBufferWriteString(writer->out, ">");
2633 if (count < 0)
2634 return -1;
2635 sum += count;
2636 p->state = XML_TEXTWRITER_TEXT;
2637 break;
2638 case XML_TEXTWRITER_CDATA:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002639 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002640 "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2641 return -1;
2642 default:
2643 return -1;
2644 }
2645 }
2646 }
2647
2648 p = (xmlTextWriterStackEntry *)
2649 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2650 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002651 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002652 "xmlTextWriterStartCDATA : out of memory!\n");
2653 return -1;
2654 }
2655
Daniel Veillard75e389d2005-07-29 22:02:24 +00002656 p->name = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002657 p->state = XML_TEXTWRITER_CDATA;
2658
2659 xmlListPushFront(writer->nodes, p);
2660
2661 count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2662 if (count < 0)
2663 return -1;
2664 sum += count;
2665
2666 return sum;
2667}
2668
2669/**
2670 * xmlTextWriterEndCDATA:
2671 * @writer: the xmlTextWriterPtr
2672 *
2673 * End an xml CDATA section.
2674 *
2675 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2676 */
2677int
2678xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2679{
2680 int count;
2681 int sum;
2682 xmlLinkPtr lk;
2683 xmlTextWriterStackEntry *p;
2684
2685 if (writer == NULL)
2686 return -1;
2687
2688 lk = xmlListFront(writer->nodes);
2689 if (lk == 0)
2690 return -1;
2691
2692 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2693 if (p == 0)
2694 return -1;
2695
2696 sum = 0;
2697 switch (p->state) {
2698 case XML_TEXTWRITER_CDATA:
2699 count = xmlOutputBufferWriteString(writer->out, "]]>");
2700 if (count < 0)
2701 return -1;
2702 sum += count;
2703 break;
2704 default:
2705 return -1;
2706 }
2707
2708 xmlListPopFront(writer->nodes);
2709 return sum;
2710}
2711
2712/**
2713 * xmlTextWriterWriteFormatCDATA:
2714 * @writer: the xmlTextWriterPtr
2715 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002716 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002717 *
2718 * Write a formatted xml CDATA.
2719 *
2720 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2721 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002722int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002723xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2724 ...)
2725{
2726 int rc;
2727 va_list ap;
2728
2729 va_start(ap, format);
2730
2731 rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2732
2733 va_end(ap);
2734 return rc;
2735}
2736
2737/**
2738 * xmlTextWriterWriteVFormatCDATA:
2739 * @writer: the xmlTextWriterPtr
2740 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002741 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002742 *
2743 * Write a formatted xml CDATA.
2744 *
2745 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2746 */
2747int
2748xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2749 va_list argptr)
2750{
2751 int rc;
2752 xmlChar *buf;
2753
2754 if (writer == NULL)
2755 return -1;
2756
2757 buf = xmlTextWriterVSprintf(format, argptr);
2758 if (buf == 0)
2759 return 0;
2760
2761 rc = xmlTextWriterWriteCDATA(writer, buf);
2762
2763 xmlFree(buf);
2764 return rc;
2765}
2766
2767/**
2768 * xmlTextWriterWriteCDATA:
2769 * @writer: the xmlTextWriterPtr
2770 * @content: CDATA content
2771 *
2772 * Write an xml CDATA.
2773 *
2774 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2775 */
2776int
2777xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2778{
2779 int count;
2780 int sum;
2781
2782 sum = 0;
2783 count = xmlTextWriterStartCDATA(writer);
2784 if (count == -1)
2785 return -1;
2786 sum += count;
2787 if (content != 0) {
2788 count = xmlTextWriterWriteString(writer, content);
2789 if (count == -1)
2790 return -1;
2791 sum += count;
2792 }
2793 count = xmlTextWriterEndCDATA(writer);
2794 if (count == -1)
2795 return -1;
2796 sum += count;
2797
2798 return sum;
2799}
2800
2801/**
2802 * xmlTextWriterStartDTD:
2803 * @writer: the xmlTextWriterPtr
2804 * @name: the name of the DTD
2805 * @pubid: the public identifier, which is an alternative to the system identifier
2806 * @sysid: the system identifier, which is the URI of the DTD
2807 *
2808 * Start an xml DTD.
2809 *
2810 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2811 */
2812int
2813xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2814 const xmlChar * name,
2815 const xmlChar * pubid, const xmlChar * sysid)
2816{
2817 int count;
2818 int sum;
2819 xmlLinkPtr lk;
2820 xmlTextWriterStackEntry *p;
2821
2822 if (writer == NULL || name == NULL || *name == '\0')
2823 return -1;
2824
2825 sum = 0;
2826 lk = xmlListFront(writer->nodes);
Daniel Veillardab69f362004-02-17 11:40:32 +00002827 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002828 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002829 "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2830 return -1;
2831 }
2832
2833 p = (xmlTextWriterStackEntry *)
2834 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2835 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002836 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002837 "xmlTextWriterStartDTD : out of memory!\n");
2838 return -1;
2839 }
2840
2841 p->name = xmlStrdup(name);
2842 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002843 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002844 "xmlTextWriterStartDTD : out of memory!\n");
2845 xmlFree(p);
2846 return -1;
2847 }
2848 p->state = XML_TEXTWRITER_DTD;
2849
2850 xmlListPushFront(writer->nodes, p);
2851
2852 count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2853 if (count < 0)
2854 return -1;
2855 sum += count;
2856 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2857 if (count < 0)
2858 return -1;
2859 sum += count;
2860
2861 if (pubid != 0) {
2862 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002863 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002864 "xmlTextWriterStartDTD : system identifier needed!\n");
2865 return -1;
2866 }
2867
Daniel Veillard500a1de2004-03-22 15:22:58 +00002868 if (writer->indent)
2869 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2870 else
2871 count = xmlOutputBufferWrite(writer->out, 1, " ");
2872 if (count < 0)
2873 return -1;
2874 sum += count;
2875
2876 count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2877 if (count < 0)
2878 return -1;
2879 sum += count;
2880
2881 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002882 if (count < 0)
2883 return -1;
2884 sum += count;
2885
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002886 count =
2887 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002888 if (count < 0)
2889 return -1;
2890 sum += count;
2891
Daniel Veillard500a1de2004-03-22 15:22:58 +00002892 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002893 if (count < 0)
2894 return -1;
2895 sum += count;
2896 }
2897
2898 if (sysid != 0) {
2899 if (pubid == 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00002900 if (writer->indent)
2901 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2902 else
2903 count = xmlOutputBufferWrite(writer->out, 1, " ");
2904 if (count < 0)
2905 return -1;
2906 sum += count;
2907 count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2908 if (count < 0)
2909 return -1;
2910 sum += count;
Rob Richardsffe47fe2005-12-09 17:52:21 +00002911 } else {
2912 if (writer->indent)
Daniel Veillard500a1de2004-03-22 15:22:58 +00002913 count = xmlOutputBufferWriteString(writer->out, "\n ");
Rob Richardsffe47fe2005-12-09 17:52:21 +00002914 else
2915 count = xmlOutputBufferWrite(writer->out, 1, " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00002916 if (count < 0)
2917 return -1;
2918 sum += count;
2919 }
2920
Daniel Veillard500a1de2004-03-22 15:22:58 +00002921 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002922 if (count < 0)
2923 return -1;
2924 sum += count;
2925
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002926 count =
2927 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002928 if (count < 0)
2929 return -1;
2930 sum += count;
2931
Daniel Veillard500a1de2004-03-22 15:22:58 +00002932 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002933 if (count < 0)
2934 return -1;
2935 sum += count;
2936 }
2937
2938 return sum;
2939}
2940
2941/**
2942 * xmlTextWriterEndDTD:
2943 * @writer: the xmlTextWriterPtr
2944 *
2945 * End an xml DTD.
2946 *
2947 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2948 */
2949int
2950xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2951{
Daniel Veillard500a1de2004-03-22 15:22:58 +00002952 int loop;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002953 int count;
2954 int sum;
2955 xmlLinkPtr lk;
2956 xmlTextWriterStackEntry *p;
2957
2958 if (writer == NULL)
2959 return -1;
2960
2961 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002962 loop = 1;
2963 while (loop) {
2964 lk = xmlListFront(writer->nodes);
2965 if (lk == NULL)
Daniel Veillard1d211e22003-10-20 22:32:39 +00002966 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002967 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2968 if (p == 0)
2969 break;
2970 switch (p->state) {
2971 case XML_TEXTWRITER_DTD_TEXT:
2972 count = xmlOutputBufferWriteString(writer->out, "]");
2973 if (count < 0)
2974 return -1;
2975 sum += count;
2976 /* fallthrough */
2977 case XML_TEXTWRITER_DTD:
2978 count = xmlOutputBufferWriteString(writer->out, ">");
2979
2980 if (writer->indent) {
2981 if (count < 0)
2982 return -1;
2983 sum += count;
2984 count = xmlOutputBufferWriteString(writer->out, "\n");
2985 }
2986
2987 xmlListPopFront(writer->nodes);
2988 break;
2989 case XML_TEXTWRITER_DTD_ELEM:
2990 case XML_TEXTWRITER_DTD_ELEM_TEXT:
2991 count = xmlTextWriterEndDTDElement(writer);
2992 break;
2993 case XML_TEXTWRITER_DTD_ATTL:
2994 case XML_TEXTWRITER_DTD_ATTL_TEXT:
2995 count = xmlTextWriterEndDTDAttlist(writer);
2996 break;
2997 case XML_TEXTWRITER_DTD_ENTY:
2998 case XML_TEXTWRITER_DTD_PENT:
2999 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3000 count = xmlTextWriterEndDTDEntity(writer);
3001 break;
3002 case XML_TEXTWRITER_COMMENT:
3003 count = xmlTextWriterEndComment(writer);
3004 break;
3005 default:
3006 loop = 0;
3007 continue;
3008 }
3009
3010 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00003011 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003012 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003013 }
3014
Daniel Veillard1d211e22003-10-20 22:32:39 +00003015 return sum;
3016}
3017
3018/**
3019 * xmlTextWriterWriteFormatDTD:
3020 * @writer: the xmlTextWriterPtr
3021 * @name: the name of the DTD
3022 * @pubid: the public identifier, which is an alternative to the system identifier
3023 * @sysid: the system identifier, which is the URI of the DTD
3024 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003025 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00003026 *
3027 * Write a DTD with a formatted markup declarations part.
3028 *
3029 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3030 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003031int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003032xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3033 const xmlChar * name,
3034 const xmlChar * pubid,
3035 const xmlChar * sysid, const char *format, ...)
3036{
3037 int rc;
3038 va_list ap;
3039
3040 va_start(ap, format);
3041
3042 rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3043 ap);
3044
3045 va_end(ap);
3046 return rc;
3047}
3048
3049/**
3050 * xmlTextWriterWriteVFormatDTD:
3051 * @writer: the xmlTextWriterPtr
3052 * @name: the name of the DTD
3053 * @pubid: the public identifier, which is an alternative to the system identifier
3054 * @sysid: the system identifier, which is the URI of the DTD
3055 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003056 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00003057 *
3058 * Write a DTD with a formatted markup declarations part.
3059 *
3060 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3061 */
3062int
3063xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3064 const xmlChar * name,
3065 const xmlChar * pubid,
3066 const xmlChar * sysid,
3067 const char *format, va_list argptr)
3068{
3069 int rc;
3070 xmlChar *buf;
3071
3072 if (writer == NULL)
3073 return -1;
3074
3075 buf = xmlTextWriterVSprintf(format, argptr);
3076 if (buf == 0)
3077 return 0;
3078
3079 rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3080
3081 xmlFree(buf);
3082 return rc;
3083}
3084
3085/**
3086 * xmlTextWriterWriteDTD:
3087 * @writer: the xmlTextWriterPtr
3088 * @name: the name of the DTD
3089 * @pubid: the public identifier, which is an alternative to the system identifier
3090 * @sysid: the system identifier, which is the URI of the DTD
William M. Brackb1d53162003-11-18 06:54:40 +00003091 * @subset: string content of the DTD
Daniel Veillard1d211e22003-10-20 22:32:39 +00003092 *
3093 * Write a DTD.
3094 *
3095 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3096 */
3097int
3098xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3099 const xmlChar * name,
3100 const xmlChar * pubid,
3101 const xmlChar * sysid, const xmlChar * subset)
3102{
3103 int count;
3104 int sum;
3105
3106 sum = 0;
3107 count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3108 if (count == -1)
3109 return -1;
3110 sum += count;
3111 if (subset != 0) {
3112 count = xmlTextWriterWriteString(writer, subset);
3113 if (count == -1)
3114 return -1;
3115 sum += count;
3116 }
3117 count = xmlTextWriterEndDTD(writer);
3118 if (count == -1)
3119 return -1;
3120 sum += count;
3121
3122 return sum;
3123}
3124
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003125/**
3126 * xmlTextWriterStartDTDElement:
3127 * @writer: the xmlTextWriterPtr
3128 * @name: the name of the DTD element
3129 *
3130 * Start an xml DTD element.
3131 *
3132 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3133 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003134int
3135xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3136{
3137 int count;
3138 int sum;
3139 xmlLinkPtr lk;
3140 xmlTextWriterStackEntry *p;
3141
3142 if (writer == NULL || name == NULL || *name == '\0')
3143 return -1;
3144
3145 sum = 0;
3146 lk = xmlListFront(writer->nodes);
3147 if (lk == 0) {
3148 return -1;
3149 }
3150
3151 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003152 if (p != 0) {
3153 switch (p->state) {
3154 case XML_TEXTWRITER_DTD:
3155 count = xmlOutputBufferWriteString(writer->out, " [");
3156 if (count < 0)
3157 return -1;
3158 sum += count;
3159 if (writer->indent) {
3160 count = xmlOutputBufferWriteString(writer->out, "\n");
3161 if (count < 0)
3162 return -1;
3163 sum += count;
3164 }
3165 p->state = XML_TEXTWRITER_DTD_TEXT;
3166 /* fallthrough */
3167 case XML_TEXTWRITER_DTD_TEXT:
3168 case XML_TEXTWRITER_NONE:
3169 break;
3170 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003171 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003172 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003173 }
3174
3175 p = (xmlTextWriterStackEntry *)
3176 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3177 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003178 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003179 "xmlTextWriterStartDTDElement : out of memory!\n");
3180 return -1;
3181 }
3182
3183 p->name = xmlStrdup(name);
3184 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003185 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003186 "xmlTextWriterStartDTDElement : out of memory!\n");
3187 xmlFree(p);
3188 return -1;
3189 }
3190 p->state = XML_TEXTWRITER_DTD_ELEM;
3191
3192 xmlListPushFront(writer->nodes, p);
3193
Daniel Veillard500a1de2004-03-22 15:22:58 +00003194 if (writer->indent) {
3195 count = xmlTextWriterWriteIndent(writer);
3196 if (count < 0)
3197 return -1;
3198 sum += count;
3199 }
3200
Daniel Veillard1d211e22003-10-20 22:32:39 +00003201 count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3202 if (count < 0)
3203 return -1;
3204 sum += count;
3205 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3206 if (count < 0)
3207 return -1;
3208 sum += count;
3209
3210 return sum;
3211}
3212
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003213/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003214 * xmlTextWriterEndDTDElement:
3215 * @writer: the xmlTextWriterPtr
3216 *
3217 * End an xml DTD element.
3218 *
3219 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3220 */
3221int
3222xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3223{
3224 int count;
3225 int sum;
3226 xmlLinkPtr lk;
3227 xmlTextWriterStackEntry *p;
3228
3229 if (writer == NULL)
3230 return -1;
3231
3232 sum = 0;
3233 lk = xmlListFront(writer->nodes);
3234 if (lk == 0)
3235 return -1;
3236
3237 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3238 if (p == 0)
3239 return -1;
3240
3241 switch (p->state) {
3242 case XML_TEXTWRITER_DTD_ELEM:
3243 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3244 count = xmlOutputBufferWriteString(writer->out, ">");
3245 if (count < 0)
3246 return -1;
3247 sum += count;
3248 break;
3249 default:
3250 return -1;
3251 }
3252
3253 if (writer->indent) {
3254 count = xmlOutputBufferWriteString(writer->out, "\n");
3255 if (count < 0)
3256 return -1;
3257 sum += count;
3258 }
3259
3260 xmlListPopFront(writer->nodes);
3261 return sum;
3262}
3263
3264/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003265 * xmlTextWriterWriteFormatDTDElement:
3266 * @writer: the xmlTextWriterPtr
3267 * @name: the name of the DTD element
3268 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003269 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003270 *
3271 * Write a formatted DTD element.
3272 *
3273 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3274 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003275int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003276xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3277 const xmlChar * name,
3278 const char *format, ...)
3279{
3280 int rc;
3281 va_list ap;
3282
3283 va_start(ap, format);
3284
3285 rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3286
3287 va_end(ap);
3288 return rc;
3289}
3290
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003291/**
3292 * xmlTextWriterWriteVFormatDTDElement:
3293 * @writer: the xmlTextWriterPtr
3294 * @name: the name of the DTD element
3295 * @format: format string (see printf)
3296 * @argptr: pointer to the first member of the variable argument list.
3297 *
3298 * Write a formatted DTD element.
3299 *
3300 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3301 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003302int
3303xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3304 const xmlChar * name,
3305 const char *format, va_list argptr)
3306{
3307 int rc;
3308 xmlChar *buf;
3309
3310 if (writer == NULL)
3311 return -1;
3312
3313 buf = xmlTextWriterVSprintf(format, argptr);
3314 if (buf == 0)
3315 return 0;
3316
3317 rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3318
3319 xmlFree(buf);
3320 return rc;
3321}
3322
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003323/**
3324 * xmlTextWriterWriteDTDElement:
3325 * @writer: the xmlTextWriterPtr
3326 * @name: the name of the DTD element
3327 * @content: content of the element
3328 *
3329 * Write a DTD element.
3330 *
3331 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3332 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003333int
3334xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3335 const xmlChar * name, const xmlChar * content)
3336{
3337 int count;
3338 int sum;
3339
3340 if (content == NULL)
3341 return -1;
3342
3343 sum = 0;
3344 count = xmlTextWriterStartDTDElement(writer, name);
3345 if (count == -1)
3346 return -1;
3347 sum += count;
3348
Daniel Veillard1d211e22003-10-20 22:32:39 +00003349 count = xmlTextWriterWriteString(writer, content);
3350 if (count == -1)
3351 return -1;
3352 sum += count;
3353
3354 count = xmlTextWriterEndDTDElement(writer);
3355 if (count == -1)
3356 return -1;
3357 sum += count;
3358
3359 return sum;
3360}
3361
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003362/**
3363 * xmlTextWriterStartDTDAttlist:
3364 * @writer: the xmlTextWriterPtr
3365 * @name: the name of the DTD ATTLIST
3366 *
3367 * Start an xml DTD ATTLIST.
3368 *
3369 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3370 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003371int
3372xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3373{
3374 int count;
3375 int sum;
3376 xmlLinkPtr lk;
3377 xmlTextWriterStackEntry *p;
3378
3379 if (writer == NULL || name == NULL || *name == '\0')
3380 return -1;
3381
3382 sum = 0;
3383 lk = xmlListFront(writer->nodes);
3384 if (lk == 0) {
3385 return -1;
3386 }
3387
3388 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003389 if (p != 0) {
3390 switch (p->state) {
3391 case XML_TEXTWRITER_DTD:
3392 count = xmlOutputBufferWriteString(writer->out, " [");
3393 if (count < 0)
3394 return -1;
3395 sum += count;
3396 if (writer->indent) {
3397 count = xmlOutputBufferWriteString(writer->out, "\n");
3398 if (count < 0)
3399 return -1;
3400 sum += count;
3401 }
3402 p->state = XML_TEXTWRITER_DTD_TEXT;
3403 /* fallthrough */
3404 case XML_TEXTWRITER_DTD_TEXT:
3405 case XML_TEXTWRITER_NONE:
3406 break;
3407 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003408 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003409 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003410 }
3411
3412 p = (xmlTextWriterStackEntry *)
3413 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3414 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003415 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003416 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3417 return -1;
3418 }
3419
3420 p->name = xmlStrdup(name);
3421 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003422 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003423 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3424 xmlFree(p);
3425 return -1;
3426 }
3427 p->state = XML_TEXTWRITER_DTD_ATTL;
3428
3429 xmlListPushFront(writer->nodes, p);
3430
Daniel Veillard500a1de2004-03-22 15:22:58 +00003431 if (writer->indent) {
3432 count = xmlTextWriterWriteIndent(writer);
3433 if (count < 0)
3434 return -1;
3435 sum += count;
3436 }
3437
Daniel Veillard1d211e22003-10-20 22:32:39 +00003438 count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3439 if (count < 0)
3440 return -1;
3441 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +00003442 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003443 if (count < 0)
3444 return -1;
3445 sum += count;
3446
3447 return sum;
3448}
3449
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003450/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003451 * xmlTextWriterEndDTDAttlist:
3452 * @writer: the xmlTextWriterPtr
3453 *
3454 * End an xml DTD attribute list.
3455 *
3456 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3457 */
3458int
3459xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3460{
3461 int count;
3462 int sum;
3463 xmlLinkPtr lk;
3464 xmlTextWriterStackEntry *p;
3465
3466 if (writer == NULL)
3467 return -1;
3468
3469 sum = 0;
3470 lk = xmlListFront(writer->nodes);
3471 if (lk == 0)
3472 return -1;
3473
3474 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3475 if (p == 0)
3476 return -1;
3477
3478 switch (p->state) {
3479 case XML_TEXTWRITER_DTD_ATTL:
3480 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3481 count = xmlOutputBufferWriteString(writer->out, ">");
3482 if (count < 0)
3483 return -1;
3484 sum += count;
3485 break;
3486 default:
3487 return -1;
3488 }
3489
3490 if (writer->indent) {
3491 count = xmlOutputBufferWriteString(writer->out, "\n");
3492 if (count < 0)
3493 return -1;
3494 sum += count;
3495 }
3496
3497 xmlListPopFront(writer->nodes);
3498 return sum;
3499}
3500
3501/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003502 * xmlTextWriterWriteFormatDTDAttlist:
3503 * @writer: the xmlTextWriterPtr
3504 * @name: the name of the DTD ATTLIST
3505 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003506 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003507 *
3508 * Write a formatted DTD ATTLIST.
3509 *
3510 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3511 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003512int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003513xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3514 const xmlChar * name,
3515 const char *format, ...)
3516{
3517 int rc;
3518 va_list ap;
3519
3520 va_start(ap, format);
3521
3522 rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3523
3524 va_end(ap);
3525 return rc;
3526}
3527
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003528/**
3529 * xmlTextWriterWriteVFormatDTDAttlist:
3530 * @writer: the xmlTextWriterPtr
3531 * @name: the name of the DTD ATTLIST
3532 * @format: format string (see printf)
3533 * @argptr: pointer to the first member of the variable argument list.
3534 *
3535 * Write a formatted DTD ATTLIST.
3536 *
3537 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3538 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003539int
3540xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3541 const xmlChar * name,
3542 const char *format, va_list argptr)
3543{
3544 int rc;
3545 xmlChar *buf;
3546
3547 if (writer == NULL)
3548 return -1;
3549
3550 buf = xmlTextWriterVSprintf(format, argptr);
3551 if (buf == 0)
3552 return 0;
3553
3554 rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3555
3556 xmlFree(buf);
3557 return rc;
3558}
3559
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003560/**
3561 * xmlTextWriterWriteDTDAttlist:
3562 * @writer: the xmlTextWriterPtr
3563 * @name: the name of the DTD ATTLIST
3564 * @content: content of the ATTLIST
3565 *
3566 * Write a DTD ATTLIST.
3567 *
3568 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3569 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003570int
3571xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3572 const xmlChar * name, const xmlChar * content)
3573{
3574 int count;
3575 int sum;
3576
3577 if (content == NULL)
3578 return -1;
3579
3580 sum = 0;
3581 count = xmlTextWriterStartDTDAttlist(writer, name);
3582 if (count == -1)
3583 return -1;
3584 sum += count;
3585
Daniel Veillard1d211e22003-10-20 22:32:39 +00003586 count = xmlTextWriterWriteString(writer, content);
3587 if (count == -1)
3588 return -1;
3589 sum += count;
3590
3591 count = xmlTextWriterEndDTDAttlist(writer);
3592 if (count == -1)
3593 return -1;
3594 sum += count;
3595
3596 return sum;
3597}
3598
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003599/**
3600 * xmlTextWriterStartDTDEntity:
3601 * @writer: the xmlTextWriterPtr
3602 * @pe: TRUE if this is a parameter entity, FALSE if not
3603 * @name: the name of the DTD ATTLIST
3604 *
3605 * Start an xml DTD ATTLIST.
3606 *
3607 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3608 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003609int
3610xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3611 int pe, const xmlChar * name)
3612{
3613 int count;
3614 int sum;
3615 xmlLinkPtr lk;
3616 xmlTextWriterStackEntry *p;
3617
3618 if (writer == NULL || name == NULL || *name == '\0')
3619 return -1;
3620
3621 sum = 0;
3622 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003623 if (lk != 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00003624
Daniel Veillard500a1de2004-03-22 15:22:58 +00003625 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3626 if (p != 0) {
3627 switch (p->state) {
3628 case XML_TEXTWRITER_DTD:
3629 count = xmlOutputBufferWriteString(writer->out, " [");
3630 if (count < 0)
3631 return -1;
3632 sum += count;
3633 if (writer->indent) {
3634 count =
3635 xmlOutputBufferWriteString(writer->out, "\n");
3636 if (count < 0)
3637 return -1;
3638 sum += count;
3639 }
3640 p->state = XML_TEXTWRITER_DTD_TEXT;
3641 /* fallthrough */
3642 case XML_TEXTWRITER_DTD_TEXT:
3643 case XML_TEXTWRITER_NONE:
3644 break;
3645 default:
3646 return -1;
3647 }
3648 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003649 }
3650
3651 p = (xmlTextWriterStackEntry *)
3652 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3653 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003654 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003655 "xmlTextWriterStartDTDElement : out of memory!\n");
3656 return -1;
3657 }
3658
3659 p->name = xmlStrdup(name);
3660 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003661 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003662 "xmlTextWriterStartDTDElement : out of memory!\n");
3663 xmlFree(p);
3664 return -1;
3665 }
Daniel Veillard500a1de2004-03-22 15:22:58 +00003666
3667 if (pe != 0)
3668 p->state = XML_TEXTWRITER_DTD_PENT;
3669 else
3670 p->state = XML_TEXTWRITER_DTD_ENTY;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003671
3672 xmlListPushFront(writer->nodes, p);
3673
Daniel Veillard500a1de2004-03-22 15:22:58 +00003674 if (writer->indent) {
3675 count = xmlTextWriterWriteIndent(writer);
3676 if (count < 0)
3677 return -1;
3678 sum += count;
3679 }
3680
Daniel Veillard1d211e22003-10-20 22:32:39 +00003681 count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3682 if (count < 0)
3683 return -1;
3684 sum += count;
3685
3686 if (pe != 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00003687 count = xmlOutputBufferWriteString(writer->out, "% ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003688 if (count < 0)
3689 return -1;
3690 sum += count;
3691 }
3692
Daniel Veillardab69f362004-02-17 11:40:32 +00003693 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003694 if (count < 0)
3695 return -1;
3696 sum += count;
3697
3698 return sum;
3699}
3700
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003701/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003702 * xmlTextWriterEndDTDEntity:
3703 * @writer: the xmlTextWriterPtr
3704 *
3705 * End an xml DTD entity.
3706 *
3707 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3708 */
3709int
3710xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3711{
3712 int count;
3713 int sum;
3714 xmlLinkPtr lk;
3715 xmlTextWriterStackEntry *p;
3716
3717 if (writer == NULL)
3718 return -1;
3719
3720 sum = 0;
3721 lk = xmlListFront(writer->nodes);
3722 if (lk == 0)
3723 return -1;
3724
3725 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3726 if (p == 0)
3727 return -1;
3728
3729 switch (p->state) {
3730 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3731 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3732 if (count < 0)
3733 return -1;
3734 sum += count;
3735 case XML_TEXTWRITER_DTD_ENTY:
3736 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard500a1de2004-03-22 15:22:58 +00003737 count = xmlOutputBufferWriteString(writer->out, ">");
3738 if (count < 0)
3739 return -1;
3740 sum += count;
3741 break;
3742 default:
3743 return -1;
3744 }
3745
3746 if (writer->indent) {
3747 count = xmlOutputBufferWriteString(writer->out, "\n");
3748 if (count < 0)
3749 return -1;
3750 sum += count;
3751 }
3752
3753 xmlListPopFront(writer->nodes);
3754 return sum;
3755}
3756
3757/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003758 * xmlTextWriterWriteFormatDTDInternalEntity:
3759 * @writer: the xmlTextWriterPtr
3760 * @pe: TRUE if this is a parameter entity, FALSE if not
3761 * @name: the name of the DTD entity
3762 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003763 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003764 *
3765 * Write a formatted DTD internal entity.
3766 *
3767 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3768 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003769int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003770xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3771 int pe,
3772 const xmlChar * name,
3773 const char *format, ...)
3774{
3775 int rc;
3776 va_list ap;
3777
3778 va_start(ap, format);
3779
3780 rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3781 format, ap);
3782
3783 va_end(ap);
3784 return rc;
3785}
3786
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003787/**
3788 * xmlTextWriterWriteVFormatDTDInternalEntity:
3789 * @writer: the xmlTextWriterPtr
3790 * @pe: TRUE if this is a parameter entity, FALSE if not
3791 * @name: the name of the DTD entity
3792 * @format: format string (see printf)
3793 * @argptr: pointer to the first member of the variable argument list.
3794 *
3795 * Write a formatted DTD internal entity.
3796 *
3797 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3798 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003799int
3800xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3801 int pe,
3802 const xmlChar * name,
3803 const char *format,
3804 va_list argptr)
3805{
3806 int rc;
3807 xmlChar *buf;
3808
3809 if (writer == NULL)
3810 return -1;
3811
3812 buf = xmlTextWriterVSprintf(format, argptr);
3813 if (buf == 0)
3814 return 0;
3815
3816 rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3817
3818 xmlFree(buf);
3819 return rc;
3820}
3821
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003822/**
3823 * xmlTextWriterWriteDTDEntity:
3824 * @writer: the xmlTextWriterPtr
3825 * @pe: TRUE if this is a parameter entity, FALSE if not
3826 * @name: the name of the DTD entity
3827 * @pubid: the public identifier, which is an alternative to the system identifier
3828 * @sysid: the system identifier, which is the URI of the DTD
3829 * @ndataid: the xml notation name.
3830 * @content: content of the entity
3831 *
3832 * Write a DTD entity.
3833 *
3834 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3835 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003836int
3837xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3838 int pe,
3839 const xmlChar * name,
3840 const xmlChar * pubid,
3841 const xmlChar * sysid,
3842 const xmlChar * ndataid,
3843 const xmlChar * content)
3844{
Daniel Veillard500a1de2004-03-22 15:22:58 +00003845 if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003846 return -1;
3847 if ((pe != 0) && (ndataid != NULL))
3848 return -1;
3849
Daniel Veillard500a1de2004-03-22 15:22:58 +00003850 if ((pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003851 return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3852 content);
3853
3854 return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3855 sysid, ndataid);
3856}
3857
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003858/**
3859 * xmlTextWriterWriteDTDInternalEntity:
3860 * @writer: the xmlTextWriterPtr
3861 * @pe: TRUE if this is a parameter entity, FALSE if not
3862 * @name: the name of the DTD entity
3863 * @content: content of the entity
3864 *
3865 * Write a DTD internal entity.
3866 *
3867 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3868 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003869int
3870xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3871 int pe,
3872 const xmlChar * name,
3873 const xmlChar * content)
3874{
3875 int count;
3876 int sum;
3877
3878 if ((name == NULL) || (*name == '\0') || (content == NULL))
3879 return -1;
3880
3881 sum = 0;
3882 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3883 if (count == -1)
3884 return -1;
3885 sum += count;
3886
Daniel Veillard1d211e22003-10-20 22:32:39 +00003887 count = xmlTextWriterWriteString(writer, content);
3888 if (count == -1)
3889 return -1;
3890 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003891
3892 count = xmlTextWriterEndDTDEntity(writer);
3893 if (count == -1)
3894 return -1;
3895 sum += count;
3896
3897 return sum;
3898}
3899
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003900/**
3901 * xmlTextWriterWriteDTDExternalEntity:
3902 * @writer: the xmlTextWriterPtr
3903 * @pe: TRUE if this is a parameter entity, FALSE if not
3904 * @name: the name of the DTD entity
3905 * @pubid: the public identifier, which is an alternative to the system identifier
3906 * @sysid: the system identifier, which is the URI of the DTD
3907 * @ndataid: the xml notation name.
3908 *
Daniel Veillard500a1de2004-03-22 15:22:58 +00003909 * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003910 *
3911 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3912 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003913int
3914xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3915 int pe,
3916 const xmlChar * name,
3917 const xmlChar * pubid,
3918 const xmlChar * sysid,
3919 const xmlChar * ndataid)
3920{
3921 int count;
3922 int sum;
3923
Daniel Veillard500a1de2004-03-22 15:22:58 +00003924 if (((pubid == NULL) && (sysid == NULL)))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003925 return -1;
3926 if ((pe != 0) && (ndataid != NULL))
3927 return -1;
3928
3929 sum = 0;
3930 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3931 if (count == -1)
3932 return -1;
3933 sum += count;
3934
Daniel Veillard500a1de2004-03-22 15:22:58 +00003935 count =
3936 xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3937 ndataid);
3938 if (count < 0)
3939 return -1;
3940 sum += count;
3941
3942 count = xmlTextWriterEndDTDEntity(writer);
3943 if (count == -1)
3944 return -1;
3945 sum += count;
3946
3947 return sum;
3948}
3949
3950/**
3951 * xmlTextWriterWriteDTDExternalEntityContents:
3952 * @writer: the xmlTextWriterPtr
3953 * @pubid: the public identifier, which is an alternative to the system identifier
3954 * @sysid: the system identifier, which is the URI of the DTD
3955 * @ndataid: the xml notation name.
3956 *
3957 * Write the contents of a DTD external entity.
3958 *
3959 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3960 */
3961int
3962xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3963 const xmlChar * pubid,
3964 const xmlChar * sysid,
3965 const xmlChar * ndataid)
3966{
3967 int count;
3968 int sum;
3969 xmlLinkPtr lk;
3970 xmlTextWriterStackEntry *p;
3971
3972 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003973 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003974 "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3975 return -1;
3976 }
3977
3978 sum = 0;
3979 lk = xmlListFront(writer->nodes);
3980 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003981 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003982 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
3983 return -1;
3984 }
3985
3986 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3987 if (p == 0)
3988 return -1;
3989
3990 switch (p->state) {
3991 case XML_TEXTWRITER_DTD_ENTY:
3992 break;
3993 case XML_TEXTWRITER_DTD_PENT:
3994 if (ndataid != NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003995 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003996 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
3997 return -1;
3998 }
3999 break;
4000 default:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004001 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004002 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4003 return -1;
4004 }
4005
Daniel Veillard1d211e22003-10-20 22:32:39 +00004006 if (pubid != 0) {
4007 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004008 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004009 "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00004010 return -1;
4011 }
4012
4013 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4014 if (count < 0)
4015 return -1;
4016 sum += count;
4017
4018 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4019 if (count < 0)
4020 return -1;
4021 sum += count;
4022
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004023 count =
4024 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004025 if (count < 0)
4026 return -1;
4027 sum += count;
4028
4029 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4030 if (count < 0)
4031 return -1;
4032 sum += count;
4033 }
4034
4035 if (sysid != 0) {
4036 if (pubid == 0) {
4037 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4038 if (count < 0)
4039 return -1;
4040 sum += count;
4041 }
4042
4043 count = xmlOutputBufferWriteString(writer->out, " ");
4044 if (count < 0)
4045 return -1;
4046 sum += count;
4047
4048 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4049 if (count < 0)
4050 return -1;
4051 sum += count;
4052
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004053 count =
4054 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004055 if (count < 0)
4056 return -1;
4057 sum += count;
4058
4059 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4060 if (count < 0)
4061 return -1;
4062 sum += count;
4063 }
4064
4065 if (ndataid != NULL) {
4066 count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4067 if (count < 0)
4068 return -1;
4069 sum += count;
4070
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004071 count =
4072 xmlOutputBufferWriteString(writer->out,
4073 (const char *) ndataid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004074 if (count < 0)
4075 return -1;
4076 sum += count;
4077 }
4078
Daniel Veillard1d211e22003-10-20 22:32:39 +00004079 return sum;
4080}
4081
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004082/**
4083 * xmlTextWriterWriteDTDNotation:
4084 * @writer: the xmlTextWriterPtr
4085 * @name: the name of the xml notation
4086 * @pubid: the public identifier, which is an alternative to the system identifier
4087 * @sysid: the system identifier, which is the URI of the DTD
4088 *
4089 * Write a DTD entity.
4090 *
4091 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4092 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00004093int
4094xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4095 const xmlChar * name,
4096 const xmlChar * pubid, const xmlChar * sysid)
4097{
4098 int count;
4099 int sum;
4100 xmlLinkPtr lk;
4101 xmlTextWriterStackEntry *p;
4102
4103 if (writer == NULL || name == NULL || *name == '\0')
4104 return -1;
4105
4106 sum = 0;
4107 lk = xmlListFront(writer->nodes);
4108 if (lk == 0) {
4109 return -1;
4110 }
4111
4112 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00004113 if (p != 0) {
4114 switch (p->state) {
4115 case XML_TEXTWRITER_DTD:
4116 count = xmlOutputBufferWriteString(writer->out, " [");
4117 if (count < 0)
4118 return -1;
4119 sum += count;
4120 if (writer->indent) {
4121 count = xmlOutputBufferWriteString(writer->out, "\n");
4122 if (count < 0)
4123 return -1;
4124 sum += count;
4125 }
4126 p->state = XML_TEXTWRITER_DTD_TEXT;
4127 /* fallthrough */
4128 case XML_TEXTWRITER_DTD_TEXT:
4129 break;
4130 default:
4131 return -1;
4132 }
4133 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00004134
Daniel Veillard500a1de2004-03-22 15:22:58 +00004135 if (writer->indent) {
4136 count = xmlTextWriterWriteIndent(writer);
4137 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004138 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004139 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004140 }
4141
4142 count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4143 if (count < 0)
4144 return -1;
4145 sum += count;
4146 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4147 if (count < 0)
4148 return -1;
4149 sum += count;
4150
4151 if (pubid != 0) {
4152 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4153 if (count < 0)
4154 return -1;
4155 sum += count;
4156 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4157 if (count < 0)
4158 return -1;
4159 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004160 count =
4161 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004162 if (count < 0)
4163 return -1;
4164 sum += count;
4165 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4166 if (count < 0)
4167 return -1;
4168 sum += count;
4169 }
4170
4171 if (sysid != 0) {
4172 if (pubid == 0) {
4173 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4174 if (count < 0)
4175 return -1;
4176 sum += count;
4177 }
4178 count = xmlOutputBufferWriteString(writer->out, " ");
4179 if (count < 0)
4180 return -1;
4181 sum += count;
4182 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4183 if (count < 0)
4184 return -1;
4185 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004186 count =
4187 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004188 if (count < 0)
4189 return -1;
4190 sum += count;
4191 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4192 if (count < 0)
4193 return -1;
4194 sum += count;
4195 }
4196
4197 count = xmlOutputBufferWriteString(writer->out, ">");
4198 if (count < 0)
4199 return -1;
4200 sum += count;
4201
4202 return sum;
4203}
4204
4205/**
4206 * xmlTextWriterFlush:
4207 * @writer: the xmlTextWriterPtr
4208 *
4209 * Flush the output buffer.
4210 *
4211 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4212 */
4213int
4214xmlTextWriterFlush(xmlTextWriterPtr writer)
4215{
4216 int count;
4217
4218 if (writer == NULL)
4219 return -1;
4220
4221 if (writer->out == NULL)
4222 count = 0;
4223 else
4224 count = xmlOutputBufferFlush(writer->out);
4225
4226 return count;
4227}
4228
4229/**
4230 * misc
4231 */
4232
4233/**
4234 * xmlFreeTextWriterStackEntry:
4235 * @lk: the xmlLinkPtr
4236 *
4237 * Free callback for the xmlList.
4238 */
4239static void
4240xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4241{
4242 xmlTextWriterStackEntry *p;
4243
4244 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4245 if (p == 0)
4246 return;
4247
4248 if (p->name != 0)
4249 xmlFree(p->name);
4250 xmlFree(p);
4251}
4252
4253/**
4254 * xmlCmpTextWriterStackEntry:
4255 * @data0: the first data
4256 * @data1: the second data
4257 *
4258 * Compare callback for the xmlList.
4259 *
4260 * Returns -1, 0, 1
4261 */
4262static int
4263xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4264{
4265 xmlTextWriterStackEntry *p0;
4266 xmlTextWriterStackEntry *p1;
4267
4268 if (data0 == data1)
4269 return 0;
4270
4271 if (data0 == 0)
4272 return -1;
4273
4274 if (data1 == 0)
4275 return 1;
4276
4277 p0 = (xmlTextWriterStackEntry *) data0;
4278 p1 = (xmlTextWriterStackEntry *) data1;
4279
4280 return xmlStrcmp(p0->name, p1->name);
4281}
4282
4283/**
4284 * misc
4285 */
4286
4287/**
Rob Richardsb8769d62007-06-08 08:50:47 +00004288 * xmlTextWriterOutputNSDecl:
4289 * @writer: the xmlTextWriterPtr
4290 *
4291 * Output the current namespace declarations.
4292 */
4293static int
4294xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4295{
4296 xmlLinkPtr lk;
4297 xmlTextWriterNsStackEntry *np;
4298 int count;
4299 int sum;
4300
4301 sum = 0;
4302 while (!xmlListEmpty(writer->nsstack)) {
4303 xmlChar *namespaceURI = NULL;
4304 xmlChar *prefix = NULL;
4305
4306 lk = xmlListFront(writer->nsstack);
4307 np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4308
4309 if (np != 0) {
4310 namespaceURI = xmlStrdup(np->uri);
4311 prefix = xmlStrdup(np->prefix);
4312 }
4313
4314 xmlListPopFront(writer->nsstack);
4315
4316 if (np != 0) {
4317 count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4318 xmlFree(namespaceURI);
4319 xmlFree(prefix);
4320
4321 if (count < 0) {
4322 xmlListDelete(writer->nsstack);
4323 writer->nsstack = NULL;
4324 return -1;
4325 }
4326 sum += count;
4327 }
4328 }
4329 return sum;
4330}
4331
4332/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004333 * xmlFreeTextWriterNsStackEntry:
4334 * @lk: the xmlLinkPtr
4335 *
4336 * Free callback for the xmlList.
4337 */
4338static void
4339xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4340{
4341 xmlTextWriterNsStackEntry *p;
4342
4343 p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4344 if (p == 0)
4345 return;
4346
4347 if (p->prefix != 0)
4348 xmlFree(p->prefix);
4349 if (p->uri != 0)
4350 xmlFree(p->uri);
4351
4352 xmlFree(p);
4353}
4354
4355/**
4356 * xmlCmpTextWriterNsStackEntry:
4357 * @data0: the first data
4358 * @data1: the second data
4359 *
4360 * Compare callback for the xmlList.
4361 *
4362 * Returns -1, 0, 1
4363 */
4364static int
4365xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4366{
4367 xmlTextWriterNsStackEntry *p0;
4368 xmlTextWriterNsStackEntry *p1;
4369 int rc;
4370
4371 if (data0 == data1)
4372 return 0;
4373
4374 if (data0 == 0)
4375 return -1;
4376
4377 if (data1 == 0)
4378 return 1;
4379
4380 p0 = (xmlTextWriterNsStackEntry *) data0;
4381 p1 = (xmlTextWriterNsStackEntry *) data1;
4382
4383 rc = xmlStrcmp(p0->prefix, p1->prefix);
4384
Rob Richardsb8769d62007-06-08 08:50:47 +00004385 if ((rc != 0) || (p0->elem != p1->elem))
4386 rc = -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004387
4388 return rc;
4389}
4390
4391/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004392 * xmlTextWriterWriteDocCallback:
4393 * @context: the xmlBufferPtr
4394 * @str: the data to write
4395 * @len: the length of the data
4396 *
4397 * Write callback for the xmlOutputBuffer with target xmlBuffer
4398 *
4399 * Returns -1, 0, 1
4400 */
4401static int
4402xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
4403{
4404 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4405 int rc;
4406
Daniel Veillard1d913862003-11-21 00:28:39 +00004407 if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004408 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004409 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4410 rc);
4411 return -1;
4412 }
4413
4414 return len;
4415}
4416
4417/**
4418 * xmlTextWriterCloseDocCallback:
4419 * @context: the xmlBufferPtr
4420 *
4421 * Close callback for the xmlOutputBuffer with target xmlBuffer
4422 *
4423 * Returns -1, 0, 1
4424 */
4425static int
4426xmlTextWriterCloseDocCallback(void *context)
4427{
4428 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4429 int rc;
4430
4431 if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004432 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004433 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4434 rc);
4435 return -1;
4436 }
4437
4438 return 0;
4439}
4440
4441/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004442 * xmlTextWriterVSprintf:
4443 * @format: see printf
4444 * @argptr: pointer to the first member of the variable argument list.
4445 *
4446 * Utility function for formatted output
4447 *
4448 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4449 */
4450static xmlChar *
4451xmlTextWriterVSprintf(const char *format, va_list argptr)
4452{
4453 int size;
4454 int count;
4455 xmlChar *buf;
William M. Brackf4caa5e2005-10-20 09:04:05 +00004456 va_list locarg;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004457
4458 size = BUFSIZ;
4459 buf = (xmlChar *) xmlMalloc(size);
4460 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004461 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004462 "xmlTextWriterVSprintf : out of memory!\n");
4463 return NULL;
4464 }
4465
William M. Brackf4caa5e2005-10-20 09:04:05 +00004466 VA_COPY(locarg, argptr);
4467 while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004468 || (count == size - 1) || (count == size) || (count > size)) {
William M. Brackf4caa5e2005-10-20 09:04:05 +00004469 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004470 xmlFree(buf);
4471 size += BUFSIZ;
4472 buf = (xmlChar *) xmlMalloc(size);
4473 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004474 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004475 "xmlTextWriterVSprintf : out of memory!\n");
4476 return NULL;
4477 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004478 VA_COPY(locarg, argptr);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004479 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004480 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004481
4482 return buf;
4483}
4484
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004485/**
4486 * xmlTextWriterStartDocumentCallback:
4487 * @ctx: the user data (XML parser context)
4488 *
4489 * called at the start of document processing.
4490 */
4491static void
4492xmlTextWriterStartDocumentCallback(void *ctx)
4493{
4494 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4495 xmlDocPtr doc;
4496
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004497 if (ctxt->html) {
4498#ifdef LIBXML_HTML_ENABLED
4499 if (ctxt->myDoc == NULL)
4500 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4501 if (ctxt->myDoc == NULL) {
4502 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4503 ctxt->sax->error(ctxt->userData,
4504 "SAX.startDocument(): out of memory\n");
4505 ctxt->errNo = XML_ERR_NO_MEMORY;
4506 ctxt->instate = XML_PARSER_EOF;
4507 ctxt->disableSAX = 1;
4508 return;
4509 }
4510#else
Daniel Veillardd0cf7f62004-11-09 16:17:02 +00004511 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004512 "libxml2 built without HTML support\n");
4513 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4514 ctxt->instate = XML_PARSER_EOF;
4515 ctxt->disableSAX = 1;
4516 return;
4517#endif
4518 } else {
4519 doc = ctxt->myDoc;
4520 if (doc == NULL)
4521 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4522 if (doc != NULL) {
4523 if (doc->children == NULL) {
4524 if (ctxt->encoding != NULL)
4525 doc->encoding = xmlStrdup(ctxt->encoding);
4526 else
4527 doc->encoding = NULL;
4528 doc->standalone = ctxt->standalone;
4529 }
4530 } else {
4531 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4532 ctxt->sax->error(ctxt->userData,
4533 "SAX.startDocument(): out of memory\n");
4534 ctxt->errNo = XML_ERR_NO_MEMORY;
4535 ctxt->instate = XML_PARSER_EOF;
4536 ctxt->disableSAX = 1;
4537 return;
4538 }
4539 }
4540 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4541 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4542 ctxt->myDoc->URL =
4543 xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4544 if (ctxt->myDoc->URL == NULL)
4545 ctxt->myDoc->URL =
4546 xmlStrdup((const xmlChar *) ctxt->input->filename);
4547 }
4548}
4549
Daniel Veillard2cca4462004-01-02 20:04:23 +00004550/**
4551 * xmlTextWriterSetIndent:
4552 * @writer: the xmlTextWriterPtr
4553 * @indent: do indentation?
4554 *
4555 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4556 *
4557 * Returns -1 on error or 0 otherwise.
4558 */
4559int
Daniel Veillardab69f362004-02-17 11:40:32 +00004560xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004561{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004562 if ((writer == NULL) || (indent < 0))
Daniel Veillardab69f362004-02-17 11:40:32 +00004563 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004564
Daniel Veillardab69f362004-02-17 11:40:32 +00004565 writer->indent = indent;
4566 writer->doindent = 1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004567
Daniel Veillardab69f362004-02-17 11:40:32 +00004568 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004569}
4570
4571/**
4572 * xmlTextWriterSetIndentString:
4573 * @writer: the xmlTextWriterPtr
4574 * @str: the xmlChar string
4575 *
4576 * Set string indentation.
4577 *
4578 * Returns -1 on error or 0 otherwise.
4579 */
4580int
Daniel Veillardab69f362004-02-17 11:40:32 +00004581xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004582{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004583 if ((writer == NULL) || (!str))
Daniel Veillardab69f362004-02-17 11:40:32 +00004584 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004585
Daniel Veillardab69f362004-02-17 11:40:32 +00004586 if (writer->ichar != NULL)
4587 xmlFree(writer->ichar);
4588 writer->ichar = xmlStrdup(str);
4589
4590 if (!writer->ichar)
4591 return -1;
4592 else
4593 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004594}
4595
4596/**
4597 * xmlTextWriterWriteIndent:
4598 * @writer: the xmlTextWriterPtr
4599 *
4600 * Write indent string.
4601 *
4602 * Returns -1 on error or the number of strings written.
Daniel Veillardab69f362004-02-17 11:40:32 +00004603 */
Daniel Veillard2cca4462004-01-02 20:04:23 +00004604static int
Daniel Veillardab69f362004-02-17 11:40:32 +00004605xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004606{
Daniel Veillardab69f362004-02-17 11:40:32 +00004607 int lksize;
4608 int i;
4609 int ret;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004610
Daniel Veillardab69f362004-02-17 11:40:32 +00004611 lksize = xmlListSize(writer->nodes);
4612 if (lksize < 1)
4613 return (-1); /* list is empty */
4614 for (i = 0; i < (lksize - 1); i++) {
4615 ret = xmlOutputBufferWriteString(writer->out,
4616 (const char *) writer->ichar);
4617 if (ret == -1)
4618 return (-1);
4619 }
4620
4621 return (lksize - 1);
Daniel Veillard2cca4462004-01-02 20:04:23 +00004622}
4623
Daniel Veillard500a1de2004-03-22 15:22:58 +00004624/**
4625 * xmlTextWriterHandleStateDependencies:
4626 * @writer: the xmlTextWriterPtr
4627 * @p: the xmlTextWriterStackEntry
4628 *
4629 * Write state dependent strings.
4630 *
4631 * Returns -1 on error or the number of characters written.
4632 */
4633static int
4634xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4635 xmlTextWriterStackEntry * p)
4636{
4637 int count;
4638 int sum;
4639 char extra[3];
4640
4641 if (writer == NULL)
4642 return -1;
4643
4644 if (p == NULL)
4645 return 0;
4646
4647 sum = 0;
4648 extra[0] = extra[1] = extra[2] = '\0';
4649 if (p != 0) {
4650 sum = 0;
4651 switch (p->state) {
4652 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00004653 /* Output namespace declarations */
4654 count = xmlTextWriterOutputNSDecl(writer);
4655 if (count < 0)
4656 return -1;
4657 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004658 extra[0] = '>';
4659 p->state = XML_TEXTWRITER_TEXT;
4660 break;
4661 case XML_TEXTWRITER_PI:
4662 extra[0] = ' ';
4663 p->state = XML_TEXTWRITER_PI_TEXT;
4664 break;
4665 case XML_TEXTWRITER_DTD:
4666 extra[0] = ' ';
4667 extra[1] = '[';
4668 p->state = XML_TEXTWRITER_DTD_TEXT;
4669 break;
4670 case XML_TEXTWRITER_DTD_ELEM:
4671 extra[0] = ' ';
4672 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4673 break;
4674 case XML_TEXTWRITER_DTD_ATTL:
4675 extra[0] = ' ';
4676 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4677 break;
4678 case XML_TEXTWRITER_DTD_ENTY:
4679 case XML_TEXTWRITER_DTD_PENT:
4680 extra[0] = ' ';
4681 extra[1] = writer->qchar;
4682 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4683 break;
4684 default:
4685 break;
4686 }
4687 }
4688
4689 if (*extra != '\0') {
4690 count = xmlOutputBufferWriteString(writer->out, extra);
4691 if (count < 0)
4692 return -1;
4693 sum += count;
4694 }
4695
4696 return sum;
4697}
4698
Daniel Veillard5d4644e2005-04-01 13:11:58 +00004699#define bottom_xmlwriter
4700#include "elfgcchack.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +00004701#endif