blob: 2d9d109043d24a25a73a48dccf419f191c8efde6 [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 *
629 * End an xml document. All open elements are closed
630 *
631 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
632 */
633int
634xmlTextWriterEndDocument(xmlTextWriterPtr writer)
635{
636 int count;
637 int sum;
638 xmlLinkPtr lk;
639 xmlTextWriterStackEntry *p;
640
Daniel Veillard500a1de2004-03-22 15:22:58 +0000641 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000642 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000643 "xmlTextWriterEndDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000644 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000645 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000646
647 sum = 0;
648 while ((lk = xmlListFront(writer->nodes)) != NULL) {
649 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
650 if (p == 0)
651 break;
652 switch (p->state) {
653 case XML_TEXTWRITER_NAME:
654 case XML_TEXTWRITER_ATTRIBUTE:
655 case XML_TEXTWRITER_TEXT:
656 count = xmlTextWriterEndElement(writer);
657 if (count < 0)
658 return -1;
659 sum += count;
660 break;
661 case XML_TEXTWRITER_PI:
662 case XML_TEXTWRITER_PI_TEXT:
663 count = xmlTextWriterEndPI(writer);
664 if (count < 0)
665 return -1;
666 sum += count;
667 break;
668 case XML_TEXTWRITER_CDATA:
669 count = xmlTextWriterEndCDATA(writer);
670 if (count < 0)
671 return -1;
672 sum += count;
673 break;
674 case XML_TEXTWRITER_DTD:
Daniel Veillard500a1de2004-03-22 15:22:58 +0000675 case XML_TEXTWRITER_DTD_TEXT:
676 case XML_TEXTWRITER_DTD_ELEM:
677 case XML_TEXTWRITER_DTD_ELEM_TEXT:
678 case XML_TEXTWRITER_DTD_ATTL:
679 case XML_TEXTWRITER_DTD_ATTL_TEXT:
680 case XML_TEXTWRITER_DTD_ENTY:
681 case XML_TEXTWRITER_DTD_ENTY_TEXT:
682 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard1d211e22003-10-20 22:32:39 +0000683 count = xmlTextWriterEndDTD(writer);
684 if (count < 0)
685 return -1;
686 sum += count;
687 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000688 case XML_TEXTWRITER_COMMENT:
689 count = xmlTextWriterEndComment(writer);
690 if (count < 0)
691 return -1;
692 sum += count;
693 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000694 default:
Daniel Veillardab69f362004-02-17 11:40:32 +0000695 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000696 }
697 }
698
Daniel Veillard2cca4462004-01-02 20:04:23 +0000699 if (!writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000700 count = xmlOutputBufferWriteString(writer->out, "\n");
701 if (count < 0)
702 return -1;
703 sum += count;
704 }
705 return sum;
706}
707
Daniel Veillardab69f362004-02-17 11:40:32 +0000708/**
709 * xmlTextWriterStartComment:
710 * @writer: the xmlTextWriterPtr
711 *
712 * Start an xml comment.
713 *
714 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
715 */
716int
717xmlTextWriterStartComment(xmlTextWriterPtr writer)
718{
719 int count;
720 int sum;
721 xmlLinkPtr lk;
722 xmlTextWriterStackEntry *p;
723
Daniel Veillard500a1de2004-03-22 15:22:58 +0000724 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000725 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000726 "xmlTextWriterStartComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000727 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000728 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000729
730 sum = 0;
731 lk = xmlListFront(writer->nodes);
732 if (lk != 0) {
733 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
734 if (p != 0) {
735 switch (p->state) {
736 case XML_TEXTWRITER_TEXT:
737 case XML_TEXTWRITER_NONE:
738 break;
739 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000740 /* Output namespace declarations */
741 count = xmlTextWriterOutputNSDecl(writer);
742 if (count < 0)
743 return -1;
744 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000745 count = xmlOutputBufferWriteString(writer->out, ">");
746 if (count < 0)
747 return -1;
748 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000749 if (writer->indent) {
750 count =
751 xmlOutputBufferWriteString(writer->out, "\n");
752 if (count < 0)
753 return -1;
754 sum += count;
755 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000756 p->state = XML_TEXTWRITER_TEXT;
757 break;
758 default:
759 return -1;
760 }
761 }
762 }
763
764 p = (xmlTextWriterStackEntry *)
765 xmlMalloc(sizeof(xmlTextWriterStackEntry));
766 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000767 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillardab69f362004-02-17 11:40:32 +0000768 "xmlTextWriterStartElement : out of memory!\n");
769 return -1;
770 }
771
Daniel Veillard75e389d2005-07-29 22:02:24 +0000772 p->name = NULL;
Daniel Veillardab69f362004-02-17 11:40:32 +0000773 p->state = XML_TEXTWRITER_COMMENT;
774
775 xmlListPushFront(writer->nodes, p);
776
777 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000778 count = xmlTextWriterWriteIndent(writer);
779 if (count < 0)
780 return -1;
781 sum += count;
782 }
783
784 count = xmlOutputBufferWriteString(writer->out, "<!--");
785 if (count < 0)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000786 return -1;
787 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000788
789 return sum;
790}
791
792/**
793 * xmlTextWriterEndComment:
794 * @writer: the xmlTextWriterPtr
795 *
796 * End the current xml coment.
797 *
798 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
799 */
800int
801xmlTextWriterEndComment(xmlTextWriterPtr writer)
802{
803 int count;
804 int sum;
805 xmlLinkPtr lk;
806 xmlTextWriterStackEntry *p;
807
Daniel Veillard500a1de2004-03-22 15:22:58 +0000808 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000809 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000810 "xmlTextWriterEndComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000811 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000812 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000813
814 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000815 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000816 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000817 "xmlTextWriterEndComment : not allowed in this context!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000818 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000819 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000820
821 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
822 if (p == 0)
823 return -1;
824
825 sum = 0;
826 switch (p->state) {
827 case XML_TEXTWRITER_COMMENT:
828 count = xmlOutputBufferWriteString(writer->out, "-->");
829 if (count < 0)
830 return -1;
831 sum += count;
832 break;
833 default:
834 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +0000835 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000836
837 if (writer->indent) {
838 count = xmlOutputBufferWriteString(writer->out, "\n");
839 if (count < 0)
840 return -1;
841 sum += count;
842 }
843
844 xmlListPopFront(writer->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000845 return sum;
846}
847
848/**
849 * xmlTextWriterWriteFormatComment:
850 * @writer: the xmlTextWriterPtr
851 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +0000852 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +0000853 *
854 * Write an xml comment.
855 *
856 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
857 */
Daniel Veillardffa3c742005-07-21 13:24:09 +0000858int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +0000859xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
860 const char *format, ...)
861{
862 int rc;
863 va_list ap;
864
865 va_start(ap, format);
866
867 rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
868
869 va_end(ap);
870 return rc;
871}
872
873/**
874 * xmlTextWriterWriteVFormatComment:
875 * @writer: the xmlTextWriterPtr
876 * @format: format string (see printf)
877 * @argptr: pointer to the first member of the variable argument list.
878 *
879 * Write an xml comment.
880 *
881 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
882 */
883int
884xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
885 const char *format, va_list argptr)
886{
887 int rc;
888 xmlChar *buf;
889
Daniel Veillard500a1de2004-03-22 15:22:58 +0000890 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000891 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000892 "xmlTextWriterWriteVFormatComment : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000893 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000894 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000895
896 buf = xmlTextWriterVSprintf(format, argptr);
897 if (buf == 0)
898 return 0;
899
900 rc = xmlTextWriterWriteComment(writer, buf);
901
902 xmlFree(buf);
903 return rc;
904}
905
906/**
907 * xmlTextWriterWriteComment:
908 * @writer: the xmlTextWriterPtr
909 * @content: comment string
910 *
911 * Write an xml comment.
912 *
913 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
914 */
915int
916xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
917{
918 int count;
919 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000920
921 sum = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000922 count = xmlTextWriterStartComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000923 if (count < 0)
924 return -1;
925 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000926 count = xmlTextWriterWriteString(writer, content);
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 = xmlTextWriterEndComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000931 if (count < 0)
932 return -1;
933 sum += count;
934
935 return sum;
936}
937
938/**
939 * xmlTextWriterStartElement:
940 * @writer: the xmlTextWriterPtr
941 * @name: element name
942 *
943 * Start an xml element.
944 *
945 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
946 */
947int
948xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
949{
950 int count;
951 int sum;
952 xmlLinkPtr lk;
953 xmlTextWriterStackEntry *p;
954
955 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
956 return -1;
957
958 sum = 0;
959 lk = xmlListFront(writer->nodes);
960 if (lk != 0) {
961 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
962 if (p != 0) {
963 switch (p->state) {
964 case XML_TEXTWRITER_PI:
965 case XML_TEXTWRITER_PI_TEXT:
966 return -1;
967 case XML_TEXTWRITER_NONE:
968 break;
Daniel Veillard614fdc12005-02-23 14:05:37 +0000969 case XML_TEXTWRITER_ATTRIBUTE:
970 count = xmlTextWriterEndAttribute(writer);
971 if (count < 0)
972 return -1;
973 sum += count;
974 /* fallthrough */
Daniel Veillard1d211e22003-10-20 22:32:39 +0000975 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000976 /* Output namespace declarations */
977 count = xmlTextWriterOutputNSDecl(writer);
978 if (count < 0)
979 return -1;
980 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000981 count = xmlOutputBufferWriteString(writer->out, ">");
982 if (count < 0)
983 return -1;
984 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000985 if (writer->indent)
986 count =
987 xmlOutputBufferWriteString(writer->out, "\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000988 p->state = XML_TEXTWRITER_TEXT;
989 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000990 default:
991 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000992 }
993 }
994 }
995
996 p = (xmlTextWriterStackEntry *)
997 xmlMalloc(sizeof(xmlTextWriterStackEntry));
998 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000999 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001000 "xmlTextWriterStartElement : out of memory!\n");
1001 return -1;
1002 }
1003
1004 p->name = xmlStrdup(name);
1005 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001006 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001007 "xmlTextWriterStartElement : out of memory!\n");
1008 xmlFree(p);
1009 return -1;
1010 }
1011 p->state = XML_TEXTWRITER_NAME;
1012
1013 xmlListPushFront(writer->nodes, p);
1014
Daniel Veillardab69f362004-02-17 11:40:32 +00001015 if (writer->indent) {
1016 count = xmlTextWriterWriteIndent(writer);
1017 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001018 }
1019
Daniel Veillard1d211e22003-10-20 22:32:39 +00001020 count = xmlOutputBufferWriteString(writer->out, "<");
1021 if (count < 0)
1022 return -1;
1023 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001024 count =
1025 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001026 if (count < 0)
1027 return -1;
1028 sum += count;
1029
1030 return sum;
1031}
1032
1033/**
1034 * xmlTextWriterStartElementNS:
1035 * @writer: the xmlTextWriterPtr
1036 * @prefix: namespace prefix or NULL
1037 * @name: element local name
1038 * @namespaceURI: namespace URI or NULL
1039 *
1040 * Start an xml element with namespace support.
1041 *
1042 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1043 */
1044int
1045xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
1046 const xmlChar * prefix, const xmlChar * name,
1047 const xmlChar * namespaceURI)
1048{
1049 int count;
1050 int sum;
1051 xmlChar *buf;
1052
1053 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1054 return -1;
1055
Daniel Veillard75e389d2005-07-29 22:02:24 +00001056 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001057 if (prefix != 0) {
1058 buf = xmlStrdup(prefix);
1059 buf = xmlStrcat(buf, BAD_CAST ":");
1060 }
1061 buf = xmlStrcat(buf, name);
1062
1063 sum = 0;
1064 count = xmlTextWriterStartElement(writer, buf);
1065 xmlFree(buf);
1066 if (count < 0)
1067 return -1;
1068 sum += count;
1069
1070 if (namespaceURI != 0) {
Rob Richardsb8769d62007-06-08 08:50:47 +00001071 xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
1072 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1073 if (p == 0) {
1074 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1075 "xmlTextWriterStartElementNS : out of memory!\n");
1076 return -1;
1077 }
1078
Daniel Veillard1d211e22003-10-20 22:32:39 +00001079 buf = xmlStrdup(BAD_CAST "xmlns");
1080 if (prefix != 0) {
1081 buf = xmlStrcat(buf, BAD_CAST ":");
1082 buf = xmlStrcat(buf, prefix);
1083 }
1084
Rob Richardsb8769d62007-06-08 08:50:47 +00001085 p->prefix = buf;
1086 p->uri = xmlStrdup(namespaceURI);
1087 if (p->uri == 0) {
1088 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1089 "xmlTextWriterStartElementNS : out of memory!\n");
1090 xmlFree(p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001091 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001092 }
1093 p->elem = xmlListFront(writer->nodes);
1094
1095 xmlListPushFront(writer->nsstack, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001096 }
1097
1098 return sum;
1099}
1100
1101/**
1102 * xmlTextWriterEndElement:
1103 * @writer: the xmlTextWriterPtr
1104 *
1105 * End the current xml element.
1106 *
1107 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1108 */
1109int
1110xmlTextWriterEndElement(xmlTextWriterPtr writer)
1111{
1112 int count;
1113 int sum;
1114 xmlLinkPtr lk;
1115 xmlTextWriterStackEntry *p;
1116
1117 if (writer == NULL)
1118 return -1;
1119
1120 lk = xmlListFront(writer->nodes);
Rob Richardsb8769d62007-06-08 08:50:47 +00001121 if (lk == 0) {
1122 xmlListDelete(writer->nsstack);
1123 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001124 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001125 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001126
1127 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Rob Richardsb8769d62007-06-08 08:50:47 +00001128 if (p == 0) {
1129 xmlListDelete(writer->nsstack);
1130 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001131 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001132 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001133
1134 sum = 0;
1135 switch (p->state) {
1136 case XML_TEXTWRITER_ATTRIBUTE:
1137 count = xmlTextWriterEndAttribute(writer);
Rob Richardsb8769d62007-06-08 08:50:47 +00001138 if (count < 0) {
1139 xmlListDelete(writer->nsstack);
1140 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001141 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001142 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001143 sum += count;
1144 /* fallthrough */
1145 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001146 /* Output namespace declarations */
1147 count = xmlTextWriterOutputNSDecl(writer);
1148 if (count < 0)
1149 return -1;
1150 sum += count;
1151
Daniel Veillardab69f362004-02-17 11:40:32 +00001152 if (writer->indent) /* next element needs indent */
1153 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001154 count = xmlOutputBufferWriteString(writer->out, "/>");
1155 if (count < 0)
1156 return -1;
1157 sum += count;
1158 break;
1159 case XML_TEXTWRITER_TEXT:
Daniel Veillardab69f362004-02-17 11:40:32 +00001160 if ((writer->indent) && (writer->doindent)) {
1161 count = xmlTextWriterWriteIndent(writer);
1162 sum += count;
1163 writer->doindent = 1;
1164 } else
1165 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001166 count = xmlOutputBufferWriteString(writer->out, "</");
1167 if (count < 0)
1168 return -1;
1169 sum += count;
1170 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001171 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001172 if (count < 0)
1173 return -1;
1174 sum += count;
1175 count = xmlOutputBufferWriteString(writer->out, ">");
1176 if (count < 0)
1177 return -1;
1178 sum += count;
1179 break;
1180 default:
1181 return -1;
1182 }
1183
Daniel Veillard2cca4462004-01-02 20:04:23 +00001184 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001185 count = xmlOutputBufferWriteString(writer->out, "\n");
1186 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001187 }
1188
Daniel Veillard1d211e22003-10-20 22:32:39 +00001189 xmlListPopFront(writer->nodes);
1190 return sum;
1191}
1192
1193/**
1194 * xmlTextWriterFullEndElement:
1195 * @writer: the xmlTextWriterPtr
1196 *
1197 * End the current xml element. Writes an end tag even if the element is empty
1198 *
1199 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1200 */
1201int
1202xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1203{
1204 int count;
1205 int sum;
1206 xmlLinkPtr lk;
1207 xmlTextWriterStackEntry *p;
1208
1209 if (writer == NULL)
1210 return -1;
1211
1212 lk = xmlListFront(writer->nodes);
1213 if (lk == 0)
1214 return -1;
1215
1216 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1217 if (p == 0)
1218 return -1;
1219
1220 sum = 0;
1221 switch (p->state) {
1222 case XML_TEXTWRITER_ATTRIBUTE:
1223 count = xmlTextWriterEndAttribute(writer);
1224 if (count < 0)
1225 return -1;
1226 sum += count;
1227 /* fallthrough */
1228 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001229 /* Output namespace declarations */
1230 count = xmlTextWriterOutputNSDecl(writer);
1231 if (count < 0)
1232 return -1;
1233 sum += count;
1234
Daniel Veillard1d211e22003-10-20 22:32:39 +00001235 count = xmlOutputBufferWriteString(writer->out, ">");
1236 if (count < 0)
1237 return -1;
1238 sum += count;
1239 /* fallthrough */
1240 case XML_TEXTWRITER_TEXT:
1241 count = xmlOutputBufferWriteString(writer->out, "</");
1242 if (count < 0)
1243 return -1;
1244 sum += count;
1245 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001246 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001247 if (count < 0)
1248 return -1;
1249 sum += count;
1250 count = xmlOutputBufferWriteString(writer->out, ">");
1251 if (count < 0)
1252 return -1;
1253 sum += count;
1254 break;
1255 default:
1256 return -1;
1257 }
1258
Daniel Veillard7e26fb42008-01-09 02:19:50 +00001259 if (writer->indent) {
1260 count = xmlOutputBufferWriteString(writer->out, "\n");
1261 sum += count;
1262 }
1263
Daniel Veillard1d211e22003-10-20 22:32:39 +00001264 xmlListPopFront(writer->nodes);
1265 return sum;
1266}
1267
1268/**
1269 * xmlTextWriterWriteFormatRaw:
1270 * @writer: the xmlTextWriterPtr
1271 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001272 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001273 *
1274 * Write a formatted raw xml text.
1275 *
1276 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1277 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001278int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001279xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1280 ...)
1281{
1282 int rc;
1283 va_list ap;
1284
1285 va_start(ap, format);
1286
1287 rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1288
1289 va_end(ap);
1290 return rc;
1291}
1292
1293/**
1294 * xmlTextWriterWriteVFormatRaw:
1295 * @writer: the xmlTextWriterPtr
1296 * @format: format string (see printf)
1297 * @argptr: pointer to the first member of the variable argument list.
1298 *
1299 * Write a formatted raw xml text.
1300 *
1301 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1302 */
1303int
1304xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1305 va_list argptr)
1306{
1307 int rc;
1308 xmlChar *buf;
1309
1310 if (writer == NULL)
1311 return -1;
1312
1313 buf = xmlTextWriterVSprintf(format, argptr);
1314 if (buf == 0)
1315 return 0;
1316
1317 rc = xmlTextWriterWriteRaw(writer, buf);
1318
1319 xmlFree(buf);
1320 return rc;
1321}
1322
1323/**
Daniel Veillard1e906612003-12-05 14:57:46 +00001324 * xmlTextWriterWriteRawLen:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001325 * @writer: the xmlTextWriterPtr
1326 * @content: text string
1327 * @len: length of the text string
1328 *
1329 * Write an xml text.
1330 * TODO: what about entities and special chars??
1331 *
1332 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1333 */
1334int
1335xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1336 int len)
1337{
1338 int count;
1339 int sum;
1340 xmlLinkPtr lk;
1341 xmlTextWriterStackEntry *p;
1342
Daniel Veillard500a1de2004-03-22 15:22:58 +00001343 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001344 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001345 "xmlTextWriterWriteRawLen : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001346 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001347 }
1348
Daniel Veillarde43cc572004-11-03 11:50:29 +00001349 if ((content == NULL) || (len < 0)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001350 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001351 "xmlTextWriterWriteRawLen : invalid content!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001352 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001353 }
1354
1355 sum = 0;
1356 lk = xmlListFront(writer->nodes);
1357 if (lk != 0) {
1358 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1359 count = xmlTextWriterHandleStateDependencies(writer, p);
1360 if (count < 0)
1361 return -1;
1362 sum += count;
1363 }
1364
1365 if (writer->indent)
1366 writer->doindent = 0;
1367
1368 if (content != NULL) {
1369 count =
1370 xmlOutputBufferWrite(writer->out, len, (const char *) content);
1371 if (count < 0)
1372 return -1;
1373 sum += count;
1374 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001375
1376 return sum;
1377}
1378
1379/**
1380 * xmlTextWriterWriteRaw:
1381 * @writer: the xmlTextWriterPtr
1382 * @content: text string
1383 *
1384 * Write a raw xml text.
1385 *
1386 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1387 */
1388int
1389xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1390{
1391 return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1392}
1393
1394/**
1395 * xmlTextWriterWriteFormatString:
1396 * @writer: the xmlTextWriterPtr
1397 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001398 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001399 *
1400 * Write a formatted xml text.
1401 *
1402 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1403 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001404int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001405xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1406 ...)
1407{
1408 int rc;
1409 va_list ap;
1410
Daniel Veillarde43cc572004-11-03 11:50:29 +00001411 if ((writer == NULL) || (format == NULL))
1412 return -1;
1413
Daniel Veillard1d211e22003-10-20 22:32:39 +00001414 va_start(ap, format);
1415
1416 rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1417
1418 va_end(ap);
1419 return rc;
1420}
1421
1422/**
1423 * xmlTextWriterWriteVFormatString:
1424 * @writer: the xmlTextWriterPtr
1425 * @format: format string (see printf)
1426 * @argptr: pointer to the first member of the variable argument list.
1427 *
1428 * Write a formatted xml text.
1429 *
1430 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1431 */
1432int
1433xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1434 const char *format, va_list argptr)
1435{
1436 int rc;
1437 xmlChar *buf;
1438
Daniel Veillarde43cc572004-11-03 11:50:29 +00001439 if ((writer == NULL) || (format == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001440 return -1;
1441
1442 buf = xmlTextWriterVSprintf(format, argptr);
1443 if (buf == 0)
1444 return 0;
1445
1446 rc = xmlTextWriterWriteString(writer, buf);
1447
1448 xmlFree(buf);
1449 return rc;
1450}
1451
1452/**
1453 * xmlTextWriterWriteString:
1454 * @writer: the xmlTextWriterPtr
1455 * @content: text string
1456 *
1457 * Write an xml text.
1458 *
1459 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1460 */
1461int
1462xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1463{
Daniel Veillard500a1de2004-03-22 15:22:58 +00001464 int count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001465 int sum;
1466 xmlLinkPtr lk;
1467 xmlTextWriterStackEntry *p;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001468 xmlChar *buf;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001469
Daniel Veillarde43cc572004-11-03 11:50:29 +00001470 if ((writer == NULL) || (content == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001471 return -1;
1472
Daniel Veillard1d211e22003-10-20 22:32:39 +00001473 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001474 buf = (xmlChar *) content;
1475 lk = xmlListFront(writer->nodes);
1476 if (lk != 0) {
1477 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1478 if (p != 0) {
1479 switch (p->state) {
1480 case XML_TEXTWRITER_NAME:
1481 case XML_TEXTWRITER_TEXT:
Daniel Veillard62040be2004-05-17 03:17:26 +00001482#if 0
1483 buf = NULL;
1484 xmlOutputBufferWriteEscape(writer->out, content, NULL);
1485#endif
Daniel Veillard500a1de2004-03-22 15:22:58 +00001486 buf = xmlEncodeSpecialChars(NULL, content);
1487 break;
1488 case XML_TEXTWRITER_ATTRIBUTE:
1489 buf = NULL;
Rob Richards9db68f02006-08-16 22:48:51 +00001490 xmlAttrSerializeTxtContent(writer->out->buffer, writer->doc,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001491 NULL, content);
1492 break;
William M. Brack87640d52004-04-17 14:58:15 +00001493 default:
1494 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001495 }
1496 }
1497 }
1498
1499 if (buf != NULL) {
1500 count = xmlTextWriterWriteRaw(writer, buf);
1501 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001502 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001503 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001504
Daniel Veillard500a1de2004-03-22 15:22:58 +00001505 if (buf != content) /* buf was allocated by us, so free it */
1506 xmlFree(buf);
William M. Bracka9c612c2004-02-01 10:04:05 +00001507 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001508
1509 return sum;
1510}
1511
1512/**
1513 * xmlOutputBufferWriteBase64:
1514 * @out: the xmlOutputBufferPtr
1515 * @data: binary data
1516 * @len: the number of bytes to encode
1517 *
1518 * Write base64 encoded data to an xmlOutputBuffer.
1519 * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1520 *
1521 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1522 */
1523static int
1524xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1525 const unsigned char *data)
1526{
1527 static unsigned char dtable[64] =
William M. Brack47a31882004-09-11 16:09:09 +00001528 {'A','B','C','D','E','F','G','H','I','J','K','L','M',
1529 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1530 'a','b','c','d','e','f','g','h','i','j','k','l','m',
1531 'n','o','p','q','r','s','t','u','v','w','x','y','z',
1532 '0','1','2','3','4','5','6','7','8','9','+','/'};
1533
Daniel Veillard1d211e22003-10-20 22:32:39 +00001534 int i;
1535 int linelen;
1536 int count;
1537 int sum;
1538
Daniel Veillarde43cc572004-11-03 11:50:29 +00001539 if ((out == NULL) || (len < 0) || (data == NULL))
1540 return(-1);
1541
Daniel Veillard1d211e22003-10-20 22:32:39 +00001542 linelen = 0;
1543 sum = 0;
1544
1545 i = 0;
1546 while (1) {
1547 unsigned char igroup[3];
1548 unsigned char ogroup[4];
1549 int c;
1550 int n;
1551
1552 igroup[0] = igroup[1] = igroup[2] = 0;
1553 for (n = 0; n < 3 && i < len; n++, i++) {
1554 c = data[i];
1555 igroup[n] = (unsigned char) c;
1556 }
1557
1558 if (n > 0) {
1559 ogroup[0] = dtable[igroup[0] >> 2];
1560 ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1561 ogroup[2] =
1562 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1563 ogroup[3] = dtable[igroup[2] & 0x3F];
1564
1565 if (n < 3) {
1566 ogroup[3] = '=';
1567 if (n < 2) {
1568 ogroup[2] = '=';
1569 }
1570 }
1571
1572 if (linelen >= B64LINELEN) {
1573 count = xmlOutputBufferWrite(out, 2, B64CRLF);
1574 if (count == -1)
1575 return -1;
1576 sum += count;
1577 linelen = 0;
1578 }
1579 count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1580 if (count == -1)
1581 return -1;
1582 sum += count;
1583
1584 linelen += 4;
1585 }
Daniel Veillard929714b2003-10-22 12:34:36 +00001586
1587 if (i >= len)
1588 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001589 }
1590
Daniel Veillard1d211e22003-10-20 22:32:39 +00001591 return sum;
1592}
1593
1594/**
1595 * xmlTextWriterWriteBase64:
1596 * @writer: the xmlTextWriterPtr
1597 * @data: binary data
1598 * @start: the position within the data of the first byte to encode
1599 * @len: the number of bytes to encode
1600 *
1601 * Write an base64 encoded xml text.
1602 *
1603 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1604 */
1605int
Daniel Veillardab69f362004-02-17 11:40:32 +00001606xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001607 int start, int len)
1608{
1609 int count;
1610 int sum;
1611 xmlLinkPtr lk;
1612 xmlTextWriterStackEntry *p;
1613
Daniel Veillarde43cc572004-11-03 11:50:29 +00001614 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001615 return -1;
1616
Daniel Veillard1d211e22003-10-20 22:32:39 +00001617 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001618 lk = xmlListFront(writer->nodes);
1619 if (lk != 0) {
1620 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1621 if (p != 0) {
1622 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001623 if (count < 0)
1624 return -1;
1625 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001626 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001627 }
1628
Daniel Veillardab69f362004-02-17 11:40:32 +00001629 if (writer->indent)
1630 writer->doindent = 0;
1631
Daniel Veillard1d211e22003-10-20 22:32:39 +00001632 count =
1633 xmlOutputBufferWriteBase64(writer->out, len,
1634 (unsigned char *) data + start);
1635 if (count < 0)
1636 return -1;
1637 sum += count;
1638
1639 return sum;
1640}
1641
1642/**
1643 * xmlOutputBufferWriteBinHex:
1644 * @out: the xmlOutputBufferPtr
1645 * @data: binary data
1646 * @len: the number of bytes to encode
1647 *
1648 * Write hqx encoded data to an xmlOutputBuffer.
1649 * ::todo
1650 *
William M. Brack47a31882004-09-11 16:09:09 +00001651 * Returns the bytes written (may be 0 because of buffering)
1652 * or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +00001653 */
1654static int
Daniel Veillardab69f362004-02-17 11:40:32 +00001655xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1656 int len, const unsigned char *data)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001657{
Daniel Veillardab69f362004-02-17 11:40:32 +00001658 int count;
1659 int sum;
William M. Brack47a31882004-09-11 16:09:09 +00001660 static char hex[16] =
1661 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
Daniel Veillardab69f362004-02-17 11:40:32 +00001662 int i;
1663
Daniel Veillarde43cc572004-11-03 11:50:29 +00001664 if ((out == NULL) || (data == NULL) || (len < 0)) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001665 return -1;
1666 }
1667
1668 sum = 0;
1669 for (i = 0; i < len; i++) {
1670 count =
1671 xmlOutputBufferWrite(out, 1,
1672 (const char *) &hex[data[i] >> 4]);
1673 if (count == -1)
1674 return -1;
1675 sum += count;
1676 count =
1677 xmlOutputBufferWrite(out, 1,
1678 (const char *) &hex[data[i] & 0xF]);
1679 if (count == -1)
1680 return -1;
1681 sum += count;
1682 }
1683
1684 return sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001685}
1686
1687/**
1688 * xmlTextWriterWriteBinHex:
1689 * @writer: the xmlTextWriterPtr
1690 * @data: binary data
1691 * @start: the position within the data of the first byte to encode
1692 * @len: the number of bytes to encode
1693 *
1694 * Write a BinHex encoded xml text.
1695 *
1696 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1697 */
1698int
Daniel Veillardab69f362004-02-17 11:40:32 +00001699xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001700 int start, int len)
1701{
1702 int count;
1703 int sum;
1704 xmlLinkPtr lk;
1705 xmlTextWriterStackEntry *p;
1706
Daniel Veillarde43cc572004-11-03 11:50:29 +00001707 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001708 return -1;
1709
Daniel Veillard1d211e22003-10-20 22:32:39 +00001710 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001711 lk = xmlListFront(writer->nodes);
1712 if (lk != 0) {
1713 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1714 if (p != 0) {
1715 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001716 if (count < 0)
1717 return -1;
1718 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001719 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001720 }
1721
Daniel Veillardab69f362004-02-17 11:40:32 +00001722 if (writer->indent)
1723 writer->doindent = 0;
1724
Daniel Veillard1d211e22003-10-20 22:32:39 +00001725 count =
1726 xmlOutputBufferWriteBinHex(writer->out, len,
1727 (unsigned char *) data + start);
1728 if (count < 0)
1729 return -1;
1730 sum += count;
1731
1732 return sum;
1733}
1734
1735/**
1736 * xmlTextWriterStartAttribute:
1737 * @writer: the xmlTextWriterPtr
1738 * @name: element name
1739 *
1740 * Start an xml attribute.
1741 *
1742 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1743 */
1744int
1745xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1746{
1747 int count;
1748 int sum;
1749 xmlLinkPtr lk;
1750 xmlTextWriterStackEntry *p;
1751
1752 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1753 return -1;
1754
1755 sum = 0;
1756 lk = xmlListFront(writer->nodes);
1757 if (lk == 0)
1758 return -1;
1759
1760 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1761 if (p == 0)
1762 return -1;
1763
1764 switch (p->state) {
1765 case XML_TEXTWRITER_ATTRIBUTE:
1766 count = xmlTextWriterEndAttribute(writer);
1767 if (count < 0)
1768 return -1;
1769 sum += count;
1770 /* fallthrough */
1771 case XML_TEXTWRITER_NAME:
1772 count = xmlOutputBufferWriteString(writer->out, " ");
1773 if (count < 0)
1774 return -1;
1775 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001776 count =
1777 xmlOutputBufferWriteString(writer->out,
1778 (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001779 if (count < 0)
1780 return -1;
1781 sum += count;
1782 count = xmlOutputBufferWriteString(writer->out, "=");
1783 if (count < 0)
1784 return -1;
1785 sum += count;
1786 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1787 if (count < 0)
1788 return -1;
1789 sum += count;
1790 p->state = XML_TEXTWRITER_ATTRIBUTE;
1791 break;
1792 default:
1793 return -1;
1794 }
1795
1796 return sum;
1797}
1798
1799/**
1800 * xmlTextWriterStartAttributeNS:
1801 * @writer: the xmlTextWriterPtr
1802 * @prefix: namespace prefix or NULL
1803 * @name: element local name
1804 * @namespaceURI: namespace URI or NULL
1805 *
1806 * Start an xml attribute with namespace support.
1807 *
1808 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1809 */
1810int
1811xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1812 const xmlChar * prefix, const xmlChar * name,
1813 const xmlChar * namespaceURI)
1814{
1815 int count;
1816 int sum;
1817 xmlChar *buf;
1818 xmlTextWriterNsStackEntry *p;
1819
1820 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1821 return -1;
1822
Rob Richardsb8769d62007-06-08 08:50:47 +00001823 /* Handle namespace first in case of error */
1824 if (namespaceURI != 0) {
1825 xmlTextWriterNsStackEntry nsentry, *curns;
1826
1827 buf = xmlStrdup(BAD_CAST "xmlns");
1828 if (prefix != 0) {
1829 buf = xmlStrcat(buf, BAD_CAST ":");
1830 buf = xmlStrcat(buf, prefix);
1831 }
1832
1833 nsentry.prefix = buf;
1834 nsentry.uri = (xmlChar *)namespaceURI;
1835 nsentry.elem = xmlListFront(writer->nodes);
1836
1837 curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
1838 (void *)&nsentry);
1839 if ((curns != NULL)) {
1840 xmlFree(buf);
1841 if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
1842 /* Namespace already defined on element skip */
1843 buf = NULL;
1844 } else {
1845 /* Prefix mismatch so error out */
1846 return -1;
1847 }
1848 }
1849
1850 /* Do not add namespace decl to list - it is already there */
1851 if (buf != NULL) {
1852 p = (xmlTextWriterNsStackEntry *)
1853 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1854 if (p == 0) {
1855 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1856 "xmlTextWriterStartAttributeNS : out of memory!\n");
1857 return -1;
1858 }
1859
1860 p->prefix = buf;
1861 p->uri = xmlStrdup(namespaceURI);
1862 if (p->uri == 0) {
1863 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1864 "xmlTextWriterStartAttributeNS : out of memory!\n");
1865 xmlFree(p);
1866 return -1;
1867 }
1868 p->elem = xmlListFront(writer->nodes);
1869
1870 xmlListPushFront(writer->nsstack, p);
1871 }
1872 }
1873
Daniel Veillard75e389d2005-07-29 22:02:24 +00001874 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001875 if (prefix != 0) {
1876 buf = xmlStrdup(prefix);
1877 buf = xmlStrcat(buf, BAD_CAST ":");
1878 }
1879 buf = xmlStrcat(buf, name);
1880
1881 sum = 0;
1882 count = xmlTextWriterStartAttribute(writer, buf);
1883 xmlFree(buf);
1884 if (count < 0)
1885 return -1;
1886 sum += count;
1887
Daniel Veillard1d211e22003-10-20 22:32:39 +00001888 return sum;
1889}
1890
1891/**
1892 * xmlTextWriterEndAttribute:
1893 * @writer: the xmlTextWriterPtr
1894 *
1895 * End the current xml element.
1896 *
1897 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1898 */
1899int
1900xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1901{
1902 int count;
1903 int sum;
1904 xmlLinkPtr lk;
1905 xmlTextWriterStackEntry *p;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001906
1907 if (writer == NULL)
1908 return -1;
1909
1910 lk = xmlListFront(writer->nodes);
1911 if (lk == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001912 return -1;
1913 }
1914
1915 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1916 if (p == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001917 return -1;
1918 }
1919
1920 sum = 0;
1921 switch (p->state) {
1922 case XML_TEXTWRITER_ATTRIBUTE:
1923 p->state = XML_TEXTWRITER_NAME;
1924
1925 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1926 if (count < 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001927 return -1;
1928 }
1929 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001930 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001931 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001932 return -1;
1933 }
1934
1935 return sum;
1936}
1937
1938/**
1939 * xmlTextWriterWriteFormatAttribute:
1940 * @writer: the xmlTextWriterPtr
1941 * @name: attribute name
1942 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001943 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001944 *
1945 * Write a formatted xml attribute.
1946 *
1947 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1948 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001949int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001950xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1951 const xmlChar * name, const char *format,
1952 ...)
1953{
1954 int rc;
1955 va_list ap;
1956
1957 va_start(ap, format);
1958
1959 rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1960
1961 va_end(ap);
1962 return rc;
1963}
1964
1965/**
1966 * xmlTextWriterWriteVFormatAttribute:
1967 * @writer: the xmlTextWriterPtr
1968 * @name: attribute name
1969 * @format: format string (see printf)
1970 * @argptr: pointer to the first member of the variable argument list.
1971 *
1972 * Write a formatted xml attribute.
1973 *
1974 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1975 */
1976int
1977xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
1978 const xmlChar * name,
1979 const char *format, va_list argptr)
1980{
1981 int rc;
1982 xmlChar *buf;
1983
1984 if (writer == NULL)
1985 return -1;
1986
1987 buf = xmlTextWriterVSprintf(format, argptr);
1988 if (buf == 0)
1989 return 0;
1990
1991 rc = xmlTextWriterWriteAttribute(writer, name, buf);
1992
1993 xmlFree(buf);
1994 return rc;
1995}
1996
1997/**
1998 * xmlTextWriterWriteAttribute:
1999 * @writer: the xmlTextWriterPtr
2000 * @name: attribute name
2001 * @content: attribute content
2002 *
2003 * Write an xml attribute.
2004 *
2005 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2006 */
2007int
2008xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
2009 const xmlChar * content)
2010{
2011 int count;
2012 int sum;
2013
2014 sum = 0;
2015 count = xmlTextWriterStartAttribute(writer, name);
2016 if (count < 0)
2017 return -1;
2018 sum += count;
2019 count = xmlTextWriterWriteString(writer, content);
2020 if (count < 0)
2021 return -1;
2022 sum += count;
2023 count = xmlTextWriterEndAttribute(writer);
2024 if (count < 0)
2025 return -1;
2026 sum += count;
2027
2028 return sum;
2029}
2030
2031/**
2032 * xmlTextWriterWriteFormatAttributeNS:
2033 * @writer: the xmlTextWriterPtr
2034 * @prefix: namespace prefix
2035 * @name: attribute local name
2036 * @namespaceURI: namespace URI
2037 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002038 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002039 *
2040 * Write a formatted xml attribute.with namespace support
2041 *
2042 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2043 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002044int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002045xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
2046 const xmlChar * prefix,
2047 const xmlChar * name,
2048 const xmlChar * namespaceURI,
2049 const char *format, ...)
2050{
2051 int rc;
2052 va_list ap;
2053
2054 va_start(ap, format);
2055
2056 rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
2057 namespaceURI, format, ap);
2058
2059 va_end(ap);
2060 return rc;
2061}
2062
2063/**
2064 * xmlTextWriterWriteVFormatAttributeNS:
2065 * @writer: the xmlTextWriterPtr
2066 * @prefix: namespace prefix
2067 * @name: attribute local name
2068 * @namespaceURI: namespace URI
2069 * @format: format string (see printf)
2070 * @argptr: pointer to the first member of the variable argument list.
2071 *
2072 * Write a formatted xml attribute.with namespace support
2073 *
2074 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2075 */
2076int
2077xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
2078 const xmlChar * prefix,
2079 const xmlChar * name,
2080 const xmlChar * namespaceURI,
2081 const char *format, va_list argptr)
2082{
2083 int rc;
2084 xmlChar *buf;
2085
2086 if (writer == NULL)
2087 return -1;
2088
2089 buf = xmlTextWriterVSprintf(format, argptr);
2090 if (buf == 0)
2091 return 0;
2092
2093 rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
2094 buf);
2095
2096 xmlFree(buf);
2097 return rc;
2098}
2099
2100/**
2101 * xmlTextWriterWriteAttributeNS:
2102 * @writer: the xmlTextWriterPtr
2103 * @prefix: namespace prefix
2104 * @name: attribute local name
2105 * @namespaceURI: namespace URI
2106 * @content: attribute content
2107 *
2108 * Write an xml attribute.
2109 *
2110 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2111 */
2112int
2113xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
2114 const xmlChar * prefix, const xmlChar * name,
2115 const xmlChar * namespaceURI,
2116 const xmlChar * content)
2117{
2118 int count;
2119 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002120
2121 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2122 return -1;
2123
Daniel Veillard1d211e22003-10-20 22:32:39 +00002124 sum = 0;
Rob Richardsb8769d62007-06-08 08:50:47 +00002125 count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
2126 if (count < 0)
2127 return -1;
2128 sum += count;
2129 count = xmlTextWriterWriteString(writer, content);
2130 if (count < 0)
2131 return -1;
2132 sum += count;
2133 count = xmlTextWriterEndAttribute(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002134 if (count < 0)
2135 return -1;
2136 sum += count;
2137
Daniel Veillard1d211e22003-10-20 22:32:39 +00002138 return sum;
2139}
2140
2141/**
2142 * xmlTextWriterWriteFormatElement:
2143 * @writer: the xmlTextWriterPtr
2144 * @name: element name
2145 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002146 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002147 *
2148 * Write a formatted xml element.
2149 *
2150 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2151 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002152int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002153xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2154 const xmlChar * name, const char *format,
2155 ...)
2156{
2157 int rc;
2158 va_list ap;
2159
2160 va_start(ap, format);
2161
2162 rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2163
2164 va_end(ap);
2165 return rc;
2166}
2167
2168/**
2169 * xmlTextWriterWriteVFormatElement:
2170 * @writer: the xmlTextWriterPtr
2171 * @name: element name
2172 * @format: format string (see printf)
2173 * @argptr: pointer to the first member of the variable argument list.
2174 *
2175 * Write a formatted xml element.
2176 *
2177 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2178 */
2179int
2180xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2181 const xmlChar * name, const char *format,
2182 va_list argptr)
2183{
2184 int rc;
2185 xmlChar *buf;
2186
2187 if (writer == NULL)
2188 return -1;
2189
2190 buf = xmlTextWriterVSprintf(format, argptr);
2191 if (buf == 0)
2192 return 0;
2193
2194 rc = xmlTextWriterWriteElement(writer, name, buf);
2195
2196 xmlFree(buf);
2197 return rc;
2198}
2199
2200/**
2201 * xmlTextWriterWriteElement:
2202 * @writer: the xmlTextWriterPtr
2203 * @name: element name
2204 * @content: element content
2205 *
2206 * Write an xml element.
2207 *
2208 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2209 */
2210int
2211xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2212 const xmlChar * content)
2213{
2214 int count;
2215 int sum;
2216
2217 sum = 0;
2218 count = xmlTextWriterStartElement(writer, name);
2219 if (count == -1)
2220 return -1;
2221 sum += count;
2222 count = xmlTextWriterWriteString(writer, content);
2223 if (count == -1)
2224 return -1;
2225 sum += count;
2226 count = xmlTextWriterEndElement(writer);
2227 if (count == -1)
2228 return -1;
2229 sum += count;
2230
2231 return sum;
2232}
2233
2234/**
2235 * xmlTextWriterWriteFormatElementNS:
2236 * @writer: the xmlTextWriterPtr
2237 * @prefix: namespace prefix
2238 * @name: element local name
2239 * @namespaceURI: namespace URI
2240 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002241 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002242 *
2243 * Write a formatted xml element with namespace support.
2244 *
2245 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2246 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002247int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002248xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2249 const xmlChar * prefix,
2250 const xmlChar * name,
2251 const xmlChar * namespaceURI,
2252 const char *format, ...)
2253{
2254 int rc;
2255 va_list ap;
2256
2257 va_start(ap, format);
2258
2259 rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2260 namespaceURI, format, ap);
2261
2262 va_end(ap);
2263 return rc;
2264}
2265
2266/**
2267 * xmlTextWriterWriteVFormatElementNS:
2268 * @writer: the xmlTextWriterPtr
2269 * @prefix: namespace prefix
2270 * @name: element local name
2271 * @namespaceURI: namespace URI
2272 * @format: format string (see printf)
2273 * @argptr: pointer to the first member of the variable argument list.
2274 *
2275 * Write a formatted xml element with namespace support.
2276 *
2277 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2278 */
2279int
2280xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2281 const xmlChar * prefix,
2282 const xmlChar * name,
2283 const xmlChar * namespaceURI,
2284 const char *format, va_list argptr)
2285{
2286 int rc;
2287 xmlChar *buf;
2288
2289 if (writer == NULL)
2290 return -1;
2291
2292 buf = xmlTextWriterVSprintf(format, argptr);
2293 if (buf == 0)
2294 return 0;
2295
2296 rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2297 buf);
2298
2299 xmlFree(buf);
2300 return rc;
2301}
2302
2303/**
2304 * xmlTextWriterWriteElementNS:
2305 * @writer: the xmlTextWriterPtr
2306 * @prefix: namespace prefix
2307 * @name: element local name
2308 * @namespaceURI: namespace URI
2309 * @content: element content
2310 *
2311 * Write an xml element with namespace support.
2312 *
2313 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2314 */
2315int
2316xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2317 const xmlChar * prefix, const xmlChar * name,
2318 const xmlChar * namespaceURI,
2319 const xmlChar * content)
2320{
2321 int count;
2322 int sum;
2323
2324 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2325 return -1;
2326
2327 sum = 0;
2328 count =
2329 xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2330 if (count < 0)
2331 return -1;
2332 sum += count;
2333 count = xmlTextWriterWriteString(writer, content);
2334 if (count == -1)
2335 return -1;
2336 sum += count;
2337 count = xmlTextWriterEndElement(writer);
2338 if (count == -1)
2339 return -1;
2340 sum += count;
2341
2342 return sum;
2343}
2344
2345/**
2346 * xmlTextWriterStartPI:
2347 * @writer: the xmlTextWriterPtr
2348 * @target: PI target
2349 *
2350 * Start an xml PI.
2351 *
2352 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2353 */
2354int
2355xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2356{
2357 int count;
2358 int sum;
2359 xmlLinkPtr lk;
2360 xmlTextWriterStackEntry *p;
2361
2362 if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2363 return -1;
2364
2365 if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002366 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002367 "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2368 return -1;
2369 }
2370
2371 sum = 0;
2372 lk = xmlListFront(writer->nodes);
2373 if (lk != 0) {
2374 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2375 if (p != 0) {
2376 switch (p->state) {
2377 case XML_TEXTWRITER_ATTRIBUTE:
2378 count = xmlTextWriterEndAttribute(writer);
2379 if (count < 0)
2380 return -1;
2381 sum += count;
2382 /* fallthrough */
2383 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002384 /* Output namespace declarations */
2385 count = xmlTextWriterOutputNSDecl(writer);
2386 if (count < 0)
2387 return -1;
2388 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002389 count = xmlOutputBufferWriteString(writer->out, ">");
2390 if (count < 0)
2391 return -1;
2392 sum += count;
2393 p->state = XML_TEXTWRITER_TEXT;
2394 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00002395 case XML_TEXTWRITER_NONE:
2396 case XML_TEXTWRITER_TEXT:
2397 case XML_TEXTWRITER_DTD:
2398 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002399 case XML_TEXTWRITER_PI:
2400 case XML_TEXTWRITER_PI_TEXT:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002401 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002402 "xmlTextWriterStartPI : nested PI!\n");
2403 return -1;
2404 default:
2405 return -1;
2406 }
2407 }
2408 }
2409
2410 p = (xmlTextWriterStackEntry *)
2411 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2412 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002413 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002414 "xmlTextWriterStartPI : out of memory!\n");
2415 return -1;
2416 }
2417
2418 p->name = xmlStrdup(target);
2419 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002420 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002421 "xmlTextWriterStartPI : out of memory!\n");
2422 xmlFree(p);
2423 return -1;
2424 }
2425 p->state = XML_TEXTWRITER_PI;
2426
2427 xmlListPushFront(writer->nodes, p);
2428
2429 count = xmlOutputBufferWriteString(writer->out, "<?");
2430 if (count < 0)
2431 return -1;
2432 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002433 count =
2434 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002435 if (count < 0)
2436 return -1;
2437 sum += count;
2438
2439 return sum;
2440}
2441
2442/**
2443 * xmlTextWriterEndPI:
2444 * @writer: the xmlTextWriterPtr
2445 *
2446 * End the current xml PI.
2447 *
2448 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2449 */
2450int
2451xmlTextWriterEndPI(xmlTextWriterPtr writer)
2452{
2453 int count;
2454 int sum;
2455 xmlLinkPtr lk;
2456 xmlTextWriterStackEntry *p;
2457
2458 if (writer == NULL)
2459 return -1;
2460
2461 lk = xmlListFront(writer->nodes);
2462 if (lk == 0)
2463 return 0;
2464
2465 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2466 if (p == 0)
2467 return 0;
2468
2469 sum = 0;
2470 switch (p->state) {
2471 case XML_TEXTWRITER_PI:
2472 case XML_TEXTWRITER_PI_TEXT:
2473 count = xmlOutputBufferWriteString(writer->out, "?>");
2474 if (count < 0)
2475 return -1;
2476 sum += count;
2477 break;
2478 default:
2479 return -1;
2480 }
2481
Daniel Veillard02c1f232006-04-27 08:10:25 +00002482 if (writer->indent) {
2483 count = xmlOutputBufferWriteString(writer->out, "\n");
2484 if (count < 0)
2485 return -1;
2486 sum += count;
2487 }
2488
Daniel Veillard1d211e22003-10-20 22:32:39 +00002489 xmlListPopFront(writer->nodes);
2490 return sum;
2491}
2492
2493/**
2494 * xmlTextWriterWriteFormatPI:
2495 * @writer: the xmlTextWriterPtr
2496 * @target: PI target
2497 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002498 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002499 *
2500 * Write a formatted PI.
2501 *
2502 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2503 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002504int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002505xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2506 const char *format, ...)
2507{
2508 int rc;
2509 va_list ap;
2510
2511 va_start(ap, format);
2512
2513 rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2514
2515 va_end(ap);
2516 return rc;
2517}
2518
2519/**
2520 * xmlTextWriterWriteVFormatPI:
2521 * @writer: the xmlTextWriterPtr
2522 * @target: PI target
2523 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002524 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002525 *
2526 * Write a formatted xml PI.
2527 *
2528 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2529 */
2530int
2531xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2532 const xmlChar * target, const char *format,
2533 va_list argptr)
2534{
2535 int rc;
2536 xmlChar *buf;
2537
2538 if (writer == NULL)
2539 return -1;
2540
2541 buf = xmlTextWriterVSprintf(format, argptr);
2542 if (buf == 0)
2543 return 0;
2544
2545 rc = xmlTextWriterWritePI(writer, target, buf);
2546
2547 xmlFree(buf);
2548 return rc;
2549}
2550
2551/**
2552 * xmlTextWriterWritePI:
2553 * @writer: the xmlTextWriterPtr
2554 * @target: PI target
2555 * @content: PI content
2556 *
2557 * Write an xml PI.
2558 *
2559 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2560 */
2561int
2562xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2563 const xmlChar * content)
2564{
2565 int count;
2566 int sum;
2567
2568 sum = 0;
2569 count = xmlTextWriterStartPI(writer, target);
2570 if (count == -1)
2571 return -1;
2572 sum += count;
2573 if (content != 0) {
2574 count = xmlTextWriterWriteString(writer, content);
2575 if (count == -1)
2576 return -1;
2577 sum += count;
2578 }
2579 count = xmlTextWriterEndPI(writer);
2580 if (count == -1)
2581 return -1;
2582 sum += count;
2583
2584 return sum;
2585}
2586
2587/**
2588 * xmlTextWriterStartCDATA:
2589 * @writer: the xmlTextWriterPtr
2590 *
2591 * Start an xml CDATA section.
2592 *
2593 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2594 */
2595int
2596xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2597{
2598 int count;
2599 int sum;
2600 xmlLinkPtr lk;
2601 xmlTextWriterStackEntry *p;
2602
2603 if (writer == NULL)
2604 return -1;
2605
2606 sum = 0;
2607 lk = xmlListFront(writer->nodes);
2608 if (lk != 0) {
2609 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2610 if (p != 0) {
2611 switch (p->state) {
2612 case XML_TEXTWRITER_NONE:
2613 case XML_TEXTWRITER_PI:
2614 case XML_TEXTWRITER_PI_TEXT:
2615 break;
2616 case XML_TEXTWRITER_ATTRIBUTE:
2617 count = xmlTextWriterEndAttribute(writer);
2618 if (count < 0)
2619 return -1;
2620 sum += count;
2621 /* fallthrough */
2622 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002623 /* Output namespace declarations */
2624 count = xmlTextWriterOutputNSDecl(writer);
2625 if (count < 0)
2626 return -1;
2627 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002628 count = xmlOutputBufferWriteString(writer->out, ">");
2629 if (count < 0)
2630 return -1;
2631 sum += count;
2632 p->state = XML_TEXTWRITER_TEXT;
2633 break;
2634 case XML_TEXTWRITER_CDATA:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002635 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002636 "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2637 return -1;
2638 default:
2639 return -1;
2640 }
2641 }
2642 }
2643
2644 p = (xmlTextWriterStackEntry *)
2645 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2646 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002647 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002648 "xmlTextWriterStartCDATA : out of memory!\n");
2649 return -1;
2650 }
2651
Daniel Veillard75e389d2005-07-29 22:02:24 +00002652 p->name = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002653 p->state = XML_TEXTWRITER_CDATA;
2654
2655 xmlListPushFront(writer->nodes, p);
2656
2657 count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2658 if (count < 0)
2659 return -1;
2660 sum += count;
2661
2662 return sum;
2663}
2664
2665/**
2666 * xmlTextWriterEndCDATA:
2667 * @writer: the xmlTextWriterPtr
2668 *
2669 * End an xml CDATA section.
2670 *
2671 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2672 */
2673int
2674xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2675{
2676 int count;
2677 int sum;
2678 xmlLinkPtr lk;
2679 xmlTextWriterStackEntry *p;
2680
2681 if (writer == NULL)
2682 return -1;
2683
2684 lk = xmlListFront(writer->nodes);
2685 if (lk == 0)
2686 return -1;
2687
2688 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2689 if (p == 0)
2690 return -1;
2691
2692 sum = 0;
2693 switch (p->state) {
2694 case XML_TEXTWRITER_CDATA:
2695 count = xmlOutputBufferWriteString(writer->out, "]]>");
2696 if (count < 0)
2697 return -1;
2698 sum += count;
2699 break;
2700 default:
2701 return -1;
2702 }
2703
2704 xmlListPopFront(writer->nodes);
2705 return sum;
2706}
2707
2708/**
2709 * xmlTextWriterWriteFormatCDATA:
2710 * @writer: the xmlTextWriterPtr
2711 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002712 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002713 *
2714 * Write a formatted xml CDATA.
2715 *
2716 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2717 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002718int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002719xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2720 ...)
2721{
2722 int rc;
2723 va_list ap;
2724
2725 va_start(ap, format);
2726
2727 rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2728
2729 va_end(ap);
2730 return rc;
2731}
2732
2733/**
2734 * xmlTextWriterWriteVFormatCDATA:
2735 * @writer: the xmlTextWriterPtr
2736 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002737 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002738 *
2739 * Write a formatted xml CDATA.
2740 *
2741 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2742 */
2743int
2744xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2745 va_list argptr)
2746{
2747 int rc;
2748 xmlChar *buf;
2749
2750 if (writer == NULL)
2751 return -1;
2752
2753 buf = xmlTextWriterVSprintf(format, argptr);
2754 if (buf == 0)
2755 return 0;
2756
2757 rc = xmlTextWriterWriteCDATA(writer, buf);
2758
2759 xmlFree(buf);
2760 return rc;
2761}
2762
2763/**
2764 * xmlTextWriterWriteCDATA:
2765 * @writer: the xmlTextWriterPtr
2766 * @content: CDATA content
2767 *
2768 * Write an xml CDATA.
2769 *
2770 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2771 */
2772int
2773xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2774{
2775 int count;
2776 int sum;
2777
2778 sum = 0;
2779 count = xmlTextWriterStartCDATA(writer);
2780 if (count == -1)
2781 return -1;
2782 sum += count;
2783 if (content != 0) {
2784 count = xmlTextWriterWriteString(writer, content);
2785 if (count == -1)
2786 return -1;
2787 sum += count;
2788 }
2789 count = xmlTextWriterEndCDATA(writer);
2790 if (count == -1)
2791 return -1;
2792 sum += count;
2793
2794 return sum;
2795}
2796
2797/**
2798 * xmlTextWriterStartDTD:
2799 * @writer: the xmlTextWriterPtr
2800 * @name: the name of the DTD
2801 * @pubid: the public identifier, which is an alternative to the system identifier
2802 * @sysid: the system identifier, which is the URI of the DTD
2803 *
2804 * Start an xml DTD.
2805 *
2806 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2807 */
2808int
2809xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2810 const xmlChar * name,
2811 const xmlChar * pubid, const xmlChar * sysid)
2812{
2813 int count;
2814 int sum;
2815 xmlLinkPtr lk;
2816 xmlTextWriterStackEntry *p;
2817
2818 if (writer == NULL || name == NULL || *name == '\0')
2819 return -1;
2820
2821 sum = 0;
2822 lk = xmlListFront(writer->nodes);
Daniel Veillardab69f362004-02-17 11:40:32 +00002823 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002824 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002825 "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2826 return -1;
2827 }
2828
2829 p = (xmlTextWriterStackEntry *)
2830 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2831 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002832 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002833 "xmlTextWriterStartDTD : out of memory!\n");
2834 return -1;
2835 }
2836
2837 p->name = xmlStrdup(name);
2838 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002839 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002840 "xmlTextWriterStartDTD : out of memory!\n");
2841 xmlFree(p);
2842 return -1;
2843 }
2844 p->state = XML_TEXTWRITER_DTD;
2845
2846 xmlListPushFront(writer->nodes, p);
2847
2848 count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2849 if (count < 0)
2850 return -1;
2851 sum += count;
2852 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2853 if (count < 0)
2854 return -1;
2855 sum += count;
2856
2857 if (pubid != 0) {
2858 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002859 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002860 "xmlTextWriterStartDTD : system identifier needed!\n");
2861 return -1;
2862 }
2863
Daniel Veillard500a1de2004-03-22 15:22:58 +00002864 if (writer->indent)
2865 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2866 else
2867 count = xmlOutputBufferWrite(writer->out, 1, " ");
2868 if (count < 0)
2869 return -1;
2870 sum += count;
2871
2872 count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2873 if (count < 0)
2874 return -1;
2875 sum += count;
2876
2877 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002878 if (count < 0)
2879 return -1;
2880 sum += count;
2881
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002882 count =
2883 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002884 if (count < 0)
2885 return -1;
2886 sum += count;
2887
Daniel Veillard500a1de2004-03-22 15:22:58 +00002888 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002889 if (count < 0)
2890 return -1;
2891 sum += count;
2892 }
2893
2894 if (sysid != 0) {
2895 if (pubid == 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00002896 if (writer->indent)
2897 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2898 else
2899 count = xmlOutputBufferWrite(writer->out, 1, " ");
2900 if (count < 0)
2901 return -1;
2902 sum += count;
2903 count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2904 if (count < 0)
2905 return -1;
2906 sum += count;
Rob Richardsffe47fe2005-12-09 17:52:21 +00002907 } else {
2908 if (writer->indent)
Daniel Veillard500a1de2004-03-22 15:22:58 +00002909 count = xmlOutputBufferWriteString(writer->out, "\n ");
Rob Richardsffe47fe2005-12-09 17:52:21 +00002910 else
2911 count = xmlOutputBufferWrite(writer->out, 1, " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00002912 if (count < 0)
2913 return -1;
2914 sum += count;
2915 }
2916
Daniel Veillard500a1de2004-03-22 15:22:58 +00002917 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002918 if (count < 0)
2919 return -1;
2920 sum += count;
2921
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002922 count =
2923 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002924 if (count < 0)
2925 return -1;
2926 sum += count;
2927
Daniel Veillard500a1de2004-03-22 15:22:58 +00002928 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002929 if (count < 0)
2930 return -1;
2931 sum += count;
2932 }
2933
2934 return sum;
2935}
2936
2937/**
2938 * xmlTextWriterEndDTD:
2939 * @writer: the xmlTextWriterPtr
2940 *
2941 * End an xml DTD.
2942 *
2943 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2944 */
2945int
2946xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2947{
Daniel Veillard500a1de2004-03-22 15:22:58 +00002948 int loop;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002949 int count;
2950 int sum;
2951 xmlLinkPtr lk;
2952 xmlTextWriterStackEntry *p;
2953
2954 if (writer == NULL)
2955 return -1;
2956
2957 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002958 loop = 1;
2959 while (loop) {
2960 lk = xmlListFront(writer->nodes);
2961 if (lk == NULL)
Daniel Veillard1d211e22003-10-20 22:32:39 +00002962 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002963 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2964 if (p == 0)
2965 break;
2966 switch (p->state) {
2967 case XML_TEXTWRITER_DTD_TEXT:
2968 count = xmlOutputBufferWriteString(writer->out, "]");
2969 if (count < 0)
2970 return -1;
2971 sum += count;
2972 /* fallthrough */
2973 case XML_TEXTWRITER_DTD:
2974 count = xmlOutputBufferWriteString(writer->out, ">");
2975
2976 if (writer->indent) {
2977 if (count < 0)
2978 return -1;
2979 sum += count;
2980 count = xmlOutputBufferWriteString(writer->out, "\n");
2981 }
2982
2983 xmlListPopFront(writer->nodes);
2984 break;
2985 case XML_TEXTWRITER_DTD_ELEM:
2986 case XML_TEXTWRITER_DTD_ELEM_TEXT:
2987 count = xmlTextWriterEndDTDElement(writer);
2988 break;
2989 case XML_TEXTWRITER_DTD_ATTL:
2990 case XML_TEXTWRITER_DTD_ATTL_TEXT:
2991 count = xmlTextWriterEndDTDAttlist(writer);
2992 break;
2993 case XML_TEXTWRITER_DTD_ENTY:
2994 case XML_TEXTWRITER_DTD_PENT:
2995 case XML_TEXTWRITER_DTD_ENTY_TEXT:
2996 count = xmlTextWriterEndDTDEntity(writer);
2997 break;
2998 case XML_TEXTWRITER_COMMENT:
2999 count = xmlTextWriterEndComment(writer);
3000 break;
3001 default:
3002 loop = 0;
3003 continue;
3004 }
3005
3006 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00003007 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003008 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003009 }
3010
Daniel Veillard1d211e22003-10-20 22:32:39 +00003011 return sum;
3012}
3013
3014/**
3015 * xmlTextWriterWriteFormatDTD:
3016 * @writer: the xmlTextWriterPtr
3017 * @name: the name of the DTD
3018 * @pubid: the public identifier, which is an alternative to the system identifier
3019 * @sysid: the system identifier, which is the URI of the DTD
3020 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003021 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00003022 *
3023 * Write a DTD with a formatted markup declarations part.
3024 *
3025 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3026 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003027int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003028xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3029 const xmlChar * name,
3030 const xmlChar * pubid,
3031 const xmlChar * sysid, const char *format, ...)
3032{
3033 int rc;
3034 va_list ap;
3035
3036 va_start(ap, format);
3037
3038 rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3039 ap);
3040
3041 va_end(ap);
3042 return rc;
3043}
3044
3045/**
3046 * xmlTextWriterWriteVFormatDTD:
3047 * @writer: the xmlTextWriterPtr
3048 * @name: the name of the DTD
3049 * @pubid: the public identifier, which is an alternative to the system identifier
3050 * @sysid: the system identifier, which is the URI of the DTD
3051 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003052 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00003053 *
3054 * Write a DTD with a formatted markup declarations part.
3055 *
3056 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3057 */
3058int
3059xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3060 const xmlChar * name,
3061 const xmlChar * pubid,
3062 const xmlChar * sysid,
3063 const char *format, va_list argptr)
3064{
3065 int rc;
3066 xmlChar *buf;
3067
3068 if (writer == NULL)
3069 return -1;
3070
3071 buf = xmlTextWriterVSprintf(format, argptr);
3072 if (buf == 0)
3073 return 0;
3074
3075 rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3076
3077 xmlFree(buf);
3078 return rc;
3079}
3080
3081/**
3082 * xmlTextWriterWriteDTD:
3083 * @writer: the xmlTextWriterPtr
3084 * @name: the name of the DTD
3085 * @pubid: the public identifier, which is an alternative to the system identifier
3086 * @sysid: the system identifier, which is the URI of the DTD
William M. Brackb1d53162003-11-18 06:54:40 +00003087 * @subset: string content of the DTD
Daniel Veillard1d211e22003-10-20 22:32:39 +00003088 *
3089 * Write a DTD.
3090 *
3091 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3092 */
3093int
3094xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3095 const xmlChar * name,
3096 const xmlChar * pubid,
3097 const xmlChar * sysid, const xmlChar * subset)
3098{
3099 int count;
3100 int sum;
3101
3102 sum = 0;
3103 count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3104 if (count == -1)
3105 return -1;
3106 sum += count;
3107 if (subset != 0) {
3108 count = xmlTextWriterWriteString(writer, subset);
3109 if (count == -1)
3110 return -1;
3111 sum += count;
3112 }
3113 count = xmlTextWriterEndDTD(writer);
3114 if (count == -1)
3115 return -1;
3116 sum += count;
3117
3118 return sum;
3119}
3120
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003121/**
3122 * xmlTextWriterStartDTDElement:
3123 * @writer: the xmlTextWriterPtr
3124 * @name: the name of the DTD element
3125 *
3126 * Start an xml DTD element.
3127 *
3128 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3129 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003130int
3131xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3132{
3133 int count;
3134 int sum;
3135 xmlLinkPtr lk;
3136 xmlTextWriterStackEntry *p;
3137
3138 if (writer == NULL || name == NULL || *name == '\0')
3139 return -1;
3140
3141 sum = 0;
3142 lk = xmlListFront(writer->nodes);
3143 if (lk == 0) {
3144 return -1;
3145 }
3146
3147 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003148 if (p != 0) {
3149 switch (p->state) {
3150 case XML_TEXTWRITER_DTD:
3151 count = xmlOutputBufferWriteString(writer->out, " [");
3152 if (count < 0)
3153 return -1;
3154 sum += count;
3155 if (writer->indent) {
3156 count = xmlOutputBufferWriteString(writer->out, "\n");
3157 if (count < 0)
3158 return -1;
3159 sum += count;
3160 }
3161 p->state = XML_TEXTWRITER_DTD_TEXT;
3162 /* fallthrough */
3163 case XML_TEXTWRITER_DTD_TEXT:
3164 case XML_TEXTWRITER_NONE:
3165 break;
3166 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003167 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003168 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003169 }
3170
3171 p = (xmlTextWriterStackEntry *)
3172 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3173 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003174 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003175 "xmlTextWriterStartDTDElement : out of memory!\n");
3176 return -1;
3177 }
3178
3179 p->name = xmlStrdup(name);
3180 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003181 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003182 "xmlTextWriterStartDTDElement : out of memory!\n");
3183 xmlFree(p);
3184 return -1;
3185 }
3186 p->state = XML_TEXTWRITER_DTD_ELEM;
3187
3188 xmlListPushFront(writer->nodes, p);
3189
Daniel Veillard500a1de2004-03-22 15:22:58 +00003190 if (writer->indent) {
3191 count = xmlTextWriterWriteIndent(writer);
3192 if (count < 0)
3193 return -1;
3194 sum += count;
3195 }
3196
Daniel Veillard1d211e22003-10-20 22:32:39 +00003197 count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3198 if (count < 0)
3199 return -1;
3200 sum += count;
3201 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3202 if (count < 0)
3203 return -1;
3204 sum += count;
3205
3206 return sum;
3207}
3208
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003209/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003210 * xmlTextWriterEndDTDElement:
3211 * @writer: the xmlTextWriterPtr
3212 *
3213 * End an xml DTD element.
3214 *
3215 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3216 */
3217int
3218xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3219{
3220 int count;
3221 int sum;
3222 xmlLinkPtr lk;
3223 xmlTextWriterStackEntry *p;
3224
3225 if (writer == NULL)
3226 return -1;
3227
3228 sum = 0;
3229 lk = xmlListFront(writer->nodes);
3230 if (lk == 0)
3231 return -1;
3232
3233 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3234 if (p == 0)
3235 return -1;
3236
3237 switch (p->state) {
3238 case XML_TEXTWRITER_DTD_ELEM:
3239 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3240 count = xmlOutputBufferWriteString(writer->out, ">");
3241 if (count < 0)
3242 return -1;
3243 sum += count;
3244 break;
3245 default:
3246 return -1;
3247 }
3248
3249 if (writer->indent) {
3250 count = xmlOutputBufferWriteString(writer->out, "\n");
3251 if (count < 0)
3252 return -1;
3253 sum += count;
3254 }
3255
3256 xmlListPopFront(writer->nodes);
3257 return sum;
3258}
3259
3260/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003261 * xmlTextWriterWriteFormatDTDElement:
3262 * @writer: the xmlTextWriterPtr
3263 * @name: the name of the DTD element
3264 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003265 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003266 *
3267 * Write a formatted DTD element.
3268 *
3269 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3270 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003271int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003272xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3273 const xmlChar * name,
3274 const char *format, ...)
3275{
3276 int rc;
3277 va_list ap;
3278
3279 va_start(ap, format);
3280
3281 rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3282
3283 va_end(ap);
3284 return rc;
3285}
3286
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003287/**
3288 * xmlTextWriterWriteVFormatDTDElement:
3289 * @writer: the xmlTextWriterPtr
3290 * @name: the name of the DTD element
3291 * @format: format string (see printf)
3292 * @argptr: pointer to the first member of the variable argument list.
3293 *
3294 * Write a formatted DTD element.
3295 *
3296 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3297 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003298int
3299xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3300 const xmlChar * name,
3301 const char *format, va_list argptr)
3302{
3303 int rc;
3304 xmlChar *buf;
3305
3306 if (writer == NULL)
3307 return -1;
3308
3309 buf = xmlTextWriterVSprintf(format, argptr);
3310 if (buf == 0)
3311 return 0;
3312
3313 rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3314
3315 xmlFree(buf);
3316 return rc;
3317}
3318
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003319/**
3320 * xmlTextWriterWriteDTDElement:
3321 * @writer: the xmlTextWriterPtr
3322 * @name: the name of the DTD element
3323 * @content: content of the element
3324 *
3325 * Write a DTD element.
3326 *
3327 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3328 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003329int
3330xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3331 const xmlChar * name, const xmlChar * content)
3332{
3333 int count;
3334 int sum;
3335
3336 if (content == NULL)
3337 return -1;
3338
3339 sum = 0;
3340 count = xmlTextWriterStartDTDElement(writer, name);
3341 if (count == -1)
3342 return -1;
3343 sum += count;
3344
Daniel Veillard1d211e22003-10-20 22:32:39 +00003345 count = xmlTextWriterWriteString(writer, content);
3346 if (count == -1)
3347 return -1;
3348 sum += count;
3349
3350 count = xmlTextWriterEndDTDElement(writer);
3351 if (count == -1)
3352 return -1;
3353 sum += count;
3354
3355 return sum;
3356}
3357
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003358/**
3359 * xmlTextWriterStartDTDAttlist:
3360 * @writer: the xmlTextWriterPtr
3361 * @name: the name of the DTD ATTLIST
3362 *
3363 * Start an xml DTD ATTLIST.
3364 *
3365 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3366 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003367int
3368xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3369{
3370 int count;
3371 int sum;
3372 xmlLinkPtr lk;
3373 xmlTextWriterStackEntry *p;
3374
3375 if (writer == NULL || name == NULL || *name == '\0')
3376 return -1;
3377
3378 sum = 0;
3379 lk = xmlListFront(writer->nodes);
3380 if (lk == 0) {
3381 return -1;
3382 }
3383
3384 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003385 if (p != 0) {
3386 switch (p->state) {
3387 case XML_TEXTWRITER_DTD:
3388 count = xmlOutputBufferWriteString(writer->out, " [");
3389 if (count < 0)
3390 return -1;
3391 sum += count;
3392 if (writer->indent) {
3393 count = xmlOutputBufferWriteString(writer->out, "\n");
3394 if (count < 0)
3395 return -1;
3396 sum += count;
3397 }
3398 p->state = XML_TEXTWRITER_DTD_TEXT;
3399 /* fallthrough */
3400 case XML_TEXTWRITER_DTD_TEXT:
3401 case XML_TEXTWRITER_NONE:
3402 break;
3403 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003404 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003405 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003406 }
3407
3408 p = (xmlTextWriterStackEntry *)
3409 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3410 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003411 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003412 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3413 return -1;
3414 }
3415
3416 p->name = xmlStrdup(name);
3417 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003418 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003419 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3420 xmlFree(p);
3421 return -1;
3422 }
3423 p->state = XML_TEXTWRITER_DTD_ATTL;
3424
3425 xmlListPushFront(writer->nodes, p);
3426
Daniel Veillard500a1de2004-03-22 15:22:58 +00003427 if (writer->indent) {
3428 count = xmlTextWriterWriteIndent(writer);
3429 if (count < 0)
3430 return -1;
3431 sum += count;
3432 }
3433
Daniel Veillard1d211e22003-10-20 22:32:39 +00003434 count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3435 if (count < 0)
3436 return -1;
3437 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +00003438 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003439 if (count < 0)
3440 return -1;
3441 sum += count;
3442
3443 return sum;
3444}
3445
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003446/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003447 * xmlTextWriterEndDTDAttlist:
3448 * @writer: the xmlTextWriterPtr
3449 *
3450 * End an xml DTD attribute list.
3451 *
3452 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3453 */
3454int
3455xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3456{
3457 int count;
3458 int sum;
3459 xmlLinkPtr lk;
3460 xmlTextWriterStackEntry *p;
3461
3462 if (writer == NULL)
3463 return -1;
3464
3465 sum = 0;
3466 lk = xmlListFront(writer->nodes);
3467 if (lk == 0)
3468 return -1;
3469
3470 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3471 if (p == 0)
3472 return -1;
3473
3474 switch (p->state) {
3475 case XML_TEXTWRITER_DTD_ATTL:
3476 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3477 count = xmlOutputBufferWriteString(writer->out, ">");
3478 if (count < 0)
3479 return -1;
3480 sum += count;
3481 break;
3482 default:
3483 return -1;
3484 }
3485
3486 if (writer->indent) {
3487 count = xmlOutputBufferWriteString(writer->out, "\n");
3488 if (count < 0)
3489 return -1;
3490 sum += count;
3491 }
3492
3493 xmlListPopFront(writer->nodes);
3494 return sum;
3495}
3496
3497/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003498 * xmlTextWriterWriteFormatDTDAttlist:
3499 * @writer: the xmlTextWriterPtr
3500 * @name: the name of the DTD ATTLIST
3501 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003502 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003503 *
3504 * Write a formatted DTD ATTLIST.
3505 *
3506 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3507 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003508int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003509xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3510 const xmlChar * name,
3511 const char *format, ...)
3512{
3513 int rc;
3514 va_list ap;
3515
3516 va_start(ap, format);
3517
3518 rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3519
3520 va_end(ap);
3521 return rc;
3522}
3523
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003524/**
3525 * xmlTextWriterWriteVFormatDTDAttlist:
3526 * @writer: the xmlTextWriterPtr
3527 * @name: the name of the DTD ATTLIST
3528 * @format: format string (see printf)
3529 * @argptr: pointer to the first member of the variable argument list.
3530 *
3531 * Write a formatted DTD ATTLIST.
3532 *
3533 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3534 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003535int
3536xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3537 const xmlChar * name,
3538 const char *format, va_list argptr)
3539{
3540 int rc;
3541 xmlChar *buf;
3542
3543 if (writer == NULL)
3544 return -1;
3545
3546 buf = xmlTextWriterVSprintf(format, argptr);
3547 if (buf == 0)
3548 return 0;
3549
3550 rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3551
3552 xmlFree(buf);
3553 return rc;
3554}
3555
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003556/**
3557 * xmlTextWriterWriteDTDAttlist:
3558 * @writer: the xmlTextWriterPtr
3559 * @name: the name of the DTD ATTLIST
3560 * @content: content of the ATTLIST
3561 *
3562 * Write a DTD ATTLIST.
3563 *
3564 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3565 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003566int
3567xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3568 const xmlChar * name, const xmlChar * content)
3569{
3570 int count;
3571 int sum;
3572
3573 if (content == NULL)
3574 return -1;
3575
3576 sum = 0;
3577 count = xmlTextWriterStartDTDAttlist(writer, name);
3578 if (count == -1)
3579 return -1;
3580 sum += count;
3581
Daniel Veillard1d211e22003-10-20 22:32:39 +00003582 count = xmlTextWriterWriteString(writer, content);
3583 if (count == -1)
3584 return -1;
3585 sum += count;
3586
3587 count = xmlTextWriterEndDTDAttlist(writer);
3588 if (count == -1)
3589 return -1;
3590 sum += count;
3591
3592 return sum;
3593}
3594
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003595/**
3596 * xmlTextWriterStartDTDEntity:
3597 * @writer: the xmlTextWriterPtr
3598 * @pe: TRUE if this is a parameter entity, FALSE if not
3599 * @name: the name of the DTD ATTLIST
3600 *
3601 * Start an xml DTD ATTLIST.
3602 *
3603 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3604 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003605int
3606xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3607 int pe, const xmlChar * name)
3608{
3609 int count;
3610 int sum;
3611 xmlLinkPtr lk;
3612 xmlTextWriterStackEntry *p;
3613
3614 if (writer == NULL || name == NULL || *name == '\0')
3615 return -1;
3616
3617 sum = 0;
3618 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003619 if (lk != 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00003620
Daniel Veillard500a1de2004-03-22 15:22:58 +00003621 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3622 if (p != 0) {
3623 switch (p->state) {
3624 case XML_TEXTWRITER_DTD:
3625 count = xmlOutputBufferWriteString(writer->out, " [");
3626 if (count < 0)
3627 return -1;
3628 sum += count;
3629 if (writer->indent) {
3630 count =
3631 xmlOutputBufferWriteString(writer->out, "\n");
3632 if (count < 0)
3633 return -1;
3634 sum += count;
3635 }
3636 p->state = XML_TEXTWRITER_DTD_TEXT;
3637 /* fallthrough */
3638 case XML_TEXTWRITER_DTD_TEXT:
3639 case XML_TEXTWRITER_NONE:
3640 break;
3641 default:
3642 return -1;
3643 }
3644 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003645 }
3646
3647 p = (xmlTextWriterStackEntry *)
3648 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3649 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003650 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003651 "xmlTextWriterStartDTDElement : out of memory!\n");
3652 return -1;
3653 }
3654
3655 p->name = xmlStrdup(name);
3656 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003657 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003658 "xmlTextWriterStartDTDElement : out of memory!\n");
3659 xmlFree(p);
3660 return -1;
3661 }
Daniel Veillard500a1de2004-03-22 15:22:58 +00003662
3663 if (pe != 0)
3664 p->state = XML_TEXTWRITER_DTD_PENT;
3665 else
3666 p->state = XML_TEXTWRITER_DTD_ENTY;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003667
3668 xmlListPushFront(writer->nodes, p);
3669
Daniel Veillard500a1de2004-03-22 15:22:58 +00003670 if (writer->indent) {
3671 count = xmlTextWriterWriteIndent(writer);
3672 if (count < 0)
3673 return -1;
3674 sum += count;
3675 }
3676
Daniel Veillard1d211e22003-10-20 22:32:39 +00003677 count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3678 if (count < 0)
3679 return -1;
3680 sum += count;
3681
3682 if (pe != 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00003683 count = xmlOutputBufferWriteString(writer->out, "% ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003684 if (count < 0)
3685 return -1;
3686 sum += count;
3687 }
3688
Daniel Veillardab69f362004-02-17 11:40:32 +00003689 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003690 if (count < 0)
3691 return -1;
3692 sum += count;
3693
3694 return sum;
3695}
3696
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003697/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003698 * xmlTextWriterEndDTDEntity:
3699 * @writer: the xmlTextWriterPtr
3700 *
3701 * End an xml DTD entity.
3702 *
3703 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3704 */
3705int
3706xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3707{
3708 int count;
3709 int sum;
3710 xmlLinkPtr lk;
3711 xmlTextWriterStackEntry *p;
3712
3713 if (writer == NULL)
3714 return -1;
3715
3716 sum = 0;
3717 lk = xmlListFront(writer->nodes);
3718 if (lk == 0)
3719 return -1;
3720
3721 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3722 if (p == 0)
3723 return -1;
3724
3725 switch (p->state) {
3726 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3727 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3728 if (count < 0)
3729 return -1;
3730 sum += count;
3731 case XML_TEXTWRITER_DTD_ENTY:
3732 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard500a1de2004-03-22 15:22:58 +00003733 count = xmlOutputBufferWriteString(writer->out, ">");
3734 if (count < 0)
3735 return -1;
3736 sum += count;
3737 break;
3738 default:
3739 return -1;
3740 }
3741
3742 if (writer->indent) {
3743 count = xmlOutputBufferWriteString(writer->out, "\n");
3744 if (count < 0)
3745 return -1;
3746 sum += count;
3747 }
3748
3749 xmlListPopFront(writer->nodes);
3750 return sum;
3751}
3752
3753/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003754 * xmlTextWriterWriteFormatDTDInternalEntity:
3755 * @writer: the xmlTextWriterPtr
3756 * @pe: TRUE if this is a parameter entity, FALSE if not
3757 * @name: the name of the DTD entity
3758 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003759 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003760 *
3761 * Write a formatted DTD internal entity.
3762 *
3763 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3764 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003765int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003766xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3767 int pe,
3768 const xmlChar * name,
3769 const char *format, ...)
3770{
3771 int rc;
3772 va_list ap;
3773
3774 va_start(ap, format);
3775
3776 rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3777 format, ap);
3778
3779 va_end(ap);
3780 return rc;
3781}
3782
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003783/**
3784 * xmlTextWriterWriteVFormatDTDInternalEntity:
3785 * @writer: the xmlTextWriterPtr
3786 * @pe: TRUE if this is a parameter entity, FALSE if not
3787 * @name: the name of the DTD entity
3788 * @format: format string (see printf)
3789 * @argptr: pointer to the first member of the variable argument list.
3790 *
3791 * Write a formatted DTD internal entity.
3792 *
3793 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3794 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003795int
3796xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3797 int pe,
3798 const xmlChar * name,
3799 const char *format,
3800 va_list argptr)
3801{
3802 int rc;
3803 xmlChar *buf;
3804
3805 if (writer == NULL)
3806 return -1;
3807
3808 buf = xmlTextWriterVSprintf(format, argptr);
3809 if (buf == 0)
3810 return 0;
3811
3812 rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3813
3814 xmlFree(buf);
3815 return rc;
3816}
3817
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003818/**
3819 * xmlTextWriterWriteDTDEntity:
3820 * @writer: the xmlTextWriterPtr
3821 * @pe: TRUE if this is a parameter entity, FALSE if not
3822 * @name: the name of the DTD entity
3823 * @pubid: the public identifier, which is an alternative to the system identifier
3824 * @sysid: the system identifier, which is the URI of the DTD
3825 * @ndataid: the xml notation name.
3826 * @content: content of the entity
3827 *
3828 * Write a DTD entity.
3829 *
3830 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3831 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003832int
3833xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3834 int pe,
3835 const xmlChar * name,
3836 const xmlChar * pubid,
3837 const xmlChar * sysid,
3838 const xmlChar * ndataid,
3839 const xmlChar * content)
3840{
Daniel Veillard500a1de2004-03-22 15:22:58 +00003841 if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003842 return -1;
3843 if ((pe != 0) && (ndataid != NULL))
3844 return -1;
3845
Daniel Veillard500a1de2004-03-22 15:22:58 +00003846 if ((pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003847 return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3848 content);
3849
3850 return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3851 sysid, ndataid);
3852}
3853
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003854/**
3855 * xmlTextWriterWriteDTDInternalEntity:
3856 * @writer: the xmlTextWriterPtr
3857 * @pe: TRUE if this is a parameter entity, FALSE if not
3858 * @name: the name of the DTD entity
3859 * @content: content of the entity
3860 *
3861 * Write a DTD internal entity.
3862 *
3863 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3864 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003865int
3866xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3867 int pe,
3868 const xmlChar * name,
3869 const xmlChar * content)
3870{
3871 int count;
3872 int sum;
3873
3874 if ((name == NULL) || (*name == '\0') || (content == NULL))
3875 return -1;
3876
3877 sum = 0;
3878 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3879 if (count == -1)
3880 return -1;
3881 sum += count;
3882
Daniel Veillard1d211e22003-10-20 22:32:39 +00003883 count = xmlTextWriterWriteString(writer, content);
3884 if (count == -1)
3885 return -1;
3886 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003887
3888 count = xmlTextWriterEndDTDEntity(writer);
3889 if (count == -1)
3890 return -1;
3891 sum += count;
3892
3893 return sum;
3894}
3895
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003896/**
3897 * xmlTextWriterWriteDTDExternalEntity:
3898 * @writer: the xmlTextWriterPtr
3899 * @pe: TRUE if this is a parameter entity, FALSE if not
3900 * @name: the name of the DTD entity
3901 * @pubid: the public identifier, which is an alternative to the system identifier
3902 * @sysid: the system identifier, which is the URI of the DTD
3903 * @ndataid: the xml notation name.
3904 *
Daniel Veillard500a1de2004-03-22 15:22:58 +00003905 * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003906 *
3907 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3908 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003909int
3910xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3911 int pe,
3912 const xmlChar * name,
3913 const xmlChar * pubid,
3914 const xmlChar * sysid,
3915 const xmlChar * ndataid)
3916{
3917 int count;
3918 int sum;
3919
Daniel Veillard500a1de2004-03-22 15:22:58 +00003920 if (((pubid == NULL) && (sysid == NULL)))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003921 return -1;
3922 if ((pe != 0) && (ndataid != NULL))
3923 return -1;
3924
3925 sum = 0;
3926 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3927 if (count == -1)
3928 return -1;
3929 sum += count;
3930
Daniel Veillard500a1de2004-03-22 15:22:58 +00003931 count =
3932 xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3933 ndataid);
3934 if (count < 0)
3935 return -1;
3936 sum += count;
3937
3938 count = xmlTextWriterEndDTDEntity(writer);
3939 if (count == -1)
3940 return -1;
3941 sum += count;
3942
3943 return sum;
3944}
3945
3946/**
3947 * xmlTextWriterWriteDTDExternalEntityContents:
3948 * @writer: the xmlTextWriterPtr
3949 * @pubid: the public identifier, which is an alternative to the system identifier
3950 * @sysid: the system identifier, which is the URI of the DTD
3951 * @ndataid: the xml notation name.
3952 *
3953 * Write the contents of a DTD external entity.
3954 *
3955 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3956 */
3957int
3958xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3959 const xmlChar * pubid,
3960 const xmlChar * sysid,
3961 const xmlChar * ndataid)
3962{
3963 int count;
3964 int sum;
3965 xmlLinkPtr lk;
3966 xmlTextWriterStackEntry *p;
3967
3968 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003969 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003970 "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3971 return -1;
3972 }
3973
3974 sum = 0;
3975 lk = xmlListFront(writer->nodes);
3976 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003977 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003978 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
3979 return -1;
3980 }
3981
3982 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3983 if (p == 0)
3984 return -1;
3985
3986 switch (p->state) {
3987 case XML_TEXTWRITER_DTD_ENTY:
3988 break;
3989 case XML_TEXTWRITER_DTD_PENT:
3990 if (ndataid != NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003991 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003992 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
3993 return -1;
3994 }
3995 break;
3996 default:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003997 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003998 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
3999 return -1;
4000 }
4001
Daniel Veillard1d211e22003-10-20 22:32:39 +00004002 if (pubid != 0) {
4003 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004004 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004005 "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00004006 return -1;
4007 }
4008
4009 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4010 if (count < 0)
4011 return -1;
4012 sum += count;
4013
4014 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4015 if (count < 0)
4016 return -1;
4017 sum += count;
4018
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004019 count =
4020 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004021 if (count < 0)
4022 return -1;
4023 sum += count;
4024
4025 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4026 if (count < 0)
4027 return -1;
4028 sum += count;
4029 }
4030
4031 if (sysid != 0) {
4032 if (pubid == 0) {
4033 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4034 if (count < 0)
4035 return -1;
4036 sum += count;
4037 }
4038
4039 count = xmlOutputBufferWriteString(writer->out, " ");
4040 if (count < 0)
4041 return -1;
4042 sum += count;
4043
4044 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4045 if (count < 0)
4046 return -1;
4047 sum += count;
4048
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004049 count =
4050 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004051 if (count < 0)
4052 return -1;
4053 sum += count;
4054
4055 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4056 if (count < 0)
4057 return -1;
4058 sum += count;
4059 }
4060
4061 if (ndataid != NULL) {
4062 count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4063 if (count < 0)
4064 return -1;
4065 sum += count;
4066
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004067 count =
4068 xmlOutputBufferWriteString(writer->out,
4069 (const char *) ndataid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004070 if (count < 0)
4071 return -1;
4072 sum += count;
4073 }
4074
Daniel Veillard1d211e22003-10-20 22:32:39 +00004075 return sum;
4076}
4077
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004078/**
4079 * xmlTextWriterWriteDTDNotation:
4080 * @writer: the xmlTextWriterPtr
4081 * @name: the name of the xml notation
4082 * @pubid: the public identifier, which is an alternative to the system identifier
4083 * @sysid: the system identifier, which is the URI of the DTD
4084 *
4085 * Write a DTD entity.
4086 *
4087 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4088 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00004089int
4090xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4091 const xmlChar * name,
4092 const xmlChar * pubid, const xmlChar * sysid)
4093{
4094 int count;
4095 int sum;
4096 xmlLinkPtr lk;
4097 xmlTextWriterStackEntry *p;
4098
4099 if (writer == NULL || name == NULL || *name == '\0')
4100 return -1;
4101
4102 sum = 0;
4103 lk = xmlListFront(writer->nodes);
4104 if (lk == 0) {
4105 return -1;
4106 }
4107
4108 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00004109 if (p != 0) {
4110 switch (p->state) {
4111 case XML_TEXTWRITER_DTD:
4112 count = xmlOutputBufferWriteString(writer->out, " [");
4113 if (count < 0)
4114 return -1;
4115 sum += count;
4116 if (writer->indent) {
4117 count = xmlOutputBufferWriteString(writer->out, "\n");
4118 if (count < 0)
4119 return -1;
4120 sum += count;
4121 }
4122 p->state = XML_TEXTWRITER_DTD_TEXT;
4123 /* fallthrough */
4124 case XML_TEXTWRITER_DTD_TEXT:
4125 break;
4126 default:
4127 return -1;
4128 }
4129 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00004130
Daniel Veillard500a1de2004-03-22 15:22:58 +00004131 if (writer->indent) {
4132 count = xmlTextWriterWriteIndent(writer);
4133 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004134 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004135 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004136 }
4137
4138 count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4139 if (count < 0)
4140 return -1;
4141 sum += count;
4142 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4143 if (count < 0)
4144 return -1;
4145 sum += count;
4146
4147 if (pubid != 0) {
4148 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4149 if (count < 0)
4150 return -1;
4151 sum += count;
4152 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4153 if (count < 0)
4154 return -1;
4155 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004156 count =
4157 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004158 if (count < 0)
4159 return -1;
4160 sum += count;
4161 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4162 if (count < 0)
4163 return -1;
4164 sum += count;
4165 }
4166
4167 if (sysid != 0) {
4168 if (pubid == 0) {
4169 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4170 if (count < 0)
4171 return -1;
4172 sum += count;
4173 }
4174 count = xmlOutputBufferWriteString(writer->out, " ");
4175 if (count < 0)
4176 return -1;
4177 sum += count;
4178 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4179 if (count < 0)
4180 return -1;
4181 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004182 count =
4183 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004184 if (count < 0)
4185 return -1;
4186 sum += count;
4187 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4188 if (count < 0)
4189 return -1;
4190 sum += count;
4191 }
4192
4193 count = xmlOutputBufferWriteString(writer->out, ">");
4194 if (count < 0)
4195 return -1;
4196 sum += count;
4197
4198 return sum;
4199}
4200
4201/**
4202 * xmlTextWriterFlush:
4203 * @writer: the xmlTextWriterPtr
4204 *
4205 * Flush the output buffer.
4206 *
4207 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4208 */
4209int
4210xmlTextWriterFlush(xmlTextWriterPtr writer)
4211{
4212 int count;
4213
4214 if (writer == NULL)
4215 return -1;
4216
4217 if (writer->out == NULL)
4218 count = 0;
4219 else
4220 count = xmlOutputBufferFlush(writer->out);
4221
4222 return count;
4223}
4224
4225/**
4226 * misc
4227 */
4228
4229/**
4230 * xmlFreeTextWriterStackEntry:
4231 * @lk: the xmlLinkPtr
4232 *
4233 * Free callback for the xmlList.
4234 */
4235static void
4236xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4237{
4238 xmlTextWriterStackEntry *p;
4239
4240 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4241 if (p == 0)
4242 return;
4243
4244 if (p->name != 0)
4245 xmlFree(p->name);
4246 xmlFree(p);
4247}
4248
4249/**
4250 * xmlCmpTextWriterStackEntry:
4251 * @data0: the first data
4252 * @data1: the second data
4253 *
4254 * Compare callback for the xmlList.
4255 *
4256 * Returns -1, 0, 1
4257 */
4258static int
4259xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4260{
4261 xmlTextWriterStackEntry *p0;
4262 xmlTextWriterStackEntry *p1;
4263
4264 if (data0 == data1)
4265 return 0;
4266
4267 if (data0 == 0)
4268 return -1;
4269
4270 if (data1 == 0)
4271 return 1;
4272
4273 p0 = (xmlTextWriterStackEntry *) data0;
4274 p1 = (xmlTextWriterStackEntry *) data1;
4275
4276 return xmlStrcmp(p0->name, p1->name);
4277}
4278
4279/**
4280 * misc
4281 */
4282
4283/**
Rob Richardsb8769d62007-06-08 08:50:47 +00004284 * xmlTextWriterOutputNSDecl:
4285 * @writer: the xmlTextWriterPtr
4286 *
4287 * Output the current namespace declarations.
4288 */
4289static int
4290xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4291{
4292 xmlLinkPtr lk;
4293 xmlTextWriterNsStackEntry *np;
4294 int count;
4295 int sum;
4296
4297 sum = 0;
4298 while (!xmlListEmpty(writer->nsstack)) {
4299 xmlChar *namespaceURI = NULL;
4300 xmlChar *prefix = NULL;
4301
4302 lk = xmlListFront(writer->nsstack);
4303 np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4304
4305 if (np != 0) {
4306 namespaceURI = xmlStrdup(np->uri);
4307 prefix = xmlStrdup(np->prefix);
4308 }
4309
4310 xmlListPopFront(writer->nsstack);
4311
4312 if (np != 0) {
4313 count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4314 xmlFree(namespaceURI);
4315 xmlFree(prefix);
4316
4317 if (count < 0) {
4318 xmlListDelete(writer->nsstack);
4319 writer->nsstack = NULL;
4320 return -1;
4321 }
4322 sum += count;
4323 }
4324 }
4325 return sum;
4326}
4327
4328/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004329 * xmlFreeTextWriterNsStackEntry:
4330 * @lk: the xmlLinkPtr
4331 *
4332 * Free callback for the xmlList.
4333 */
4334static void
4335xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4336{
4337 xmlTextWriterNsStackEntry *p;
4338
4339 p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4340 if (p == 0)
4341 return;
4342
4343 if (p->prefix != 0)
4344 xmlFree(p->prefix);
4345 if (p->uri != 0)
4346 xmlFree(p->uri);
4347
4348 xmlFree(p);
4349}
4350
4351/**
4352 * xmlCmpTextWriterNsStackEntry:
4353 * @data0: the first data
4354 * @data1: the second data
4355 *
4356 * Compare callback for the xmlList.
4357 *
4358 * Returns -1, 0, 1
4359 */
4360static int
4361xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4362{
4363 xmlTextWriterNsStackEntry *p0;
4364 xmlTextWriterNsStackEntry *p1;
4365 int rc;
4366
4367 if (data0 == data1)
4368 return 0;
4369
4370 if (data0 == 0)
4371 return -1;
4372
4373 if (data1 == 0)
4374 return 1;
4375
4376 p0 = (xmlTextWriterNsStackEntry *) data0;
4377 p1 = (xmlTextWriterNsStackEntry *) data1;
4378
4379 rc = xmlStrcmp(p0->prefix, p1->prefix);
4380
Rob Richardsb8769d62007-06-08 08:50:47 +00004381 if ((rc != 0) || (p0->elem != p1->elem))
4382 rc = -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004383
4384 return rc;
4385}
4386
4387/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004388 * xmlTextWriterWriteDocCallback:
4389 * @context: the xmlBufferPtr
4390 * @str: the data to write
4391 * @len: the length of the data
4392 *
4393 * Write callback for the xmlOutputBuffer with target xmlBuffer
4394 *
4395 * Returns -1, 0, 1
4396 */
4397static int
4398xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
4399{
4400 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4401 int rc;
4402
Daniel Veillard1d913862003-11-21 00:28:39 +00004403 if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004404 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004405 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4406 rc);
4407 return -1;
4408 }
4409
4410 return len;
4411}
4412
4413/**
4414 * xmlTextWriterCloseDocCallback:
4415 * @context: the xmlBufferPtr
4416 *
4417 * Close callback for the xmlOutputBuffer with target xmlBuffer
4418 *
4419 * Returns -1, 0, 1
4420 */
4421static int
4422xmlTextWriterCloseDocCallback(void *context)
4423{
4424 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4425 int rc;
4426
4427 if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004428 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004429 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4430 rc);
4431 return -1;
4432 }
4433
4434 return 0;
4435}
4436
4437/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004438 * xmlTextWriterVSprintf:
4439 * @format: see printf
4440 * @argptr: pointer to the first member of the variable argument list.
4441 *
4442 * Utility function for formatted output
4443 *
4444 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4445 */
4446static xmlChar *
4447xmlTextWriterVSprintf(const char *format, va_list argptr)
4448{
4449 int size;
4450 int count;
4451 xmlChar *buf;
William M. Brackf4caa5e2005-10-20 09:04:05 +00004452 va_list locarg;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004453
4454 size = BUFSIZ;
4455 buf = (xmlChar *) xmlMalloc(size);
4456 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004457 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004458 "xmlTextWriterVSprintf : out of memory!\n");
4459 return NULL;
4460 }
4461
William M. Brackf4caa5e2005-10-20 09:04:05 +00004462 VA_COPY(locarg, argptr);
4463 while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004464 || (count == size - 1) || (count == size) || (count > size)) {
William M. Brackf4caa5e2005-10-20 09:04:05 +00004465 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004466 xmlFree(buf);
4467 size += BUFSIZ;
4468 buf = (xmlChar *) xmlMalloc(size);
4469 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004470 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004471 "xmlTextWriterVSprintf : out of memory!\n");
4472 return NULL;
4473 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004474 VA_COPY(locarg, argptr);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004475 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004476 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004477
4478 return buf;
4479}
4480
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004481/**
4482 * xmlTextWriterStartDocumentCallback:
4483 * @ctx: the user data (XML parser context)
4484 *
4485 * called at the start of document processing.
4486 */
4487static void
4488xmlTextWriterStartDocumentCallback(void *ctx)
4489{
4490 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4491 xmlDocPtr doc;
4492
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004493 if (ctxt->html) {
4494#ifdef LIBXML_HTML_ENABLED
4495 if (ctxt->myDoc == NULL)
4496 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4497 if (ctxt->myDoc == NULL) {
4498 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4499 ctxt->sax->error(ctxt->userData,
4500 "SAX.startDocument(): out of memory\n");
4501 ctxt->errNo = XML_ERR_NO_MEMORY;
4502 ctxt->instate = XML_PARSER_EOF;
4503 ctxt->disableSAX = 1;
4504 return;
4505 }
4506#else
Daniel Veillardd0cf7f62004-11-09 16:17:02 +00004507 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004508 "libxml2 built without HTML support\n");
4509 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4510 ctxt->instate = XML_PARSER_EOF;
4511 ctxt->disableSAX = 1;
4512 return;
4513#endif
4514 } else {
4515 doc = ctxt->myDoc;
4516 if (doc == NULL)
4517 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4518 if (doc != NULL) {
4519 if (doc->children == NULL) {
4520 if (ctxt->encoding != NULL)
4521 doc->encoding = xmlStrdup(ctxt->encoding);
4522 else
4523 doc->encoding = NULL;
4524 doc->standalone = ctxt->standalone;
4525 }
4526 } else {
4527 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4528 ctxt->sax->error(ctxt->userData,
4529 "SAX.startDocument(): out of memory\n");
4530 ctxt->errNo = XML_ERR_NO_MEMORY;
4531 ctxt->instate = XML_PARSER_EOF;
4532 ctxt->disableSAX = 1;
4533 return;
4534 }
4535 }
4536 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4537 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4538 ctxt->myDoc->URL =
4539 xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4540 if (ctxt->myDoc->URL == NULL)
4541 ctxt->myDoc->URL =
4542 xmlStrdup((const xmlChar *) ctxt->input->filename);
4543 }
4544}
4545
Daniel Veillard2cca4462004-01-02 20:04:23 +00004546/**
4547 * xmlTextWriterSetIndent:
4548 * @writer: the xmlTextWriterPtr
4549 * @indent: do indentation?
4550 *
4551 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4552 *
4553 * Returns -1 on error or 0 otherwise.
4554 */
4555int
Daniel Veillardab69f362004-02-17 11:40:32 +00004556xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004557{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004558 if ((writer == NULL) || (indent < 0))
Daniel Veillardab69f362004-02-17 11:40:32 +00004559 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004560
Daniel Veillardab69f362004-02-17 11:40:32 +00004561 writer->indent = indent;
4562 writer->doindent = 1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004563
Daniel Veillardab69f362004-02-17 11:40:32 +00004564 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004565}
4566
4567/**
4568 * xmlTextWriterSetIndentString:
4569 * @writer: the xmlTextWriterPtr
4570 * @str: the xmlChar string
4571 *
4572 * Set string indentation.
4573 *
4574 * Returns -1 on error or 0 otherwise.
4575 */
4576int
Daniel Veillardab69f362004-02-17 11:40:32 +00004577xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004578{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004579 if ((writer == NULL) || (!str))
Daniel Veillardab69f362004-02-17 11:40:32 +00004580 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004581
Daniel Veillardab69f362004-02-17 11:40:32 +00004582 if (writer->ichar != NULL)
4583 xmlFree(writer->ichar);
4584 writer->ichar = xmlStrdup(str);
4585
4586 if (!writer->ichar)
4587 return -1;
4588 else
4589 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004590}
4591
4592/**
4593 * xmlTextWriterWriteIndent:
4594 * @writer: the xmlTextWriterPtr
4595 *
4596 * Write indent string.
4597 *
4598 * Returns -1 on error or the number of strings written.
Daniel Veillardab69f362004-02-17 11:40:32 +00004599 */
Daniel Veillard2cca4462004-01-02 20:04:23 +00004600static int
Daniel Veillardab69f362004-02-17 11:40:32 +00004601xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004602{
Daniel Veillardab69f362004-02-17 11:40:32 +00004603 int lksize;
4604 int i;
4605 int ret;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004606
Daniel Veillardab69f362004-02-17 11:40:32 +00004607 lksize = xmlListSize(writer->nodes);
4608 if (lksize < 1)
4609 return (-1); /* list is empty */
4610 for (i = 0; i < (lksize - 1); i++) {
4611 ret = xmlOutputBufferWriteString(writer->out,
4612 (const char *) writer->ichar);
4613 if (ret == -1)
4614 return (-1);
4615 }
4616
4617 return (lksize - 1);
Daniel Veillard2cca4462004-01-02 20:04:23 +00004618}
4619
Daniel Veillard500a1de2004-03-22 15:22:58 +00004620/**
4621 * xmlTextWriterHandleStateDependencies:
4622 * @writer: the xmlTextWriterPtr
4623 * @p: the xmlTextWriterStackEntry
4624 *
4625 * Write state dependent strings.
4626 *
4627 * Returns -1 on error or the number of characters written.
4628 */
4629static int
4630xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4631 xmlTextWriterStackEntry * p)
4632{
4633 int count;
4634 int sum;
4635 char extra[3];
4636
4637 if (writer == NULL)
4638 return -1;
4639
4640 if (p == NULL)
4641 return 0;
4642
4643 sum = 0;
4644 extra[0] = extra[1] = extra[2] = '\0';
4645 if (p != 0) {
4646 sum = 0;
4647 switch (p->state) {
4648 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00004649 /* Output namespace declarations */
4650 count = xmlTextWriterOutputNSDecl(writer);
4651 if (count < 0)
4652 return -1;
4653 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004654 extra[0] = '>';
4655 p->state = XML_TEXTWRITER_TEXT;
4656 break;
4657 case XML_TEXTWRITER_PI:
4658 extra[0] = ' ';
4659 p->state = XML_TEXTWRITER_PI_TEXT;
4660 break;
4661 case XML_TEXTWRITER_DTD:
4662 extra[0] = ' ';
4663 extra[1] = '[';
4664 p->state = XML_TEXTWRITER_DTD_TEXT;
4665 break;
4666 case XML_TEXTWRITER_DTD_ELEM:
4667 extra[0] = ' ';
4668 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4669 break;
4670 case XML_TEXTWRITER_DTD_ATTL:
4671 extra[0] = ' ';
4672 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4673 break;
4674 case XML_TEXTWRITER_DTD_ENTY:
4675 case XML_TEXTWRITER_DTD_PENT:
4676 extra[0] = ' ';
4677 extra[1] = writer->qchar;
4678 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4679 break;
4680 default:
4681 break;
4682 }
4683 }
4684
4685 if (*extra != '\0') {
4686 count = xmlOutputBufferWriteString(writer->out, extra);
4687 if (count < 0)
4688 return -1;
4689 sum += count;
4690 }
4691
4692 return sum;
4693}
4694
Daniel Veillard5d4644e2005-04-01 13:11:58 +00004695#define bottom_xmlwriter
4696#include "elfgcchack.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +00004697#endif