blob: 69d4b8522fbadda1e75d3a2125964bf2b806fd0d [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:
Daniel Veillardccc476f2008-03-04 13:19:49 +00002617 case XML_TEXTWRITER_TEXT:
Daniel Veillard1d211e22003-10-20 22:32:39 +00002618 case XML_TEXTWRITER_PI:
2619 case XML_TEXTWRITER_PI_TEXT:
2620 break;
2621 case XML_TEXTWRITER_ATTRIBUTE:
2622 count = xmlTextWriterEndAttribute(writer);
2623 if (count < 0)
2624 return -1;
2625 sum += count;
2626 /* fallthrough */
2627 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002628 /* Output namespace declarations */
2629 count = xmlTextWriterOutputNSDecl(writer);
2630 if (count < 0)
2631 return -1;
2632 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002633 count = xmlOutputBufferWriteString(writer->out, ">");
2634 if (count < 0)
2635 return -1;
2636 sum += count;
2637 p->state = XML_TEXTWRITER_TEXT;
2638 break;
2639 case XML_TEXTWRITER_CDATA:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002640 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002641 "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2642 return -1;
2643 default:
2644 return -1;
2645 }
2646 }
2647 }
2648
2649 p = (xmlTextWriterStackEntry *)
2650 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2651 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002652 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002653 "xmlTextWriterStartCDATA : out of memory!\n");
2654 return -1;
2655 }
2656
Daniel Veillard75e389d2005-07-29 22:02:24 +00002657 p->name = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002658 p->state = XML_TEXTWRITER_CDATA;
2659
2660 xmlListPushFront(writer->nodes, p);
2661
2662 count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2663 if (count < 0)
2664 return -1;
2665 sum += count;
2666
2667 return sum;
2668}
2669
2670/**
2671 * xmlTextWriterEndCDATA:
2672 * @writer: the xmlTextWriterPtr
2673 *
2674 * End an xml CDATA section.
2675 *
2676 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2677 */
2678int
2679xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2680{
2681 int count;
2682 int sum;
2683 xmlLinkPtr lk;
2684 xmlTextWriterStackEntry *p;
2685
2686 if (writer == NULL)
2687 return -1;
2688
2689 lk = xmlListFront(writer->nodes);
2690 if (lk == 0)
2691 return -1;
2692
2693 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2694 if (p == 0)
2695 return -1;
2696
2697 sum = 0;
2698 switch (p->state) {
2699 case XML_TEXTWRITER_CDATA:
2700 count = xmlOutputBufferWriteString(writer->out, "]]>");
2701 if (count < 0)
2702 return -1;
2703 sum += count;
2704 break;
2705 default:
2706 return -1;
2707 }
2708
2709 xmlListPopFront(writer->nodes);
2710 return sum;
2711}
2712
2713/**
2714 * xmlTextWriterWriteFormatCDATA:
2715 * @writer: the xmlTextWriterPtr
2716 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002717 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002718 *
2719 * Write a formatted xml CDATA.
2720 *
2721 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2722 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002723int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002724xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2725 ...)
2726{
2727 int rc;
2728 va_list ap;
2729
2730 va_start(ap, format);
2731
2732 rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2733
2734 va_end(ap);
2735 return rc;
2736}
2737
2738/**
2739 * xmlTextWriterWriteVFormatCDATA:
2740 * @writer: the xmlTextWriterPtr
2741 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002742 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002743 *
2744 * Write a formatted xml CDATA.
2745 *
2746 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2747 */
2748int
2749xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2750 va_list argptr)
2751{
2752 int rc;
2753 xmlChar *buf;
2754
2755 if (writer == NULL)
2756 return -1;
2757
2758 buf = xmlTextWriterVSprintf(format, argptr);
2759 if (buf == 0)
2760 return 0;
2761
2762 rc = xmlTextWriterWriteCDATA(writer, buf);
2763
2764 xmlFree(buf);
2765 return rc;
2766}
2767
2768/**
2769 * xmlTextWriterWriteCDATA:
2770 * @writer: the xmlTextWriterPtr
2771 * @content: CDATA content
2772 *
2773 * Write an xml CDATA.
2774 *
2775 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2776 */
2777int
2778xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2779{
2780 int count;
2781 int sum;
2782
2783 sum = 0;
2784 count = xmlTextWriterStartCDATA(writer);
2785 if (count == -1)
2786 return -1;
2787 sum += count;
2788 if (content != 0) {
2789 count = xmlTextWriterWriteString(writer, content);
2790 if (count == -1)
2791 return -1;
2792 sum += count;
2793 }
2794 count = xmlTextWriterEndCDATA(writer);
2795 if (count == -1)
2796 return -1;
2797 sum += count;
2798
2799 return sum;
2800}
2801
2802/**
2803 * xmlTextWriterStartDTD:
2804 * @writer: the xmlTextWriterPtr
2805 * @name: the name of the DTD
2806 * @pubid: the public identifier, which is an alternative to the system identifier
2807 * @sysid: the system identifier, which is the URI of the DTD
2808 *
2809 * Start an xml DTD.
2810 *
2811 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2812 */
2813int
2814xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2815 const xmlChar * name,
2816 const xmlChar * pubid, const xmlChar * sysid)
2817{
2818 int count;
2819 int sum;
2820 xmlLinkPtr lk;
2821 xmlTextWriterStackEntry *p;
2822
2823 if (writer == NULL || name == NULL || *name == '\0')
2824 return -1;
2825
2826 sum = 0;
2827 lk = xmlListFront(writer->nodes);
Daniel Veillardab69f362004-02-17 11:40:32 +00002828 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002829 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002830 "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2831 return -1;
2832 }
2833
2834 p = (xmlTextWriterStackEntry *)
2835 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2836 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002837 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002838 "xmlTextWriterStartDTD : out of memory!\n");
2839 return -1;
2840 }
2841
2842 p->name = xmlStrdup(name);
2843 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002844 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002845 "xmlTextWriterStartDTD : out of memory!\n");
2846 xmlFree(p);
2847 return -1;
2848 }
2849 p->state = XML_TEXTWRITER_DTD;
2850
2851 xmlListPushFront(writer->nodes, p);
2852
2853 count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2854 if (count < 0)
2855 return -1;
2856 sum += count;
2857 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2858 if (count < 0)
2859 return -1;
2860 sum += count;
2861
2862 if (pubid != 0) {
2863 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002864 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002865 "xmlTextWriterStartDTD : system identifier needed!\n");
2866 return -1;
2867 }
2868
Daniel Veillard500a1de2004-03-22 15:22:58 +00002869 if (writer->indent)
2870 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2871 else
2872 count = xmlOutputBufferWrite(writer->out, 1, " ");
2873 if (count < 0)
2874 return -1;
2875 sum += count;
2876
2877 count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2878 if (count < 0)
2879 return -1;
2880 sum += count;
2881
2882 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002883 if (count < 0)
2884 return -1;
2885 sum += count;
2886
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002887 count =
2888 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002889 if (count < 0)
2890 return -1;
2891 sum += count;
2892
Daniel Veillard500a1de2004-03-22 15:22:58 +00002893 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002894 if (count < 0)
2895 return -1;
2896 sum += count;
2897 }
2898
2899 if (sysid != 0) {
2900 if (pubid == 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00002901 if (writer->indent)
2902 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2903 else
2904 count = xmlOutputBufferWrite(writer->out, 1, " ");
2905 if (count < 0)
2906 return -1;
2907 sum += count;
2908 count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2909 if (count < 0)
2910 return -1;
2911 sum += count;
Rob Richardsffe47fe2005-12-09 17:52:21 +00002912 } else {
2913 if (writer->indent)
Daniel Veillard500a1de2004-03-22 15:22:58 +00002914 count = xmlOutputBufferWriteString(writer->out, "\n ");
Rob Richardsffe47fe2005-12-09 17:52:21 +00002915 else
2916 count = xmlOutputBufferWrite(writer->out, 1, " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00002917 if (count < 0)
2918 return -1;
2919 sum += count;
2920 }
2921
Daniel Veillard500a1de2004-03-22 15:22:58 +00002922 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002923 if (count < 0)
2924 return -1;
2925 sum += count;
2926
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002927 count =
2928 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002929 if (count < 0)
2930 return -1;
2931 sum += count;
2932
Daniel Veillard500a1de2004-03-22 15:22:58 +00002933 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002934 if (count < 0)
2935 return -1;
2936 sum += count;
2937 }
2938
2939 return sum;
2940}
2941
2942/**
2943 * xmlTextWriterEndDTD:
2944 * @writer: the xmlTextWriterPtr
2945 *
2946 * End an xml DTD.
2947 *
2948 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2949 */
2950int
2951xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2952{
Daniel Veillard500a1de2004-03-22 15:22:58 +00002953 int loop;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002954 int count;
2955 int sum;
2956 xmlLinkPtr lk;
2957 xmlTextWriterStackEntry *p;
2958
2959 if (writer == NULL)
2960 return -1;
2961
2962 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002963 loop = 1;
2964 while (loop) {
2965 lk = xmlListFront(writer->nodes);
2966 if (lk == NULL)
Daniel Veillard1d211e22003-10-20 22:32:39 +00002967 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002968 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2969 if (p == 0)
2970 break;
2971 switch (p->state) {
2972 case XML_TEXTWRITER_DTD_TEXT:
2973 count = xmlOutputBufferWriteString(writer->out, "]");
2974 if (count < 0)
2975 return -1;
2976 sum += count;
2977 /* fallthrough */
2978 case XML_TEXTWRITER_DTD:
2979 count = xmlOutputBufferWriteString(writer->out, ">");
2980
2981 if (writer->indent) {
2982 if (count < 0)
2983 return -1;
2984 sum += count;
2985 count = xmlOutputBufferWriteString(writer->out, "\n");
2986 }
2987
2988 xmlListPopFront(writer->nodes);
2989 break;
2990 case XML_TEXTWRITER_DTD_ELEM:
2991 case XML_TEXTWRITER_DTD_ELEM_TEXT:
2992 count = xmlTextWriterEndDTDElement(writer);
2993 break;
2994 case XML_TEXTWRITER_DTD_ATTL:
2995 case XML_TEXTWRITER_DTD_ATTL_TEXT:
2996 count = xmlTextWriterEndDTDAttlist(writer);
2997 break;
2998 case XML_TEXTWRITER_DTD_ENTY:
2999 case XML_TEXTWRITER_DTD_PENT:
3000 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3001 count = xmlTextWriterEndDTDEntity(writer);
3002 break;
3003 case XML_TEXTWRITER_COMMENT:
3004 count = xmlTextWriterEndComment(writer);
3005 break;
3006 default:
3007 loop = 0;
3008 continue;
3009 }
3010
3011 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00003012 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003013 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003014 }
3015
Daniel Veillard1d211e22003-10-20 22:32:39 +00003016 return sum;
3017}
3018
3019/**
3020 * xmlTextWriterWriteFormatDTD:
3021 * @writer: the xmlTextWriterPtr
3022 * @name: the name of the DTD
3023 * @pubid: the public identifier, which is an alternative to the system identifier
3024 * @sysid: the system identifier, which is the URI of the DTD
3025 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003026 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00003027 *
3028 * Write a DTD with a formatted markup declarations part.
3029 *
3030 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3031 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003032int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003033xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3034 const xmlChar * name,
3035 const xmlChar * pubid,
3036 const xmlChar * sysid, const char *format, ...)
3037{
3038 int rc;
3039 va_list ap;
3040
3041 va_start(ap, format);
3042
3043 rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3044 ap);
3045
3046 va_end(ap);
3047 return rc;
3048}
3049
3050/**
3051 * xmlTextWriterWriteVFormatDTD:
3052 * @writer: the xmlTextWriterPtr
3053 * @name: the name of the DTD
3054 * @pubid: the public identifier, which is an alternative to the system identifier
3055 * @sysid: the system identifier, which is the URI of the DTD
3056 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003057 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00003058 *
3059 * Write a DTD with a formatted markup declarations part.
3060 *
3061 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3062 */
3063int
3064xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3065 const xmlChar * name,
3066 const xmlChar * pubid,
3067 const xmlChar * sysid,
3068 const char *format, va_list argptr)
3069{
3070 int rc;
3071 xmlChar *buf;
3072
3073 if (writer == NULL)
3074 return -1;
3075
3076 buf = xmlTextWriterVSprintf(format, argptr);
3077 if (buf == 0)
3078 return 0;
3079
3080 rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3081
3082 xmlFree(buf);
3083 return rc;
3084}
3085
3086/**
3087 * xmlTextWriterWriteDTD:
3088 * @writer: the xmlTextWriterPtr
3089 * @name: the name of the DTD
3090 * @pubid: the public identifier, which is an alternative to the system identifier
3091 * @sysid: the system identifier, which is the URI of the DTD
William M. Brackb1d53162003-11-18 06:54:40 +00003092 * @subset: string content of the DTD
Daniel Veillard1d211e22003-10-20 22:32:39 +00003093 *
3094 * Write a DTD.
3095 *
3096 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3097 */
3098int
3099xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3100 const xmlChar * name,
3101 const xmlChar * pubid,
3102 const xmlChar * sysid, const xmlChar * subset)
3103{
3104 int count;
3105 int sum;
3106
3107 sum = 0;
3108 count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3109 if (count == -1)
3110 return -1;
3111 sum += count;
3112 if (subset != 0) {
3113 count = xmlTextWriterWriteString(writer, subset);
3114 if (count == -1)
3115 return -1;
3116 sum += count;
3117 }
3118 count = xmlTextWriterEndDTD(writer);
3119 if (count == -1)
3120 return -1;
3121 sum += count;
3122
3123 return sum;
3124}
3125
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003126/**
3127 * xmlTextWriterStartDTDElement:
3128 * @writer: the xmlTextWriterPtr
3129 * @name: the name of the DTD element
3130 *
3131 * Start an xml DTD element.
3132 *
3133 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3134 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003135int
3136xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3137{
3138 int count;
3139 int sum;
3140 xmlLinkPtr lk;
3141 xmlTextWriterStackEntry *p;
3142
3143 if (writer == NULL || name == NULL || *name == '\0')
3144 return -1;
3145
3146 sum = 0;
3147 lk = xmlListFront(writer->nodes);
3148 if (lk == 0) {
3149 return -1;
3150 }
3151
3152 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003153 if (p != 0) {
3154 switch (p->state) {
3155 case XML_TEXTWRITER_DTD:
3156 count = xmlOutputBufferWriteString(writer->out, " [");
3157 if (count < 0)
3158 return -1;
3159 sum += count;
3160 if (writer->indent) {
3161 count = xmlOutputBufferWriteString(writer->out, "\n");
3162 if (count < 0)
3163 return -1;
3164 sum += count;
3165 }
3166 p->state = XML_TEXTWRITER_DTD_TEXT;
3167 /* fallthrough */
3168 case XML_TEXTWRITER_DTD_TEXT:
3169 case XML_TEXTWRITER_NONE:
3170 break;
3171 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003172 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003173 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003174 }
3175
3176 p = (xmlTextWriterStackEntry *)
3177 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3178 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003179 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003180 "xmlTextWriterStartDTDElement : out of memory!\n");
3181 return -1;
3182 }
3183
3184 p->name = xmlStrdup(name);
3185 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003186 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003187 "xmlTextWriterStartDTDElement : out of memory!\n");
3188 xmlFree(p);
3189 return -1;
3190 }
3191 p->state = XML_TEXTWRITER_DTD_ELEM;
3192
3193 xmlListPushFront(writer->nodes, p);
3194
Daniel Veillard500a1de2004-03-22 15:22:58 +00003195 if (writer->indent) {
3196 count = xmlTextWriterWriteIndent(writer);
3197 if (count < 0)
3198 return -1;
3199 sum += count;
3200 }
3201
Daniel Veillard1d211e22003-10-20 22:32:39 +00003202 count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3203 if (count < 0)
3204 return -1;
3205 sum += count;
3206 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3207 if (count < 0)
3208 return -1;
3209 sum += count;
3210
3211 return sum;
3212}
3213
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003214/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003215 * xmlTextWriterEndDTDElement:
3216 * @writer: the xmlTextWriterPtr
3217 *
3218 * End an xml DTD element.
3219 *
3220 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3221 */
3222int
3223xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3224{
3225 int count;
3226 int sum;
3227 xmlLinkPtr lk;
3228 xmlTextWriterStackEntry *p;
3229
3230 if (writer == NULL)
3231 return -1;
3232
3233 sum = 0;
3234 lk = xmlListFront(writer->nodes);
3235 if (lk == 0)
3236 return -1;
3237
3238 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3239 if (p == 0)
3240 return -1;
3241
3242 switch (p->state) {
3243 case XML_TEXTWRITER_DTD_ELEM:
3244 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3245 count = xmlOutputBufferWriteString(writer->out, ">");
3246 if (count < 0)
3247 return -1;
3248 sum += count;
3249 break;
3250 default:
3251 return -1;
3252 }
3253
3254 if (writer->indent) {
3255 count = xmlOutputBufferWriteString(writer->out, "\n");
3256 if (count < 0)
3257 return -1;
3258 sum += count;
3259 }
3260
3261 xmlListPopFront(writer->nodes);
3262 return sum;
3263}
3264
3265/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003266 * xmlTextWriterWriteFormatDTDElement:
3267 * @writer: the xmlTextWriterPtr
3268 * @name: the name of the DTD element
3269 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003270 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003271 *
3272 * Write a formatted DTD element.
3273 *
3274 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3275 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003276int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003277xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3278 const xmlChar * name,
3279 const char *format, ...)
3280{
3281 int rc;
3282 va_list ap;
3283
3284 va_start(ap, format);
3285
3286 rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3287
3288 va_end(ap);
3289 return rc;
3290}
3291
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003292/**
3293 * xmlTextWriterWriteVFormatDTDElement:
3294 * @writer: the xmlTextWriterPtr
3295 * @name: the name of the DTD element
3296 * @format: format string (see printf)
3297 * @argptr: pointer to the first member of the variable argument list.
3298 *
3299 * Write a formatted DTD element.
3300 *
3301 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3302 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003303int
3304xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3305 const xmlChar * name,
3306 const char *format, va_list argptr)
3307{
3308 int rc;
3309 xmlChar *buf;
3310
3311 if (writer == NULL)
3312 return -1;
3313
3314 buf = xmlTextWriterVSprintf(format, argptr);
3315 if (buf == 0)
3316 return 0;
3317
3318 rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3319
3320 xmlFree(buf);
3321 return rc;
3322}
3323
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003324/**
3325 * xmlTextWriterWriteDTDElement:
3326 * @writer: the xmlTextWriterPtr
3327 * @name: the name of the DTD element
3328 * @content: content of the element
3329 *
3330 * Write a DTD element.
3331 *
3332 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3333 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003334int
3335xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3336 const xmlChar * name, const xmlChar * content)
3337{
3338 int count;
3339 int sum;
3340
3341 if (content == NULL)
3342 return -1;
3343
3344 sum = 0;
3345 count = xmlTextWriterStartDTDElement(writer, name);
3346 if (count == -1)
3347 return -1;
3348 sum += count;
3349
Daniel Veillard1d211e22003-10-20 22:32:39 +00003350 count = xmlTextWriterWriteString(writer, content);
3351 if (count == -1)
3352 return -1;
3353 sum += count;
3354
3355 count = xmlTextWriterEndDTDElement(writer);
3356 if (count == -1)
3357 return -1;
3358 sum += count;
3359
3360 return sum;
3361}
3362
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003363/**
3364 * xmlTextWriterStartDTDAttlist:
3365 * @writer: the xmlTextWriterPtr
3366 * @name: the name of the DTD ATTLIST
3367 *
3368 * Start an xml DTD ATTLIST.
3369 *
3370 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3371 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003372int
3373xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3374{
3375 int count;
3376 int sum;
3377 xmlLinkPtr lk;
3378 xmlTextWriterStackEntry *p;
3379
3380 if (writer == NULL || name == NULL || *name == '\0')
3381 return -1;
3382
3383 sum = 0;
3384 lk = xmlListFront(writer->nodes);
3385 if (lk == 0) {
3386 return -1;
3387 }
3388
3389 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003390 if (p != 0) {
3391 switch (p->state) {
3392 case XML_TEXTWRITER_DTD:
3393 count = xmlOutputBufferWriteString(writer->out, " [");
3394 if (count < 0)
3395 return -1;
3396 sum += count;
3397 if (writer->indent) {
3398 count = xmlOutputBufferWriteString(writer->out, "\n");
3399 if (count < 0)
3400 return -1;
3401 sum += count;
3402 }
3403 p->state = XML_TEXTWRITER_DTD_TEXT;
3404 /* fallthrough */
3405 case XML_TEXTWRITER_DTD_TEXT:
3406 case XML_TEXTWRITER_NONE:
3407 break;
3408 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003409 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003410 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003411 }
3412
3413 p = (xmlTextWriterStackEntry *)
3414 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3415 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003416 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003417 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3418 return -1;
3419 }
3420
3421 p->name = xmlStrdup(name);
3422 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003423 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003424 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3425 xmlFree(p);
3426 return -1;
3427 }
3428 p->state = XML_TEXTWRITER_DTD_ATTL;
3429
3430 xmlListPushFront(writer->nodes, p);
3431
Daniel Veillard500a1de2004-03-22 15:22:58 +00003432 if (writer->indent) {
3433 count = xmlTextWriterWriteIndent(writer);
3434 if (count < 0)
3435 return -1;
3436 sum += count;
3437 }
3438
Daniel Veillard1d211e22003-10-20 22:32:39 +00003439 count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3440 if (count < 0)
3441 return -1;
3442 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +00003443 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003444 if (count < 0)
3445 return -1;
3446 sum += count;
3447
3448 return sum;
3449}
3450
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003451/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003452 * xmlTextWriterEndDTDAttlist:
3453 * @writer: the xmlTextWriterPtr
3454 *
3455 * End an xml DTD attribute list.
3456 *
3457 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3458 */
3459int
3460xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3461{
3462 int count;
3463 int sum;
3464 xmlLinkPtr lk;
3465 xmlTextWriterStackEntry *p;
3466
3467 if (writer == NULL)
3468 return -1;
3469
3470 sum = 0;
3471 lk = xmlListFront(writer->nodes);
3472 if (lk == 0)
3473 return -1;
3474
3475 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3476 if (p == 0)
3477 return -1;
3478
3479 switch (p->state) {
3480 case XML_TEXTWRITER_DTD_ATTL:
3481 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3482 count = xmlOutputBufferWriteString(writer->out, ">");
3483 if (count < 0)
3484 return -1;
3485 sum += count;
3486 break;
3487 default:
3488 return -1;
3489 }
3490
3491 if (writer->indent) {
3492 count = xmlOutputBufferWriteString(writer->out, "\n");
3493 if (count < 0)
3494 return -1;
3495 sum += count;
3496 }
3497
3498 xmlListPopFront(writer->nodes);
3499 return sum;
3500}
3501
3502/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003503 * xmlTextWriterWriteFormatDTDAttlist:
3504 * @writer: the xmlTextWriterPtr
3505 * @name: the name of the DTD ATTLIST
3506 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003507 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003508 *
3509 * Write a formatted DTD ATTLIST.
3510 *
3511 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3512 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003513int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003514xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3515 const xmlChar * name,
3516 const char *format, ...)
3517{
3518 int rc;
3519 va_list ap;
3520
3521 va_start(ap, format);
3522
3523 rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3524
3525 va_end(ap);
3526 return rc;
3527}
3528
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003529/**
3530 * xmlTextWriterWriteVFormatDTDAttlist:
3531 * @writer: the xmlTextWriterPtr
3532 * @name: the name of the DTD ATTLIST
3533 * @format: format string (see printf)
3534 * @argptr: pointer to the first member of the variable argument list.
3535 *
3536 * Write a formatted DTD ATTLIST.
3537 *
3538 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3539 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003540int
3541xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3542 const xmlChar * name,
3543 const char *format, va_list argptr)
3544{
3545 int rc;
3546 xmlChar *buf;
3547
3548 if (writer == NULL)
3549 return -1;
3550
3551 buf = xmlTextWriterVSprintf(format, argptr);
3552 if (buf == 0)
3553 return 0;
3554
3555 rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3556
3557 xmlFree(buf);
3558 return rc;
3559}
3560
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003561/**
3562 * xmlTextWriterWriteDTDAttlist:
3563 * @writer: the xmlTextWriterPtr
3564 * @name: the name of the DTD ATTLIST
3565 * @content: content of the ATTLIST
3566 *
3567 * Write a DTD ATTLIST.
3568 *
3569 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3570 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003571int
3572xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3573 const xmlChar * name, const xmlChar * content)
3574{
3575 int count;
3576 int sum;
3577
3578 if (content == NULL)
3579 return -1;
3580
3581 sum = 0;
3582 count = xmlTextWriterStartDTDAttlist(writer, name);
3583 if (count == -1)
3584 return -1;
3585 sum += count;
3586
Daniel Veillard1d211e22003-10-20 22:32:39 +00003587 count = xmlTextWriterWriteString(writer, content);
3588 if (count == -1)
3589 return -1;
3590 sum += count;
3591
3592 count = xmlTextWriterEndDTDAttlist(writer);
3593 if (count == -1)
3594 return -1;
3595 sum += count;
3596
3597 return sum;
3598}
3599
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003600/**
3601 * xmlTextWriterStartDTDEntity:
3602 * @writer: the xmlTextWriterPtr
3603 * @pe: TRUE if this is a parameter entity, FALSE if not
3604 * @name: the name of the DTD ATTLIST
3605 *
3606 * Start an xml DTD ATTLIST.
3607 *
3608 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3609 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003610int
3611xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3612 int pe, const xmlChar * name)
3613{
3614 int count;
3615 int sum;
3616 xmlLinkPtr lk;
3617 xmlTextWriterStackEntry *p;
3618
3619 if (writer == NULL || name == NULL || *name == '\0')
3620 return -1;
3621
3622 sum = 0;
3623 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003624 if (lk != 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00003625
Daniel Veillard500a1de2004-03-22 15:22:58 +00003626 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3627 if (p != 0) {
3628 switch (p->state) {
3629 case XML_TEXTWRITER_DTD:
3630 count = xmlOutputBufferWriteString(writer->out, " [");
3631 if (count < 0)
3632 return -1;
3633 sum += count;
3634 if (writer->indent) {
3635 count =
3636 xmlOutputBufferWriteString(writer->out, "\n");
3637 if (count < 0)
3638 return -1;
3639 sum += count;
3640 }
3641 p->state = XML_TEXTWRITER_DTD_TEXT;
3642 /* fallthrough */
3643 case XML_TEXTWRITER_DTD_TEXT:
3644 case XML_TEXTWRITER_NONE:
3645 break;
3646 default:
3647 return -1;
3648 }
3649 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003650 }
3651
3652 p = (xmlTextWriterStackEntry *)
3653 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3654 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003655 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003656 "xmlTextWriterStartDTDElement : out of memory!\n");
3657 return -1;
3658 }
3659
3660 p->name = xmlStrdup(name);
3661 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003662 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003663 "xmlTextWriterStartDTDElement : out of memory!\n");
3664 xmlFree(p);
3665 return -1;
3666 }
Daniel Veillard500a1de2004-03-22 15:22:58 +00003667
3668 if (pe != 0)
3669 p->state = XML_TEXTWRITER_DTD_PENT;
3670 else
3671 p->state = XML_TEXTWRITER_DTD_ENTY;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003672
3673 xmlListPushFront(writer->nodes, p);
3674
Daniel Veillard500a1de2004-03-22 15:22:58 +00003675 if (writer->indent) {
3676 count = xmlTextWriterWriteIndent(writer);
3677 if (count < 0)
3678 return -1;
3679 sum += count;
3680 }
3681
Daniel Veillard1d211e22003-10-20 22:32:39 +00003682 count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3683 if (count < 0)
3684 return -1;
3685 sum += count;
3686
3687 if (pe != 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00003688 count = xmlOutputBufferWriteString(writer->out, "% ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003689 if (count < 0)
3690 return -1;
3691 sum += count;
3692 }
3693
Daniel Veillardab69f362004-02-17 11:40:32 +00003694 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003695 if (count < 0)
3696 return -1;
3697 sum += count;
3698
3699 return sum;
3700}
3701
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003702/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003703 * xmlTextWriterEndDTDEntity:
3704 * @writer: the xmlTextWriterPtr
3705 *
3706 * End an xml DTD entity.
3707 *
3708 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3709 */
3710int
3711xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3712{
3713 int count;
3714 int sum;
3715 xmlLinkPtr lk;
3716 xmlTextWriterStackEntry *p;
3717
3718 if (writer == NULL)
3719 return -1;
3720
3721 sum = 0;
3722 lk = xmlListFront(writer->nodes);
3723 if (lk == 0)
3724 return -1;
3725
3726 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3727 if (p == 0)
3728 return -1;
3729
3730 switch (p->state) {
3731 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3732 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3733 if (count < 0)
3734 return -1;
3735 sum += count;
3736 case XML_TEXTWRITER_DTD_ENTY:
3737 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard500a1de2004-03-22 15:22:58 +00003738 count = xmlOutputBufferWriteString(writer->out, ">");
3739 if (count < 0)
3740 return -1;
3741 sum += count;
3742 break;
3743 default:
3744 return -1;
3745 }
3746
3747 if (writer->indent) {
3748 count = xmlOutputBufferWriteString(writer->out, "\n");
3749 if (count < 0)
3750 return -1;
3751 sum += count;
3752 }
3753
3754 xmlListPopFront(writer->nodes);
3755 return sum;
3756}
3757
3758/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003759 * xmlTextWriterWriteFormatDTDInternalEntity:
3760 * @writer: the xmlTextWriterPtr
3761 * @pe: TRUE if this is a parameter entity, FALSE if not
3762 * @name: the name of the DTD entity
3763 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003764 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003765 *
3766 * Write a formatted DTD internal entity.
3767 *
3768 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3769 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003770int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003771xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3772 int pe,
3773 const xmlChar * name,
3774 const char *format, ...)
3775{
3776 int rc;
3777 va_list ap;
3778
3779 va_start(ap, format);
3780
3781 rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3782 format, ap);
3783
3784 va_end(ap);
3785 return rc;
3786}
3787
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003788/**
3789 * xmlTextWriterWriteVFormatDTDInternalEntity:
3790 * @writer: the xmlTextWriterPtr
3791 * @pe: TRUE if this is a parameter entity, FALSE if not
3792 * @name: the name of the DTD entity
3793 * @format: format string (see printf)
3794 * @argptr: pointer to the first member of the variable argument list.
3795 *
3796 * Write a formatted DTD internal entity.
3797 *
3798 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3799 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003800int
3801xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3802 int pe,
3803 const xmlChar * name,
3804 const char *format,
3805 va_list argptr)
3806{
3807 int rc;
3808 xmlChar *buf;
3809
3810 if (writer == NULL)
3811 return -1;
3812
3813 buf = xmlTextWriterVSprintf(format, argptr);
3814 if (buf == 0)
3815 return 0;
3816
3817 rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3818
3819 xmlFree(buf);
3820 return rc;
3821}
3822
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003823/**
3824 * xmlTextWriterWriteDTDEntity:
3825 * @writer: the xmlTextWriterPtr
3826 * @pe: TRUE if this is a parameter entity, FALSE if not
3827 * @name: the name of the DTD entity
3828 * @pubid: the public identifier, which is an alternative to the system identifier
3829 * @sysid: the system identifier, which is the URI of the DTD
3830 * @ndataid: the xml notation name.
3831 * @content: content of the entity
3832 *
3833 * Write a DTD entity.
3834 *
3835 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3836 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003837int
3838xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3839 int pe,
3840 const xmlChar * name,
3841 const xmlChar * pubid,
3842 const xmlChar * sysid,
3843 const xmlChar * ndataid,
3844 const xmlChar * content)
3845{
Daniel Veillard500a1de2004-03-22 15:22:58 +00003846 if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003847 return -1;
3848 if ((pe != 0) && (ndataid != NULL))
3849 return -1;
3850
Daniel Veillard500a1de2004-03-22 15:22:58 +00003851 if ((pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003852 return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3853 content);
3854
3855 return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3856 sysid, ndataid);
3857}
3858
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003859/**
3860 * xmlTextWriterWriteDTDInternalEntity:
3861 * @writer: the xmlTextWriterPtr
3862 * @pe: TRUE if this is a parameter entity, FALSE if not
3863 * @name: the name of the DTD entity
3864 * @content: content of the entity
3865 *
3866 * Write a DTD internal entity.
3867 *
3868 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3869 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003870int
3871xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3872 int pe,
3873 const xmlChar * name,
3874 const xmlChar * content)
3875{
3876 int count;
3877 int sum;
3878
3879 if ((name == NULL) || (*name == '\0') || (content == NULL))
3880 return -1;
3881
3882 sum = 0;
3883 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3884 if (count == -1)
3885 return -1;
3886 sum += count;
3887
Daniel Veillard1d211e22003-10-20 22:32:39 +00003888 count = xmlTextWriterWriteString(writer, content);
3889 if (count == -1)
3890 return -1;
3891 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003892
3893 count = xmlTextWriterEndDTDEntity(writer);
3894 if (count == -1)
3895 return -1;
3896 sum += count;
3897
3898 return sum;
3899}
3900
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003901/**
3902 * xmlTextWriterWriteDTDExternalEntity:
3903 * @writer: the xmlTextWriterPtr
3904 * @pe: TRUE if this is a parameter entity, FALSE if not
3905 * @name: the name of the DTD entity
3906 * @pubid: the public identifier, which is an alternative to the system identifier
3907 * @sysid: the system identifier, which is the URI of the DTD
3908 * @ndataid: the xml notation name.
3909 *
Daniel Veillard500a1de2004-03-22 15:22:58 +00003910 * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003911 *
3912 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3913 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003914int
3915xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3916 int pe,
3917 const xmlChar * name,
3918 const xmlChar * pubid,
3919 const xmlChar * sysid,
3920 const xmlChar * ndataid)
3921{
3922 int count;
3923 int sum;
3924
Daniel Veillard500a1de2004-03-22 15:22:58 +00003925 if (((pubid == NULL) && (sysid == NULL)))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003926 return -1;
3927 if ((pe != 0) && (ndataid != NULL))
3928 return -1;
3929
3930 sum = 0;
3931 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3932 if (count == -1)
3933 return -1;
3934 sum += count;
3935
Daniel Veillard500a1de2004-03-22 15:22:58 +00003936 count =
3937 xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3938 ndataid);
3939 if (count < 0)
3940 return -1;
3941 sum += count;
3942
3943 count = xmlTextWriterEndDTDEntity(writer);
3944 if (count == -1)
3945 return -1;
3946 sum += count;
3947
3948 return sum;
3949}
3950
3951/**
3952 * xmlTextWriterWriteDTDExternalEntityContents:
3953 * @writer: the xmlTextWriterPtr
3954 * @pubid: the public identifier, which is an alternative to the system identifier
3955 * @sysid: the system identifier, which is the URI of the DTD
3956 * @ndataid: the xml notation name.
3957 *
3958 * Write the contents of a DTD external entity.
3959 *
3960 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3961 */
3962int
3963xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3964 const xmlChar * pubid,
3965 const xmlChar * sysid,
3966 const xmlChar * ndataid)
3967{
3968 int count;
3969 int sum;
3970 xmlLinkPtr lk;
3971 xmlTextWriterStackEntry *p;
3972
3973 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003974 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003975 "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3976 return -1;
3977 }
3978
3979 sum = 0;
3980 lk = xmlListFront(writer->nodes);
3981 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003982 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003983 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
3984 return -1;
3985 }
3986
3987 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3988 if (p == 0)
3989 return -1;
3990
3991 switch (p->state) {
3992 case XML_TEXTWRITER_DTD_ENTY:
3993 break;
3994 case XML_TEXTWRITER_DTD_PENT:
3995 if (ndataid != NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003996 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003997 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
3998 return -1;
3999 }
4000 break;
4001 default:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004002 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004003 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4004 return -1;
4005 }
4006
Daniel Veillard1d211e22003-10-20 22:32:39 +00004007 if (pubid != 0) {
4008 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004009 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004010 "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00004011 return -1;
4012 }
4013
4014 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4015 if (count < 0)
4016 return -1;
4017 sum += count;
4018
4019 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4020 if (count < 0)
4021 return -1;
4022 sum += count;
4023
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004024 count =
4025 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004026 if (count < 0)
4027 return -1;
4028 sum += count;
4029
4030 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4031 if (count < 0)
4032 return -1;
4033 sum += count;
4034 }
4035
4036 if (sysid != 0) {
4037 if (pubid == 0) {
4038 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4039 if (count < 0)
4040 return -1;
4041 sum += count;
4042 }
4043
4044 count = xmlOutputBufferWriteString(writer->out, " ");
4045 if (count < 0)
4046 return -1;
4047 sum += count;
4048
4049 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4050 if (count < 0)
4051 return -1;
4052 sum += count;
4053
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004054 count =
4055 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004056 if (count < 0)
4057 return -1;
4058 sum += count;
4059
4060 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4061 if (count < 0)
4062 return -1;
4063 sum += count;
4064 }
4065
4066 if (ndataid != NULL) {
4067 count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4068 if (count < 0)
4069 return -1;
4070 sum += count;
4071
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004072 count =
4073 xmlOutputBufferWriteString(writer->out,
4074 (const char *) ndataid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004075 if (count < 0)
4076 return -1;
4077 sum += count;
4078 }
4079
Daniel Veillard1d211e22003-10-20 22:32:39 +00004080 return sum;
4081}
4082
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004083/**
4084 * xmlTextWriterWriteDTDNotation:
4085 * @writer: the xmlTextWriterPtr
4086 * @name: the name of the xml notation
4087 * @pubid: the public identifier, which is an alternative to the system identifier
4088 * @sysid: the system identifier, which is the URI of the DTD
4089 *
4090 * Write a DTD entity.
4091 *
4092 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4093 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00004094int
4095xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4096 const xmlChar * name,
4097 const xmlChar * pubid, const xmlChar * sysid)
4098{
4099 int count;
4100 int sum;
4101 xmlLinkPtr lk;
4102 xmlTextWriterStackEntry *p;
4103
4104 if (writer == NULL || name == NULL || *name == '\0')
4105 return -1;
4106
4107 sum = 0;
4108 lk = xmlListFront(writer->nodes);
4109 if (lk == 0) {
4110 return -1;
4111 }
4112
4113 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00004114 if (p != 0) {
4115 switch (p->state) {
4116 case XML_TEXTWRITER_DTD:
4117 count = xmlOutputBufferWriteString(writer->out, " [");
4118 if (count < 0)
4119 return -1;
4120 sum += count;
4121 if (writer->indent) {
4122 count = xmlOutputBufferWriteString(writer->out, "\n");
4123 if (count < 0)
4124 return -1;
4125 sum += count;
4126 }
4127 p->state = XML_TEXTWRITER_DTD_TEXT;
4128 /* fallthrough */
4129 case XML_TEXTWRITER_DTD_TEXT:
4130 break;
4131 default:
4132 return -1;
4133 }
4134 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00004135
Daniel Veillard500a1de2004-03-22 15:22:58 +00004136 if (writer->indent) {
4137 count = xmlTextWriterWriteIndent(writer);
4138 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004139 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004140 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004141 }
4142
4143 count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4144 if (count < 0)
4145 return -1;
4146 sum += count;
4147 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4148 if (count < 0)
4149 return -1;
4150 sum += count;
4151
4152 if (pubid != 0) {
4153 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4154 if (count < 0)
4155 return -1;
4156 sum += count;
4157 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4158 if (count < 0)
4159 return -1;
4160 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004161 count =
4162 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004163 if (count < 0)
4164 return -1;
4165 sum += count;
4166 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4167 if (count < 0)
4168 return -1;
4169 sum += count;
4170 }
4171
4172 if (sysid != 0) {
4173 if (pubid == 0) {
4174 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4175 if (count < 0)
4176 return -1;
4177 sum += count;
4178 }
4179 count = xmlOutputBufferWriteString(writer->out, " ");
4180 if (count < 0)
4181 return -1;
4182 sum += count;
4183 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4184 if (count < 0)
4185 return -1;
4186 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004187 count =
4188 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004189 if (count < 0)
4190 return -1;
4191 sum += count;
4192 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4193 if (count < 0)
4194 return -1;
4195 sum += count;
4196 }
4197
4198 count = xmlOutputBufferWriteString(writer->out, ">");
4199 if (count < 0)
4200 return -1;
4201 sum += count;
4202
4203 return sum;
4204}
4205
4206/**
4207 * xmlTextWriterFlush:
4208 * @writer: the xmlTextWriterPtr
4209 *
4210 * Flush the output buffer.
4211 *
4212 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4213 */
4214int
4215xmlTextWriterFlush(xmlTextWriterPtr writer)
4216{
4217 int count;
4218
4219 if (writer == NULL)
4220 return -1;
4221
4222 if (writer->out == NULL)
4223 count = 0;
4224 else
4225 count = xmlOutputBufferFlush(writer->out);
4226
4227 return count;
4228}
4229
4230/**
4231 * misc
4232 */
4233
4234/**
4235 * xmlFreeTextWriterStackEntry:
4236 * @lk: the xmlLinkPtr
4237 *
4238 * Free callback for the xmlList.
4239 */
4240static void
4241xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4242{
4243 xmlTextWriterStackEntry *p;
4244
4245 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4246 if (p == 0)
4247 return;
4248
4249 if (p->name != 0)
4250 xmlFree(p->name);
4251 xmlFree(p);
4252}
4253
4254/**
4255 * xmlCmpTextWriterStackEntry:
4256 * @data0: the first data
4257 * @data1: the second data
4258 *
4259 * Compare callback for the xmlList.
4260 *
4261 * Returns -1, 0, 1
4262 */
4263static int
4264xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4265{
4266 xmlTextWriterStackEntry *p0;
4267 xmlTextWriterStackEntry *p1;
4268
4269 if (data0 == data1)
4270 return 0;
4271
4272 if (data0 == 0)
4273 return -1;
4274
4275 if (data1 == 0)
4276 return 1;
4277
4278 p0 = (xmlTextWriterStackEntry *) data0;
4279 p1 = (xmlTextWriterStackEntry *) data1;
4280
4281 return xmlStrcmp(p0->name, p1->name);
4282}
4283
4284/**
4285 * misc
4286 */
4287
4288/**
Rob Richardsb8769d62007-06-08 08:50:47 +00004289 * xmlTextWriterOutputNSDecl:
4290 * @writer: the xmlTextWriterPtr
4291 *
4292 * Output the current namespace declarations.
4293 */
4294static int
4295xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4296{
4297 xmlLinkPtr lk;
4298 xmlTextWriterNsStackEntry *np;
4299 int count;
4300 int sum;
4301
4302 sum = 0;
4303 while (!xmlListEmpty(writer->nsstack)) {
4304 xmlChar *namespaceURI = NULL;
4305 xmlChar *prefix = NULL;
4306
4307 lk = xmlListFront(writer->nsstack);
4308 np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4309
4310 if (np != 0) {
4311 namespaceURI = xmlStrdup(np->uri);
4312 prefix = xmlStrdup(np->prefix);
4313 }
4314
4315 xmlListPopFront(writer->nsstack);
4316
4317 if (np != 0) {
4318 count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4319 xmlFree(namespaceURI);
4320 xmlFree(prefix);
4321
4322 if (count < 0) {
4323 xmlListDelete(writer->nsstack);
4324 writer->nsstack = NULL;
4325 return -1;
4326 }
4327 sum += count;
4328 }
4329 }
4330 return sum;
4331}
4332
4333/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004334 * xmlFreeTextWriterNsStackEntry:
4335 * @lk: the xmlLinkPtr
4336 *
4337 * Free callback for the xmlList.
4338 */
4339static void
4340xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4341{
4342 xmlTextWriterNsStackEntry *p;
4343
4344 p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4345 if (p == 0)
4346 return;
4347
4348 if (p->prefix != 0)
4349 xmlFree(p->prefix);
4350 if (p->uri != 0)
4351 xmlFree(p->uri);
4352
4353 xmlFree(p);
4354}
4355
4356/**
4357 * xmlCmpTextWriterNsStackEntry:
4358 * @data0: the first data
4359 * @data1: the second data
4360 *
4361 * Compare callback for the xmlList.
4362 *
4363 * Returns -1, 0, 1
4364 */
4365static int
4366xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4367{
4368 xmlTextWriterNsStackEntry *p0;
4369 xmlTextWriterNsStackEntry *p1;
4370 int rc;
4371
4372 if (data0 == data1)
4373 return 0;
4374
4375 if (data0 == 0)
4376 return -1;
4377
4378 if (data1 == 0)
4379 return 1;
4380
4381 p0 = (xmlTextWriterNsStackEntry *) data0;
4382 p1 = (xmlTextWriterNsStackEntry *) data1;
4383
4384 rc = xmlStrcmp(p0->prefix, p1->prefix);
4385
Rob Richardsb8769d62007-06-08 08:50:47 +00004386 if ((rc != 0) || (p0->elem != p1->elem))
4387 rc = -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004388
4389 return rc;
4390}
4391
4392/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004393 * xmlTextWriterWriteDocCallback:
4394 * @context: the xmlBufferPtr
4395 * @str: the data to write
4396 * @len: the length of the data
4397 *
4398 * Write callback for the xmlOutputBuffer with target xmlBuffer
4399 *
4400 * Returns -1, 0, 1
4401 */
4402static int
4403xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
4404{
4405 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4406 int rc;
4407
Daniel Veillard1d913862003-11-21 00:28:39 +00004408 if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004409 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004410 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4411 rc);
4412 return -1;
4413 }
4414
4415 return len;
4416}
4417
4418/**
4419 * xmlTextWriterCloseDocCallback:
4420 * @context: the xmlBufferPtr
4421 *
4422 * Close callback for the xmlOutputBuffer with target xmlBuffer
4423 *
4424 * Returns -1, 0, 1
4425 */
4426static int
4427xmlTextWriterCloseDocCallback(void *context)
4428{
4429 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4430 int rc;
4431
4432 if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004433 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004434 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4435 rc);
4436 return -1;
4437 }
4438
4439 return 0;
4440}
4441
4442/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004443 * xmlTextWriterVSprintf:
4444 * @format: see printf
4445 * @argptr: pointer to the first member of the variable argument list.
4446 *
4447 * Utility function for formatted output
4448 *
4449 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4450 */
4451static xmlChar *
4452xmlTextWriterVSprintf(const char *format, va_list argptr)
4453{
4454 int size;
4455 int count;
4456 xmlChar *buf;
William M. Brackf4caa5e2005-10-20 09:04:05 +00004457 va_list locarg;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004458
4459 size = BUFSIZ;
4460 buf = (xmlChar *) xmlMalloc(size);
4461 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004462 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004463 "xmlTextWriterVSprintf : out of memory!\n");
4464 return NULL;
4465 }
4466
William M. Brackf4caa5e2005-10-20 09:04:05 +00004467 VA_COPY(locarg, argptr);
4468 while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004469 || (count == size - 1) || (count == size) || (count > size)) {
William M. Brackf4caa5e2005-10-20 09:04:05 +00004470 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004471 xmlFree(buf);
4472 size += BUFSIZ;
4473 buf = (xmlChar *) xmlMalloc(size);
4474 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004475 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004476 "xmlTextWriterVSprintf : out of memory!\n");
4477 return NULL;
4478 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004479 VA_COPY(locarg, argptr);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004480 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004481 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004482
4483 return buf;
4484}
4485
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004486/**
4487 * xmlTextWriterStartDocumentCallback:
4488 * @ctx: the user data (XML parser context)
4489 *
4490 * called at the start of document processing.
4491 */
4492static void
4493xmlTextWriterStartDocumentCallback(void *ctx)
4494{
4495 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4496 xmlDocPtr doc;
4497
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004498 if (ctxt->html) {
4499#ifdef LIBXML_HTML_ENABLED
4500 if (ctxt->myDoc == NULL)
4501 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4502 if (ctxt->myDoc == NULL) {
4503 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4504 ctxt->sax->error(ctxt->userData,
4505 "SAX.startDocument(): out of memory\n");
4506 ctxt->errNo = XML_ERR_NO_MEMORY;
4507 ctxt->instate = XML_PARSER_EOF;
4508 ctxt->disableSAX = 1;
4509 return;
4510 }
4511#else
Daniel Veillardd0cf7f62004-11-09 16:17:02 +00004512 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004513 "libxml2 built without HTML support\n");
4514 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4515 ctxt->instate = XML_PARSER_EOF;
4516 ctxt->disableSAX = 1;
4517 return;
4518#endif
4519 } else {
4520 doc = ctxt->myDoc;
4521 if (doc == NULL)
4522 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4523 if (doc != NULL) {
4524 if (doc->children == NULL) {
4525 if (ctxt->encoding != NULL)
4526 doc->encoding = xmlStrdup(ctxt->encoding);
4527 else
4528 doc->encoding = NULL;
4529 doc->standalone = ctxt->standalone;
4530 }
4531 } else {
4532 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4533 ctxt->sax->error(ctxt->userData,
4534 "SAX.startDocument(): out of memory\n");
4535 ctxt->errNo = XML_ERR_NO_MEMORY;
4536 ctxt->instate = XML_PARSER_EOF;
4537 ctxt->disableSAX = 1;
4538 return;
4539 }
4540 }
4541 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4542 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4543 ctxt->myDoc->URL =
4544 xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4545 if (ctxt->myDoc->URL == NULL)
4546 ctxt->myDoc->URL =
4547 xmlStrdup((const xmlChar *) ctxt->input->filename);
4548 }
4549}
4550
Daniel Veillard2cca4462004-01-02 20:04:23 +00004551/**
4552 * xmlTextWriterSetIndent:
4553 * @writer: the xmlTextWriterPtr
4554 * @indent: do indentation?
4555 *
4556 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4557 *
4558 * Returns -1 on error or 0 otherwise.
4559 */
4560int
Daniel Veillardab69f362004-02-17 11:40:32 +00004561xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004562{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004563 if ((writer == NULL) || (indent < 0))
Daniel Veillardab69f362004-02-17 11:40:32 +00004564 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004565
Daniel Veillardab69f362004-02-17 11:40:32 +00004566 writer->indent = indent;
4567 writer->doindent = 1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004568
Daniel Veillardab69f362004-02-17 11:40:32 +00004569 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004570}
4571
4572/**
4573 * xmlTextWriterSetIndentString:
4574 * @writer: the xmlTextWriterPtr
4575 * @str: the xmlChar string
4576 *
4577 * Set string indentation.
4578 *
4579 * Returns -1 on error or 0 otherwise.
4580 */
4581int
Daniel Veillardab69f362004-02-17 11:40:32 +00004582xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004583{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004584 if ((writer == NULL) || (!str))
Daniel Veillardab69f362004-02-17 11:40:32 +00004585 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004586
Daniel Veillardab69f362004-02-17 11:40:32 +00004587 if (writer->ichar != NULL)
4588 xmlFree(writer->ichar);
4589 writer->ichar = xmlStrdup(str);
4590
4591 if (!writer->ichar)
4592 return -1;
4593 else
4594 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004595}
4596
4597/**
4598 * xmlTextWriterWriteIndent:
4599 * @writer: the xmlTextWriterPtr
4600 *
4601 * Write indent string.
4602 *
4603 * Returns -1 on error or the number of strings written.
Daniel Veillardab69f362004-02-17 11:40:32 +00004604 */
Daniel Veillard2cca4462004-01-02 20:04:23 +00004605static int
Daniel Veillardab69f362004-02-17 11:40:32 +00004606xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004607{
Daniel Veillardab69f362004-02-17 11:40:32 +00004608 int lksize;
4609 int i;
4610 int ret;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004611
Daniel Veillardab69f362004-02-17 11:40:32 +00004612 lksize = xmlListSize(writer->nodes);
4613 if (lksize < 1)
4614 return (-1); /* list is empty */
4615 for (i = 0; i < (lksize - 1); i++) {
4616 ret = xmlOutputBufferWriteString(writer->out,
4617 (const char *) writer->ichar);
4618 if (ret == -1)
4619 return (-1);
4620 }
4621
4622 return (lksize - 1);
Daniel Veillard2cca4462004-01-02 20:04:23 +00004623}
4624
Daniel Veillard500a1de2004-03-22 15:22:58 +00004625/**
4626 * xmlTextWriterHandleStateDependencies:
4627 * @writer: the xmlTextWriterPtr
4628 * @p: the xmlTextWriterStackEntry
4629 *
4630 * Write state dependent strings.
4631 *
4632 * Returns -1 on error or the number of characters written.
4633 */
4634static int
4635xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4636 xmlTextWriterStackEntry * p)
4637{
4638 int count;
4639 int sum;
4640 char extra[3];
4641
4642 if (writer == NULL)
4643 return -1;
4644
4645 if (p == NULL)
4646 return 0;
4647
4648 sum = 0;
4649 extra[0] = extra[1] = extra[2] = '\0';
4650 if (p != 0) {
4651 sum = 0;
4652 switch (p->state) {
4653 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00004654 /* Output namespace declarations */
4655 count = xmlTextWriterOutputNSDecl(writer);
4656 if (count < 0)
4657 return -1;
4658 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004659 extra[0] = '>';
4660 p->state = XML_TEXTWRITER_TEXT;
4661 break;
4662 case XML_TEXTWRITER_PI:
4663 extra[0] = ' ';
4664 p->state = XML_TEXTWRITER_PI_TEXT;
4665 break;
4666 case XML_TEXTWRITER_DTD:
4667 extra[0] = ' ';
4668 extra[1] = '[';
4669 p->state = XML_TEXTWRITER_DTD_TEXT;
4670 break;
4671 case XML_TEXTWRITER_DTD_ELEM:
4672 extra[0] = ' ';
4673 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4674 break;
4675 case XML_TEXTWRITER_DTD_ATTL:
4676 extra[0] = ' ';
4677 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4678 break;
4679 case XML_TEXTWRITER_DTD_ENTY:
4680 case XML_TEXTWRITER_DTD_PENT:
4681 extra[0] = ' ';
4682 extra[1] = writer->qchar;
4683 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4684 break;
4685 default:
4686 break;
4687 }
4688 }
4689
4690 if (*extra != '\0') {
4691 count = xmlOutputBufferWriteString(writer->out, extra);
4692 if (count < 0)
4693 return -1;
4694 sum += count;
4695 }
4696
4697 return sum;
4698}
4699
Daniel Veillard5d4644e2005-04-01 13:11:58 +00004700#define bottom_xmlwriter
4701#include "elfgcchack.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +00004702#endif