blob: 4acd2fd581d6e79577270fff264a34d38ff0b527 [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
Daniel Veillarddbf54112012-07-16 14:54:45 +080024#include "buf.h"
25#include "enc.h"
26#include "save.h"
27
Daniel Veillard1d211e22003-10-20 22:32:39 +000028#define B64LINELEN 72
29#define B64CRLF "\r\n"
30
31/*
William M. Brackf4caa5e2005-10-20 09:04:05 +000032 * The following VA_COPY was coded following an example in
33 * the Samba project. It may not be sufficient for some
34 * esoteric implementations of va_list (i.e. it may need
35 * something involving a memcpy) but (hopefully) will be
36 * sufficient for libxml2.
37 */
38#ifndef VA_COPY
39 #ifdef HAVE_VA_COPY
40 #define VA_COPY(dest, src) va_copy(dest, src)
41 #else
42 #ifdef HAVE___VA_COPY
43 #define VA_COPY(dest,src) __va_copy(dest, src)
44 #else
45 #define VA_COPY(dest,src) (dest) = (src)
46 #endif
47 #endif
48#endif
49
50/*
Daniel Veillard1d211e22003-10-20 22:32:39 +000051 * Types are kept private
52 */
53typedef enum {
54 XML_TEXTWRITER_NONE = 0,
55 XML_TEXTWRITER_NAME,
56 XML_TEXTWRITER_ATTRIBUTE,
57 XML_TEXTWRITER_TEXT,
58 XML_TEXTWRITER_PI,
59 XML_TEXTWRITER_PI_TEXT,
60 XML_TEXTWRITER_CDATA,
61 XML_TEXTWRITER_DTD,
62 XML_TEXTWRITER_DTD_TEXT,
63 XML_TEXTWRITER_DTD_ELEM,
Daniel Veillard500a1de2004-03-22 15:22:58 +000064 XML_TEXTWRITER_DTD_ELEM_TEXT,
Daniel Veillard1d211e22003-10-20 22:32:39 +000065 XML_TEXTWRITER_DTD_ATTL,
Daniel Veillard500a1de2004-03-22 15:22:58 +000066 XML_TEXTWRITER_DTD_ATTL_TEXT,
67 XML_TEXTWRITER_DTD_ENTY, /* entity */
68 XML_TEXTWRITER_DTD_ENTY_TEXT,
69 XML_TEXTWRITER_DTD_PENT, /* parameter entity */
William M. Brack87640d52004-04-17 14:58:15 +000070 XML_TEXTWRITER_COMMENT
Daniel Veillard1d211e22003-10-20 22:32:39 +000071} xmlTextWriterState;
72
73typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
74
75struct _xmlTextWriterStackEntry {
76 xmlChar *name;
77 xmlTextWriterState state;
78};
79
80typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
81struct _xmlTextWriterNsStackEntry {
82 xmlChar *prefix;
83 xmlChar *uri;
84 xmlLinkPtr elem;
85};
86
87struct _xmlTextWriter {
Daniel Veillardab69f362004-02-17 11:40:32 +000088 xmlOutputBufferPtr out; /* output buffer */
89 xmlListPtr nodes; /* element name stack */
90 xmlListPtr nsstack; /* name spaces stack */
Daniel Veillard1d211e22003-10-20 22:32:39 +000091 int level;
Daniel Veillardab69f362004-02-17 11:40:32 +000092 int indent; /* enable indent */
93 int doindent; /* internal indent flag */
94 xmlChar *ichar; /* indent character */
95 char qchar; /* character used for quoting attribute values */
Daniel Veillard20c5e782004-01-21 09:57:31 +000096 xmlParserCtxtPtr ctxt;
Daniel Veillarda521d282004-11-09 14:59:59 +000097 int no_doc_free;
Rob Richards9db68f02006-08-16 22:48:51 +000098 xmlDocPtr doc;
Daniel Veillard1d211e22003-10-20 22:32:39 +000099};
100
101static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
102static int xmlCmpTextWriterStackEntry(const void *data0,
103 const void *data1);
Rob Richardsb8769d62007-06-08 08:50:47 +0000104static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000105static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
106static int xmlCmpTextWriterNsStackEntry(const void *data0,
107 const void *data1);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000108static int xmlTextWriterWriteDocCallback(void *context,
109 const xmlChar * str, int len);
110static int xmlTextWriterCloseDocCallback(void *context);
111
Daniel Veillard1d211e22003-10-20 22:32:39 +0000112static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);
113static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
114 const unsigned char *data);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000115static void xmlTextWriterStartDocumentCallback(void *ctx);
Daniel Veillardab69f362004-02-17 11:40:32 +0000116static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000117static int
118 xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
119 xmlTextWriterStackEntry * p);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000120
121/**
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000122 * xmlWriterErrMsg:
123 * @ctxt: a writer context
124 * @error: the error number
125 * @msg: the error message
126 *
127 * Handle a writer error
128 */
129static void
130xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,
131 const char *msg)
132{
133 if (ctxt != NULL) {
134 __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
135 NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
Daniel Veillardbccae2d2009-06-04 11:22:45 +0200136 NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000137 } else {
138 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
Daniel Veillardbccae2d2009-06-04 11:22:45 +0200139 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000140 }
141}
142
143/**
144 * xmlWriterErrMsgInt:
145 * @ctxt: a writer context
146 * @error: the error number
147 * @msg: the error message
148 * @val: an int
149 *
150 * Handle a writer error
151 */
152static void
153xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,
154 const char *msg, int val)
155{
156 if (ctxt != NULL) {
157 __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
158 NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
159 NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
160 } else {
161 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
162 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
163 }
164}
165
166/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000167 * xmlNewTextWriter:
168 * @out: an xmlOutputBufferPtr
169 *
170 * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
Daniel Veillardd5cc0f72004-11-06 19:24:28 +0000171 * NOTE: the @out parameter will be deallocated when the writer is closed
172 * (if the call succeed.)
Daniel Veillard1d211e22003-10-20 22:32:39 +0000173 *
174 * Returns the new xmlTextWriterPtr or NULL in case of error
175 */
176xmlTextWriterPtr
177xmlNewTextWriter(xmlOutputBufferPtr out)
178{
179 xmlTextWriterPtr ret;
180
181 ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
182 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000183 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000184 "xmlNewTextWriter : out of memory!\n");
185 return NULL;
186 }
187 memset(ret, 0, (size_t) sizeof(xmlTextWriter));
188
189 ret->nodes = xmlListCreate((xmlListDeallocator)
190 xmlFreeTextWriterStackEntry,
191 (xmlListDataCompare)
192 xmlCmpTextWriterStackEntry);
193 if (ret->nodes == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000194 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000195 "xmlNewTextWriter : out of memory!\n");
196 xmlFree(ret);
197 return NULL;
198 }
199
200 ret->nsstack = xmlListCreate((xmlListDeallocator)
201 xmlFreeTextWriterNsStackEntry,
202 (xmlListDataCompare)
203 xmlCmpTextWriterNsStackEntry);
204 if (ret->nsstack == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000205 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000206 "xmlNewTextWriter : out of memory!\n");
Daniel Veillard500a1de2004-03-22 15:22:58 +0000207 xmlListDelete(ret->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000208 xmlFree(ret);
209 return NULL;
210 }
211
212 ret->out = out;
Daniel Veillardab69f362004-02-17 11:40:32 +0000213 ret->ichar = xmlStrdup(BAD_CAST " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000214 ret->qchar = '"';
215
Daniel Veillard500a1de2004-03-22 15:22:58 +0000216 if (!ret->ichar) {
217 xmlListDelete(ret->nodes);
218 xmlListDelete(ret->nsstack);
219 xmlFree(ret);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000220 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000221 "xmlNewTextWriter : out of memory!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000222 return NULL;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000223 }
Rob Richards9db68f02006-08-16 22:48:51 +0000224
225 ret->doc = xmlNewDoc(NULL);
226
Daniel Veillarda521d282004-11-09 14:59:59 +0000227 ret->no_doc_free = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000228
Daniel Veillard1d211e22003-10-20 22:32:39 +0000229 return ret;
230}
231
232/**
233 * xmlNewTextWriterFilename:
234 * @uri: the URI of the resource for the output
235 * @compression: compress the output?
236 *
237 * Create a new xmlNewTextWriter structure with @uri as output
238 *
239 * Returns the new xmlTextWriterPtr or NULL in case of error
240 */
241xmlTextWriterPtr
242xmlNewTextWriterFilename(const char *uri, int compression)
243{
244 xmlTextWriterPtr ret;
245 xmlOutputBufferPtr out;
246
247 out = xmlOutputBufferCreateFilename(uri, NULL, compression);
248 if (out == NULL) {
Rob Richards798743a2009-06-19 13:54:25 -0400249 xmlWriterErrMsg(NULL, XML_IO_EIO,
250 "xmlNewTextWriterFilename : cannot open uri\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000251 return NULL;
252 }
253
254 ret = xmlNewTextWriter(out);
255 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000256 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000257 "xmlNewTextWriterFilename : out of memory!\n");
258 xmlOutputBufferClose(out);
259 return NULL;
260 }
261
Daniel Veillard2cca4462004-01-02 20:04:23 +0000262 ret->indent = 0;
263 ret->doindent = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000264 return ret;
265}
266
267/**
268 * xmlNewTextWriterMemory:
269 * @buf: xmlBufferPtr
270 * @compression: compress the output?
271 *
272 * Create a new xmlNewTextWriter structure with @buf as output
273 * TODO: handle compression
274 *
275 * Returns the new xmlTextWriterPtr or NULL in case of error
276 */
277xmlTextWriterPtr
278xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
279{
280 xmlTextWriterPtr ret;
281 xmlOutputBufferPtr out;
282
283/*::todo handle compression */
Rob Richardsa44f2342005-11-09 18:03:45 +0000284 out = xmlOutputBufferCreateBuffer(buf, NULL);
285
Daniel Veillard1d211e22003-10-20 22:32:39 +0000286 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000287 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000288 "xmlNewTextWriterMemory : out of memory!\n");
289 return NULL;
290 }
291
292 ret = xmlNewTextWriter(out);
293 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000294 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000295 "xmlNewTextWriterMemory : out of memory!\n");
296 xmlOutputBufferClose(out);
297 return NULL;
298 }
299
300 return ret;
301}
302
303/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000304 * xmlNewTextWriterPushParser:
305 * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
306 * @compression: compress the output?
307 *
308 * Create a new xmlNewTextWriter structure with @ctxt as output
Daniel Veillardd5cc0f72004-11-06 19:24:28 +0000309 * NOTE: the @ctxt context will be freed with the resulting writer
310 * (if the call succeeds).
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000311 * TODO: handle compression
312 *
313 * Returns the new xmlTextWriterPtr or NULL in case of error
314 */
315xmlTextWriterPtr
Daniel Veillard1d913862003-11-21 00:28:39 +0000316xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
317 int compression ATTRIBUTE_UNUSED)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000318{
319 xmlTextWriterPtr ret;
320 xmlOutputBufferPtr out;
321
Daniel Veillard500a1de2004-03-22 15:22:58 +0000322 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000323 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000324 "xmlNewTextWriterPushParser : invalid context!\n");
325 return NULL;
326 }
327
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000328 out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
329 xmlTextWriterWriteDocCallback,
330 (xmlOutputCloseCallback)
331 xmlTextWriterCloseDocCallback,
332 (void *) ctxt, NULL);
333 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000334 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000335 "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
336 return NULL;
337 }
338
339 ret = xmlNewTextWriter(out);
340 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000341 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000342 "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
343 xmlOutputBufferClose(out);
344 return NULL;
345 }
346
Daniel Veillard20c5e782004-01-21 09:57:31 +0000347 ret->ctxt = ctxt;
348
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000349 return ret;
350}
351
352/**
353 * xmlNewTextWriterDoc:
354 * @doc: address of a xmlDocPtr to hold the new XML document tree
355 * @compression: compress the output?
356 *
357 * Create a new xmlNewTextWriter structure with @*doc as output
358 *
359 * Returns the new xmlTextWriterPtr or NULL in case of error
360 */
361xmlTextWriterPtr
362xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
363{
364 xmlTextWriterPtr ret;
365 xmlSAXHandler saxHandler;
366 xmlParserCtxtPtr ctxt;
367
368 memset(&saxHandler, '\0', sizeof(saxHandler));
369 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
370 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
371 saxHandler.startElement = xmlSAX2StartElement;
372 saxHandler.endElement = xmlSAX2EndElement;
373
374 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
375 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000376 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillardeb0a0b22009-02-20 08:19:53 +0000377 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000378 return NULL;
379 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000380 /*
381 * For some reason this seems to completely break if node names
382 * are interned.
383 */
384 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000385
Daniel Veillard1d913862003-11-21 00:28:39 +0000386 ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000387 if (ctxt->myDoc == NULL) {
388 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000389 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000390 "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
391 return NULL;
392 }
393
394 ret = xmlNewTextWriterPushParser(ctxt, compression);
395 if (ret == NULL) {
Daniel Veillardeb0a0b22009-02-20 08:19:53 +0000396 xmlFreeDoc(ctxt->myDoc);
397 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000398 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillardeb0a0b22009-02-20 08:19:53 +0000399 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000400 return NULL;
401 }
402
Daniel Veillard500a1de2004-03-22 15:22:58 +0000403 xmlSetDocCompressMode(ctxt->myDoc, compression);
404
Daniel Veillarda521d282004-11-09 14:59:59 +0000405 if (doc != NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000406 *doc = ctxt->myDoc;
Daniel Veillarda521d282004-11-09 14:59:59 +0000407 ret->no_doc_free = 1;
408 }
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000409
410 return ret;
411}
412
413/**
414 * xmlNewTextWriterTree:
415 * @doc: xmlDocPtr
416 * @node: xmlNodePtr or NULL for doc->children
417 * @compression: compress the output?
418 *
419 * Create a new xmlNewTextWriter structure with @doc as output
420 * starting at @node
421 *
422 * Returns the new xmlTextWriterPtr or NULL in case of error
423 */
424xmlTextWriterPtr
425xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
426{
427 xmlTextWriterPtr ret;
428 xmlSAXHandler saxHandler;
429 xmlParserCtxtPtr ctxt;
430
431 if (doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000432 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000433 "xmlNewTextWriterTree : invalid document tree!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000434 return NULL;
435 }
436
437 memset(&saxHandler, '\0', sizeof(saxHandler));
438 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
439 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
440 saxHandler.startElement = xmlSAX2StartElement;
441 saxHandler.endElement = xmlSAX2EndElement;
442
443 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
444 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000445 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000446 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
447 return NULL;
448 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000449 /*
450 * For some reason this seems to completely break if node names
451 * are interned.
452 */
453 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000454
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000455 ret = xmlNewTextWriterPushParser(ctxt, compression);
456 if (ret == NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000457 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000458 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000459 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
460 return NULL;
461 }
462
Daniel Veillard500a1de2004-03-22 15:22:58 +0000463 ctxt->myDoc = doc;
464 ctxt->node = node;
Daniel Veillarda521d282004-11-09 14:59:59 +0000465 ret->no_doc_free = 1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000466
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000467 xmlSetDocCompressMode(doc, compression);
468
469 return ret;
470}
471
472/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000473 * xmlFreeTextWriter:
474 * @writer: the xmlTextWriterPtr
475 *
476 * Deallocate all the resources associated to the writer
477 */
478void
479xmlFreeTextWriter(xmlTextWriterPtr writer)
480{
481 if (writer == NULL)
482 return;
483
484 if (writer->out != NULL)
485 xmlOutputBufferClose(writer->out);
486
487 if (writer->nodes != NULL)
488 xmlListDelete(writer->nodes);
489
490 if (writer->nsstack != NULL)
491 xmlListDelete(writer->nsstack);
492
Daniel Veillarda521d282004-11-09 14:59:59 +0000493 if (writer->ctxt != NULL) {
494 if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
495 xmlFreeDoc(writer->ctxt->myDoc);
496 writer->ctxt->myDoc = NULL;
497 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000498 xmlFreeParserCtxt(writer->ctxt);
Daniel Veillarda521d282004-11-09 14:59:59 +0000499 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000500
Rob Richards9db68f02006-08-16 22:48:51 +0000501 if (writer->doc != NULL)
502 xmlFreeDoc(writer->doc);
503
Daniel Veillard4773df22004-01-23 13:15:13 +0000504 if (writer->ichar != NULL)
505 xmlFree(writer->ichar);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000506 xmlFree(writer);
507}
508
509/**
510 * xmlTextWriterStartDocument:
511 * @writer: the xmlTextWriterPtr
512 * @version: the xml version ("1.0") or NULL for default ("1.0")
513 * @encoding: the encoding or NULL for default
514 * @standalone: "yes" or "no" or NULL for default
515 *
516 * Start a new xml document
517 *
518 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
519 */
520int
521xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
522 const char *encoding, const char *standalone)
523{
524 int count;
525 int sum;
526 xmlLinkPtr lk;
527 xmlCharEncodingHandlerPtr encoder;
528
Daniel Veillard500a1de2004-03-22 15:22:58 +0000529 if ((writer == NULL) || (writer->out == NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000530 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000531 "xmlTextWriterStartDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000532 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000533 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000534
535 lk = xmlListFront(writer->nodes);
536 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000537 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000538 "xmlTextWriterStartDocument : not allowed in this context!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000539 return -1;
540 }
541
542 encoder = NULL;
543 if (encoding != NULL) {
544 encoder = xmlFindCharEncodingHandler(encoding);
545 if (encoder == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000546 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000547 "xmlTextWriterStartDocument : out of memory!\n");
548 return -1;
549 }
550 }
551
552 writer->out->encoder = encoder;
553 if (encoder != NULL) {
Daniel Veillardcaa19512007-07-04 15:42:46 +0000554 if (writer->out->conv == NULL) {
Daniel Veillarddbf54112012-07-16 14:54:45 +0800555 writer->out->conv = xmlBufCreateSize(4000);
Daniel Veillardcaa19512007-07-04 15:42:46 +0000556 }
Daniel Veillarddbf54112012-07-16 14:54:45 +0800557 xmlCharEncOutput(writer->out, 1);
Rob Richards9db68f02006-08-16 22:48:51 +0000558 if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
559 writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000560 } else
561 writer->out->conv = NULL;
562
563 sum = 0;
564 count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
565 if (count < 0)
566 return -1;
567 sum += count;
568 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
569 if (count < 0)
570 return -1;
571 sum += count;
572 if (version != 0)
573 count = xmlOutputBufferWriteString(writer->out, version);
574 else
575 count = xmlOutputBufferWriteString(writer->out, "1.0");
576 if (count < 0)
577 return -1;
578 sum += count;
579 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
580 if (count < 0)
581 return -1;
582 sum += count;
583 if (writer->out->encoder != 0) {
584 count = xmlOutputBufferWriteString(writer->out, " encoding=");
585 if (count < 0)
586 return -1;
587 sum += count;
588 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
589 if (count < 0)
590 return -1;
591 sum += count;
592 count =
593 xmlOutputBufferWriteString(writer->out,
594 writer->out->encoder->name);
595 if (count < 0)
596 return -1;
597 sum += count;
598 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
599 if (count < 0)
600 return -1;
601 sum += count;
602 }
603
604 if (standalone != 0) {
605 count = xmlOutputBufferWriteString(writer->out, " standalone=");
606 if (count < 0)
607 return -1;
608 sum += count;
609 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
610 if (count < 0)
611 return -1;
612 sum += count;
613 count = xmlOutputBufferWriteString(writer->out, standalone);
614 if (count < 0)
615 return -1;
616 sum += count;
617 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
618 if (count < 0)
619 return -1;
620 sum += count;
621 }
622
623 count = xmlOutputBufferWriteString(writer->out, "?>\n");
624 if (count < 0)
625 return -1;
626 sum += count;
627
628 return sum;
629}
630
631/**
632 * xmlTextWriterEndDocument:
633 * @writer: the xmlTextWriterPtr
634 *
Daniel Veillard3ff24112008-02-13 10:17:41 +0000635 * End an xml document. All open elements are closed, and
636 * the content is flushed to the output.
Daniel Veillard1d211e22003-10-20 22:32:39 +0000637 *
Daniel Veillard3ff24112008-02-13 10:17:41 +0000638 * Returns the bytes written or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +0000639 */
640int
641xmlTextWriterEndDocument(xmlTextWriterPtr writer)
642{
643 int count;
644 int sum;
645 xmlLinkPtr lk;
646 xmlTextWriterStackEntry *p;
647
Daniel Veillard500a1de2004-03-22 15:22:58 +0000648 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000649 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000650 "xmlTextWriterEndDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000651 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000652 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000653
654 sum = 0;
655 while ((lk = xmlListFront(writer->nodes)) != NULL) {
656 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
657 if (p == 0)
658 break;
659 switch (p->state) {
660 case XML_TEXTWRITER_NAME:
661 case XML_TEXTWRITER_ATTRIBUTE:
662 case XML_TEXTWRITER_TEXT:
663 count = xmlTextWriterEndElement(writer);
664 if (count < 0)
665 return -1;
666 sum += count;
667 break;
668 case XML_TEXTWRITER_PI:
669 case XML_TEXTWRITER_PI_TEXT:
670 count = xmlTextWriterEndPI(writer);
671 if (count < 0)
672 return -1;
673 sum += count;
674 break;
675 case XML_TEXTWRITER_CDATA:
676 count = xmlTextWriterEndCDATA(writer);
677 if (count < 0)
678 return -1;
679 sum += count;
680 break;
681 case XML_TEXTWRITER_DTD:
Daniel Veillard500a1de2004-03-22 15:22:58 +0000682 case XML_TEXTWRITER_DTD_TEXT:
683 case XML_TEXTWRITER_DTD_ELEM:
684 case XML_TEXTWRITER_DTD_ELEM_TEXT:
685 case XML_TEXTWRITER_DTD_ATTL:
686 case XML_TEXTWRITER_DTD_ATTL_TEXT:
687 case XML_TEXTWRITER_DTD_ENTY:
688 case XML_TEXTWRITER_DTD_ENTY_TEXT:
689 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard1d211e22003-10-20 22:32:39 +0000690 count = xmlTextWriterEndDTD(writer);
691 if (count < 0)
692 return -1;
693 sum += count;
694 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000695 case XML_TEXTWRITER_COMMENT:
696 count = xmlTextWriterEndComment(writer);
697 if (count < 0)
698 return -1;
699 sum += count;
700 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000701 default:
Daniel Veillardab69f362004-02-17 11:40:32 +0000702 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000703 }
704 }
705
Daniel Veillard2cca4462004-01-02 20:04:23 +0000706 if (!writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000707 count = xmlOutputBufferWriteString(writer->out, "\n");
708 if (count < 0)
709 return -1;
710 sum += count;
711 }
Daniel Veillard3ff24112008-02-13 10:17:41 +0000712
713 sum += xmlTextWriterFlush(writer);
714
Daniel Veillardab69f362004-02-17 11:40:32 +0000715 return sum;
716}
717
Daniel Veillardab69f362004-02-17 11:40:32 +0000718/**
719 * xmlTextWriterStartComment:
720 * @writer: the xmlTextWriterPtr
721 *
722 * Start an xml comment.
723 *
724 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
725 */
726int
727xmlTextWriterStartComment(xmlTextWriterPtr writer)
728{
729 int count;
730 int sum;
731 xmlLinkPtr lk;
732 xmlTextWriterStackEntry *p;
733
Daniel Veillard500a1de2004-03-22 15:22:58 +0000734 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000735 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000736 "xmlTextWriterStartComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000737 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000738 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000739
740 sum = 0;
741 lk = xmlListFront(writer->nodes);
742 if (lk != 0) {
743 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
744 if (p != 0) {
745 switch (p->state) {
746 case XML_TEXTWRITER_TEXT:
747 case XML_TEXTWRITER_NONE:
748 break;
749 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000750 /* Output namespace declarations */
751 count = xmlTextWriterOutputNSDecl(writer);
752 if (count < 0)
753 return -1;
754 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000755 count = xmlOutputBufferWriteString(writer->out, ">");
756 if (count < 0)
757 return -1;
758 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000759 if (writer->indent) {
760 count =
761 xmlOutputBufferWriteString(writer->out, "\n");
762 if (count < 0)
763 return -1;
764 sum += count;
765 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000766 p->state = XML_TEXTWRITER_TEXT;
767 break;
768 default:
769 return -1;
770 }
771 }
772 }
773
774 p = (xmlTextWriterStackEntry *)
775 xmlMalloc(sizeof(xmlTextWriterStackEntry));
776 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000777 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillardab69f362004-02-17 11:40:32 +0000778 "xmlTextWriterStartElement : out of memory!\n");
779 return -1;
780 }
781
Daniel Veillard75e389d2005-07-29 22:02:24 +0000782 p->name = NULL;
Daniel Veillardab69f362004-02-17 11:40:32 +0000783 p->state = XML_TEXTWRITER_COMMENT;
784
785 xmlListPushFront(writer->nodes, p);
786
787 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000788 count = xmlTextWriterWriteIndent(writer);
789 if (count < 0)
790 return -1;
791 sum += count;
792 }
793
794 count = xmlOutputBufferWriteString(writer->out, "<!--");
795 if (count < 0)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000796 return -1;
797 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000798
799 return sum;
800}
801
802/**
803 * xmlTextWriterEndComment:
804 * @writer: the xmlTextWriterPtr
805 *
806 * End the current xml coment.
807 *
808 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
809 */
810int
811xmlTextWriterEndComment(xmlTextWriterPtr writer)
812{
813 int count;
814 int sum;
815 xmlLinkPtr lk;
816 xmlTextWriterStackEntry *p;
817
Daniel Veillard500a1de2004-03-22 15:22:58 +0000818 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000819 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000820 "xmlTextWriterEndComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000821 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000822 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000823
824 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000825 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000826 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000827 "xmlTextWriterEndComment : not allowed in this context!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000828 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000829 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000830
831 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
832 if (p == 0)
833 return -1;
834
835 sum = 0;
836 switch (p->state) {
837 case XML_TEXTWRITER_COMMENT:
838 count = xmlOutputBufferWriteString(writer->out, "-->");
839 if (count < 0)
840 return -1;
841 sum += count;
842 break;
843 default:
844 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +0000845 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000846
847 if (writer->indent) {
848 count = xmlOutputBufferWriteString(writer->out, "\n");
849 if (count < 0)
850 return -1;
851 sum += count;
852 }
853
854 xmlListPopFront(writer->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000855 return sum;
856}
857
858/**
859 * xmlTextWriterWriteFormatComment:
860 * @writer: the xmlTextWriterPtr
861 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +0000862 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +0000863 *
864 * Write an xml comment.
865 *
866 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
867 */
Daniel Veillardffa3c742005-07-21 13:24:09 +0000868int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +0000869xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
870 const char *format, ...)
871{
872 int rc;
873 va_list ap;
874
875 va_start(ap, format);
876
877 rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
878
879 va_end(ap);
880 return rc;
881}
882
883/**
884 * xmlTextWriterWriteVFormatComment:
885 * @writer: the xmlTextWriterPtr
886 * @format: format string (see printf)
887 * @argptr: pointer to the first member of the variable argument list.
888 *
889 * Write an xml comment.
890 *
891 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
892 */
893int
894xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
895 const char *format, va_list argptr)
896{
897 int rc;
898 xmlChar *buf;
899
Daniel Veillard500a1de2004-03-22 15:22:58 +0000900 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000901 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000902 "xmlTextWriterWriteVFormatComment : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000903 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000904 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000905
906 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +0000907 if (buf == NULL)
908 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000909
910 rc = xmlTextWriterWriteComment(writer, buf);
911
912 xmlFree(buf);
913 return rc;
914}
915
916/**
917 * xmlTextWriterWriteComment:
918 * @writer: the xmlTextWriterPtr
919 * @content: comment string
920 *
921 * Write an xml comment.
922 *
923 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
924 */
925int
926xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
927{
928 int count;
929 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000930
931 sum = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000932 count = xmlTextWriterStartComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000933 if (count < 0)
934 return -1;
935 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000936 count = xmlTextWriterWriteString(writer, content);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000937 if (count < 0)
938 return -1;
939 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000940 count = xmlTextWriterEndComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000941 if (count < 0)
942 return -1;
943 sum += count;
944
945 return sum;
946}
947
948/**
949 * xmlTextWriterStartElement:
950 * @writer: the xmlTextWriterPtr
951 * @name: element name
952 *
953 * Start an xml element.
954 *
955 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
956 */
957int
958xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
959{
960 int count;
961 int sum;
962 xmlLinkPtr lk;
963 xmlTextWriterStackEntry *p;
964
965 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
966 return -1;
967
968 sum = 0;
969 lk = xmlListFront(writer->nodes);
970 if (lk != 0) {
971 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
972 if (p != 0) {
973 switch (p->state) {
974 case XML_TEXTWRITER_PI:
975 case XML_TEXTWRITER_PI_TEXT:
976 return -1;
977 case XML_TEXTWRITER_NONE:
978 break;
Daniel Veillard614fdc12005-02-23 14:05:37 +0000979 case XML_TEXTWRITER_ATTRIBUTE:
980 count = xmlTextWriterEndAttribute(writer);
981 if (count < 0)
982 return -1;
983 sum += count;
984 /* fallthrough */
Daniel Veillard1d211e22003-10-20 22:32:39 +0000985 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000986 /* Output namespace declarations */
987 count = xmlTextWriterOutputNSDecl(writer);
988 if (count < 0)
989 return -1;
990 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000991 count = xmlOutputBufferWriteString(writer->out, ">");
992 if (count < 0)
993 return -1;
994 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000995 if (writer->indent)
996 count =
997 xmlOutputBufferWriteString(writer->out, "\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000998 p->state = XML_TEXTWRITER_TEXT;
999 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00001000 default:
1001 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001002 }
1003 }
1004 }
1005
1006 p = (xmlTextWriterStackEntry *)
1007 xmlMalloc(sizeof(xmlTextWriterStackEntry));
1008 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001009 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001010 "xmlTextWriterStartElement : out of memory!\n");
1011 return -1;
1012 }
1013
1014 p->name = xmlStrdup(name);
1015 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001016 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001017 "xmlTextWriterStartElement : out of memory!\n");
1018 xmlFree(p);
1019 return -1;
1020 }
1021 p->state = XML_TEXTWRITER_NAME;
1022
1023 xmlListPushFront(writer->nodes, p);
1024
Daniel Veillardab69f362004-02-17 11:40:32 +00001025 if (writer->indent) {
1026 count = xmlTextWriterWriteIndent(writer);
1027 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001028 }
1029
Daniel Veillard1d211e22003-10-20 22:32:39 +00001030 count = xmlOutputBufferWriteString(writer->out, "<");
1031 if (count < 0)
1032 return -1;
1033 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001034 count =
1035 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001036 if (count < 0)
1037 return -1;
1038 sum += count;
1039
1040 return sum;
1041}
1042
1043/**
1044 * xmlTextWriterStartElementNS:
1045 * @writer: the xmlTextWriterPtr
1046 * @prefix: namespace prefix or NULL
1047 * @name: element local name
1048 * @namespaceURI: namespace URI or NULL
1049 *
1050 * Start an xml element with namespace support.
1051 *
1052 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1053 */
1054int
1055xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
1056 const xmlChar * prefix, const xmlChar * name,
1057 const xmlChar * namespaceURI)
1058{
1059 int count;
1060 int sum;
1061 xmlChar *buf;
1062
1063 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1064 return -1;
1065
Daniel Veillard75e389d2005-07-29 22:02:24 +00001066 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001067 if (prefix != 0) {
1068 buf = xmlStrdup(prefix);
1069 buf = xmlStrcat(buf, BAD_CAST ":");
1070 }
1071 buf = xmlStrcat(buf, name);
1072
1073 sum = 0;
1074 count = xmlTextWriterStartElement(writer, buf);
1075 xmlFree(buf);
1076 if (count < 0)
1077 return -1;
1078 sum += count;
1079
1080 if (namespaceURI != 0) {
Rob Richardsb8769d62007-06-08 08:50:47 +00001081 xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
1082 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1083 if (p == 0) {
1084 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1085 "xmlTextWriterStartElementNS : out of memory!\n");
1086 return -1;
1087 }
1088
Daniel Veillard1d211e22003-10-20 22:32:39 +00001089 buf = xmlStrdup(BAD_CAST "xmlns");
1090 if (prefix != 0) {
1091 buf = xmlStrcat(buf, BAD_CAST ":");
1092 buf = xmlStrcat(buf, prefix);
1093 }
1094
Rob Richardsb8769d62007-06-08 08:50:47 +00001095 p->prefix = buf;
1096 p->uri = xmlStrdup(namespaceURI);
1097 if (p->uri == 0) {
1098 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1099 "xmlTextWriterStartElementNS : out of memory!\n");
1100 xmlFree(p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001101 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001102 }
1103 p->elem = xmlListFront(writer->nodes);
1104
1105 xmlListPushFront(writer->nsstack, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001106 }
1107
1108 return sum;
1109}
1110
1111/**
1112 * xmlTextWriterEndElement:
1113 * @writer: the xmlTextWriterPtr
1114 *
1115 * End the current xml element.
1116 *
1117 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1118 */
1119int
1120xmlTextWriterEndElement(xmlTextWriterPtr writer)
1121{
1122 int count;
1123 int sum;
1124 xmlLinkPtr lk;
1125 xmlTextWriterStackEntry *p;
1126
1127 if (writer == NULL)
1128 return -1;
1129
1130 lk = xmlListFront(writer->nodes);
Rob Richardsb8769d62007-06-08 08:50:47 +00001131 if (lk == 0) {
1132 xmlListDelete(writer->nsstack);
1133 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001134 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001135 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001136
1137 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Rob Richardsb8769d62007-06-08 08:50:47 +00001138 if (p == 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
1144 sum = 0;
1145 switch (p->state) {
1146 case XML_TEXTWRITER_ATTRIBUTE:
1147 count = xmlTextWriterEndAttribute(writer);
Rob Richardsb8769d62007-06-08 08:50:47 +00001148 if (count < 0) {
1149 xmlListDelete(writer->nsstack);
1150 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001151 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001152 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001153 sum += count;
1154 /* fallthrough */
1155 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001156 /* Output namespace declarations */
1157 count = xmlTextWriterOutputNSDecl(writer);
1158 if (count < 0)
1159 return -1;
1160 sum += count;
1161
Daniel Veillardab69f362004-02-17 11:40:32 +00001162 if (writer->indent) /* next element needs indent */
1163 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001164 count = xmlOutputBufferWriteString(writer->out, "/>");
1165 if (count < 0)
1166 return -1;
1167 sum += count;
1168 break;
1169 case XML_TEXTWRITER_TEXT:
Daniel Veillardab69f362004-02-17 11:40:32 +00001170 if ((writer->indent) && (writer->doindent)) {
1171 count = xmlTextWriterWriteIndent(writer);
1172 sum += count;
1173 writer->doindent = 1;
1174 } else
1175 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001176 count = xmlOutputBufferWriteString(writer->out, "</");
1177 if (count < 0)
1178 return -1;
1179 sum += count;
1180 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001181 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001182 if (count < 0)
1183 return -1;
1184 sum += count;
1185 count = xmlOutputBufferWriteString(writer->out, ">");
1186 if (count < 0)
1187 return -1;
1188 sum += count;
1189 break;
1190 default:
1191 return -1;
1192 }
1193
Daniel Veillard2cca4462004-01-02 20:04:23 +00001194 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001195 count = xmlOutputBufferWriteString(writer->out, "\n");
1196 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001197 }
1198
Daniel Veillard1d211e22003-10-20 22:32:39 +00001199 xmlListPopFront(writer->nodes);
1200 return sum;
1201}
1202
1203/**
1204 * xmlTextWriterFullEndElement:
1205 * @writer: the xmlTextWriterPtr
1206 *
1207 * End the current xml element. Writes an end tag even if the element is empty
1208 *
1209 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1210 */
1211int
1212xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1213{
1214 int count;
1215 int sum;
1216 xmlLinkPtr lk;
1217 xmlTextWriterStackEntry *p;
1218
1219 if (writer == NULL)
1220 return -1;
1221
1222 lk = xmlListFront(writer->nodes);
1223 if (lk == 0)
1224 return -1;
1225
1226 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1227 if (p == 0)
1228 return -1;
1229
1230 sum = 0;
1231 switch (p->state) {
1232 case XML_TEXTWRITER_ATTRIBUTE:
1233 count = xmlTextWriterEndAttribute(writer);
1234 if (count < 0)
1235 return -1;
1236 sum += count;
1237 /* fallthrough */
1238 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001239 /* Output namespace declarations */
1240 count = xmlTextWriterOutputNSDecl(writer);
1241 if (count < 0)
1242 return -1;
1243 sum += count;
1244
Daniel Veillard1d211e22003-10-20 22:32:39 +00001245 count = xmlOutputBufferWriteString(writer->out, ">");
1246 if (count < 0)
1247 return -1;
1248 sum += count;
Rob Richards5a7d8bd2008-12-27 13:17:43 +00001249 if (writer->indent)
1250 writer->doindent = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001251 /* fallthrough */
1252 case XML_TEXTWRITER_TEXT:
Rob Richards5a7d8bd2008-12-27 13:17:43 +00001253 if ((writer->indent) && (writer->doindent)) {
1254 count = xmlTextWriterWriteIndent(writer);
1255 sum += count;
1256 writer->doindent = 1;
1257 } else
1258 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001259 count = xmlOutputBufferWriteString(writer->out, "</");
1260 if (count < 0)
1261 return -1;
1262 sum += count;
1263 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001264 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001265 if (count < 0)
1266 return -1;
1267 sum += count;
1268 count = xmlOutputBufferWriteString(writer->out, ">");
1269 if (count < 0)
1270 return -1;
1271 sum += count;
1272 break;
1273 default:
1274 return -1;
1275 }
1276
Daniel Veillard7e26fb42008-01-09 02:19:50 +00001277 if (writer->indent) {
1278 count = xmlOutputBufferWriteString(writer->out, "\n");
1279 sum += count;
1280 }
1281
Daniel Veillard1d211e22003-10-20 22:32:39 +00001282 xmlListPopFront(writer->nodes);
1283 return sum;
1284}
1285
1286/**
1287 * xmlTextWriterWriteFormatRaw:
1288 * @writer: the xmlTextWriterPtr
1289 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001290 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001291 *
1292 * Write a formatted raw xml text.
1293 *
1294 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1295 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001296int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001297xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1298 ...)
1299{
1300 int rc;
1301 va_list ap;
1302
1303 va_start(ap, format);
1304
1305 rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1306
1307 va_end(ap);
1308 return rc;
1309}
1310
1311/**
1312 * xmlTextWriterWriteVFormatRaw:
1313 * @writer: the xmlTextWriterPtr
1314 * @format: format string (see printf)
1315 * @argptr: pointer to the first member of the variable argument list.
1316 *
1317 * Write a formatted raw xml text.
1318 *
1319 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1320 */
1321int
1322xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1323 va_list argptr)
1324{
1325 int rc;
1326 xmlChar *buf;
1327
1328 if (writer == NULL)
1329 return -1;
1330
1331 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00001332 if (buf == NULL)
1333 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001334
1335 rc = xmlTextWriterWriteRaw(writer, buf);
1336
1337 xmlFree(buf);
1338 return rc;
1339}
1340
1341/**
Daniel Veillard1e906612003-12-05 14:57:46 +00001342 * xmlTextWriterWriteRawLen:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001343 * @writer: the xmlTextWriterPtr
1344 * @content: text string
1345 * @len: length of the text string
1346 *
1347 * Write an xml text.
1348 * TODO: what about entities and special chars??
1349 *
1350 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1351 */
1352int
1353xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1354 int len)
1355{
1356 int count;
1357 int sum;
1358 xmlLinkPtr lk;
1359 xmlTextWriterStackEntry *p;
1360
Daniel Veillard500a1de2004-03-22 15:22:58 +00001361 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001362 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001363 "xmlTextWriterWriteRawLen : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001364 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001365 }
1366
Daniel Veillarde43cc572004-11-03 11:50:29 +00001367 if ((content == NULL) || (len < 0)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001368 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001369 "xmlTextWriterWriteRawLen : invalid content!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001370 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001371 }
1372
1373 sum = 0;
1374 lk = xmlListFront(writer->nodes);
1375 if (lk != 0) {
1376 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1377 count = xmlTextWriterHandleStateDependencies(writer, p);
1378 if (count < 0)
1379 return -1;
1380 sum += count;
1381 }
1382
1383 if (writer->indent)
1384 writer->doindent = 0;
1385
1386 if (content != NULL) {
1387 count =
1388 xmlOutputBufferWrite(writer->out, len, (const char *) content);
1389 if (count < 0)
1390 return -1;
1391 sum += count;
1392 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001393
1394 return sum;
1395}
1396
1397/**
1398 * xmlTextWriterWriteRaw:
1399 * @writer: the xmlTextWriterPtr
1400 * @content: text string
1401 *
1402 * Write a raw xml text.
1403 *
1404 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1405 */
1406int
1407xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1408{
1409 return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1410}
1411
1412/**
1413 * xmlTextWriterWriteFormatString:
1414 * @writer: the xmlTextWriterPtr
1415 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001416 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001417 *
1418 * Write a formatted xml text.
1419 *
1420 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1421 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001422int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001423xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1424 ...)
1425{
1426 int rc;
1427 va_list ap;
1428
Daniel Veillarde43cc572004-11-03 11:50:29 +00001429 if ((writer == NULL) || (format == NULL))
1430 return -1;
1431
Daniel Veillard1d211e22003-10-20 22:32:39 +00001432 va_start(ap, format);
1433
1434 rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1435
1436 va_end(ap);
1437 return rc;
1438}
1439
1440/**
1441 * xmlTextWriterWriteVFormatString:
1442 * @writer: the xmlTextWriterPtr
1443 * @format: format string (see printf)
1444 * @argptr: pointer to the first member of the variable argument list.
1445 *
1446 * Write a formatted xml text.
1447 *
1448 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1449 */
1450int
1451xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1452 const char *format, va_list argptr)
1453{
1454 int rc;
1455 xmlChar *buf;
1456
Daniel Veillarde43cc572004-11-03 11:50:29 +00001457 if ((writer == NULL) || (format == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001458 return -1;
1459
1460 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00001461 if (buf == NULL)
1462 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001463
1464 rc = xmlTextWriterWriteString(writer, buf);
1465
1466 xmlFree(buf);
1467 return rc;
1468}
1469
1470/**
1471 * xmlTextWriterWriteString:
1472 * @writer: the xmlTextWriterPtr
1473 * @content: text string
1474 *
1475 * Write an xml text.
1476 *
1477 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1478 */
1479int
1480xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1481{
Daniel Veillard500a1de2004-03-22 15:22:58 +00001482 int count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001483 int sum;
1484 xmlLinkPtr lk;
1485 xmlTextWriterStackEntry *p;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001486 xmlChar *buf;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001487
Daniel Veillarde43cc572004-11-03 11:50:29 +00001488 if ((writer == NULL) || (content == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001489 return -1;
1490
Daniel Veillard1d211e22003-10-20 22:32:39 +00001491 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001492 buf = (xmlChar *) content;
1493 lk = xmlListFront(writer->nodes);
1494 if (lk != 0) {
1495 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1496 if (p != 0) {
1497 switch (p->state) {
1498 case XML_TEXTWRITER_NAME:
1499 case XML_TEXTWRITER_TEXT:
Daniel Veillard62040be2004-05-17 03:17:26 +00001500#if 0
1501 buf = NULL;
1502 xmlOutputBufferWriteEscape(writer->out, content, NULL);
1503#endif
Daniel Veillard500a1de2004-03-22 15:22:58 +00001504 buf = xmlEncodeSpecialChars(NULL, content);
1505 break;
1506 case XML_TEXTWRITER_ATTRIBUTE:
1507 buf = NULL;
Daniel Veillarddbf54112012-07-16 14:54:45 +08001508 xmlBufAttrSerializeTxtContent(writer->out->buffer,
1509 writer->doc, NULL, content);
Daniel Veillard500a1de2004-03-22 15:22:58 +00001510 break;
William M. Brack87640d52004-04-17 14:58:15 +00001511 default:
1512 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001513 }
1514 }
1515 }
1516
1517 if (buf != NULL) {
1518 count = xmlTextWriterWriteRaw(writer, buf);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001519
Daniel Veillard500a1de2004-03-22 15:22:58 +00001520 if (buf != content) /* buf was allocated by us, so free it */
1521 xmlFree(buf);
Daniel Veillardeb0a0b22009-02-20 08:19:53 +00001522
1523 if (count < 0)
1524 return -1;
1525 sum += count;
William M. Bracka9c612c2004-02-01 10:04:05 +00001526 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001527
1528 return sum;
1529}
1530
1531/**
1532 * xmlOutputBufferWriteBase64:
1533 * @out: the xmlOutputBufferPtr
1534 * @data: binary data
1535 * @len: the number of bytes to encode
1536 *
1537 * Write base64 encoded data to an xmlOutputBuffer.
1538 * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1539 *
1540 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1541 */
1542static int
1543xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1544 const unsigned char *data)
1545{
1546 static unsigned char dtable[64] =
William M. Brack47a31882004-09-11 16:09:09 +00001547 {'A','B','C','D','E','F','G','H','I','J','K','L','M',
1548 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1549 'a','b','c','d','e','f','g','h','i','j','k','l','m',
1550 'n','o','p','q','r','s','t','u','v','w','x','y','z',
1551 '0','1','2','3','4','5','6','7','8','9','+','/'};
1552
Daniel Veillard1d211e22003-10-20 22:32:39 +00001553 int i;
1554 int linelen;
1555 int count;
1556 int sum;
1557
Daniel Veillarde43cc572004-11-03 11:50:29 +00001558 if ((out == NULL) || (len < 0) || (data == NULL))
1559 return(-1);
1560
Daniel Veillard1d211e22003-10-20 22:32:39 +00001561 linelen = 0;
1562 sum = 0;
1563
1564 i = 0;
1565 while (1) {
1566 unsigned char igroup[3];
1567 unsigned char ogroup[4];
1568 int c;
1569 int n;
1570
1571 igroup[0] = igroup[1] = igroup[2] = 0;
1572 for (n = 0; n < 3 && i < len; n++, i++) {
1573 c = data[i];
1574 igroup[n] = (unsigned char) c;
1575 }
1576
1577 if (n > 0) {
1578 ogroup[0] = dtable[igroup[0] >> 2];
1579 ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1580 ogroup[2] =
1581 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1582 ogroup[3] = dtable[igroup[2] & 0x3F];
1583
1584 if (n < 3) {
1585 ogroup[3] = '=';
1586 if (n < 2) {
1587 ogroup[2] = '=';
1588 }
1589 }
1590
1591 if (linelen >= B64LINELEN) {
1592 count = xmlOutputBufferWrite(out, 2, B64CRLF);
1593 if (count == -1)
1594 return -1;
1595 sum += count;
1596 linelen = 0;
1597 }
1598 count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1599 if (count == -1)
1600 return -1;
1601 sum += count;
1602
1603 linelen += 4;
1604 }
Daniel Veillard929714b2003-10-22 12:34:36 +00001605
1606 if (i >= len)
1607 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001608 }
1609
Daniel Veillard1d211e22003-10-20 22:32:39 +00001610 return sum;
1611}
1612
1613/**
1614 * xmlTextWriterWriteBase64:
1615 * @writer: the xmlTextWriterPtr
1616 * @data: binary data
1617 * @start: the position within the data of the first byte to encode
1618 * @len: the number of bytes to encode
1619 *
1620 * Write an base64 encoded xml text.
1621 *
1622 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1623 */
1624int
Daniel Veillardab69f362004-02-17 11:40:32 +00001625xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001626 int start, int len)
1627{
1628 int count;
1629 int sum;
1630 xmlLinkPtr lk;
1631 xmlTextWriterStackEntry *p;
1632
Daniel Veillarde43cc572004-11-03 11:50:29 +00001633 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001634 return -1;
1635
Daniel Veillard1d211e22003-10-20 22:32:39 +00001636 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001637 lk = xmlListFront(writer->nodes);
1638 if (lk != 0) {
1639 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1640 if (p != 0) {
1641 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001642 if (count < 0)
1643 return -1;
1644 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001645 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001646 }
1647
Daniel Veillardab69f362004-02-17 11:40:32 +00001648 if (writer->indent)
1649 writer->doindent = 0;
1650
Daniel Veillard1d211e22003-10-20 22:32:39 +00001651 count =
1652 xmlOutputBufferWriteBase64(writer->out, len,
1653 (unsigned char *) data + start);
1654 if (count < 0)
1655 return -1;
1656 sum += count;
1657
1658 return sum;
1659}
1660
1661/**
1662 * xmlOutputBufferWriteBinHex:
1663 * @out: the xmlOutputBufferPtr
1664 * @data: binary data
1665 * @len: the number of bytes to encode
1666 *
1667 * Write hqx encoded data to an xmlOutputBuffer.
1668 * ::todo
1669 *
William M. Brack47a31882004-09-11 16:09:09 +00001670 * Returns the bytes written (may be 0 because of buffering)
1671 * or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +00001672 */
1673static int
Daniel Veillardab69f362004-02-17 11:40:32 +00001674xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1675 int len, const unsigned char *data)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001676{
Daniel Veillardab69f362004-02-17 11:40:32 +00001677 int count;
1678 int sum;
William M. Brack47a31882004-09-11 16:09:09 +00001679 static char hex[16] =
1680 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
Daniel Veillardab69f362004-02-17 11:40:32 +00001681 int i;
1682
Daniel Veillarde43cc572004-11-03 11:50:29 +00001683 if ((out == NULL) || (data == NULL) || (len < 0)) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001684 return -1;
1685 }
1686
1687 sum = 0;
1688 for (i = 0; i < len; i++) {
1689 count =
1690 xmlOutputBufferWrite(out, 1,
1691 (const char *) &hex[data[i] >> 4]);
1692 if (count == -1)
1693 return -1;
1694 sum += count;
1695 count =
1696 xmlOutputBufferWrite(out, 1,
1697 (const char *) &hex[data[i] & 0xF]);
1698 if (count == -1)
1699 return -1;
1700 sum += count;
1701 }
1702
1703 return sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001704}
1705
1706/**
1707 * xmlTextWriterWriteBinHex:
1708 * @writer: the xmlTextWriterPtr
1709 * @data: binary data
1710 * @start: the position within the data of the first byte to encode
1711 * @len: the number of bytes to encode
1712 *
1713 * Write a BinHex encoded xml text.
1714 *
1715 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1716 */
1717int
Daniel Veillardab69f362004-02-17 11:40:32 +00001718xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001719 int start, int len)
1720{
1721 int count;
1722 int sum;
1723 xmlLinkPtr lk;
1724 xmlTextWriterStackEntry *p;
1725
Daniel Veillarde43cc572004-11-03 11:50:29 +00001726 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001727 return -1;
1728
Daniel Veillard1d211e22003-10-20 22:32:39 +00001729 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001730 lk = xmlListFront(writer->nodes);
1731 if (lk != 0) {
1732 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1733 if (p != 0) {
1734 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001735 if (count < 0)
1736 return -1;
1737 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001738 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001739 }
1740
Daniel Veillardab69f362004-02-17 11:40:32 +00001741 if (writer->indent)
1742 writer->doindent = 0;
1743
Daniel Veillard1d211e22003-10-20 22:32:39 +00001744 count =
1745 xmlOutputBufferWriteBinHex(writer->out, len,
1746 (unsigned char *) data + start);
1747 if (count < 0)
1748 return -1;
1749 sum += count;
1750
1751 return sum;
1752}
1753
1754/**
1755 * xmlTextWriterStartAttribute:
1756 * @writer: the xmlTextWriterPtr
1757 * @name: element name
1758 *
1759 * Start an xml attribute.
1760 *
1761 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1762 */
1763int
1764xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1765{
1766 int count;
1767 int sum;
1768 xmlLinkPtr lk;
1769 xmlTextWriterStackEntry *p;
1770
1771 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1772 return -1;
1773
1774 sum = 0;
1775 lk = xmlListFront(writer->nodes);
1776 if (lk == 0)
1777 return -1;
1778
1779 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1780 if (p == 0)
1781 return -1;
1782
1783 switch (p->state) {
1784 case XML_TEXTWRITER_ATTRIBUTE:
1785 count = xmlTextWriterEndAttribute(writer);
1786 if (count < 0)
1787 return -1;
1788 sum += count;
1789 /* fallthrough */
1790 case XML_TEXTWRITER_NAME:
1791 count = xmlOutputBufferWriteString(writer->out, " ");
1792 if (count < 0)
1793 return -1;
1794 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001795 count =
1796 xmlOutputBufferWriteString(writer->out,
1797 (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001798 if (count < 0)
1799 return -1;
1800 sum += count;
1801 count = xmlOutputBufferWriteString(writer->out, "=");
1802 if (count < 0)
1803 return -1;
1804 sum += count;
1805 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1806 if (count < 0)
1807 return -1;
1808 sum += count;
1809 p->state = XML_TEXTWRITER_ATTRIBUTE;
1810 break;
1811 default:
1812 return -1;
1813 }
1814
1815 return sum;
1816}
1817
1818/**
1819 * xmlTextWriterStartAttributeNS:
1820 * @writer: the xmlTextWriterPtr
1821 * @prefix: namespace prefix or NULL
1822 * @name: element local name
1823 * @namespaceURI: namespace URI or NULL
1824 *
1825 * Start an xml attribute with namespace support.
1826 *
1827 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1828 */
1829int
1830xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1831 const xmlChar * prefix, const xmlChar * name,
1832 const xmlChar * namespaceURI)
1833{
1834 int count;
1835 int sum;
1836 xmlChar *buf;
1837 xmlTextWriterNsStackEntry *p;
1838
1839 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1840 return -1;
1841
Rob Richardsb8769d62007-06-08 08:50:47 +00001842 /* Handle namespace first in case of error */
1843 if (namespaceURI != 0) {
1844 xmlTextWriterNsStackEntry nsentry, *curns;
1845
1846 buf = xmlStrdup(BAD_CAST "xmlns");
1847 if (prefix != 0) {
1848 buf = xmlStrcat(buf, BAD_CAST ":");
1849 buf = xmlStrcat(buf, prefix);
1850 }
1851
1852 nsentry.prefix = buf;
1853 nsentry.uri = (xmlChar *)namespaceURI;
1854 nsentry.elem = xmlListFront(writer->nodes);
1855
1856 curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
1857 (void *)&nsentry);
1858 if ((curns != NULL)) {
1859 xmlFree(buf);
1860 if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
1861 /* Namespace already defined on element skip */
1862 buf = NULL;
1863 } else {
1864 /* Prefix mismatch so error out */
1865 return -1;
1866 }
1867 }
1868
1869 /* Do not add namespace decl to list - it is already there */
1870 if (buf != NULL) {
1871 p = (xmlTextWriterNsStackEntry *)
1872 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1873 if (p == 0) {
1874 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1875 "xmlTextWriterStartAttributeNS : out of memory!\n");
1876 return -1;
1877 }
1878
1879 p->prefix = buf;
1880 p->uri = xmlStrdup(namespaceURI);
1881 if (p->uri == 0) {
1882 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1883 "xmlTextWriterStartAttributeNS : out of memory!\n");
1884 xmlFree(p);
1885 return -1;
1886 }
1887 p->elem = xmlListFront(writer->nodes);
1888
1889 xmlListPushFront(writer->nsstack, p);
1890 }
1891 }
1892
Daniel Veillard75e389d2005-07-29 22:02:24 +00001893 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001894 if (prefix != 0) {
1895 buf = xmlStrdup(prefix);
1896 buf = xmlStrcat(buf, BAD_CAST ":");
1897 }
1898 buf = xmlStrcat(buf, name);
1899
1900 sum = 0;
1901 count = xmlTextWriterStartAttribute(writer, buf);
1902 xmlFree(buf);
1903 if (count < 0)
1904 return -1;
1905 sum += count;
1906
Daniel Veillard1d211e22003-10-20 22:32:39 +00001907 return sum;
1908}
1909
1910/**
1911 * xmlTextWriterEndAttribute:
1912 * @writer: the xmlTextWriterPtr
1913 *
1914 * End the current xml element.
1915 *
1916 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1917 */
1918int
1919xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1920{
1921 int count;
1922 int sum;
1923 xmlLinkPtr lk;
1924 xmlTextWriterStackEntry *p;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001925
1926 if (writer == NULL)
1927 return -1;
1928
1929 lk = xmlListFront(writer->nodes);
1930 if (lk == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001931 return -1;
1932 }
1933
1934 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1935 if (p == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001936 return -1;
1937 }
1938
1939 sum = 0;
1940 switch (p->state) {
1941 case XML_TEXTWRITER_ATTRIBUTE:
1942 p->state = XML_TEXTWRITER_NAME;
1943
1944 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1945 if (count < 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001946 return -1;
1947 }
1948 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001949 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001950 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001951 return -1;
1952 }
1953
1954 return sum;
1955}
1956
1957/**
1958 * xmlTextWriterWriteFormatAttribute:
1959 * @writer: the xmlTextWriterPtr
1960 * @name: attribute name
1961 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001962 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001963 *
1964 * Write a formatted xml attribute.
1965 *
1966 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1967 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001968int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001969xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1970 const xmlChar * name, const char *format,
1971 ...)
1972{
1973 int rc;
1974 va_list ap;
1975
1976 va_start(ap, format);
1977
1978 rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1979
1980 va_end(ap);
1981 return rc;
1982}
1983
1984/**
1985 * xmlTextWriterWriteVFormatAttribute:
1986 * @writer: the xmlTextWriterPtr
1987 * @name: attribute name
1988 * @format: format string (see printf)
1989 * @argptr: pointer to the first member of the variable argument list.
1990 *
1991 * Write a formatted xml attribute.
1992 *
1993 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1994 */
1995int
1996xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
1997 const xmlChar * name,
1998 const char *format, va_list argptr)
1999{
2000 int rc;
2001 xmlChar *buf;
2002
2003 if (writer == NULL)
2004 return -1;
2005
2006 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002007 if (buf == NULL)
2008 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002009
2010 rc = xmlTextWriterWriteAttribute(writer, name, buf);
2011
2012 xmlFree(buf);
2013 return rc;
2014}
2015
2016/**
2017 * xmlTextWriterWriteAttribute:
2018 * @writer: the xmlTextWriterPtr
2019 * @name: attribute name
2020 * @content: attribute content
2021 *
2022 * Write an xml attribute.
2023 *
2024 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2025 */
2026int
2027xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
2028 const xmlChar * content)
2029{
2030 int count;
2031 int sum;
2032
2033 sum = 0;
2034 count = xmlTextWriterStartAttribute(writer, name);
2035 if (count < 0)
2036 return -1;
2037 sum += count;
2038 count = xmlTextWriterWriteString(writer, content);
2039 if (count < 0)
2040 return -1;
2041 sum += count;
2042 count = xmlTextWriterEndAttribute(writer);
2043 if (count < 0)
2044 return -1;
2045 sum += count;
2046
2047 return sum;
2048}
2049
2050/**
2051 * xmlTextWriterWriteFormatAttributeNS:
2052 * @writer: the xmlTextWriterPtr
2053 * @prefix: namespace prefix
2054 * @name: attribute local name
2055 * @namespaceURI: namespace URI
2056 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002057 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002058 *
2059 * Write a formatted xml attribute.with namespace support
2060 *
2061 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2062 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002063int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002064xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
2065 const xmlChar * prefix,
2066 const xmlChar * name,
2067 const xmlChar * namespaceURI,
2068 const char *format, ...)
2069{
2070 int rc;
2071 va_list ap;
2072
2073 va_start(ap, format);
2074
2075 rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
2076 namespaceURI, format, ap);
2077
2078 va_end(ap);
2079 return rc;
2080}
2081
2082/**
2083 * xmlTextWriterWriteVFormatAttributeNS:
2084 * @writer: the xmlTextWriterPtr
2085 * @prefix: namespace prefix
2086 * @name: attribute local name
2087 * @namespaceURI: namespace URI
2088 * @format: format string (see printf)
2089 * @argptr: pointer to the first member of the variable argument list.
2090 *
2091 * Write a formatted xml attribute.with namespace support
2092 *
2093 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2094 */
2095int
2096xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
2097 const xmlChar * prefix,
2098 const xmlChar * name,
2099 const xmlChar * namespaceURI,
2100 const char *format, va_list argptr)
2101{
2102 int rc;
2103 xmlChar *buf;
2104
2105 if (writer == NULL)
2106 return -1;
2107
2108 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002109 if (buf == NULL)
2110 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002111
2112 rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
2113 buf);
2114
2115 xmlFree(buf);
2116 return rc;
2117}
2118
2119/**
2120 * xmlTextWriterWriteAttributeNS:
2121 * @writer: the xmlTextWriterPtr
2122 * @prefix: namespace prefix
2123 * @name: attribute local name
2124 * @namespaceURI: namespace URI
2125 * @content: attribute content
2126 *
2127 * Write an xml attribute.
2128 *
2129 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2130 */
2131int
2132xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
2133 const xmlChar * prefix, const xmlChar * name,
2134 const xmlChar * namespaceURI,
2135 const xmlChar * content)
2136{
2137 int count;
2138 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002139
2140 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2141 return -1;
2142
Daniel Veillard1d211e22003-10-20 22:32:39 +00002143 sum = 0;
Rob Richardsb8769d62007-06-08 08:50:47 +00002144 count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
2145 if (count < 0)
2146 return -1;
2147 sum += count;
2148 count = xmlTextWriterWriteString(writer, content);
2149 if (count < 0)
2150 return -1;
2151 sum += count;
2152 count = xmlTextWriterEndAttribute(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002153 if (count < 0)
2154 return -1;
2155 sum += count;
2156
Daniel Veillard1d211e22003-10-20 22:32:39 +00002157 return sum;
2158}
2159
2160/**
2161 * xmlTextWriterWriteFormatElement:
2162 * @writer: the xmlTextWriterPtr
2163 * @name: element name
2164 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002165 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002166 *
2167 * Write a formatted xml element.
2168 *
2169 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2170 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002171int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002172xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2173 const xmlChar * name, const char *format,
2174 ...)
2175{
2176 int rc;
2177 va_list ap;
2178
2179 va_start(ap, format);
2180
2181 rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2182
2183 va_end(ap);
2184 return rc;
2185}
2186
2187/**
2188 * xmlTextWriterWriteVFormatElement:
2189 * @writer: the xmlTextWriterPtr
2190 * @name: element name
2191 * @format: format string (see printf)
2192 * @argptr: pointer to the first member of the variable argument list.
2193 *
2194 * Write a formatted xml element.
2195 *
2196 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2197 */
2198int
2199xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2200 const xmlChar * name, const char *format,
2201 va_list argptr)
2202{
2203 int rc;
2204 xmlChar *buf;
2205
2206 if (writer == NULL)
2207 return -1;
2208
2209 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002210 if (buf == NULL)
2211 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002212
2213 rc = xmlTextWriterWriteElement(writer, name, buf);
2214
2215 xmlFree(buf);
2216 return rc;
2217}
2218
2219/**
2220 * xmlTextWriterWriteElement:
2221 * @writer: the xmlTextWriterPtr
2222 * @name: element name
2223 * @content: element content
2224 *
2225 * Write an xml element.
2226 *
2227 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2228 */
2229int
2230xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2231 const xmlChar * content)
2232{
2233 int count;
2234 int sum;
2235
2236 sum = 0;
2237 count = xmlTextWriterStartElement(writer, name);
2238 if (count == -1)
2239 return -1;
2240 sum += count;
2241 count = xmlTextWriterWriteString(writer, content);
2242 if (count == -1)
2243 return -1;
2244 sum += count;
2245 count = xmlTextWriterEndElement(writer);
2246 if (count == -1)
2247 return -1;
2248 sum += count;
2249
2250 return sum;
2251}
2252
2253/**
2254 * xmlTextWriterWriteFormatElementNS:
2255 * @writer: the xmlTextWriterPtr
2256 * @prefix: namespace prefix
2257 * @name: element local name
2258 * @namespaceURI: namespace URI
2259 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002260 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002261 *
2262 * Write a formatted xml element with namespace support.
2263 *
2264 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2265 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002266int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002267xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2268 const xmlChar * prefix,
2269 const xmlChar * name,
2270 const xmlChar * namespaceURI,
2271 const char *format, ...)
2272{
2273 int rc;
2274 va_list ap;
2275
2276 va_start(ap, format);
2277
2278 rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2279 namespaceURI, format, ap);
2280
2281 va_end(ap);
2282 return rc;
2283}
2284
2285/**
2286 * xmlTextWriterWriteVFormatElementNS:
2287 * @writer: the xmlTextWriterPtr
2288 * @prefix: namespace prefix
2289 * @name: element local name
2290 * @namespaceURI: namespace URI
2291 * @format: format string (see printf)
2292 * @argptr: pointer to the first member of the variable argument list.
2293 *
2294 * Write a formatted xml element with namespace support.
2295 *
2296 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2297 */
2298int
2299xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2300 const xmlChar * prefix,
2301 const xmlChar * name,
2302 const xmlChar * namespaceURI,
2303 const char *format, va_list argptr)
2304{
2305 int rc;
2306 xmlChar *buf;
2307
2308 if (writer == NULL)
2309 return -1;
2310
2311 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002312 if (buf == NULL)
2313 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002314
2315 rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2316 buf);
2317
2318 xmlFree(buf);
2319 return rc;
2320}
2321
2322/**
2323 * xmlTextWriterWriteElementNS:
2324 * @writer: the xmlTextWriterPtr
2325 * @prefix: namespace prefix
2326 * @name: element local name
2327 * @namespaceURI: namespace URI
2328 * @content: element content
2329 *
2330 * Write an xml element with namespace support.
2331 *
2332 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2333 */
2334int
2335xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2336 const xmlChar * prefix, const xmlChar * name,
2337 const xmlChar * namespaceURI,
2338 const xmlChar * content)
2339{
2340 int count;
2341 int sum;
2342
2343 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2344 return -1;
2345
2346 sum = 0;
2347 count =
2348 xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2349 if (count < 0)
2350 return -1;
2351 sum += count;
2352 count = xmlTextWriterWriteString(writer, content);
2353 if (count == -1)
2354 return -1;
2355 sum += count;
2356 count = xmlTextWriterEndElement(writer);
2357 if (count == -1)
2358 return -1;
2359 sum += count;
2360
2361 return sum;
2362}
2363
2364/**
2365 * xmlTextWriterStartPI:
2366 * @writer: the xmlTextWriterPtr
2367 * @target: PI target
2368 *
2369 * Start an xml PI.
2370 *
2371 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2372 */
2373int
2374xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2375{
2376 int count;
2377 int sum;
2378 xmlLinkPtr lk;
2379 xmlTextWriterStackEntry *p;
2380
2381 if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2382 return -1;
2383
2384 if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002385 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002386 "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2387 return -1;
2388 }
2389
2390 sum = 0;
2391 lk = xmlListFront(writer->nodes);
2392 if (lk != 0) {
2393 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2394 if (p != 0) {
2395 switch (p->state) {
2396 case XML_TEXTWRITER_ATTRIBUTE:
2397 count = xmlTextWriterEndAttribute(writer);
2398 if (count < 0)
2399 return -1;
2400 sum += count;
2401 /* fallthrough */
2402 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002403 /* Output namespace declarations */
2404 count = xmlTextWriterOutputNSDecl(writer);
2405 if (count < 0)
2406 return -1;
2407 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002408 count = xmlOutputBufferWriteString(writer->out, ">");
2409 if (count < 0)
2410 return -1;
2411 sum += count;
2412 p->state = XML_TEXTWRITER_TEXT;
2413 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00002414 case XML_TEXTWRITER_NONE:
2415 case XML_TEXTWRITER_TEXT:
2416 case XML_TEXTWRITER_DTD:
2417 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002418 case XML_TEXTWRITER_PI:
2419 case XML_TEXTWRITER_PI_TEXT:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002420 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002421 "xmlTextWriterStartPI : nested PI!\n");
2422 return -1;
2423 default:
2424 return -1;
2425 }
2426 }
2427 }
2428
2429 p = (xmlTextWriterStackEntry *)
2430 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2431 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002432 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002433 "xmlTextWriterStartPI : out of memory!\n");
2434 return -1;
2435 }
2436
2437 p->name = xmlStrdup(target);
2438 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002439 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002440 "xmlTextWriterStartPI : out of memory!\n");
2441 xmlFree(p);
2442 return -1;
2443 }
2444 p->state = XML_TEXTWRITER_PI;
2445
2446 xmlListPushFront(writer->nodes, p);
2447
2448 count = xmlOutputBufferWriteString(writer->out, "<?");
2449 if (count < 0)
2450 return -1;
2451 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002452 count =
2453 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002454 if (count < 0)
2455 return -1;
2456 sum += count;
2457
2458 return sum;
2459}
2460
2461/**
2462 * xmlTextWriterEndPI:
2463 * @writer: the xmlTextWriterPtr
2464 *
2465 * End the current xml PI.
2466 *
2467 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2468 */
2469int
2470xmlTextWriterEndPI(xmlTextWriterPtr writer)
2471{
2472 int count;
2473 int sum;
2474 xmlLinkPtr lk;
2475 xmlTextWriterStackEntry *p;
2476
2477 if (writer == NULL)
2478 return -1;
2479
2480 lk = xmlListFront(writer->nodes);
2481 if (lk == 0)
2482 return 0;
2483
2484 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2485 if (p == 0)
2486 return 0;
2487
2488 sum = 0;
2489 switch (p->state) {
2490 case XML_TEXTWRITER_PI:
2491 case XML_TEXTWRITER_PI_TEXT:
2492 count = xmlOutputBufferWriteString(writer->out, "?>");
2493 if (count < 0)
2494 return -1;
2495 sum += count;
2496 break;
2497 default:
2498 return -1;
2499 }
2500
Daniel Veillard02c1f232006-04-27 08:10:25 +00002501 if (writer->indent) {
2502 count = xmlOutputBufferWriteString(writer->out, "\n");
2503 if (count < 0)
2504 return -1;
2505 sum += count;
2506 }
2507
Daniel Veillard1d211e22003-10-20 22:32:39 +00002508 xmlListPopFront(writer->nodes);
2509 return sum;
2510}
2511
2512/**
2513 * xmlTextWriterWriteFormatPI:
2514 * @writer: the xmlTextWriterPtr
2515 * @target: PI target
2516 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002517 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002518 *
2519 * Write a formatted PI.
2520 *
2521 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2522 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002523int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002524xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2525 const char *format, ...)
2526{
2527 int rc;
2528 va_list ap;
2529
2530 va_start(ap, format);
2531
2532 rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2533
2534 va_end(ap);
2535 return rc;
2536}
2537
2538/**
2539 * xmlTextWriterWriteVFormatPI:
2540 * @writer: the xmlTextWriterPtr
2541 * @target: PI target
2542 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002543 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002544 *
2545 * Write a formatted xml PI.
2546 *
2547 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2548 */
2549int
2550xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2551 const xmlChar * target, const char *format,
2552 va_list argptr)
2553{
2554 int rc;
2555 xmlChar *buf;
2556
2557 if (writer == NULL)
2558 return -1;
2559
2560 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002561 if (buf == NULL)
2562 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002563
2564 rc = xmlTextWriterWritePI(writer, target, buf);
2565
2566 xmlFree(buf);
2567 return rc;
2568}
2569
2570/**
2571 * xmlTextWriterWritePI:
2572 * @writer: the xmlTextWriterPtr
2573 * @target: PI target
2574 * @content: PI content
2575 *
2576 * Write an xml PI.
2577 *
2578 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2579 */
2580int
2581xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2582 const xmlChar * content)
2583{
2584 int count;
2585 int sum;
2586
2587 sum = 0;
2588 count = xmlTextWriterStartPI(writer, target);
2589 if (count == -1)
2590 return -1;
2591 sum += count;
2592 if (content != 0) {
2593 count = xmlTextWriterWriteString(writer, content);
2594 if (count == -1)
2595 return -1;
2596 sum += count;
2597 }
2598 count = xmlTextWriterEndPI(writer);
2599 if (count == -1)
2600 return -1;
2601 sum += count;
2602
2603 return sum;
2604}
2605
2606/**
2607 * xmlTextWriterStartCDATA:
2608 * @writer: the xmlTextWriterPtr
2609 *
2610 * Start an xml CDATA section.
2611 *
2612 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2613 */
2614int
2615xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2616{
2617 int count;
2618 int sum;
2619 xmlLinkPtr lk;
2620 xmlTextWriterStackEntry *p;
2621
2622 if (writer == NULL)
2623 return -1;
2624
2625 sum = 0;
2626 lk = xmlListFront(writer->nodes);
2627 if (lk != 0) {
2628 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2629 if (p != 0) {
2630 switch (p->state) {
2631 case XML_TEXTWRITER_NONE:
Daniel Veillardccc476f2008-03-04 13:19:49 +00002632 case XML_TEXTWRITER_TEXT:
Daniel Veillard1d211e22003-10-20 22:32:39 +00002633 case XML_TEXTWRITER_PI:
2634 case XML_TEXTWRITER_PI_TEXT:
2635 break;
2636 case XML_TEXTWRITER_ATTRIBUTE:
2637 count = xmlTextWriterEndAttribute(writer);
2638 if (count < 0)
2639 return -1;
2640 sum += count;
2641 /* fallthrough */
2642 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002643 /* Output namespace declarations */
2644 count = xmlTextWriterOutputNSDecl(writer);
2645 if (count < 0)
2646 return -1;
2647 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002648 count = xmlOutputBufferWriteString(writer->out, ">");
2649 if (count < 0)
2650 return -1;
2651 sum += count;
2652 p->state = XML_TEXTWRITER_TEXT;
2653 break;
2654 case XML_TEXTWRITER_CDATA:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002655 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002656 "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2657 return -1;
2658 default:
2659 return -1;
2660 }
2661 }
2662 }
2663
2664 p = (xmlTextWriterStackEntry *)
2665 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2666 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002667 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002668 "xmlTextWriterStartCDATA : out of memory!\n");
2669 return -1;
2670 }
2671
Daniel Veillard75e389d2005-07-29 22:02:24 +00002672 p->name = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002673 p->state = XML_TEXTWRITER_CDATA;
2674
2675 xmlListPushFront(writer->nodes, p);
2676
2677 count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2678 if (count < 0)
2679 return -1;
2680 sum += count;
2681
2682 return sum;
2683}
2684
2685/**
2686 * xmlTextWriterEndCDATA:
2687 * @writer: the xmlTextWriterPtr
2688 *
2689 * End an xml CDATA section.
2690 *
2691 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2692 */
2693int
2694xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2695{
2696 int count;
2697 int sum;
2698 xmlLinkPtr lk;
2699 xmlTextWriterStackEntry *p;
2700
2701 if (writer == NULL)
2702 return -1;
2703
2704 lk = xmlListFront(writer->nodes);
2705 if (lk == 0)
2706 return -1;
2707
2708 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2709 if (p == 0)
2710 return -1;
2711
2712 sum = 0;
2713 switch (p->state) {
2714 case XML_TEXTWRITER_CDATA:
2715 count = xmlOutputBufferWriteString(writer->out, "]]>");
2716 if (count < 0)
2717 return -1;
2718 sum += count;
2719 break;
2720 default:
2721 return -1;
2722 }
2723
2724 xmlListPopFront(writer->nodes);
2725 return sum;
2726}
2727
2728/**
2729 * xmlTextWriterWriteFormatCDATA:
2730 * @writer: the xmlTextWriterPtr
2731 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002732 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002733 *
2734 * Write a formatted xml CDATA.
2735 *
2736 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2737 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002738int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002739xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2740 ...)
2741{
2742 int rc;
2743 va_list ap;
2744
2745 va_start(ap, format);
2746
2747 rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2748
2749 va_end(ap);
2750 return rc;
2751}
2752
2753/**
2754 * xmlTextWriterWriteVFormatCDATA:
2755 * @writer: the xmlTextWriterPtr
2756 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002757 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002758 *
2759 * Write a formatted xml CDATA.
2760 *
2761 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2762 */
2763int
2764xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2765 va_list argptr)
2766{
2767 int rc;
2768 xmlChar *buf;
2769
2770 if (writer == NULL)
2771 return -1;
2772
2773 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002774 if (buf == NULL)
2775 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002776
2777 rc = xmlTextWriterWriteCDATA(writer, buf);
2778
2779 xmlFree(buf);
2780 return rc;
2781}
2782
2783/**
2784 * xmlTextWriterWriteCDATA:
2785 * @writer: the xmlTextWriterPtr
2786 * @content: CDATA content
2787 *
2788 * Write an xml CDATA.
2789 *
2790 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2791 */
2792int
2793xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2794{
2795 int count;
2796 int sum;
2797
2798 sum = 0;
2799 count = xmlTextWriterStartCDATA(writer);
2800 if (count == -1)
2801 return -1;
2802 sum += count;
2803 if (content != 0) {
2804 count = xmlTextWriterWriteString(writer, content);
2805 if (count == -1)
2806 return -1;
2807 sum += count;
2808 }
2809 count = xmlTextWriterEndCDATA(writer);
2810 if (count == -1)
2811 return -1;
2812 sum += count;
2813
2814 return sum;
2815}
2816
2817/**
2818 * xmlTextWriterStartDTD:
2819 * @writer: the xmlTextWriterPtr
2820 * @name: the name of the DTD
2821 * @pubid: the public identifier, which is an alternative to the system identifier
2822 * @sysid: the system identifier, which is the URI of the DTD
2823 *
2824 * Start an xml DTD.
2825 *
2826 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2827 */
2828int
2829xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2830 const xmlChar * name,
2831 const xmlChar * pubid, const xmlChar * sysid)
2832{
2833 int count;
2834 int sum;
2835 xmlLinkPtr lk;
2836 xmlTextWriterStackEntry *p;
2837
2838 if (writer == NULL || name == NULL || *name == '\0')
2839 return -1;
2840
2841 sum = 0;
2842 lk = xmlListFront(writer->nodes);
Daniel Veillardab69f362004-02-17 11:40:32 +00002843 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002844 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002845 "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2846 return -1;
2847 }
2848
2849 p = (xmlTextWriterStackEntry *)
2850 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2851 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002852 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002853 "xmlTextWriterStartDTD : out of memory!\n");
2854 return -1;
2855 }
2856
2857 p->name = xmlStrdup(name);
2858 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002859 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002860 "xmlTextWriterStartDTD : out of memory!\n");
2861 xmlFree(p);
2862 return -1;
2863 }
2864 p->state = XML_TEXTWRITER_DTD;
2865
2866 xmlListPushFront(writer->nodes, p);
2867
2868 count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2869 if (count < 0)
2870 return -1;
2871 sum += count;
2872 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2873 if (count < 0)
2874 return -1;
2875 sum += count;
2876
2877 if (pubid != 0) {
2878 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002879 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002880 "xmlTextWriterStartDTD : system identifier needed!\n");
2881 return -1;
2882 }
2883
Daniel Veillard500a1de2004-03-22 15:22:58 +00002884 if (writer->indent)
2885 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2886 else
2887 count = xmlOutputBufferWrite(writer->out, 1, " ");
2888 if (count < 0)
2889 return -1;
2890 sum += count;
2891
2892 count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2893 if (count < 0)
2894 return -1;
2895 sum += count;
2896
2897 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002898 if (count < 0)
2899 return -1;
2900 sum += count;
2901
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002902 count =
2903 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002904 if (count < 0)
2905 return -1;
2906 sum += count;
2907
Daniel Veillard500a1de2004-03-22 15:22:58 +00002908 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002909 if (count < 0)
2910 return -1;
2911 sum += count;
2912 }
2913
2914 if (sysid != 0) {
2915 if (pubid == 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00002916 if (writer->indent)
2917 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2918 else
2919 count = xmlOutputBufferWrite(writer->out, 1, " ");
2920 if (count < 0)
2921 return -1;
2922 sum += count;
2923 count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2924 if (count < 0)
2925 return -1;
2926 sum += count;
Rob Richardsffe47fe2005-12-09 17:52:21 +00002927 } else {
2928 if (writer->indent)
Daniel Veillard500a1de2004-03-22 15:22:58 +00002929 count = xmlOutputBufferWriteString(writer->out, "\n ");
Rob Richardsffe47fe2005-12-09 17:52:21 +00002930 else
2931 count = xmlOutputBufferWrite(writer->out, 1, " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00002932 if (count < 0)
2933 return -1;
2934 sum += count;
2935 }
2936
Daniel Veillard500a1de2004-03-22 15:22:58 +00002937 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002938 if (count < 0)
2939 return -1;
2940 sum += count;
2941
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002942 count =
2943 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002944 if (count < 0)
2945 return -1;
2946 sum += count;
2947
Daniel Veillard500a1de2004-03-22 15:22:58 +00002948 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002949 if (count < 0)
2950 return -1;
2951 sum += count;
2952 }
2953
2954 return sum;
2955}
2956
2957/**
2958 * xmlTextWriterEndDTD:
2959 * @writer: the xmlTextWriterPtr
2960 *
2961 * End an xml DTD.
2962 *
2963 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2964 */
2965int
2966xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2967{
Daniel Veillard500a1de2004-03-22 15:22:58 +00002968 int loop;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002969 int count;
2970 int sum;
2971 xmlLinkPtr lk;
2972 xmlTextWriterStackEntry *p;
2973
2974 if (writer == NULL)
2975 return -1;
2976
2977 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002978 loop = 1;
2979 while (loop) {
2980 lk = xmlListFront(writer->nodes);
2981 if (lk == NULL)
Daniel Veillard1d211e22003-10-20 22:32:39 +00002982 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002983 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2984 if (p == 0)
2985 break;
2986 switch (p->state) {
2987 case XML_TEXTWRITER_DTD_TEXT:
2988 count = xmlOutputBufferWriteString(writer->out, "]");
2989 if (count < 0)
2990 return -1;
2991 sum += count;
2992 /* fallthrough */
2993 case XML_TEXTWRITER_DTD:
2994 count = xmlOutputBufferWriteString(writer->out, ">");
2995
2996 if (writer->indent) {
2997 if (count < 0)
2998 return -1;
2999 sum += count;
3000 count = xmlOutputBufferWriteString(writer->out, "\n");
3001 }
3002
3003 xmlListPopFront(writer->nodes);
3004 break;
3005 case XML_TEXTWRITER_DTD_ELEM:
3006 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3007 count = xmlTextWriterEndDTDElement(writer);
3008 break;
3009 case XML_TEXTWRITER_DTD_ATTL:
3010 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3011 count = xmlTextWriterEndDTDAttlist(writer);
3012 break;
3013 case XML_TEXTWRITER_DTD_ENTY:
3014 case XML_TEXTWRITER_DTD_PENT:
3015 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3016 count = xmlTextWriterEndDTDEntity(writer);
3017 break;
3018 case XML_TEXTWRITER_COMMENT:
3019 count = xmlTextWriterEndComment(writer);
3020 break;
3021 default:
3022 loop = 0;
3023 continue;
3024 }
3025
3026 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00003027 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003028 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003029 }
3030
Daniel Veillard1d211e22003-10-20 22:32:39 +00003031 return sum;
3032}
3033
3034/**
3035 * xmlTextWriterWriteFormatDTD:
3036 * @writer: the xmlTextWriterPtr
3037 * @name: the name of the DTD
3038 * @pubid: the public identifier, which is an alternative to the system identifier
3039 * @sysid: the system identifier, which is the URI of the DTD
3040 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003041 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00003042 *
3043 * Write a DTD with a formatted markup declarations part.
3044 *
3045 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3046 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003047int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003048xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3049 const xmlChar * name,
3050 const xmlChar * pubid,
3051 const xmlChar * sysid, const char *format, ...)
3052{
3053 int rc;
3054 va_list ap;
3055
3056 va_start(ap, format);
3057
3058 rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3059 ap);
3060
3061 va_end(ap);
3062 return rc;
3063}
3064
3065/**
3066 * xmlTextWriterWriteVFormatDTD:
3067 * @writer: the xmlTextWriterPtr
3068 * @name: the name of the DTD
3069 * @pubid: the public identifier, which is an alternative to the system identifier
3070 * @sysid: the system identifier, which is the URI of the DTD
3071 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003072 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00003073 *
3074 * Write a DTD with a formatted markup declarations part.
3075 *
3076 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3077 */
3078int
3079xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3080 const xmlChar * name,
3081 const xmlChar * pubid,
3082 const xmlChar * sysid,
3083 const char *format, va_list argptr)
3084{
3085 int rc;
3086 xmlChar *buf;
3087
3088 if (writer == NULL)
3089 return -1;
3090
3091 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003092 if (buf == NULL)
3093 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003094
3095 rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3096
3097 xmlFree(buf);
3098 return rc;
3099}
3100
3101/**
3102 * xmlTextWriterWriteDTD:
3103 * @writer: the xmlTextWriterPtr
3104 * @name: the name of the DTD
3105 * @pubid: the public identifier, which is an alternative to the system identifier
3106 * @sysid: the system identifier, which is the URI of the DTD
William M. Brackb1d53162003-11-18 06:54:40 +00003107 * @subset: string content of the DTD
Daniel Veillard1d211e22003-10-20 22:32:39 +00003108 *
3109 * Write a DTD.
3110 *
3111 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3112 */
3113int
3114xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3115 const xmlChar * name,
3116 const xmlChar * pubid,
3117 const xmlChar * sysid, const xmlChar * subset)
3118{
3119 int count;
3120 int sum;
3121
3122 sum = 0;
3123 count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3124 if (count == -1)
3125 return -1;
3126 sum += count;
3127 if (subset != 0) {
3128 count = xmlTextWriterWriteString(writer, subset);
3129 if (count == -1)
3130 return -1;
3131 sum += count;
3132 }
3133 count = xmlTextWriterEndDTD(writer);
3134 if (count == -1)
3135 return -1;
3136 sum += count;
3137
3138 return sum;
3139}
3140
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003141/**
3142 * xmlTextWriterStartDTDElement:
3143 * @writer: the xmlTextWriterPtr
3144 * @name: the name of the DTD element
3145 *
3146 * Start an xml DTD element.
3147 *
3148 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3149 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003150int
3151xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3152{
3153 int count;
3154 int sum;
3155 xmlLinkPtr lk;
3156 xmlTextWriterStackEntry *p;
3157
3158 if (writer == NULL || name == NULL || *name == '\0')
3159 return -1;
3160
3161 sum = 0;
3162 lk = xmlListFront(writer->nodes);
3163 if (lk == 0) {
3164 return -1;
3165 }
3166
3167 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003168 if (p != 0) {
3169 switch (p->state) {
3170 case XML_TEXTWRITER_DTD:
3171 count = xmlOutputBufferWriteString(writer->out, " [");
3172 if (count < 0)
3173 return -1;
3174 sum += count;
3175 if (writer->indent) {
3176 count = xmlOutputBufferWriteString(writer->out, "\n");
3177 if (count < 0)
3178 return -1;
3179 sum += count;
3180 }
3181 p->state = XML_TEXTWRITER_DTD_TEXT;
3182 /* fallthrough */
3183 case XML_TEXTWRITER_DTD_TEXT:
3184 case XML_TEXTWRITER_NONE:
3185 break;
3186 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003187 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003188 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003189 }
3190
3191 p = (xmlTextWriterStackEntry *)
3192 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3193 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003194 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003195 "xmlTextWriterStartDTDElement : out of memory!\n");
3196 return -1;
3197 }
3198
3199 p->name = xmlStrdup(name);
3200 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003201 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003202 "xmlTextWriterStartDTDElement : out of memory!\n");
3203 xmlFree(p);
3204 return -1;
3205 }
3206 p->state = XML_TEXTWRITER_DTD_ELEM;
3207
3208 xmlListPushFront(writer->nodes, p);
3209
Daniel Veillard500a1de2004-03-22 15:22:58 +00003210 if (writer->indent) {
3211 count = xmlTextWriterWriteIndent(writer);
3212 if (count < 0)
3213 return -1;
3214 sum += count;
3215 }
3216
Daniel Veillard1d211e22003-10-20 22:32:39 +00003217 count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3218 if (count < 0)
3219 return -1;
3220 sum += count;
3221 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3222 if (count < 0)
3223 return -1;
3224 sum += count;
3225
3226 return sum;
3227}
3228
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003229/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003230 * xmlTextWriterEndDTDElement:
3231 * @writer: the xmlTextWriterPtr
3232 *
3233 * End an xml DTD element.
3234 *
3235 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3236 */
3237int
3238xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3239{
3240 int count;
3241 int sum;
3242 xmlLinkPtr lk;
3243 xmlTextWriterStackEntry *p;
3244
3245 if (writer == NULL)
3246 return -1;
3247
3248 sum = 0;
3249 lk = xmlListFront(writer->nodes);
3250 if (lk == 0)
3251 return -1;
3252
3253 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3254 if (p == 0)
3255 return -1;
3256
3257 switch (p->state) {
3258 case XML_TEXTWRITER_DTD_ELEM:
3259 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3260 count = xmlOutputBufferWriteString(writer->out, ">");
3261 if (count < 0)
3262 return -1;
3263 sum += count;
3264 break;
3265 default:
3266 return -1;
3267 }
3268
3269 if (writer->indent) {
3270 count = xmlOutputBufferWriteString(writer->out, "\n");
3271 if (count < 0)
3272 return -1;
3273 sum += count;
3274 }
3275
3276 xmlListPopFront(writer->nodes);
3277 return sum;
3278}
3279
3280/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003281 * xmlTextWriterWriteFormatDTDElement:
3282 * @writer: the xmlTextWriterPtr
3283 * @name: the name of the DTD element
3284 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003285 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003286 *
3287 * Write a formatted DTD element.
3288 *
3289 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3290 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003291int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003292xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3293 const xmlChar * name,
3294 const char *format, ...)
3295{
3296 int rc;
3297 va_list ap;
3298
3299 va_start(ap, format);
3300
3301 rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3302
3303 va_end(ap);
3304 return rc;
3305}
3306
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003307/**
3308 * xmlTextWriterWriteVFormatDTDElement:
3309 * @writer: the xmlTextWriterPtr
3310 * @name: the name of the DTD element
3311 * @format: format string (see printf)
3312 * @argptr: pointer to the first member of the variable argument list.
3313 *
3314 * Write a formatted DTD element.
3315 *
3316 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3317 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003318int
3319xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3320 const xmlChar * name,
3321 const char *format, va_list argptr)
3322{
3323 int rc;
3324 xmlChar *buf;
3325
3326 if (writer == NULL)
3327 return -1;
3328
3329 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003330 if (buf == NULL)
3331 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003332
3333 rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3334
3335 xmlFree(buf);
3336 return rc;
3337}
3338
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003339/**
3340 * xmlTextWriterWriteDTDElement:
3341 * @writer: the xmlTextWriterPtr
3342 * @name: the name of the DTD element
3343 * @content: content of the element
3344 *
3345 * Write a DTD element.
3346 *
3347 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3348 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003349int
3350xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3351 const xmlChar * name, const xmlChar * content)
3352{
3353 int count;
3354 int sum;
3355
3356 if (content == NULL)
3357 return -1;
3358
3359 sum = 0;
3360 count = xmlTextWriterStartDTDElement(writer, name);
3361 if (count == -1)
3362 return -1;
3363 sum += count;
3364
Daniel Veillard1d211e22003-10-20 22:32:39 +00003365 count = xmlTextWriterWriteString(writer, content);
3366 if (count == -1)
3367 return -1;
3368 sum += count;
3369
3370 count = xmlTextWriterEndDTDElement(writer);
3371 if (count == -1)
3372 return -1;
3373 sum += count;
3374
3375 return sum;
3376}
3377
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003378/**
3379 * xmlTextWriterStartDTDAttlist:
3380 * @writer: the xmlTextWriterPtr
3381 * @name: the name of the DTD ATTLIST
3382 *
3383 * Start an xml DTD ATTLIST.
3384 *
3385 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3386 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003387int
3388xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3389{
3390 int count;
3391 int sum;
3392 xmlLinkPtr lk;
3393 xmlTextWriterStackEntry *p;
3394
3395 if (writer == NULL || name == NULL || *name == '\0')
3396 return -1;
3397
3398 sum = 0;
3399 lk = xmlListFront(writer->nodes);
3400 if (lk == 0) {
3401 return -1;
3402 }
3403
3404 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003405 if (p != 0) {
3406 switch (p->state) {
3407 case XML_TEXTWRITER_DTD:
3408 count = xmlOutputBufferWriteString(writer->out, " [");
3409 if (count < 0)
3410 return -1;
3411 sum += count;
3412 if (writer->indent) {
3413 count = xmlOutputBufferWriteString(writer->out, "\n");
3414 if (count < 0)
3415 return -1;
3416 sum += count;
3417 }
3418 p->state = XML_TEXTWRITER_DTD_TEXT;
3419 /* fallthrough */
3420 case XML_TEXTWRITER_DTD_TEXT:
3421 case XML_TEXTWRITER_NONE:
3422 break;
3423 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003424 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003425 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003426 }
3427
3428 p = (xmlTextWriterStackEntry *)
3429 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3430 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003431 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003432 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3433 return -1;
3434 }
3435
3436 p->name = xmlStrdup(name);
3437 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003438 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003439 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3440 xmlFree(p);
3441 return -1;
3442 }
3443 p->state = XML_TEXTWRITER_DTD_ATTL;
3444
3445 xmlListPushFront(writer->nodes, p);
3446
Daniel Veillard500a1de2004-03-22 15:22:58 +00003447 if (writer->indent) {
3448 count = xmlTextWriterWriteIndent(writer);
3449 if (count < 0)
3450 return -1;
3451 sum += count;
3452 }
3453
Daniel Veillard1d211e22003-10-20 22:32:39 +00003454 count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3455 if (count < 0)
3456 return -1;
3457 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +00003458 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003459 if (count < 0)
3460 return -1;
3461 sum += count;
3462
3463 return sum;
3464}
3465
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003466/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003467 * xmlTextWriterEndDTDAttlist:
3468 * @writer: the xmlTextWriterPtr
3469 *
3470 * End an xml DTD attribute list.
3471 *
3472 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3473 */
3474int
3475xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3476{
3477 int count;
3478 int sum;
3479 xmlLinkPtr lk;
3480 xmlTextWriterStackEntry *p;
3481
3482 if (writer == NULL)
3483 return -1;
3484
3485 sum = 0;
3486 lk = xmlListFront(writer->nodes);
3487 if (lk == 0)
3488 return -1;
3489
3490 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3491 if (p == 0)
3492 return -1;
3493
3494 switch (p->state) {
3495 case XML_TEXTWRITER_DTD_ATTL:
3496 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3497 count = xmlOutputBufferWriteString(writer->out, ">");
3498 if (count < 0)
3499 return -1;
3500 sum += count;
3501 break;
3502 default:
3503 return -1;
3504 }
3505
3506 if (writer->indent) {
3507 count = xmlOutputBufferWriteString(writer->out, "\n");
3508 if (count < 0)
3509 return -1;
3510 sum += count;
3511 }
3512
3513 xmlListPopFront(writer->nodes);
3514 return sum;
3515}
3516
3517/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003518 * xmlTextWriterWriteFormatDTDAttlist:
3519 * @writer: the xmlTextWriterPtr
3520 * @name: the name of the DTD ATTLIST
3521 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003522 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003523 *
3524 * Write a formatted DTD ATTLIST.
3525 *
3526 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3527 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003528int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003529xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3530 const xmlChar * name,
3531 const char *format, ...)
3532{
3533 int rc;
3534 va_list ap;
3535
3536 va_start(ap, format);
3537
3538 rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3539
3540 va_end(ap);
3541 return rc;
3542}
3543
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003544/**
3545 * xmlTextWriterWriteVFormatDTDAttlist:
3546 * @writer: the xmlTextWriterPtr
3547 * @name: the name of the DTD ATTLIST
3548 * @format: format string (see printf)
3549 * @argptr: pointer to the first member of the variable argument list.
3550 *
3551 * Write a formatted DTD ATTLIST.
3552 *
3553 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3554 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003555int
3556xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3557 const xmlChar * name,
3558 const char *format, va_list argptr)
3559{
3560 int rc;
3561 xmlChar *buf;
3562
3563 if (writer == NULL)
3564 return -1;
3565
3566 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003567 if (buf == NULL)
3568 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003569
3570 rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3571
3572 xmlFree(buf);
3573 return rc;
3574}
3575
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003576/**
3577 * xmlTextWriterWriteDTDAttlist:
3578 * @writer: the xmlTextWriterPtr
3579 * @name: the name of the DTD ATTLIST
3580 * @content: content of the ATTLIST
3581 *
3582 * Write a DTD ATTLIST.
3583 *
3584 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3585 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003586int
3587xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3588 const xmlChar * name, const xmlChar * content)
3589{
3590 int count;
3591 int sum;
3592
3593 if (content == NULL)
3594 return -1;
3595
3596 sum = 0;
3597 count = xmlTextWriterStartDTDAttlist(writer, name);
3598 if (count == -1)
3599 return -1;
3600 sum += count;
3601
Daniel Veillard1d211e22003-10-20 22:32:39 +00003602 count = xmlTextWriterWriteString(writer, content);
3603 if (count == -1)
3604 return -1;
3605 sum += count;
3606
3607 count = xmlTextWriterEndDTDAttlist(writer);
3608 if (count == -1)
3609 return -1;
3610 sum += count;
3611
3612 return sum;
3613}
3614
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003615/**
3616 * xmlTextWriterStartDTDEntity:
3617 * @writer: the xmlTextWriterPtr
3618 * @pe: TRUE if this is a parameter entity, FALSE if not
3619 * @name: the name of the DTD ATTLIST
3620 *
3621 * Start an xml DTD ATTLIST.
3622 *
3623 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3624 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003625int
3626xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3627 int pe, const xmlChar * name)
3628{
3629 int count;
3630 int sum;
3631 xmlLinkPtr lk;
3632 xmlTextWriterStackEntry *p;
3633
3634 if (writer == NULL || name == NULL || *name == '\0')
3635 return -1;
3636
3637 sum = 0;
3638 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003639 if (lk != 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00003640
Daniel Veillard500a1de2004-03-22 15:22:58 +00003641 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3642 if (p != 0) {
3643 switch (p->state) {
3644 case XML_TEXTWRITER_DTD:
3645 count = xmlOutputBufferWriteString(writer->out, " [");
3646 if (count < 0)
3647 return -1;
3648 sum += count;
3649 if (writer->indent) {
3650 count =
3651 xmlOutputBufferWriteString(writer->out, "\n");
3652 if (count < 0)
3653 return -1;
3654 sum += count;
3655 }
3656 p->state = XML_TEXTWRITER_DTD_TEXT;
3657 /* fallthrough */
3658 case XML_TEXTWRITER_DTD_TEXT:
3659 case XML_TEXTWRITER_NONE:
3660 break;
3661 default:
3662 return -1;
3663 }
3664 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003665 }
3666
3667 p = (xmlTextWriterStackEntry *)
3668 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3669 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003670 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003671 "xmlTextWriterStartDTDElement : out of memory!\n");
3672 return -1;
3673 }
3674
3675 p->name = xmlStrdup(name);
3676 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003677 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003678 "xmlTextWriterStartDTDElement : out of memory!\n");
3679 xmlFree(p);
3680 return -1;
3681 }
Daniel Veillard500a1de2004-03-22 15:22:58 +00003682
3683 if (pe != 0)
3684 p->state = XML_TEXTWRITER_DTD_PENT;
3685 else
3686 p->state = XML_TEXTWRITER_DTD_ENTY;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003687
3688 xmlListPushFront(writer->nodes, p);
3689
Daniel Veillard500a1de2004-03-22 15:22:58 +00003690 if (writer->indent) {
3691 count = xmlTextWriterWriteIndent(writer);
3692 if (count < 0)
3693 return -1;
3694 sum += count;
3695 }
3696
Daniel Veillard1d211e22003-10-20 22:32:39 +00003697 count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3698 if (count < 0)
3699 return -1;
3700 sum += count;
3701
3702 if (pe != 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00003703 count = xmlOutputBufferWriteString(writer->out, "% ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003704 if (count < 0)
3705 return -1;
3706 sum += count;
3707 }
3708
Daniel Veillardab69f362004-02-17 11:40:32 +00003709 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003710 if (count < 0)
3711 return -1;
3712 sum += count;
3713
3714 return sum;
3715}
3716
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003717/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003718 * xmlTextWriterEndDTDEntity:
3719 * @writer: the xmlTextWriterPtr
3720 *
3721 * End an xml DTD entity.
3722 *
3723 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3724 */
3725int
3726xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3727{
3728 int count;
3729 int sum;
3730 xmlLinkPtr lk;
3731 xmlTextWriterStackEntry *p;
3732
3733 if (writer == NULL)
3734 return -1;
3735
3736 sum = 0;
3737 lk = xmlListFront(writer->nodes);
3738 if (lk == 0)
3739 return -1;
3740
3741 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3742 if (p == 0)
3743 return -1;
3744
3745 switch (p->state) {
3746 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3747 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3748 if (count < 0)
3749 return -1;
3750 sum += count;
3751 case XML_TEXTWRITER_DTD_ENTY:
3752 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard500a1de2004-03-22 15:22:58 +00003753 count = xmlOutputBufferWriteString(writer->out, ">");
3754 if (count < 0)
3755 return -1;
3756 sum += count;
3757 break;
3758 default:
3759 return -1;
3760 }
3761
3762 if (writer->indent) {
3763 count = xmlOutputBufferWriteString(writer->out, "\n");
3764 if (count < 0)
3765 return -1;
3766 sum += count;
3767 }
3768
3769 xmlListPopFront(writer->nodes);
3770 return sum;
3771}
3772
3773/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003774 * xmlTextWriterWriteFormatDTDInternalEntity:
3775 * @writer: the xmlTextWriterPtr
3776 * @pe: TRUE if this is a parameter entity, FALSE if not
3777 * @name: the name of the DTD entity
3778 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003779 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003780 *
3781 * Write a formatted DTD internal entity.
3782 *
3783 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3784 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003785int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003786xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3787 int pe,
3788 const xmlChar * name,
3789 const char *format, ...)
3790{
3791 int rc;
3792 va_list ap;
3793
3794 va_start(ap, format);
3795
3796 rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3797 format, ap);
3798
3799 va_end(ap);
3800 return rc;
3801}
3802
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003803/**
3804 * xmlTextWriterWriteVFormatDTDInternalEntity:
3805 * @writer: the xmlTextWriterPtr
3806 * @pe: TRUE if this is a parameter entity, FALSE if not
3807 * @name: the name of the DTD entity
3808 * @format: format string (see printf)
3809 * @argptr: pointer to the first member of the variable argument list.
3810 *
3811 * Write a formatted DTD internal entity.
3812 *
3813 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3814 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003815int
3816xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3817 int pe,
3818 const xmlChar * name,
3819 const char *format,
3820 va_list argptr)
3821{
3822 int rc;
3823 xmlChar *buf;
3824
3825 if (writer == NULL)
3826 return -1;
3827
3828 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003829 if (buf == NULL)
3830 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003831
3832 rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3833
3834 xmlFree(buf);
3835 return rc;
3836}
3837
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003838/**
3839 * xmlTextWriterWriteDTDEntity:
3840 * @writer: the xmlTextWriterPtr
3841 * @pe: TRUE if this is a parameter entity, FALSE if not
3842 * @name: the name of the DTD entity
3843 * @pubid: the public identifier, which is an alternative to the system identifier
3844 * @sysid: the system identifier, which is the URI of the DTD
3845 * @ndataid: the xml notation name.
3846 * @content: content of the entity
3847 *
3848 * Write a DTD entity.
3849 *
3850 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3851 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003852int
3853xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3854 int pe,
3855 const xmlChar * name,
3856 const xmlChar * pubid,
3857 const xmlChar * sysid,
3858 const xmlChar * ndataid,
3859 const xmlChar * content)
3860{
Daniel Veillard500a1de2004-03-22 15:22:58 +00003861 if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003862 return -1;
3863 if ((pe != 0) && (ndataid != NULL))
3864 return -1;
3865
Daniel Veillard500a1de2004-03-22 15:22:58 +00003866 if ((pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003867 return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3868 content);
3869
3870 return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3871 sysid, ndataid);
3872}
3873
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003874/**
3875 * xmlTextWriterWriteDTDInternalEntity:
3876 * @writer: the xmlTextWriterPtr
3877 * @pe: TRUE if this is a parameter entity, FALSE if not
3878 * @name: the name of the DTD entity
3879 * @content: content of the entity
3880 *
3881 * Write a DTD internal entity.
3882 *
3883 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3884 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003885int
3886xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3887 int pe,
3888 const xmlChar * name,
3889 const xmlChar * content)
3890{
3891 int count;
3892 int sum;
3893
3894 if ((name == NULL) || (*name == '\0') || (content == NULL))
3895 return -1;
3896
3897 sum = 0;
3898 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3899 if (count == -1)
3900 return -1;
3901 sum += count;
3902
Daniel Veillard1d211e22003-10-20 22:32:39 +00003903 count = xmlTextWriterWriteString(writer, content);
3904 if (count == -1)
3905 return -1;
3906 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003907
3908 count = xmlTextWriterEndDTDEntity(writer);
3909 if (count == -1)
3910 return -1;
3911 sum += count;
3912
3913 return sum;
3914}
3915
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003916/**
3917 * xmlTextWriterWriteDTDExternalEntity:
3918 * @writer: the xmlTextWriterPtr
3919 * @pe: TRUE if this is a parameter entity, FALSE if not
3920 * @name: the name of the DTD entity
3921 * @pubid: the public identifier, which is an alternative to the system identifier
3922 * @sysid: the system identifier, which is the URI of the DTD
3923 * @ndataid: the xml notation name.
3924 *
Daniel Veillard500a1de2004-03-22 15:22:58 +00003925 * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003926 *
3927 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3928 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003929int
3930xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3931 int pe,
3932 const xmlChar * name,
3933 const xmlChar * pubid,
3934 const xmlChar * sysid,
3935 const xmlChar * ndataid)
3936{
3937 int count;
3938 int sum;
3939
Daniel Veillard500a1de2004-03-22 15:22:58 +00003940 if (((pubid == NULL) && (sysid == NULL)))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003941 return -1;
3942 if ((pe != 0) && (ndataid != NULL))
3943 return -1;
3944
3945 sum = 0;
3946 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3947 if (count == -1)
3948 return -1;
3949 sum += count;
3950
Daniel Veillard500a1de2004-03-22 15:22:58 +00003951 count =
3952 xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3953 ndataid);
3954 if (count < 0)
3955 return -1;
3956 sum += count;
3957
3958 count = xmlTextWriterEndDTDEntity(writer);
3959 if (count == -1)
3960 return -1;
3961 sum += count;
3962
3963 return sum;
3964}
3965
3966/**
3967 * xmlTextWriterWriteDTDExternalEntityContents:
3968 * @writer: the xmlTextWriterPtr
3969 * @pubid: the public identifier, which is an alternative to the system identifier
3970 * @sysid: the system identifier, which is the URI of the DTD
3971 * @ndataid: the xml notation name.
3972 *
3973 * Write the contents of a DTD external entity.
3974 *
3975 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3976 */
3977int
3978xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3979 const xmlChar * pubid,
3980 const xmlChar * sysid,
3981 const xmlChar * ndataid)
3982{
3983 int count;
3984 int sum;
3985 xmlLinkPtr lk;
3986 xmlTextWriterStackEntry *p;
3987
3988 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003989 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003990 "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3991 return -1;
3992 }
3993
3994 sum = 0;
3995 lk = xmlListFront(writer->nodes);
3996 if (lk == 0) {
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
4002 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4003 if (p == 0)
4004 return -1;
4005
4006 switch (p->state) {
4007 case XML_TEXTWRITER_DTD_ENTY:
4008 break;
4009 case XML_TEXTWRITER_DTD_PENT:
4010 if (ndataid != NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004011 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004012 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
4013 return -1;
4014 }
4015 break;
4016 default:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004017 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004018 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4019 return -1;
4020 }
4021
Daniel Veillard1d211e22003-10-20 22:32:39 +00004022 if (pubid != 0) {
4023 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004024 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004025 "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00004026 return -1;
4027 }
4028
4029 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4030 if (count < 0)
4031 return -1;
4032 sum += count;
4033
4034 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4035 if (count < 0)
4036 return -1;
4037 sum += count;
4038
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004039 count =
4040 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004041 if (count < 0)
4042 return -1;
4043 sum += count;
4044
4045 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4046 if (count < 0)
4047 return -1;
4048 sum += count;
4049 }
4050
4051 if (sysid != 0) {
4052 if (pubid == 0) {
4053 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4054 if (count < 0)
4055 return -1;
4056 sum += count;
4057 }
4058
4059 count = xmlOutputBufferWriteString(writer->out, " ");
4060 if (count < 0)
4061 return -1;
4062 sum += count;
4063
4064 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4065 if (count < 0)
4066 return -1;
4067 sum += count;
4068
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004069 count =
4070 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004071 if (count < 0)
4072 return -1;
4073 sum += count;
4074
4075 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4076 if (count < 0)
4077 return -1;
4078 sum += count;
4079 }
4080
4081 if (ndataid != NULL) {
4082 count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4083 if (count < 0)
4084 return -1;
4085 sum += count;
4086
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004087 count =
4088 xmlOutputBufferWriteString(writer->out,
4089 (const char *) ndataid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004090 if (count < 0)
4091 return -1;
4092 sum += count;
4093 }
4094
Daniel Veillard1d211e22003-10-20 22:32:39 +00004095 return sum;
4096}
4097
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004098/**
4099 * xmlTextWriterWriteDTDNotation:
4100 * @writer: the xmlTextWriterPtr
4101 * @name: the name of the xml notation
4102 * @pubid: the public identifier, which is an alternative to the system identifier
4103 * @sysid: the system identifier, which is the URI of the DTD
4104 *
4105 * Write a DTD entity.
4106 *
4107 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4108 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00004109int
4110xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4111 const xmlChar * name,
4112 const xmlChar * pubid, const xmlChar * sysid)
4113{
4114 int count;
4115 int sum;
4116 xmlLinkPtr lk;
4117 xmlTextWriterStackEntry *p;
4118
4119 if (writer == NULL || name == NULL || *name == '\0')
4120 return -1;
4121
4122 sum = 0;
4123 lk = xmlListFront(writer->nodes);
4124 if (lk == 0) {
4125 return -1;
4126 }
4127
4128 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00004129 if (p != 0) {
4130 switch (p->state) {
4131 case XML_TEXTWRITER_DTD:
4132 count = xmlOutputBufferWriteString(writer->out, " [");
4133 if (count < 0)
4134 return -1;
4135 sum += count;
4136 if (writer->indent) {
4137 count = xmlOutputBufferWriteString(writer->out, "\n");
4138 if (count < 0)
4139 return -1;
4140 sum += count;
4141 }
4142 p->state = XML_TEXTWRITER_DTD_TEXT;
4143 /* fallthrough */
4144 case XML_TEXTWRITER_DTD_TEXT:
4145 break;
4146 default:
4147 return -1;
4148 }
4149 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00004150
Daniel Veillard500a1de2004-03-22 15:22:58 +00004151 if (writer->indent) {
4152 count = xmlTextWriterWriteIndent(writer);
4153 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004154 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004155 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004156 }
4157
4158 count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4159 if (count < 0)
4160 return -1;
4161 sum += count;
4162 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4163 if (count < 0)
4164 return -1;
4165 sum += count;
4166
4167 if (pubid != 0) {
4168 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4169 if (count < 0)
4170 return -1;
4171 sum += count;
4172 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4173 if (count < 0)
4174 return -1;
4175 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004176 count =
4177 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004178 if (count < 0)
4179 return -1;
4180 sum += count;
4181 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4182 if (count < 0)
4183 return -1;
4184 sum += count;
4185 }
4186
4187 if (sysid != 0) {
4188 if (pubid == 0) {
4189 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4190 if (count < 0)
4191 return -1;
4192 sum += count;
4193 }
4194 count = xmlOutputBufferWriteString(writer->out, " ");
4195 if (count < 0)
4196 return -1;
4197 sum += count;
4198 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4199 if (count < 0)
4200 return -1;
4201 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004202 count =
4203 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004204 if (count < 0)
4205 return -1;
4206 sum += count;
4207 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4208 if (count < 0)
4209 return -1;
4210 sum += count;
4211 }
4212
4213 count = xmlOutputBufferWriteString(writer->out, ">");
4214 if (count < 0)
4215 return -1;
4216 sum += count;
4217
4218 return sum;
4219}
4220
4221/**
4222 * xmlTextWriterFlush:
4223 * @writer: the xmlTextWriterPtr
4224 *
4225 * Flush the output buffer.
4226 *
4227 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4228 */
4229int
4230xmlTextWriterFlush(xmlTextWriterPtr writer)
4231{
4232 int count;
4233
4234 if (writer == NULL)
4235 return -1;
4236
4237 if (writer->out == NULL)
4238 count = 0;
4239 else
4240 count = xmlOutputBufferFlush(writer->out);
4241
4242 return count;
4243}
4244
4245/**
4246 * misc
4247 */
4248
4249/**
4250 * xmlFreeTextWriterStackEntry:
4251 * @lk: the xmlLinkPtr
4252 *
4253 * Free callback for the xmlList.
4254 */
4255static void
4256xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4257{
4258 xmlTextWriterStackEntry *p;
4259
4260 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4261 if (p == 0)
4262 return;
4263
4264 if (p->name != 0)
4265 xmlFree(p->name);
4266 xmlFree(p);
4267}
4268
4269/**
4270 * xmlCmpTextWriterStackEntry:
4271 * @data0: the first data
4272 * @data1: the second data
4273 *
4274 * Compare callback for the xmlList.
4275 *
4276 * Returns -1, 0, 1
4277 */
4278static int
4279xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4280{
4281 xmlTextWriterStackEntry *p0;
4282 xmlTextWriterStackEntry *p1;
4283
4284 if (data0 == data1)
4285 return 0;
4286
4287 if (data0 == 0)
4288 return -1;
4289
4290 if (data1 == 0)
4291 return 1;
4292
4293 p0 = (xmlTextWriterStackEntry *) data0;
4294 p1 = (xmlTextWriterStackEntry *) data1;
4295
4296 return xmlStrcmp(p0->name, p1->name);
4297}
4298
4299/**
4300 * misc
4301 */
4302
4303/**
Rob Richardsb8769d62007-06-08 08:50:47 +00004304 * xmlTextWriterOutputNSDecl:
4305 * @writer: the xmlTextWriterPtr
4306 *
4307 * Output the current namespace declarations.
4308 */
4309static int
4310xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4311{
4312 xmlLinkPtr lk;
4313 xmlTextWriterNsStackEntry *np;
4314 int count;
4315 int sum;
4316
4317 sum = 0;
4318 while (!xmlListEmpty(writer->nsstack)) {
4319 xmlChar *namespaceURI = NULL;
4320 xmlChar *prefix = NULL;
4321
4322 lk = xmlListFront(writer->nsstack);
4323 np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4324
4325 if (np != 0) {
4326 namespaceURI = xmlStrdup(np->uri);
4327 prefix = xmlStrdup(np->prefix);
4328 }
4329
4330 xmlListPopFront(writer->nsstack);
4331
4332 if (np != 0) {
4333 count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4334 xmlFree(namespaceURI);
4335 xmlFree(prefix);
4336
4337 if (count < 0) {
4338 xmlListDelete(writer->nsstack);
4339 writer->nsstack = NULL;
4340 return -1;
4341 }
4342 sum += count;
4343 }
4344 }
4345 return sum;
4346}
4347
4348/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004349 * xmlFreeTextWriterNsStackEntry:
4350 * @lk: the xmlLinkPtr
4351 *
4352 * Free callback for the xmlList.
4353 */
4354static void
4355xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4356{
4357 xmlTextWriterNsStackEntry *p;
4358
4359 p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4360 if (p == 0)
4361 return;
4362
4363 if (p->prefix != 0)
4364 xmlFree(p->prefix);
4365 if (p->uri != 0)
4366 xmlFree(p->uri);
4367
4368 xmlFree(p);
4369}
4370
4371/**
4372 * xmlCmpTextWriterNsStackEntry:
4373 * @data0: the first data
4374 * @data1: the second data
4375 *
4376 * Compare callback for the xmlList.
4377 *
4378 * Returns -1, 0, 1
4379 */
4380static int
4381xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4382{
4383 xmlTextWriterNsStackEntry *p0;
4384 xmlTextWriterNsStackEntry *p1;
4385 int rc;
4386
4387 if (data0 == data1)
4388 return 0;
4389
4390 if (data0 == 0)
4391 return -1;
4392
4393 if (data1 == 0)
4394 return 1;
4395
4396 p0 = (xmlTextWriterNsStackEntry *) data0;
4397 p1 = (xmlTextWriterNsStackEntry *) data1;
4398
4399 rc = xmlStrcmp(p0->prefix, p1->prefix);
4400
Rob Richardsb8769d62007-06-08 08:50:47 +00004401 if ((rc != 0) || (p0->elem != p1->elem))
4402 rc = -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004403
4404 return rc;
4405}
4406
4407/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004408 * xmlTextWriterWriteDocCallback:
4409 * @context: the xmlBufferPtr
4410 * @str: the data to write
4411 * @len: the length of the data
4412 *
4413 * Write callback for the xmlOutputBuffer with target xmlBuffer
4414 *
4415 * Returns -1, 0, 1
4416 */
4417static int
4418xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
4419{
4420 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4421 int rc;
4422
Daniel Veillard1d913862003-11-21 00:28:39 +00004423 if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004424 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004425 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4426 rc);
4427 return -1;
4428 }
4429
4430 return len;
4431}
4432
4433/**
4434 * xmlTextWriterCloseDocCallback:
4435 * @context: the xmlBufferPtr
4436 *
4437 * Close callback for the xmlOutputBuffer with target xmlBuffer
4438 *
4439 * Returns -1, 0, 1
4440 */
4441static int
4442xmlTextWriterCloseDocCallback(void *context)
4443{
4444 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4445 int rc;
4446
4447 if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004448 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004449 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4450 rc);
4451 return -1;
4452 }
4453
4454 return 0;
4455}
4456
4457/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004458 * xmlTextWriterVSprintf:
4459 * @format: see printf
4460 * @argptr: pointer to the first member of the variable argument list.
4461 *
4462 * Utility function for formatted output
4463 *
4464 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4465 */
4466static xmlChar *
4467xmlTextWriterVSprintf(const char *format, va_list argptr)
4468{
4469 int size;
4470 int count;
4471 xmlChar *buf;
William M. Brackf4caa5e2005-10-20 09:04:05 +00004472 va_list locarg;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004473
4474 size = BUFSIZ;
4475 buf = (xmlChar *) xmlMalloc(size);
4476 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004477 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004478 "xmlTextWriterVSprintf : out of memory!\n");
4479 return NULL;
4480 }
4481
William M. Brackf4caa5e2005-10-20 09:04:05 +00004482 VA_COPY(locarg, argptr);
4483 while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004484 || (count == size - 1) || (count == size) || (count > size)) {
William M. Brackf4caa5e2005-10-20 09:04:05 +00004485 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004486 xmlFree(buf);
4487 size += BUFSIZ;
4488 buf = (xmlChar *) xmlMalloc(size);
4489 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004490 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004491 "xmlTextWriterVSprintf : out of memory!\n");
4492 return NULL;
4493 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004494 VA_COPY(locarg, argptr);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004495 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004496 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004497
4498 return buf;
4499}
4500
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004501/**
4502 * xmlTextWriterStartDocumentCallback:
4503 * @ctx: the user data (XML parser context)
4504 *
4505 * called at the start of document processing.
4506 */
4507static void
4508xmlTextWriterStartDocumentCallback(void *ctx)
4509{
4510 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4511 xmlDocPtr doc;
4512
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004513 if (ctxt->html) {
4514#ifdef LIBXML_HTML_ENABLED
4515 if (ctxt->myDoc == NULL)
4516 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4517 if (ctxt->myDoc == NULL) {
4518 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4519 ctxt->sax->error(ctxt->userData,
4520 "SAX.startDocument(): out of memory\n");
4521 ctxt->errNo = XML_ERR_NO_MEMORY;
4522 ctxt->instate = XML_PARSER_EOF;
4523 ctxt->disableSAX = 1;
4524 return;
4525 }
4526#else
Daniel Veillardd0cf7f62004-11-09 16:17:02 +00004527 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004528 "libxml2 built without HTML support\n");
4529 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4530 ctxt->instate = XML_PARSER_EOF;
4531 ctxt->disableSAX = 1;
4532 return;
4533#endif
4534 } else {
4535 doc = ctxt->myDoc;
4536 if (doc == NULL)
4537 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4538 if (doc != NULL) {
4539 if (doc->children == NULL) {
4540 if (ctxt->encoding != NULL)
4541 doc->encoding = xmlStrdup(ctxt->encoding);
4542 else
4543 doc->encoding = NULL;
4544 doc->standalone = ctxt->standalone;
4545 }
4546 } else {
4547 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4548 ctxt->sax->error(ctxt->userData,
4549 "SAX.startDocument(): out of memory\n");
4550 ctxt->errNo = XML_ERR_NO_MEMORY;
4551 ctxt->instate = XML_PARSER_EOF;
4552 ctxt->disableSAX = 1;
4553 return;
4554 }
4555 }
4556 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4557 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4558 ctxt->myDoc->URL =
4559 xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4560 if (ctxt->myDoc->URL == NULL)
4561 ctxt->myDoc->URL =
4562 xmlStrdup((const xmlChar *) ctxt->input->filename);
4563 }
4564}
4565
Daniel Veillard2cca4462004-01-02 20:04:23 +00004566/**
4567 * xmlTextWriterSetIndent:
4568 * @writer: the xmlTextWriterPtr
4569 * @indent: do indentation?
4570 *
4571 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4572 *
4573 * Returns -1 on error or 0 otherwise.
4574 */
4575int
Daniel Veillardab69f362004-02-17 11:40:32 +00004576xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004577{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004578 if ((writer == NULL) || (indent < 0))
Daniel Veillardab69f362004-02-17 11:40:32 +00004579 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004580
Daniel Veillardab69f362004-02-17 11:40:32 +00004581 writer->indent = indent;
4582 writer->doindent = 1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004583
Daniel Veillardab69f362004-02-17 11:40:32 +00004584 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004585}
4586
4587/**
4588 * xmlTextWriterSetIndentString:
4589 * @writer: the xmlTextWriterPtr
4590 * @str: the xmlChar string
4591 *
4592 * Set string indentation.
4593 *
4594 * Returns -1 on error or 0 otherwise.
4595 */
4596int
Daniel Veillardab69f362004-02-17 11:40:32 +00004597xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004598{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004599 if ((writer == NULL) || (!str))
Daniel Veillardab69f362004-02-17 11:40:32 +00004600 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004601
Daniel Veillardab69f362004-02-17 11:40:32 +00004602 if (writer->ichar != NULL)
4603 xmlFree(writer->ichar);
4604 writer->ichar = xmlStrdup(str);
4605
4606 if (!writer->ichar)
4607 return -1;
4608 else
4609 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004610}
4611
4612/**
Csaba Raduly429d3a02012-09-11 11:50:25 +08004613 * xmlTextWriterSetQuoteChar:
4614 * @writer: the xmlTextWriterPtr
4615 * @quotechar: the quote character
4616 *
4617 * Set the character used for quoting attributes.
4618 *
4619 * Returns -1 on error or 0 otherwise.
4620 */
4621int
4622xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar)
4623{
4624 if ((writer == NULL) || ((quotechar != '\'') && (quotechar != '"')))
4625 return -1;
4626
4627 writer->qchar = quotechar;
4628
4629 return 0;
4630}
4631
4632/**
Daniel Veillard2cca4462004-01-02 20:04:23 +00004633 * xmlTextWriterWriteIndent:
4634 * @writer: the xmlTextWriterPtr
4635 *
4636 * Write indent string.
4637 *
4638 * Returns -1 on error or the number of strings written.
Daniel Veillardab69f362004-02-17 11:40:32 +00004639 */
Daniel Veillard2cca4462004-01-02 20:04:23 +00004640static int
Daniel Veillardab69f362004-02-17 11:40:32 +00004641xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004642{
Daniel Veillardab69f362004-02-17 11:40:32 +00004643 int lksize;
4644 int i;
4645 int ret;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004646
Daniel Veillardab69f362004-02-17 11:40:32 +00004647 lksize = xmlListSize(writer->nodes);
4648 if (lksize < 1)
4649 return (-1); /* list is empty */
4650 for (i = 0; i < (lksize - 1); i++) {
4651 ret = xmlOutputBufferWriteString(writer->out,
4652 (const char *) writer->ichar);
4653 if (ret == -1)
4654 return (-1);
4655 }
4656
4657 return (lksize - 1);
Daniel Veillard2cca4462004-01-02 20:04:23 +00004658}
4659
Daniel Veillard500a1de2004-03-22 15:22:58 +00004660/**
4661 * xmlTextWriterHandleStateDependencies:
4662 * @writer: the xmlTextWriterPtr
4663 * @p: the xmlTextWriterStackEntry
4664 *
4665 * Write state dependent strings.
4666 *
4667 * Returns -1 on error or the number of characters written.
4668 */
4669static int
4670xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4671 xmlTextWriterStackEntry * p)
4672{
4673 int count;
4674 int sum;
4675 char extra[3];
4676
4677 if (writer == NULL)
4678 return -1;
4679
4680 if (p == NULL)
4681 return 0;
4682
4683 sum = 0;
4684 extra[0] = extra[1] = extra[2] = '\0';
4685 if (p != 0) {
4686 sum = 0;
4687 switch (p->state) {
4688 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00004689 /* Output namespace declarations */
4690 count = xmlTextWriterOutputNSDecl(writer);
4691 if (count < 0)
4692 return -1;
4693 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004694 extra[0] = '>';
4695 p->state = XML_TEXTWRITER_TEXT;
4696 break;
4697 case XML_TEXTWRITER_PI:
4698 extra[0] = ' ';
4699 p->state = XML_TEXTWRITER_PI_TEXT;
4700 break;
4701 case XML_TEXTWRITER_DTD:
4702 extra[0] = ' ';
4703 extra[1] = '[';
4704 p->state = XML_TEXTWRITER_DTD_TEXT;
4705 break;
4706 case XML_TEXTWRITER_DTD_ELEM:
4707 extra[0] = ' ';
4708 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4709 break;
4710 case XML_TEXTWRITER_DTD_ATTL:
4711 extra[0] = ' ';
4712 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4713 break;
4714 case XML_TEXTWRITER_DTD_ENTY:
4715 case XML_TEXTWRITER_DTD_PENT:
4716 extra[0] = ' ';
4717 extra[1] = writer->qchar;
4718 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4719 break;
4720 default:
4721 break;
4722 }
4723 }
4724
4725 if (*extra != '\0') {
4726 count = xmlOutputBufferWriteString(writer->out, extra);
4727 if (count < 0)
4728 return -1;
4729 sum += count;
4730 }
4731
4732 return sum;
4733}
4734
Daniel Veillard5d4644e2005-04-01 13:11:58 +00004735#define bottom_xmlwriter
4736#include "elfgcchack.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +00004737#endif