blob: f618610d3c7434f52b97673e9ff3a946bd8ff511 [file] [log] [blame]
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001
Daniel Veillard1d211e22003-10-20 22:32:39 +00002/*
3 * xmlwriter.c: XML text writer implementation
4 *
5 * For license and disclaimer see the license and disclaimer of
6 * libxml2.
7 *
8 * alfred@mickautsch.de
9 */
10
Igor Zlatkovicb23de5a2003-11-27 18:36:46 +000011#define IN_LIBXML
William M. Brackc1099be2007-01-31 18:38:56 +000012#include "libxml.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +000013#include <string.h>
Daniel Veillard1d211e22003-10-20 22:32:39 +000014
Daniel Veillard1d211e22003-10-20 22:32:39 +000015#include <libxml/xmlmemory.h>
16#include <libxml/parser.h>
Daniel Veillard5841f0e2003-11-20 11:59:09 +000017#include <libxml/uri.h>
18#include <libxml/HTMLtree.h>
Daniel Veillard1d211e22003-10-20 22:32:39 +000019
20#ifdef LIBXML_WRITER_ENABLED
21
22#include <libxml/xmlwriter.h>
23
24#define B64LINELEN 72
25#define B64CRLF "\r\n"
26
27/*
William M. Brackf4caa5e2005-10-20 09:04:05 +000028 * The following VA_COPY was coded following an example in
29 * the Samba project. It may not be sufficient for some
30 * esoteric implementations of va_list (i.e. it may need
31 * something involving a memcpy) but (hopefully) will be
32 * sufficient for libxml2.
33 */
34#ifndef VA_COPY
35 #ifdef HAVE_VA_COPY
36 #define VA_COPY(dest, src) va_copy(dest, src)
37 #else
38 #ifdef HAVE___VA_COPY
39 #define VA_COPY(dest,src) __va_copy(dest, src)
40 #else
41 #define VA_COPY(dest,src) (dest) = (src)
42 #endif
43 #endif
44#endif
45
46/*
Daniel Veillard1d211e22003-10-20 22:32:39 +000047 * Types are kept private
48 */
49typedef enum {
50 XML_TEXTWRITER_NONE = 0,
51 XML_TEXTWRITER_NAME,
52 XML_TEXTWRITER_ATTRIBUTE,
53 XML_TEXTWRITER_TEXT,
54 XML_TEXTWRITER_PI,
55 XML_TEXTWRITER_PI_TEXT,
56 XML_TEXTWRITER_CDATA,
57 XML_TEXTWRITER_DTD,
58 XML_TEXTWRITER_DTD_TEXT,
59 XML_TEXTWRITER_DTD_ELEM,
Daniel Veillard500a1de2004-03-22 15:22:58 +000060 XML_TEXTWRITER_DTD_ELEM_TEXT,
Daniel Veillard1d211e22003-10-20 22:32:39 +000061 XML_TEXTWRITER_DTD_ATTL,
Daniel Veillard500a1de2004-03-22 15:22:58 +000062 XML_TEXTWRITER_DTD_ATTL_TEXT,
63 XML_TEXTWRITER_DTD_ENTY, /* entity */
64 XML_TEXTWRITER_DTD_ENTY_TEXT,
65 XML_TEXTWRITER_DTD_PENT, /* parameter entity */
William M. Brack87640d52004-04-17 14:58:15 +000066 XML_TEXTWRITER_COMMENT
Daniel Veillard1d211e22003-10-20 22:32:39 +000067} xmlTextWriterState;
68
69typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
70
71struct _xmlTextWriterStackEntry {
72 xmlChar *name;
73 xmlTextWriterState state;
74};
75
76typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
77struct _xmlTextWriterNsStackEntry {
78 xmlChar *prefix;
79 xmlChar *uri;
80 xmlLinkPtr elem;
81};
82
83struct _xmlTextWriter {
Daniel Veillardab69f362004-02-17 11:40:32 +000084 xmlOutputBufferPtr out; /* output buffer */
85 xmlListPtr nodes; /* element name stack */
86 xmlListPtr nsstack; /* name spaces stack */
Daniel Veillard1d211e22003-10-20 22:32:39 +000087 int level;
Daniel Veillardab69f362004-02-17 11:40:32 +000088 int indent; /* enable indent */
89 int doindent; /* internal indent flag */
90 xmlChar *ichar; /* indent character */
91 char qchar; /* character used for quoting attribute values */
Daniel Veillard20c5e782004-01-21 09:57:31 +000092 xmlParserCtxtPtr ctxt;
Daniel Veillarda521d282004-11-09 14:59:59 +000093 int no_doc_free;
Rob Richards9db68f02006-08-16 22:48:51 +000094 xmlDocPtr doc;
Daniel Veillard1d211e22003-10-20 22:32:39 +000095};
96
97static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
98static int xmlCmpTextWriterStackEntry(const void *data0,
99 const void *data1);
Rob Richardsb8769d62007-06-08 08:50:47 +0000100static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000101static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
102static int xmlCmpTextWriterNsStackEntry(const void *data0,
103 const void *data1);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000104static int xmlTextWriterWriteDocCallback(void *context,
105 const xmlChar * str, int len);
106static int xmlTextWriterCloseDocCallback(void *context);
107
Daniel Veillard1d211e22003-10-20 22:32:39 +0000108static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);
109static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
110 const unsigned char *data);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000111static void xmlTextWriterStartDocumentCallback(void *ctx);
Daniel Veillardab69f362004-02-17 11:40:32 +0000112static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000113static int
114 xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
115 xmlTextWriterStackEntry * p);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000116
117/**
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000118 * xmlWriterErrMsg:
119 * @ctxt: a writer context
120 * @error: the error number
121 * @msg: the error message
122 *
123 * Handle a writer error
124 */
125static void
126xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,
127 const char *msg)
128{
129 if (ctxt != NULL) {
130 __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
131 NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
132 NULL, 0, NULL, NULL, NULL, 0, 0, msg);
133 } else {
134 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
135 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, msg);
136 }
137}
138
139/**
140 * xmlWriterErrMsgInt:
141 * @ctxt: a writer context
142 * @error: the error number
143 * @msg: the error message
144 * @val: an int
145 *
146 * Handle a writer error
147 */
148static void
149xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,
150 const char *msg, int val)
151{
152 if (ctxt != NULL) {
153 __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
154 NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
155 NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
156 } else {
157 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
158 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
159 }
160}
161
162/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000163 * xmlNewTextWriter:
164 * @out: an xmlOutputBufferPtr
165 *
166 * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
Daniel Veillardd5cc0f72004-11-06 19:24:28 +0000167 * NOTE: the @out parameter will be deallocated when the writer is closed
168 * (if the call succeed.)
Daniel Veillard1d211e22003-10-20 22:32:39 +0000169 *
170 * Returns the new xmlTextWriterPtr or NULL in case of error
171 */
172xmlTextWriterPtr
173xmlNewTextWriter(xmlOutputBufferPtr out)
174{
175 xmlTextWriterPtr ret;
176
177 ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
178 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000179 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000180 "xmlNewTextWriter : out of memory!\n");
181 return NULL;
182 }
183 memset(ret, 0, (size_t) sizeof(xmlTextWriter));
184
185 ret->nodes = xmlListCreate((xmlListDeallocator)
186 xmlFreeTextWriterStackEntry,
187 (xmlListDataCompare)
188 xmlCmpTextWriterStackEntry);
189 if (ret->nodes == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000190 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000191 "xmlNewTextWriter : out of memory!\n");
192 xmlFree(ret);
193 return NULL;
194 }
195
196 ret->nsstack = xmlListCreate((xmlListDeallocator)
197 xmlFreeTextWriterNsStackEntry,
198 (xmlListDataCompare)
199 xmlCmpTextWriterNsStackEntry);
200 if (ret->nsstack == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000201 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000202 "xmlNewTextWriter : out of memory!\n");
Daniel Veillard500a1de2004-03-22 15:22:58 +0000203 xmlListDelete(ret->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000204 xmlFree(ret);
205 return NULL;
206 }
207
208 ret->out = out;
Daniel Veillardab69f362004-02-17 11:40:32 +0000209 ret->ichar = xmlStrdup(BAD_CAST " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000210 ret->qchar = '"';
211
Daniel Veillard500a1de2004-03-22 15:22:58 +0000212 if (!ret->ichar) {
213 xmlListDelete(ret->nodes);
214 xmlListDelete(ret->nsstack);
215 xmlFree(ret);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000216 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000217 "xmlNewTextWriter : out of memory!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000218 return NULL;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000219 }
Rob Richards9db68f02006-08-16 22:48:51 +0000220
221 ret->doc = xmlNewDoc(NULL);
222
Daniel Veillarda521d282004-11-09 14:59:59 +0000223 ret->no_doc_free = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000224
Daniel Veillard1d211e22003-10-20 22:32:39 +0000225 return ret;
226}
227
228/**
229 * xmlNewTextWriterFilename:
230 * @uri: the URI of the resource for the output
231 * @compression: compress the output?
232 *
233 * Create a new xmlNewTextWriter structure with @uri as output
234 *
235 * Returns the new xmlTextWriterPtr or NULL in case of error
236 */
237xmlTextWriterPtr
238xmlNewTextWriterFilename(const char *uri, int compression)
239{
240 xmlTextWriterPtr ret;
241 xmlOutputBufferPtr out;
242
243 out = xmlOutputBufferCreateFilename(uri, NULL, compression);
244 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000245 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000246 "xmlNewTextWriterFilename : out of memory!\n");
247 return NULL;
248 }
249
250 ret = xmlNewTextWriter(out);
251 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000252 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000253 "xmlNewTextWriterFilename : out of memory!\n");
254 xmlOutputBufferClose(out);
255 return NULL;
256 }
257
Daniel Veillard2cca4462004-01-02 20:04:23 +0000258 ret->indent = 0;
259 ret->doindent = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000260 return ret;
261}
262
263/**
264 * xmlNewTextWriterMemory:
265 * @buf: xmlBufferPtr
266 * @compression: compress the output?
267 *
268 * Create a new xmlNewTextWriter structure with @buf as output
269 * TODO: handle compression
270 *
271 * Returns the new xmlTextWriterPtr or NULL in case of error
272 */
273xmlTextWriterPtr
274xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
275{
276 xmlTextWriterPtr ret;
277 xmlOutputBufferPtr out;
278
279/*::todo handle compression */
Rob Richardsa44f2342005-11-09 18:03:45 +0000280 out = xmlOutputBufferCreateBuffer(buf, NULL);
281
Daniel Veillard1d211e22003-10-20 22:32:39 +0000282 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000283 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000284 "xmlNewTextWriterMemory : out of memory!\n");
285 return NULL;
286 }
287
288 ret = xmlNewTextWriter(out);
289 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000290 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000291 "xmlNewTextWriterMemory : out of memory!\n");
292 xmlOutputBufferClose(out);
293 return NULL;
294 }
295
296 return ret;
297}
298
299/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000300 * xmlNewTextWriterPushParser:
301 * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
302 * @compression: compress the output?
303 *
304 * Create a new xmlNewTextWriter structure with @ctxt as output
Daniel Veillardd5cc0f72004-11-06 19:24:28 +0000305 * NOTE: the @ctxt context will be freed with the resulting writer
306 * (if the call succeeds).
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000307 * TODO: handle compression
308 *
309 * Returns the new xmlTextWriterPtr or NULL in case of error
310 */
311xmlTextWriterPtr
Daniel Veillard1d913862003-11-21 00:28:39 +0000312xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
313 int compression ATTRIBUTE_UNUSED)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000314{
315 xmlTextWriterPtr ret;
316 xmlOutputBufferPtr out;
317
Daniel Veillard500a1de2004-03-22 15:22:58 +0000318 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000319 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000320 "xmlNewTextWriterPushParser : invalid context!\n");
321 return NULL;
322 }
323
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000324 out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
325 xmlTextWriterWriteDocCallback,
326 (xmlOutputCloseCallback)
327 xmlTextWriterCloseDocCallback,
328 (void *) ctxt, NULL);
329 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000330 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000331 "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
332 return NULL;
333 }
334
335 ret = xmlNewTextWriter(out);
336 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000337 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000338 "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
339 xmlOutputBufferClose(out);
340 return NULL;
341 }
342
Daniel Veillard20c5e782004-01-21 09:57:31 +0000343 ret->ctxt = ctxt;
344
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000345 return ret;
346}
347
348/**
349 * xmlNewTextWriterDoc:
350 * @doc: address of a xmlDocPtr to hold the new XML document tree
351 * @compression: compress the output?
352 *
353 * Create a new xmlNewTextWriter structure with @*doc as output
354 *
355 * Returns the new xmlTextWriterPtr or NULL in case of error
356 */
357xmlTextWriterPtr
358xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
359{
360 xmlTextWriterPtr ret;
361 xmlSAXHandler saxHandler;
362 xmlParserCtxtPtr ctxt;
363
364 memset(&saxHandler, '\0', sizeof(saxHandler));
365 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
366 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
367 saxHandler.startElement = xmlSAX2StartElement;
368 saxHandler.endElement = xmlSAX2EndElement;
369
370 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
371 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000372 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000373 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
374 return NULL;
375 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000376 /*
377 * For some reason this seems to completely break if node names
378 * are interned.
379 */
380 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000381
Daniel Veillard1d913862003-11-21 00:28:39 +0000382 ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000383 if (ctxt->myDoc == NULL) {
384 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000385 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000386 "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
387 return NULL;
388 }
389
390 ret = xmlNewTextWriterPushParser(ctxt, compression);
391 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000392 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000393 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
394 return NULL;
395 }
396
Daniel Veillard500a1de2004-03-22 15:22:58 +0000397 xmlSetDocCompressMode(ctxt->myDoc, compression);
398
Daniel Veillarda521d282004-11-09 14:59:59 +0000399 if (doc != NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000400 *doc = ctxt->myDoc;
Daniel Veillarda521d282004-11-09 14:59:59 +0000401 ret->no_doc_free = 1;
402 }
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000403
404 return ret;
405}
406
407/**
408 * xmlNewTextWriterTree:
409 * @doc: xmlDocPtr
410 * @node: xmlNodePtr or NULL for doc->children
411 * @compression: compress the output?
412 *
413 * Create a new xmlNewTextWriter structure with @doc as output
414 * starting at @node
415 *
416 * Returns the new xmlTextWriterPtr or NULL in case of error
417 */
418xmlTextWriterPtr
419xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
420{
421 xmlTextWriterPtr ret;
422 xmlSAXHandler saxHandler;
423 xmlParserCtxtPtr ctxt;
424
425 if (doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000426 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000427 "xmlNewTextWriterTree : invalid document tree!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000428 return NULL;
429 }
430
431 memset(&saxHandler, '\0', sizeof(saxHandler));
432 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
433 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
434 saxHandler.startElement = xmlSAX2StartElement;
435 saxHandler.endElement = xmlSAX2EndElement;
436
437 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
438 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000439 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000440 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
441 return NULL;
442 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000443 /*
444 * For some reason this seems to completely break if node names
445 * are interned.
446 */
447 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000448
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000449 ret = xmlNewTextWriterPushParser(ctxt, compression);
450 if (ret == NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000451 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000452 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000453 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
454 return NULL;
455 }
456
Daniel Veillard500a1de2004-03-22 15:22:58 +0000457 ctxt->myDoc = doc;
458 ctxt->node = node;
Daniel Veillarda521d282004-11-09 14:59:59 +0000459 ret->no_doc_free = 1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000460
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000461 xmlSetDocCompressMode(doc, compression);
462
463 return ret;
464}
465
466/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000467 * xmlFreeTextWriter:
468 * @writer: the xmlTextWriterPtr
469 *
470 * Deallocate all the resources associated to the writer
471 */
472void
473xmlFreeTextWriter(xmlTextWriterPtr writer)
474{
475 if (writer == NULL)
476 return;
477
478 if (writer->out != NULL)
479 xmlOutputBufferClose(writer->out);
480
481 if (writer->nodes != NULL)
482 xmlListDelete(writer->nodes);
483
484 if (writer->nsstack != NULL)
485 xmlListDelete(writer->nsstack);
486
Daniel Veillarda521d282004-11-09 14:59:59 +0000487 if (writer->ctxt != NULL) {
488 if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
489 xmlFreeDoc(writer->ctxt->myDoc);
490 writer->ctxt->myDoc = NULL;
491 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000492 xmlFreeParserCtxt(writer->ctxt);
Daniel Veillarda521d282004-11-09 14:59:59 +0000493 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000494
Rob Richards9db68f02006-08-16 22:48:51 +0000495 if (writer->doc != NULL)
496 xmlFreeDoc(writer->doc);
497
Daniel Veillard4773df22004-01-23 13:15:13 +0000498 if (writer->ichar != NULL)
499 xmlFree(writer->ichar);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000500 xmlFree(writer);
501}
502
503/**
504 * xmlTextWriterStartDocument:
505 * @writer: the xmlTextWriterPtr
506 * @version: the xml version ("1.0") or NULL for default ("1.0")
507 * @encoding: the encoding or NULL for default
508 * @standalone: "yes" or "no" or NULL for default
509 *
510 * Start a new xml document
511 *
512 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
513 */
514int
515xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
516 const char *encoding, const char *standalone)
517{
518 int count;
519 int sum;
520 xmlLinkPtr lk;
521 xmlCharEncodingHandlerPtr encoder;
522
Daniel Veillard500a1de2004-03-22 15:22:58 +0000523 if ((writer == NULL) || (writer->out == NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000524 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000525 "xmlTextWriterStartDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000526 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000527 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000528
529 lk = xmlListFront(writer->nodes);
530 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000531 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000532 "xmlTextWriterStartDocument : not allowed in this context!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000533 return -1;
534 }
535
536 encoder = NULL;
537 if (encoding != NULL) {
538 encoder = xmlFindCharEncodingHandler(encoding);
539 if (encoder == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000540 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000541 "xmlTextWriterStartDocument : out of memory!\n");
542 return -1;
543 }
544 }
545
546 writer->out->encoder = encoder;
547 if (encoder != NULL) {
548 writer->out->conv = xmlBufferCreateSize(4000);
549 xmlCharEncOutFunc(encoder, writer->out->conv, NULL);
Rob Richards9db68f02006-08-16 22:48:51 +0000550 if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
551 writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000552 } else
553 writer->out->conv = NULL;
554
555 sum = 0;
556 count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
557 if (count < 0)
558 return -1;
559 sum += count;
560 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
561 if (count < 0)
562 return -1;
563 sum += count;
564 if (version != 0)
565 count = xmlOutputBufferWriteString(writer->out, version);
566 else
567 count = xmlOutputBufferWriteString(writer->out, "1.0");
568 if (count < 0)
569 return -1;
570 sum += count;
571 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
572 if (count < 0)
573 return -1;
574 sum += count;
575 if (writer->out->encoder != 0) {
576 count = xmlOutputBufferWriteString(writer->out, " encoding=");
577 if (count < 0)
578 return -1;
579 sum += count;
580 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
581 if (count < 0)
582 return -1;
583 sum += count;
584 count =
585 xmlOutputBufferWriteString(writer->out,
586 writer->out->encoder->name);
587 if (count < 0)
588 return -1;
589 sum += count;
590 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
591 if (count < 0)
592 return -1;
593 sum += count;
594 }
595
596 if (standalone != 0) {
597 count = xmlOutputBufferWriteString(writer->out, " standalone=");
598 if (count < 0)
599 return -1;
600 sum += count;
601 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
602 if (count < 0)
603 return -1;
604 sum += count;
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 }
614
615 count = xmlOutputBufferWriteString(writer->out, "?>\n");
616 if (count < 0)
617 return -1;
618 sum += count;
619
620 return sum;
621}
622
623/**
624 * xmlTextWriterEndDocument:
625 * @writer: the xmlTextWriterPtr
626 *
627 * End an xml document. All open elements are closed
628 *
629 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
630 */
631int
632xmlTextWriterEndDocument(xmlTextWriterPtr writer)
633{
634 int count;
635 int sum;
636 xmlLinkPtr lk;
637 xmlTextWriterStackEntry *p;
638
Daniel Veillard500a1de2004-03-22 15:22:58 +0000639 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000640 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000641 "xmlTextWriterEndDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000642 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000643 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000644
645 sum = 0;
646 while ((lk = xmlListFront(writer->nodes)) != NULL) {
647 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
648 if (p == 0)
649 break;
650 switch (p->state) {
651 case XML_TEXTWRITER_NAME:
652 case XML_TEXTWRITER_ATTRIBUTE:
653 case XML_TEXTWRITER_TEXT:
654 count = xmlTextWriterEndElement(writer);
655 if (count < 0)
656 return -1;
657 sum += count;
658 break;
659 case XML_TEXTWRITER_PI:
660 case XML_TEXTWRITER_PI_TEXT:
661 count = xmlTextWriterEndPI(writer);
662 if (count < 0)
663 return -1;
664 sum += count;
665 break;
666 case XML_TEXTWRITER_CDATA:
667 count = xmlTextWriterEndCDATA(writer);
668 if (count < 0)
669 return -1;
670 sum += count;
671 break;
672 case XML_TEXTWRITER_DTD:
Daniel Veillard500a1de2004-03-22 15:22:58 +0000673 case XML_TEXTWRITER_DTD_TEXT:
674 case XML_TEXTWRITER_DTD_ELEM:
675 case XML_TEXTWRITER_DTD_ELEM_TEXT:
676 case XML_TEXTWRITER_DTD_ATTL:
677 case XML_TEXTWRITER_DTD_ATTL_TEXT:
678 case XML_TEXTWRITER_DTD_ENTY:
679 case XML_TEXTWRITER_DTD_ENTY_TEXT:
680 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard1d211e22003-10-20 22:32:39 +0000681 count = xmlTextWriterEndDTD(writer);
682 if (count < 0)
683 return -1;
684 sum += count;
685 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000686 case XML_TEXTWRITER_COMMENT:
687 count = xmlTextWriterEndComment(writer);
688 if (count < 0)
689 return -1;
690 sum += count;
691 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000692 default:
Daniel Veillardab69f362004-02-17 11:40:32 +0000693 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000694 }
695 }
696
Daniel Veillard2cca4462004-01-02 20:04:23 +0000697 if (!writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000698 count = xmlOutputBufferWriteString(writer->out, "\n");
699 if (count < 0)
700 return -1;
701 sum += count;
702 }
703 return sum;
704}
705
Daniel Veillardab69f362004-02-17 11:40:32 +0000706/**
707 * xmlTextWriterStartComment:
708 * @writer: the xmlTextWriterPtr
709 *
710 * Start an xml comment.
711 *
712 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
713 */
714int
715xmlTextWriterStartComment(xmlTextWriterPtr writer)
716{
717 int count;
718 int sum;
719 xmlLinkPtr lk;
720 xmlTextWriterStackEntry *p;
721
Daniel Veillard500a1de2004-03-22 15:22:58 +0000722 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000723 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000724 "xmlTextWriterStartComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000725 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000726 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000727
728 sum = 0;
729 lk = xmlListFront(writer->nodes);
730 if (lk != 0) {
731 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
732 if (p != 0) {
733 switch (p->state) {
734 case XML_TEXTWRITER_TEXT:
735 case XML_TEXTWRITER_NONE:
736 break;
737 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000738 /* Output namespace declarations */
739 count = xmlTextWriterOutputNSDecl(writer);
740 if (count < 0)
741 return -1;
742 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000743 count = xmlOutputBufferWriteString(writer->out, ">");
744 if (count < 0)
745 return -1;
746 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000747 if (writer->indent) {
748 count =
749 xmlOutputBufferWriteString(writer->out, "\n");
750 if (count < 0)
751 return -1;
752 sum += count;
753 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000754 p->state = XML_TEXTWRITER_TEXT;
755 break;
756 default:
757 return -1;
758 }
759 }
760 }
761
762 p = (xmlTextWriterStackEntry *)
763 xmlMalloc(sizeof(xmlTextWriterStackEntry));
764 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000765 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillardab69f362004-02-17 11:40:32 +0000766 "xmlTextWriterStartElement : out of memory!\n");
767 return -1;
768 }
769
Daniel Veillard75e389d2005-07-29 22:02:24 +0000770 p->name = NULL;
Daniel Veillardab69f362004-02-17 11:40:32 +0000771 p->state = XML_TEXTWRITER_COMMENT;
772
773 xmlListPushFront(writer->nodes, p);
774
775 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000776 count = xmlTextWriterWriteIndent(writer);
777 if (count < 0)
778 return -1;
779 sum += count;
780 }
781
782 count = xmlOutputBufferWriteString(writer->out, "<!--");
783 if (count < 0)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000784 return -1;
785 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000786
787 return sum;
788}
789
790/**
791 * xmlTextWriterEndComment:
792 * @writer: the xmlTextWriterPtr
793 *
794 * End the current xml coment.
795 *
796 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
797 */
798int
799xmlTextWriterEndComment(xmlTextWriterPtr writer)
800{
801 int count;
802 int sum;
803 xmlLinkPtr lk;
804 xmlTextWriterStackEntry *p;
805
Daniel Veillard500a1de2004-03-22 15:22:58 +0000806 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000807 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000808 "xmlTextWriterEndComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000809 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000810 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000811
812 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000813 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000814 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000815 "xmlTextWriterEndComment : not allowed in this context!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000816 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000817 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000818
819 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
820 if (p == 0)
821 return -1;
822
823 sum = 0;
824 switch (p->state) {
825 case XML_TEXTWRITER_COMMENT:
826 count = xmlOutputBufferWriteString(writer->out, "-->");
827 if (count < 0)
828 return -1;
829 sum += count;
830 break;
831 default:
832 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +0000833 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000834
835 if (writer->indent) {
836 count = xmlOutputBufferWriteString(writer->out, "\n");
837 if (count < 0)
838 return -1;
839 sum += count;
840 }
841
842 xmlListPopFront(writer->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000843 return sum;
844}
845
846/**
847 * xmlTextWriterWriteFormatComment:
848 * @writer: the xmlTextWriterPtr
849 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +0000850 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +0000851 *
852 * Write an xml comment.
853 *
854 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
855 */
Daniel Veillardffa3c742005-07-21 13:24:09 +0000856int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +0000857xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
858 const char *format, ...)
859{
860 int rc;
861 va_list ap;
862
863 va_start(ap, format);
864
865 rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
866
867 va_end(ap);
868 return rc;
869}
870
871/**
872 * xmlTextWriterWriteVFormatComment:
873 * @writer: the xmlTextWriterPtr
874 * @format: format string (see printf)
875 * @argptr: pointer to the first member of the variable argument list.
876 *
877 * Write an xml comment.
878 *
879 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
880 */
881int
882xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
883 const char *format, va_list argptr)
884{
885 int rc;
886 xmlChar *buf;
887
Daniel Veillard500a1de2004-03-22 15:22:58 +0000888 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000889 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000890 "xmlTextWriterWriteVFormatComment : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000891 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000892 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000893
894 buf = xmlTextWriterVSprintf(format, argptr);
895 if (buf == 0)
896 return 0;
897
898 rc = xmlTextWriterWriteComment(writer, buf);
899
900 xmlFree(buf);
901 return rc;
902}
903
904/**
905 * xmlTextWriterWriteComment:
906 * @writer: the xmlTextWriterPtr
907 * @content: comment string
908 *
909 * Write an xml comment.
910 *
911 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
912 */
913int
914xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
915{
916 int count;
917 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000918
919 sum = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000920 count = xmlTextWriterStartComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000921 if (count < 0)
922 return -1;
923 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000924 count = xmlTextWriterWriteString(writer, content);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000925 if (count < 0)
926 return -1;
927 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000928 count = xmlTextWriterEndComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000929 if (count < 0)
930 return -1;
931 sum += count;
932
933 return sum;
934}
935
936/**
937 * xmlTextWriterStartElement:
938 * @writer: the xmlTextWriterPtr
939 * @name: element name
940 *
941 * Start an xml element.
942 *
943 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
944 */
945int
946xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
947{
948 int count;
949 int sum;
950 xmlLinkPtr lk;
951 xmlTextWriterStackEntry *p;
952
953 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
954 return -1;
955
956 sum = 0;
957 lk = xmlListFront(writer->nodes);
958 if (lk != 0) {
959 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
960 if (p != 0) {
961 switch (p->state) {
962 case XML_TEXTWRITER_PI:
963 case XML_TEXTWRITER_PI_TEXT:
964 return -1;
965 case XML_TEXTWRITER_NONE:
966 break;
Daniel Veillard614fdc12005-02-23 14:05:37 +0000967 case XML_TEXTWRITER_ATTRIBUTE:
968 count = xmlTextWriterEndAttribute(writer);
969 if (count < 0)
970 return -1;
971 sum += count;
972 /* fallthrough */
Daniel Veillard1d211e22003-10-20 22:32:39 +0000973 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000974 /* Output namespace declarations */
975 count = xmlTextWriterOutputNSDecl(writer);
976 if (count < 0)
977 return -1;
978 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000979 count = xmlOutputBufferWriteString(writer->out, ">");
980 if (count < 0)
981 return -1;
982 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000983 if (writer->indent)
984 count =
985 xmlOutputBufferWriteString(writer->out, "\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000986 p->state = XML_TEXTWRITER_TEXT;
987 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000988 default:
989 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000990 }
991 }
992 }
993
994 p = (xmlTextWriterStackEntry *)
995 xmlMalloc(sizeof(xmlTextWriterStackEntry));
996 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000997 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000998 "xmlTextWriterStartElement : out of memory!\n");
999 return -1;
1000 }
1001
1002 p->name = xmlStrdup(name);
1003 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001004 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001005 "xmlTextWriterStartElement : out of memory!\n");
1006 xmlFree(p);
1007 return -1;
1008 }
1009 p->state = XML_TEXTWRITER_NAME;
1010
1011 xmlListPushFront(writer->nodes, p);
1012
Daniel Veillardab69f362004-02-17 11:40:32 +00001013 if (writer->indent) {
1014 count = xmlTextWriterWriteIndent(writer);
1015 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001016 }
1017
Daniel Veillard1d211e22003-10-20 22:32:39 +00001018 count = xmlOutputBufferWriteString(writer->out, "<");
1019 if (count < 0)
1020 return -1;
1021 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001022 count =
1023 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001024 if (count < 0)
1025 return -1;
1026 sum += count;
1027
1028 return sum;
1029}
1030
1031/**
1032 * xmlTextWriterStartElementNS:
1033 * @writer: the xmlTextWriterPtr
1034 * @prefix: namespace prefix or NULL
1035 * @name: element local name
1036 * @namespaceURI: namespace URI or NULL
1037 *
1038 * Start an xml element with namespace support.
1039 *
1040 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1041 */
1042int
1043xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
1044 const xmlChar * prefix, const xmlChar * name,
1045 const xmlChar * namespaceURI)
1046{
1047 int count;
1048 int sum;
1049 xmlChar *buf;
1050
1051 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1052 return -1;
1053
Daniel Veillard75e389d2005-07-29 22:02:24 +00001054 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001055 if (prefix != 0) {
1056 buf = xmlStrdup(prefix);
1057 buf = xmlStrcat(buf, BAD_CAST ":");
1058 }
1059 buf = xmlStrcat(buf, name);
1060
1061 sum = 0;
1062 count = xmlTextWriterStartElement(writer, buf);
1063 xmlFree(buf);
1064 if (count < 0)
1065 return -1;
1066 sum += count;
1067
1068 if (namespaceURI != 0) {
Rob Richardsb8769d62007-06-08 08:50:47 +00001069 xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
1070 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1071 if (p == 0) {
1072 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1073 "xmlTextWriterStartElementNS : out of memory!\n");
1074 return -1;
1075 }
1076
Daniel Veillard1d211e22003-10-20 22:32:39 +00001077 buf = xmlStrdup(BAD_CAST "xmlns");
1078 if (prefix != 0) {
1079 buf = xmlStrcat(buf, BAD_CAST ":");
1080 buf = xmlStrcat(buf, prefix);
1081 }
1082
Rob Richardsb8769d62007-06-08 08:50:47 +00001083 p->prefix = buf;
1084 p->uri = xmlStrdup(namespaceURI);
1085 if (p->uri == 0) {
1086 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1087 "xmlTextWriterStartElementNS : out of memory!\n");
1088 xmlFree(p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001089 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001090 }
1091 p->elem = xmlListFront(writer->nodes);
1092
1093 xmlListPushFront(writer->nsstack, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001094 }
1095
1096 return sum;
1097}
1098
1099/**
1100 * xmlTextWriterEndElement:
1101 * @writer: the xmlTextWriterPtr
1102 *
1103 * End the current xml element.
1104 *
1105 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1106 */
1107int
1108xmlTextWriterEndElement(xmlTextWriterPtr writer)
1109{
1110 int count;
1111 int sum;
1112 xmlLinkPtr lk;
1113 xmlTextWriterStackEntry *p;
1114
1115 if (writer == NULL)
1116 return -1;
1117
1118 lk = xmlListFront(writer->nodes);
Rob Richardsb8769d62007-06-08 08:50:47 +00001119 if (lk == 0) {
1120 xmlListDelete(writer->nsstack);
1121 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001122 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001123 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001124
1125 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Rob Richardsb8769d62007-06-08 08:50:47 +00001126 if (p == 0) {
1127 xmlListDelete(writer->nsstack);
1128 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001129 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001130 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001131
1132 sum = 0;
1133 switch (p->state) {
1134 case XML_TEXTWRITER_ATTRIBUTE:
1135 count = xmlTextWriterEndAttribute(writer);
Rob Richardsb8769d62007-06-08 08:50:47 +00001136 if (count < 0) {
1137 xmlListDelete(writer->nsstack);
1138 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001139 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001140 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001141 sum += count;
1142 /* fallthrough */
1143 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001144 /* Output namespace declarations */
1145 count = xmlTextWriterOutputNSDecl(writer);
1146 if (count < 0)
1147 return -1;
1148 sum += count;
1149
Daniel Veillardab69f362004-02-17 11:40:32 +00001150 if (writer->indent) /* next element needs indent */
1151 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001152 count = xmlOutputBufferWriteString(writer->out, "/>");
1153 if (count < 0)
1154 return -1;
1155 sum += count;
1156 break;
1157 case XML_TEXTWRITER_TEXT:
Daniel Veillardab69f362004-02-17 11:40:32 +00001158 if ((writer->indent) && (writer->doindent)) {
1159 count = xmlTextWriterWriteIndent(writer);
1160 sum += count;
1161 writer->doindent = 1;
1162 } else
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 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001169 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001170 if (count < 0)
1171 return -1;
1172 sum += count;
1173 count = xmlOutputBufferWriteString(writer->out, ">");
1174 if (count < 0)
1175 return -1;
1176 sum += count;
1177 break;
1178 default:
1179 return -1;
1180 }
1181
Daniel Veillard2cca4462004-01-02 20:04:23 +00001182 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001183 count = xmlOutputBufferWriteString(writer->out, "\n");
1184 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001185 }
1186
Daniel Veillard1d211e22003-10-20 22:32:39 +00001187 xmlListPopFront(writer->nodes);
1188 return sum;
1189}
1190
1191/**
1192 * xmlTextWriterFullEndElement:
1193 * @writer: the xmlTextWriterPtr
1194 *
1195 * End the current xml element. Writes an end tag even if the element is empty
1196 *
1197 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1198 */
1199int
1200xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1201{
1202 int count;
1203 int sum;
1204 xmlLinkPtr lk;
1205 xmlTextWriterStackEntry *p;
1206
1207 if (writer == NULL)
1208 return -1;
1209
1210 lk = xmlListFront(writer->nodes);
1211 if (lk == 0)
1212 return -1;
1213
1214 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1215 if (p == 0)
1216 return -1;
1217
1218 sum = 0;
1219 switch (p->state) {
1220 case XML_TEXTWRITER_ATTRIBUTE:
1221 count = xmlTextWriterEndAttribute(writer);
1222 if (count < 0)
1223 return -1;
1224 sum += count;
1225 /* fallthrough */
1226 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001227 /* Output namespace declarations */
1228 count = xmlTextWriterOutputNSDecl(writer);
1229 if (count < 0)
1230 return -1;
1231 sum += count;
1232
Daniel Veillard1d211e22003-10-20 22:32:39 +00001233 count = xmlOutputBufferWriteString(writer->out, ">");
1234 if (count < 0)
1235 return -1;
1236 sum += count;
1237 /* fallthrough */
1238 case XML_TEXTWRITER_TEXT:
1239 count = xmlOutputBufferWriteString(writer->out, "</");
1240 if (count < 0)
1241 return -1;
1242 sum += count;
1243 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001244 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001245 if (count < 0)
1246 return -1;
1247 sum += count;
1248 count = xmlOutputBufferWriteString(writer->out, ">");
1249 if (count < 0)
1250 return -1;
1251 sum += count;
1252 break;
1253 default:
1254 return -1;
1255 }
1256
1257 xmlListPopFront(writer->nodes);
1258 return sum;
1259}
1260
1261/**
1262 * xmlTextWriterWriteFormatRaw:
1263 * @writer: the xmlTextWriterPtr
1264 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001265 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001266 *
1267 * Write a formatted raw xml text.
1268 *
1269 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1270 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001271int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001272xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1273 ...)
1274{
1275 int rc;
1276 va_list ap;
1277
1278 va_start(ap, format);
1279
1280 rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1281
1282 va_end(ap);
1283 return rc;
1284}
1285
1286/**
1287 * xmlTextWriterWriteVFormatRaw:
1288 * @writer: the xmlTextWriterPtr
1289 * @format: format string (see printf)
1290 * @argptr: pointer to the first member of the variable argument list.
1291 *
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 */
1296int
1297xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1298 va_list argptr)
1299{
1300 int rc;
1301 xmlChar *buf;
1302
1303 if (writer == NULL)
1304 return -1;
1305
1306 buf = xmlTextWriterVSprintf(format, argptr);
1307 if (buf == 0)
1308 return 0;
1309
1310 rc = xmlTextWriterWriteRaw(writer, buf);
1311
1312 xmlFree(buf);
1313 return rc;
1314}
1315
1316/**
Daniel Veillard1e906612003-12-05 14:57:46 +00001317 * xmlTextWriterWriteRawLen:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001318 * @writer: the xmlTextWriterPtr
1319 * @content: text string
1320 * @len: length of the text string
1321 *
1322 * Write an xml text.
1323 * TODO: what about entities and special chars??
1324 *
1325 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1326 */
1327int
1328xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1329 int len)
1330{
1331 int count;
1332 int sum;
1333 xmlLinkPtr lk;
1334 xmlTextWriterStackEntry *p;
1335
Daniel Veillard500a1de2004-03-22 15:22:58 +00001336 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001337 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001338 "xmlTextWriterWriteRawLen : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001339 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001340 }
1341
Daniel Veillarde43cc572004-11-03 11:50:29 +00001342 if ((content == NULL) || (len < 0)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001343 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001344 "xmlTextWriterWriteRawLen : invalid content!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001345 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001346 }
1347
1348 sum = 0;
1349 lk = xmlListFront(writer->nodes);
1350 if (lk != 0) {
1351 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1352 count = xmlTextWriterHandleStateDependencies(writer, p);
1353 if (count < 0)
1354 return -1;
1355 sum += count;
1356 }
1357
1358 if (writer->indent)
1359 writer->doindent = 0;
1360
1361 if (content != NULL) {
1362 count =
1363 xmlOutputBufferWrite(writer->out, len, (const char *) content);
1364 if (count < 0)
1365 return -1;
1366 sum += count;
1367 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001368
1369 return sum;
1370}
1371
1372/**
1373 * xmlTextWriterWriteRaw:
1374 * @writer: the xmlTextWriterPtr
1375 * @content: text string
1376 *
1377 * Write a raw xml text.
1378 *
1379 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1380 */
1381int
1382xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1383{
1384 return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1385}
1386
1387/**
1388 * xmlTextWriterWriteFormatString:
1389 * @writer: the xmlTextWriterPtr
1390 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001391 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001392 *
1393 * Write a formatted xml text.
1394 *
1395 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1396 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001397int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001398xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1399 ...)
1400{
1401 int rc;
1402 va_list ap;
1403
Daniel Veillarde43cc572004-11-03 11:50:29 +00001404 if ((writer == NULL) || (format == NULL))
1405 return -1;
1406
Daniel Veillard1d211e22003-10-20 22:32:39 +00001407 va_start(ap, format);
1408
1409 rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1410
1411 va_end(ap);
1412 return rc;
1413}
1414
1415/**
1416 * xmlTextWriterWriteVFormatString:
1417 * @writer: the xmlTextWriterPtr
1418 * @format: format string (see printf)
1419 * @argptr: pointer to the first member of the variable argument list.
1420 *
1421 * Write a formatted xml text.
1422 *
1423 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1424 */
1425int
1426xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1427 const char *format, va_list argptr)
1428{
1429 int rc;
1430 xmlChar *buf;
1431
Daniel Veillarde43cc572004-11-03 11:50:29 +00001432 if ((writer == NULL) || (format == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001433 return -1;
1434
1435 buf = xmlTextWriterVSprintf(format, argptr);
1436 if (buf == 0)
1437 return 0;
1438
1439 rc = xmlTextWriterWriteString(writer, buf);
1440
1441 xmlFree(buf);
1442 return rc;
1443}
1444
1445/**
1446 * xmlTextWriterWriteString:
1447 * @writer: the xmlTextWriterPtr
1448 * @content: text string
1449 *
1450 * Write an xml text.
1451 *
1452 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1453 */
1454int
1455xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1456{
Daniel Veillard500a1de2004-03-22 15:22:58 +00001457 int count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001458 int sum;
1459 xmlLinkPtr lk;
1460 xmlTextWriterStackEntry *p;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001461 xmlChar *buf;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001462
Daniel Veillarde43cc572004-11-03 11:50:29 +00001463 if ((writer == NULL) || (content == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001464 return -1;
1465
Daniel Veillard1d211e22003-10-20 22:32:39 +00001466 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001467 buf = (xmlChar *) content;
1468 lk = xmlListFront(writer->nodes);
1469 if (lk != 0) {
1470 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1471 if (p != 0) {
1472 switch (p->state) {
1473 case XML_TEXTWRITER_NAME:
1474 case XML_TEXTWRITER_TEXT:
Daniel Veillard62040be2004-05-17 03:17:26 +00001475#if 0
1476 buf = NULL;
1477 xmlOutputBufferWriteEscape(writer->out, content, NULL);
1478#endif
Daniel Veillard500a1de2004-03-22 15:22:58 +00001479 buf = xmlEncodeSpecialChars(NULL, content);
1480 break;
1481 case XML_TEXTWRITER_ATTRIBUTE:
1482 buf = NULL;
Rob Richards9db68f02006-08-16 22:48:51 +00001483 xmlAttrSerializeTxtContent(writer->out->buffer, writer->doc,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001484 NULL, content);
1485 break;
William M. Brack87640d52004-04-17 14:58:15 +00001486 default:
1487 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001488 }
1489 }
1490 }
1491
1492 if (buf != NULL) {
1493 count = xmlTextWriterWriteRaw(writer, buf);
1494 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001495 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001496 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001497
Daniel Veillard500a1de2004-03-22 15:22:58 +00001498 if (buf != content) /* buf was allocated by us, so free it */
1499 xmlFree(buf);
William M. Bracka9c612c2004-02-01 10:04:05 +00001500 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001501
1502 return sum;
1503}
1504
1505/**
1506 * xmlOutputBufferWriteBase64:
1507 * @out: the xmlOutputBufferPtr
1508 * @data: binary data
1509 * @len: the number of bytes to encode
1510 *
1511 * Write base64 encoded data to an xmlOutputBuffer.
1512 * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1513 *
1514 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1515 */
1516static int
1517xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1518 const unsigned char *data)
1519{
1520 static unsigned char dtable[64] =
William M. Brack47a31882004-09-11 16:09:09 +00001521 {'A','B','C','D','E','F','G','H','I','J','K','L','M',
1522 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1523 'a','b','c','d','e','f','g','h','i','j','k','l','m',
1524 'n','o','p','q','r','s','t','u','v','w','x','y','z',
1525 '0','1','2','3','4','5','6','7','8','9','+','/'};
1526
Daniel Veillard1d211e22003-10-20 22:32:39 +00001527 int i;
1528 int linelen;
1529 int count;
1530 int sum;
1531
Daniel Veillarde43cc572004-11-03 11:50:29 +00001532 if ((out == NULL) || (len < 0) || (data == NULL))
1533 return(-1);
1534
Daniel Veillard1d211e22003-10-20 22:32:39 +00001535 linelen = 0;
1536 sum = 0;
1537
1538 i = 0;
1539 while (1) {
1540 unsigned char igroup[3];
1541 unsigned char ogroup[4];
1542 int c;
1543 int n;
1544
1545 igroup[0] = igroup[1] = igroup[2] = 0;
1546 for (n = 0; n < 3 && i < len; n++, i++) {
1547 c = data[i];
1548 igroup[n] = (unsigned char) c;
1549 }
1550
1551 if (n > 0) {
1552 ogroup[0] = dtable[igroup[0] >> 2];
1553 ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1554 ogroup[2] =
1555 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1556 ogroup[3] = dtable[igroup[2] & 0x3F];
1557
1558 if (n < 3) {
1559 ogroup[3] = '=';
1560 if (n < 2) {
1561 ogroup[2] = '=';
1562 }
1563 }
1564
1565 if (linelen >= B64LINELEN) {
1566 count = xmlOutputBufferWrite(out, 2, B64CRLF);
1567 if (count == -1)
1568 return -1;
1569 sum += count;
1570 linelen = 0;
1571 }
1572 count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1573 if (count == -1)
1574 return -1;
1575 sum += count;
1576
1577 linelen += 4;
1578 }
Daniel Veillard929714b2003-10-22 12:34:36 +00001579
1580 if (i >= len)
1581 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001582 }
1583
Daniel Veillard1d211e22003-10-20 22:32:39 +00001584 return sum;
1585}
1586
1587/**
1588 * xmlTextWriterWriteBase64:
1589 * @writer: the xmlTextWriterPtr
1590 * @data: binary data
1591 * @start: the position within the data of the first byte to encode
1592 * @len: the number of bytes to encode
1593 *
1594 * Write an base64 encoded xml text.
1595 *
1596 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1597 */
1598int
Daniel Veillardab69f362004-02-17 11:40:32 +00001599xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001600 int start, int len)
1601{
1602 int count;
1603 int sum;
1604 xmlLinkPtr lk;
1605 xmlTextWriterStackEntry *p;
1606
Daniel Veillarde43cc572004-11-03 11:50:29 +00001607 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001608 return -1;
1609
Daniel Veillard1d211e22003-10-20 22:32:39 +00001610 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001611 lk = xmlListFront(writer->nodes);
1612 if (lk != 0) {
1613 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1614 if (p != 0) {
1615 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001616 if (count < 0)
1617 return -1;
1618 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001619 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001620 }
1621
Daniel Veillardab69f362004-02-17 11:40:32 +00001622 if (writer->indent)
1623 writer->doindent = 0;
1624
Daniel Veillard1d211e22003-10-20 22:32:39 +00001625 count =
1626 xmlOutputBufferWriteBase64(writer->out, len,
1627 (unsigned char *) data + start);
1628 if (count < 0)
1629 return -1;
1630 sum += count;
1631
1632 return sum;
1633}
1634
1635/**
1636 * xmlOutputBufferWriteBinHex:
1637 * @out: the xmlOutputBufferPtr
1638 * @data: binary data
1639 * @len: the number of bytes to encode
1640 *
1641 * Write hqx encoded data to an xmlOutputBuffer.
1642 * ::todo
1643 *
William M. Brack47a31882004-09-11 16:09:09 +00001644 * Returns the bytes written (may be 0 because of buffering)
1645 * or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +00001646 */
1647static int
Daniel Veillardab69f362004-02-17 11:40:32 +00001648xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1649 int len, const unsigned char *data)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001650{
Daniel Veillardab69f362004-02-17 11:40:32 +00001651 int count;
1652 int sum;
William M. Brack47a31882004-09-11 16:09:09 +00001653 static char hex[16] =
1654 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
Daniel Veillardab69f362004-02-17 11:40:32 +00001655 int i;
1656
Daniel Veillarde43cc572004-11-03 11:50:29 +00001657 if ((out == NULL) || (data == NULL) || (len < 0)) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001658 return -1;
1659 }
1660
1661 sum = 0;
1662 for (i = 0; i < len; i++) {
1663 count =
1664 xmlOutputBufferWrite(out, 1,
1665 (const char *) &hex[data[i] >> 4]);
1666 if (count == -1)
1667 return -1;
1668 sum += count;
1669 count =
1670 xmlOutputBufferWrite(out, 1,
1671 (const char *) &hex[data[i] & 0xF]);
1672 if (count == -1)
1673 return -1;
1674 sum += count;
1675 }
1676
1677 return sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001678}
1679
1680/**
1681 * xmlTextWriterWriteBinHex:
1682 * @writer: the xmlTextWriterPtr
1683 * @data: binary data
1684 * @start: the position within the data of the first byte to encode
1685 * @len: the number of bytes to encode
1686 *
1687 * Write a BinHex encoded xml text.
1688 *
1689 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1690 */
1691int
Daniel Veillardab69f362004-02-17 11:40:32 +00001692xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001693 int start, int len)
1694{
1695 int count;
1696 int sum;
1697 xmlLinkPtr lk;
1698 xmlTextWriterStackEntry *p;
1699
Daniel Veillarde43cc572004-11-03 11:50:29 +00001700 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001701 return -1;
1702
Daniel Veillard1d211e22003-10-20 22:32:39 +00001703 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001704 lk = xmlListFront(writer->nodes);
1705 if (lk != 0) {
1706 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1707 if (p != 0) {
1708 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001709 if (count < 0)
1710 return -1;
1711 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001712 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001713 }
1714
Daniel Veillardab69f362004-02-17 11:40:32 +00001715 if (writer->indent)
1716 writer->doindent = 0;
1717
Daniel Veillard1d211e22003-10-20 22:32:39 +00001718 count =
1719 xmlOutputBufferWriteBinHex(writer->out, len,
1720 (unsigned char *) data + start);
1721 if (count < 0)
1722 return -1;
1723 sum += count;
1724
1725 return sum;
1726}
1727
1728/**
1729 * xmlTextWriterStartAttribute:
1730 * @writer: the xmlTextWriterPtr
1731 * @name: element name
1732 *
1733 * Start an xml attribute.
1734 *
1735 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1736 */
1737int
1738xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1739{
1740 int count;
1741 int sum;
1742 xmlLinkPtr lk;
1743 xmlTextWriterStackEntry *p;
1744
1745 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1746 return -1;
1747
1748 sum = 0;
1749 lk = xmlListFront(writer->nodes);
1750 if (lk == 0)
1751 return -1;
1752
1753 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1754 if (p == 0)
1755 return -1;
1756
1757 switch (p->state) {
1758 case XML_TEXTWRITER_ATTRIBUTE:
1759 count = xmlTextWriterEndAttribute(writer);
1760 if (count < 0)
1761 return -1;
1762 sum += count;
1763 /* fallthrough */
1764 case XML_TEXTWRITER_NAME:
1765 count = xmlOutputBufferWriteString(writer->out, " ");
1766 if (count < 0)
1767 return -1;
1768 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001769 count =
1770 xmlOutputBufferWriteString(writer->out,
1771 (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001772 if (count < 0)
1773 return -1;
1774 sum += count;
1775 count = xmlOutputBufferWriteString(writer->out, "=");
1776 if (count < 0)
1777 return -1;
1778 sum += count;
1779 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1780 if (count < 0)
1781 return -1;
1782 sum += count;
1783 p->state = XML_TEXTWRITER_ATTRIBUTE;
1784 break;
1785 default:
1786 return -1;
1787 }
1788
1789 return sum;
1790}
1791
1792/**
1793 * xmlTextWriterStartAttributeNS:
1794 * @writer: the xmlTextWriterPtr
1795 * @prefix: namespace prefix or NULL
1796 * @name: element local name
1797 * @namespaceURI: namespace URI or NULL
1798 *
1799 * Start an xml attribute with namespace support.
1800 *
1801 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1802 */
1803int
1804xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1805 const xmlChar * prefix, const xmlChar * name,
1806 const xmlChar * namespaceURI)
1807{
1808 int count;
1809 int sum;
1810 xmlChar *buf;
1811 xmlTextWriterNsStackEntry *p;
1812
1813 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1814 return -1;
1815
Rob Richardsb8769d62007-06-08 08:50:47 +00001816 /* Handle namespace first in case of error */
1817 if (namespaceURI != 0) {
1818 xmlTextWriterNsStackEntry nsentry, *curns;
1819
1820 buf = xmlStrdup(BAD_CAST "xmlns");
1821 if (prefix != 0) {
1822 buf = xmlStrcat(buf, BAD_CAST ":");
1823 buf = xmlStrcat(buf, prefix);
1824 }
1825
1826 nsentry.prefix = buf;
1827 nsentry.uri = (xmlChar *)namespaceURI;
1828 nsentry.elem = xmlListFront(writer->nodes);
1829
1830 curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
1831 (void *)&nsentry);
1832 if ((curns != NULL)) {
1833 xmlFree(buf);
1834 if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
1835 /* Namespace already defined on element skip */
1836 buf = NULL;
1837 } else {
1838 /* Prefix mismatch so error out */
1839 return -1;
1840 }
1841 }
1842
1843 /* Do not add namespace decl to list - it is already there */
1844 if (buf != NULL) {
1845 p = (xmlTextWriterNsStackEntry *)
1846 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1847 if (p == 0) {
1848 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1849 "xmlTextWriterStartAttributeNS : out of memory!\n");
1850 return -1;
1851 }
1852
1853 p->prefix = buf;
1854 p->uri = xmlStrdup(namespaceURI);
1855 if (p->uri == 0) {
1856 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1857 "xmlTextWriterStartAttributeNS : out of memory!\n");
1858 xmlFree(p);
1859 return -1;
1860 }
1861 p->elem = xmlListFront(writer->nodes);
1862
1863 xmlListPushFront(writer->nsstack, p);
1864 }
1865 }
1866
Daniel Veillard75e389d2005-07-29 22:02:24 +00001867 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001868 if (prefix != 0) {
1869 buf = xmlStrdup(prefix);
1870 buf = xmlStrcat(buf, BAD_CAST ":");
1871 }
1872 buf = xmlStrcat(buf, name);
1873
1874 sum = 0;
1875 count = xmlTextWriterStartAttribute(writer, buf);
1876 xmlFree(buf);
1877 if (count < 0)
1878 return -1;
1879 sum += count;
1880
Daniel Veillard1d211e22003-10-20 22:32:39 +00001881 return sum;
1882}
1883
1884/**
1885 * xmlTextWriterEndAttribute:
1886 * @writer: the xmlTextWriterPtr
1887 *
1888 * End the current xml element.
1889 *
1890 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1891 */
1892int
1893xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1894{
1895 int count;
1896 int sum;
1897 xmlLinkPtr lk;
1898 xmlTextWriterStackEntry *p;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001899
1900 if (writer == NULL)
1901 return -1;
1902
1903 lk = xmlListFront(writer->nodes);
1904 if (lk == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001905 return -1;
1906 }
1907
1908 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1909 if (p == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001910 return -1;
1911 }
1912
1913 sum = 0;
1914 switch (p->state) {
1915 case XML_TEXTWRITER_ATTRIBUTE:
1916 p->state = XML_TEXTWRITER_NAME;
1917
1918 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1919 if (count < 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001920 return -1;
1921 }
1922 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001923 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001924 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001925 return -1;
1926 }
1927
1928 return sum;
1929}
1930
1931/**
1932 * xmlTextWriterWriteFormatAttribute:
1933 * @writer: the xmlTextWriterPtr
1934 * @name: attribute name
1935 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001936 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001937 *
1938 * Write a formatted xml attribute.
1939 *
1940 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1941 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001942int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001943xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1944 const xmlChar * name, const char *format,
1945 ...)
1946{
1947 int rc;
1948 va_list ap;
1949
1950 va_start(ap, format);
1951
1952 rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1953
1954 va_end(ap);
1955 return rc;
1956}
1957
1958/**
1959 * xmlTextWriterWriteVFormatAttribute:
1960 * @writer: the xmlTextWriterPtr
1961 * @name: attribute name
1962 * @format: format string (see printf)
1963 * @argptr: pointer to the first member of the variable argument list.
1964 *
1965 * Write a formatted xml attribute.
1966 *
1967 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1968 */
1969int
1970xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
1971 const xmlChar * name,
1972 const char *format, va_list argptr)
1973{
1974 int rc;
1975 xmlChar *buf;
1976
1977 if (writer == NULL)
1978 return -1;
1979
1980 buf = xmlTextWriterVSprintf(format, argptr);
1981 if (buf == 0)
1982 return 0;
1983
1984 rc = xmlTextWriterWriteAttribute(writer, name, buf);
1985
1986 xmlFree(buf);
1987 return rc;
1988}
1989
1990/**
1991 * xmlTextWriterWriteAttribute:
1992 * @writer: the xmlTextWriterPtr
1993 * @name: attribute name
1994 * @content: attribute content
1995 *
1996 * Write an xml attribute.
1997 *
1998 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1999 */
2000int
2001xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
2002 const xmlChar * content)
2003{
2004 int count;
2005 int sum;
2006
2007 sum = 0;
2008 count = xmlTextWriterStartAttribute(writer, name);
2009 if (count < 0)
2010 return -1;
2011 sum += count;
2012 count = xmlTextWriterWriteString(writer, content);
2013 if (count < 0)
2014 return -1;
2015 sum += count;
2016 count = xmlTextWriterEndAttribute(writer);
2017 if (count < 0)
2018 return -1;
2019 sum += count;
2020
2021 return sum;
2022}
2023
2024/**
2025 * xmlTextWriterWriteFormatAttributeNS:
2026 * @writer: the xmlTextWriterPtr
2027 * @prefix: namespace prefix
2028 * @name: attribute local name
2029 * @namespaceURI: namespace URI
2030 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002031 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002032 *
2033 * Write a formatted xml attribute.with namespace support
2034 *
2035 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2036 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002037int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002038xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
2039 const xmlChar * prefix,
2040 const xmlChar * name,
2041 const xmlChar * namespaceURI,
2042 const char *format, ...)
2043{
2044 int rc;
2045 va_list ap;
2046
2047 va_start(ap, format);
2048
2049 rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
2050 namespaceURI, format, ap);
2051
2052 va_end(ap);
2053 return rc;
2054}
2055
2056/**
2057 * xmlTextWriterWriteVFormatAttributeNS:
2058 * @writer: the xmlTextWriterPtr
2059 * @prefix: namespace prefix
2060 * @name: attribute local name
2061 * @namespaceURI: namespace URI
2062 * @format: format string (see printf)
2063 * @argptr: pointer to the first member of the variable argument list.
2064 *
2065 * Write a formatted xml attribute.with namespace support
2066 *
2067 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2068 */
2069int
2070xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
2071 const xmlChar * prefix,
2072 const xmlChar * name,
2073 const xmlChar * namespaceURI,
2074 const char *format, va_list argptr)
2075{
2076 int rc;
2077 xmlChar *buf;
2078
2079 if (writer == NULL)
2080 return -1;
2081
2082 buf = xmlTextWriterVSprintf(format, argptr);
2083 if (buf == 0)
2084 return 0;
2085
2086 rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
2087 buf);
2088
2089 xmlFree(buf);
2090 return rc;
2091}
2092
2093/**
2094 * xmlTextWriterWriteAttributeNS:
2095 * @writer: the xmlTextWriterPtr
2096 * @prefix: namespace prefix
2097 * @name: attribute local name
2098 * @namespaceURI: namespace URI
2099 * @content: attribute content
2100 *
2101 * Write an xml attribute.
2102 *
2103 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2104 */
2105int
2106xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
2107 const xmlChar * prefix, const xmlChar * name,
2108 const xmlChar * namespaceURI,
2109 const xmlChar * content)
2110{
2111 int count;
2112 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002113
2114 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2115 return -1;
2116
Daniel Veillard1d211e22003-10-20 22:32:39 +00002117 sum = 0;
Rob Richardsb8769d62007-06-08 08:50:47 +00002118 count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
2119 if (count < 0)
2120 return -1;
2121 sum += count;
2122 count = xmlTextWriterWriteString(writer, content);
2123 if (count < 0)
2124 return -1;
2125 sum += count;
2126 count = xmlTextWriterEndAttribute(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002127 if (count < 0)
2128 return -1;
2129 sum += count;
2130
Daniel Veillard1d211e22003-10-20 22:32:39 +00002131 return sum;
2132}
2133
2134/**
2135 * xmlTextWriterWriteFormatElement:
2136 * @writer: the xmlTextWriterPtr
2137 * @name: element name
2138 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002139 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002140 *
2141 * Write a formatted xml element.
2142 *
2143 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2144 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002145int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002146xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2147 const xmlChar * name, const char *format,
2148 ...)
2149{
2150 int rc;
2151 va_list ap;
2152
2153 va_start(ap, format);
2154
2155 rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2156
2157 va_end(ap);
2158 return rc;
2159}
2160
2161/**
2162 * xmlTextWriterWriteVFormatElement:
2163 * @writer: the xmlTextWriterPtr
2164 * @name: element name
2165 * @format: format string (see printf)
2166 * @argptr: pointer to the first member of the variable argument list.
2167 *
2168 * Write a formatted xml element.
2169 *
2170 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2171 */
2172int
2173xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2174 const xmlChar * name, const char *format,
2175 va_list argptr)
2176{
2177 int rc;
2178 xmlChar *buf;
2179
2180 if (writer == NULL)
2181 return -1;
2182
2183 buf = xmlTextWriterVSprintf(format, argptr);
2184 if (buf == 0)
2185 return 0;
2186
2187 rc = xmlTextWriterWriteElement(writer, name, buf);
2188
2189 xmlFree(buf);
2190 return rc;
2191}
2192
2193/**
2194 * xmlTextWriterWriteElement:
2195 * @writer: the xmlTextWriterPtr
2196 * @name: element name
2197 * @content: element content
2198 *
2199 * Write an xml element.
2200 *
2201 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2202 */
2203int
2204xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2205 const xmlChar * content)
2206{
2207 int count;
2208 int sum;
2209
2210 sum = 0;
2211 count = xmlTextWriterStartElement(writer, name);
2212 if (count == -1)
2213 return -1;
2214 sum += count;
2215 count = xmlTextWriterWriteString(writer, content);
2216 if (count == -1)
2217 return -1;
2218 sum += count;
2219 count = xmlTextWriterEndElement(writer);
2220 if (count == -1)
2221 return -1;
2222 sum += count;
2223
2224 return sum;
2225}
2226
2227/**
2228 * xmlTextWriterWriteFormatElementNS:
2229 * @writer: the xmlTextWriterPtr
2230 * @prefix: namespace prefix
2231 * @name: element local name
2232 * @namespaceURI: namespace URI
2233 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002234 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002235 *
2236 * Write a formatted xml element with namespace support.
2237 *
2238 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2239 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002240int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002241xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2242 const xmlChar * prefix,
2243 const xmlChar * name,
2244 const xmlChar * namespaceURI,
2245 const char *format, ...)
2246{
2247 int rc;
2248 va_list ap;
2249
2250 va_start(ap, format);
2251
2252 rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2253 namespaceURI, format, ap);
2254
2255 va_end(ap);
2256 return rc;
2257}
2258
2259/**
2260 * xmlTextWriterWriteVFormatElementNS:
2261 * @writer: the xmlTextWriterPtr
2262 * @prefix: namespace prefix
2263 * @name: element local name
2264 * @namespaceURI: namespace URI
2265 * @format: format string (see printf)
2266 * @argptr: pointer to the first member of the variable argument list.
2267 *
2268 * Write a formatted xml element with namespace support.
2269 *
2270 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2271 */
2272int
2273xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2274 const xmlChar * prefix,
2275 const xmlChar * name,
2276 const xmlChar * namespaceURI,
2277 const char *format, va_list argptr)
2278{
2279 int rc;
2280 xmlChar *buf;
2281
2282 if (writer == NULL)
2283 return -1;
2284
2285 buf = xmlTextWriterVSprintf(format, argptr);
2286 if (buf == 0)
2287 return 0;
2288
2289 rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2290 buf);
2291
2292 xmlFree(buf);
2293 return rc;
2294}
2295
2296/**
2297 * xmlTextWriterWriteElementNS:
2298 * @writer: the xmlTextWriterPtr
2299 * @prefix: namespace prefix
2300 * @name: element local name
2301 * @namespaceURI: namespace URI
2302 * @content: element content
2303 *
2304 * Write an xml element with namespace support.
2305 *
2306 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2307 */
2308int
2309xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2310 const xmlChar * prefix, const xmlChar * name,
2311 const xmlChar * namespaceURI,
2312 const xmlChar * content)
2313{
2314 int count;
2315 int sum;
2316
2317 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2318 return -1;
2319
2320 sum = 0;
2321 count =
2322 xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2323 if (count < 0)
2324 return -1;
2325 sum += count;
2326 count = xmlTextWriterWriteString(writer, content);
2327 if (count == -1)
2328 return -1;
2329 sum += count;
2330 count = xmlTextWriterEndElement(writer);
2331 if (count == -1)
2332 return -1;
2333 sum += count;
2334
2335 return sum;
2336}
2337
2338/**
2339 * xmlTextWriterStartPI:
2340 * @writer: the xmlTextWriterPtr
2341 * @target: PI target
2342 *
2343 * Start an xml PI.
2344 *
2345 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2346 */
2347int
2348xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2349{
2350 int count;
2351 int sum;
2352 xmlLinkPtr lk;
2353 xmlTextWriterStackEntry *p;
2354
2355 if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2356 return -1;
2357
2358 if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002359 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002360 "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2361 return -1;
2362 }
2363
2364 sum = 0;
2365 lk = xmlListFront(writer->nodes);
2366 if (lk != 0) {
2367 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2368 if (p != 0) {
2369 switch (p->state) {
2370 case XML_TEXTWRITER_ATTRIBUTE:
2371 count = xmlTextWriterEndAttribute(writer);
2372 if (count < 0)
2373 return -1;
2374 sum += count;
2375 /* fallthrough */
2376 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002377 /* Output namespace declarations */
2378 count = xmlTextWriterOutputNSDecl(writer);
2379 if (count < 0)
2380 return -1;
2381 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002382 count = xmlOutputBufferWriteString(writer->out, ">");
2383 if (count < 0)
2384 return -1;
2385 sum += count;
2386 p->state = XML_TEXTWRITER_TEXT;
2387 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00002388 case XML_TEXTWRITER_NONE:
2389 case XML_TEXTWRITER_TEXT:
2390 case XML_TEXTWRITER_DTD:
2391 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002392 case XML_TEXTWRITER_PI:
2393 case XML_TEXTWRITER_PI_TEXT:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002394 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002395 "xmlTextWriterStartPI : nested PI!\n");
2396 return -1;
2397 default:
2398 return -1;
2399 }
2400 }
2401 }
2402
2403 p = (xmlTextWriterStackEntry *)
2404 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2405 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002406 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002407 "xmlTextWriterStartPI : out of memory!\n");
2408 return -1;
2409 }
2410
2411 p->name = xmlStrdup(target);
2412 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002413 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002414 "xmlTextWriterStartPI : out of memory!\n");
2415 xmlFree(p);
2416 return -1;
2417 }
2418 p->state = XML_TEXTWRITER_PI;
2419
2420 xmlListPushFront(writer->nodes, p);
2421
2422 count = xmlOutputBufferWriteString(writer->out, "<?");
2423 if (count < 0)
2424 return -1;
2425 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002426 count =
2427 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002428 if (count < 0)
2429 return -1;
2430 sum += count;
2431
2432 return sum;
2433}
2434
2435/**
2436 * xmlTextWriterEndPI:
2437 * @writer: the xmlTextWriterPtr
2438 *
2439 * End the current xml PI.
2440 *
2441 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2442 */
2443int
2444xmlTextWriterEndPI(xmlTextWriterPtr writer)
2445{
2446 int count;
2447 int sum;
2448 xmlLinkPtr lk;
2449 xmlTextWriterStackEntry *p;
2450
2451 if (writer == NULL)
2452 return -1;
2453
2454 lk = xmlListFront(writer->nodes);
2455 if (lk == 0)
2456 return 0;
2457
2458 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2459 if (p == 0)
2460 return 0;
2461
2462 sum = 0;
2463 switch (p->state) {
2464 case XML_TEXTWRITER_PI:
2465 case XML_TEXTWRITER_PI_TEXT:
2466 count = xmlOutputBufferWriteString(writer->out, "?>");
2467 if (count < 0)
2468 return -1;
2469 sum += count;
2470 break;
2471 default:
2472 return -1;
2473 }
2474
Daniel Veillard02c1f232006-04-27 08:10:25 +00002475 if (writer->indent) {
2476 count = xmlOutputBufferWriteString(writer->out, "\n");
2477 if (count < 0)
2478 return -1;
2479 sum += count;
2480 }
2481
Daniel Veillard1d211e22003-10-20 22:32:39 +00002482 xmlListPopFront(writer->nodes);
2483 return sum;
2484}
2485
2486/**
2487 * xmlTextWriterWriteFormatPI:
2488 * @writer: the xmlTextWriterPtr
2489 * @target: PI target
2490 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002491 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002492 *
2493 * Write a formatted PI.
2494 *
2495 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2496 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002497int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002498xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2499 const char *format, ...)
2500{
2501 int rc;
2502 va_list ap;
2503
2504 va_start(ap, format);
2505
2506 rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2507
2508 va_end(ap);
2509 return rc;
2510}
2511
2512/**
2513 * xmlTextWriterWriteVFormatPI:
2514 * @writer: the xmlTextWriterPtr
2515 * @target: PI target
2516 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002517 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002518 *
2519 * Write a formatted xml PI.
2520 *
2521 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2522 */
2523int
2524xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2525 const xmlChar * target, const char *format,
2526 va_list argptr)
2527{
2528 int rc;
2529 xmlChar *buf;
2530
2531 if (writer == NULL)
2532 return -1;
2533
2534 buf = xmlTextWriterVSprintf(format, argptr);
2535 if (buf == 0)
2536 return 0;
2537
2538 rc = xmlTextWriterWritePI(writer, target, buf);
2539
2540 xmlFree(buf);
2541 return rc;
2542}
2543
2544/**
2545 * xmlTextWriterWritePI:
2546 * @writer: the xmlTextWriterPtr
2547 * @target: PI target
2548 * @content: PI content
2549 *
2550 * Write an xml PI.
2551 *
2552 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2553 */
2554int
2555xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2556 const xmlChar * content)
2557{
2558 int count;
2559 int sum;
2560
2561 sum = 0;
2562 count = xmlTextWriterStartPI(writer, target);
2563 if (count == -1)
2564 return -1;
2565 sum += count;
2566 if (content != 0) {
2567 count = xmlTextWriterWriteString(writer, content);
2568 if (count == -1)
2569 return -1;
2570 sum += count;
2571 }
2572 count = xmlTextWriterEndPI(writer);
2573 if (count == -1)
2574 return -1;
2575 sum += count;
2576
2577 return sum;
2578}
2579
2580/**
2581 * xmlTextWriterStartCDATA:
2582 * @writer: the xmlTextWriterPtr
2583 *
2584 * Start an xml CDATA section.
2585 *
2586 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2587 */
2588int
2589xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2590{
2591 int count;
2592 int sum;
2593 xmlLinkPtr lk;
2594 xmlTextWriterStackEntry *p;
2595
2596 if (writer == NULL)
2597 return -1;
2598
2599 sum = 0;
2600 lk = xmlListFront(writer->nodes);
2601 if (lk != 0) {
2602 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2603 if (p != 0) {
2604 switch (p->state) {
2605 case XML_TEXTWRITER_NONE:
2606 case XML_TEXTWRITER_PI:
2607 case XML_TEXTWRITER_PI_TEXT:
2608 break;
2609 case XML_TEXTWRITER_ATTRIBUTE:
2610 count = xmlTextWriterEndAttribute(writer);
2611 if (count < 0)
2612 return -1;
2613 sum += count;
2614 /* fallthrough */
2615 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002616 /* Output namespace declarations */
2617 count = xmlTextWriterOutputNSDecl(writer);
2618 if (count < 0)
2619 return -1;
2620 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002621 count = xmlOutputBufferWriteString(writer->out, ">");
2622 if (count < 0)
2623 return -1;
2624 sum += count;
2625 p->state = XML_TEXTWRITER_TEXT;
2626 break;
2627 case XML_TEXTWRITER_CDATA:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002628 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002629 "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2630 return -1;
2631 default:
2632 return -1;
2633 }
2634 }
2635 }
2636
2637 p = (xmlTextWriterStackEntry *)
2638 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2639 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002640 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002641 "xmlTextWriterStartCDATA : out of memory!\n");
2642 return -1;
2643 }
2644
Daniel Veillard75e389d2005-07-29 22:02:24 +00002645 p->name = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002646 p->state = XML_TEXTWRITER_CDATA;
2647
2648 xmlListPushFront(writer->nodes, p);
2649
2650 count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2651 if (count < 0)
2652 return -1;
2653 sum += count;
2654
2655 return sum;
2656}
2657
2658/**
2659 * xmlTextWriterEndCDATA:
2660 * @writer: the xmlTextWriterPtr
2661 *
2662 * End an xml CDATA section.
2663 *
2664 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2665 */
2666int
2667xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2668{
2669 int count;
2670 int sum;
2671 xmlLinkPtr lk;
2672 xmlTextWriterStackEntry *p;
2673
2674 if (writer == NULL)
2675 return -1;
2676
2677 lk = xmlListFront(writer->nodes);
2678 if (lk == 0)
2679 return -1;
2680
2681 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2682 if (p == 0)
2683 return -1;
2684
2685 sum = 0;
2686 switch (p->state) {
2687 case XML_TEXTWRITER_CDATA:
2688 count = xmlOutputBufferWriteString(writer->out, "]]>");
2689 if (count < 0)
2690 return -1;
2691 sum += count;
2692 break;
2693 default:
2694 return -1;
2695 }
2696
2697 xmlListPopFront(writer->nodes);
2698 return sum;
2699}
2700
2701/**
2702 * xmlTextWriterWriteFormatCDATA:
2703 * @writer: the xmlTextWriterPtr
2704 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002705 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002706 *
2707 * Write a formatted xml CDATA.
2708 *
2709 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2710 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002711int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002712xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2713 ...)
2714{
2715 int rc;
2716 va_list ap;
2717
2718 va_start(ap, format);
2719
2720 rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2721
2722 va_end(ap);
2723 return rc;
2724}
2725
2726/**
2727 * xmlTextWriterWriteVFormatCDATA:
2728 * @writer: the xmlTextWriterPtr
2729 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002730 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002731 *
2732 * Write a formatted xml CDATA.
2733 *
2734 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2735 */
2736int
2737xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2738 va_list argptr)
2739{
2740 int rc;
2741 xmlChar *buf;
2742
2743 if (writer == NULL)
2744 return -1;
2745
2746 buf = xmlTextWriterVSprintf(format, argptr);
2747 if (buf == 0)
2748 return 0;
2749
2750 rc = xmlTextWriterWriteCDATA(writer, buf);
2751
2752 xmlFree(buf);
2753 return rc;
2754}
2755
2756/**
2757 * xmlTextWriterWriteCDATA:
2758 * @writer: the xmlTextWriterPtr
2759 * @content: CDATA content
2760 *
2761 * Write an xml CDATA.
2762 *
2763 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2764 */
2765int
2766xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2767{
2768 int count;
2769 int sum;
2770
2771 sum = 0;
2772 count = xmlTextWriterStartCDATA(writer);
2773 if (count == -1)
2774 return -1;
2775 sum += count;
2776 if (content != 0) {
2777 count = xmlTextWriterWriteString(writer, content);
2778 if (count == -1)
2779 return -1;
2780 sum += count;
2781 }
2782 count = xmlTextWriterEndCDATA(writer);
2783 if (count == -1)
2784 return -1;
2785 sum += count;
2786
2787 return sum;
2788}
2789
2790/**
2791 * xmlTextWriterStartDTD:
2792 * @writer: the xmlTextWriterPtr
2793 * @name: the name of the DTD
2794 * @pubid: the public identifier, which is an alternative to the system identifier
2795 * @sysid: the system identifier, which is the URI of the DTD
2796 *
2797 * Start an xml DTD.
2798 *
2799 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2800 */
2801int
2802xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2803 const xmlChar * name,
2804 const xmlChar * pubid, const xmlChar * sysid)
2805{
2806 int count;
2807 int sum;
2808 xmlLinkPtr lk;
2809 xmlTextWriterStackEntry *p;
2810
2811 if (writer == NULL || name == NULL || *name == '\0')
2812 return -1;
2813
2814 sum = 0;
2815 lk = xmlListFront(writer->nodes);
Daniel Veillardab69f362004-02-17 11:40:32 +00002816 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002817 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002818 "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2819 return -1;
2820 }
2821
2822 p = (xmlTextWriterStackEntry *)
2823 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2824 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002825 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002826 "xmlTextWriterStartDTD : out of memory!\n");
2827 return -1;
2828 }
2829
2830 p->name = xmlStrdup(name);
2831 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002832 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002833 "xmlTextWriterStartDTD : out of memory!\n");
2834 xmlFree(p);
2835 return -1;
2836 }
2837 p->state = XML_TEXTWRITER_DTD;
2838
2839 xmlListPushFront(writer->nodes, p);
2840
2841 count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2842 if (count < 0)
2843 return -1;
2844 sum += count;
2845 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2846 if (count < 0)
2847 return -1;
2848 sum += count;
2849
2850 if (pubid != 0) {
2851 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002852 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002853 "xmlTextWriterStartDTD : system identifier needed!\n");
2854 return -1;
2855 }
2856
Daniel Veillard500a1de2004-03-22 15:22:58 +00002857 if (writer->indent)
2858 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2859 else
2860 count = xmlOutputBufferWrite(writer->out, 1, " ");
2861 if (count < 0)
2862 return -1;
2863 sum += count;
2864
2865 count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2866 if (count < 0)
2867 return -1;
2868 sum += count;
2869
2870 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002871 if (count < 0)
2872 return -1;
2873 sum += count;
2874
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002875 count =
2876 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002877 if (count < 0)
2878 return -1;
2879 sum += count;
2880
Daniel Veillard500a1de2004-03-22 15:22:58 +00002881 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002882 if (count < 0)
2883 return -1;
2884 sum += count;
2885 }
2886
2887 if (sysid != 0) {
2888 if (pubid == 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00002889 if (writer->indent)
2890 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2891 else
2892 count = xmlOutputBufferWrite(writer->out, 1, " ");
2893 if (count < 0)
2894 return -1;
2895 sum += count;
2896 count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2897 if (count < 0)
2898 return -1;
2899 sum += count;
Rob Richardsffe47fe2005-12-09 17:52:21 +00002900 } else {
2901 if (writer->indent)
Daniel Veillard500a1de2004-03-22 15:22:58 +00002902 count = xmlOutputBufferWriteString(writer->out, "\n ");
Rob Richardsffe47fe2005-12-09 17:52:21 +00002903 else
2904 count = xmlOutputBufferWrite(writer->out, 1, " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00002905 if (count < 0)
2906 return -1;
2907 sum += count;
2908 }
2909
Daniel Veillard500a1de2004-03-22 15:22:58 +00002910 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002911 if (count < 0)
2912 return -1;
2913 sum += count;
2914
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002915 count =
2916 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002917 if (count < 0)
2918 return -1;
2919 sum += count;
2920
Daniel Veillard500a1de2004-03-22 15:22:58 +00002921 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002922 if (count < 0)
2923 return -1;
2924 sum += count;
2925 }
2926
2927 return sum;
2928}
2929
2930/**
2931 * xmlTextWriterEndDTD:
2932 * @writer: the xmlTextWriterPtr
2933 *
2934 * End an xml DTD.
2935 *
2936 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2937 */
2938int
2939xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2940{
Daniel Veillard500a1de2004-03-22 15:22:58 +00002941 int loop;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002942 int count;
2943 int sum;
2944 xmlLinkPtr lk;
2945 xmlTextWriterStackEntry *p;
2946
2947 if (writer == NULL)
2948 return -1;
2949
2950 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002951 loop = 1;
2952 while (loop) {
2953 lk = xmlListFront(writer->nodes);
2954 if (lk == NULL)
Daniel Veillard1d211e22003-10-20 22:32:39 +00002955 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002956 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2957 if (p == 0)
2958 break;
2959 switch (p->state) {
2960 case XML_TEXTWRITER_DTD_TEXT:
2961 count = xmlOutputBufferWriteString(writer->out, "]");
2962 if (count < 0)
2963 return -1;
2964 sum += count;
2965 /* fallthrough */
2966 case XML_TEXTWRITER_DTD:
2967 count = xmlOutputBufferWriteString(writer->out, ">");
2968
2969 if (writer->indent) {
2970 if (count < 0)
2971 return -1;
2972 sum += count;
2973 count = xmlOutputBufferWriteString(writer->out, "\n");
2974 }
2975
2976 xmlListPopFront(writer->nodes);
2977 break;
2978 case XML_TEXTWRITER_DTD_ELEM:
2979 case XML_TEXTWRITER_DTD_ELEM_TEXT:
2980 count = xmlTextWriterEndDTDElement(writer);
2981 break;
2982 case XML_TEXTWRITER_DTD_ATTL:
2983 case XML_TEXTWRITER_DTD_ATTL_TEXT:
2984 count = xmlTextWriterEndDTDAttlist(writer);
2985 break;
2986 case XML_TEXTWRITER_DTD_ENTY:
2987 case XML_TEXTWRITER_DTD_PENT:
2988 case XML_TEXTWRITER_DTD_ENTY_TEXT:
2989 count = xmlTextWriterEndDTDEntity(writer);
2990 break;
2991 case XML_TEXTWRITER_COMMENT:
2992 count = xmlTextWriterEndComment(writer);
2993 break;
2994 default:
2995 loop = 0;
2996 continue;
2997 }
2998
2999 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00003000 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003001 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003002 }
3003
Daniel Veillard1d211e22003-10-20 22:32:39 +00003004 return sum;
3005}
3006
3007/**
3008 * xmlTextWriterWriteFormatDTD:
3009 * @writer: the xmlTextWriterPtr
3010 * @name: the name of the DTD
3011 * @pubid: the public identifier, which is an alternative to the system identifier
3012 * @sysid: the system identifier, which is the URI of the DTD
3013 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003014 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00003015 *
3016 * Write a DTD with a formatted markup declarations part.
3017 *
3018 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3019 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003020int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003021xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3022 const xmlChar * name,
3023 const xmlChar * pubid,
3024 const xmlChar * sysid, const char *format, ...)
3025{
3026 int rc;
3027 va_list ap;
3028
3029 va_start(ap, format);
3030
3031 rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3032 ap);
3033
3034 va_end(ap);
3035 return rc;
3036}
3037
3038/**
3039 * xmlTextWriterWriteVFormatDTD:
3040 * @writer: the xmlTextWriterPtr
3041 * @name: the name of the DTD
3042 * @pubid: the public identifier, which is an alternative to the system identifier
3043 * @sysid: the system identifier, which is the URI of the DTD
3044 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003045 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00003046 *
3047 * Write a DTD with a formatted markup declarations part.
3048 *
3049 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3050 */
3051int
3052xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3053 const xmlChar * name,
3054 const xmlChar * pubid,
3055 const xmlChar * sysid,
3056 const char *format, va_list argptr)
3057{
3058 int rc;
3059 xmlChar *buf;
3060
3061 if (writer == NULL)
3062 return -1;
3063
3064 buf = xmlTextWriterVSprintf(format, argptr);
3065 if (buf == 0)
3066 return 0;
3067
3068 rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3069
3070 xmlFree(buf);
3071 return rc;
3072}
3073
3074/**
3075 * xmlTextWriterWriteDTD:
3076 * @writer: the xmlTextWriterPtr
3077 * @name: the name of the DTD
3078 * @pubid: the public identifier, which is an alternative to the system identifier
3079 * @sysid: the system identifier, which is the URI of the DTD
William M. Brackb1d53162003-11-18 06:54:40 +00003080 * @subset: string content of the DTD
Daniel Veillard1d211e22003-10-20 22:32:39 +00003081 *
3082 * Write a DTD.
3083 *
3084 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3085 */
3086int
3087xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3088 const xmlChar * name,
3089 const xmlChar * pubid,
3090 const xmlChar * sysid, const xmlChar * subset)
3091{
3092 int count;
3093 int sum;
3094
3095 sum = 0;
3096 count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3097 if (count == -1)
3098 return -1;
3099 sum += count;
3100 if (subset != 0) {
3101 count = xmlTextWriterWriteString(writer, subset);
3102 if (count == -1)
3103 return -1;
3104 sum += count;
3105 }
3106 count = xmlTextWriterEndDTD(writer);
3107 if (count == -1)
3108 return -1;
3109 sum += count;
3110
3111 return sum;
3112}
3113
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003114/**
3115 * xmlTextWriterStartDTDElement:
3116 * @writer: the xmlTextWriterPtr
3117 * @name: the name of the DTD element
3118 *
3119 * Start an xml DTD element.
3120 *
3121 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3122 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003123int
3124xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3125{
3126 int count;
3127 int sum;
3128 xmlLinkPtr lk;
3129 xmlTextWriterStackEntry *p;
3130
3131 if (writer == NULL || name == NULL || *name == '\0')
3132 return -1;
3133
3134 sum = 0;
3135 lk = xmlListFront(writer->nodes);
3136 if (lk == 0) {
3137 return -1;
3138 }
3139
3140 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003141 if (p != 0) {
3142 switch (p->state) {
3143 case XML_TEXTWRITER_DTD:
3144 count = xmlOutputBufferWriteString(writer->out, " [");
3145 if (count < 0)
3146 return -1;
3147 sum += count;
3148 if (writer->indent) {
3149 count = xmlOutputBufferWriteString(writer->out, "\n");
3150 if (count < 0)
3151 return -1;
3152 sum += count;
3153 }
3154 p->state = XML_TEXTWRITER_DTD_TEXT;
3155 /* fallthrough */
3156 case XML_TEXTWRITER_DTD_TEXT:
3157 case XML_TEXTWRITER_NONE:
3158 break;
3159 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003160 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003161 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003162 }
3163
3164 p = (xmlTextWriterStackEntry *)
3165 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3166 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003167 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003168 "xmlTextWriterStartDTDElement : out of memory!\n");
3169 return -1;
3170 }
3171
3172 p->name = xmlStrdup(name);
3173 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003174 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003175 "xmlTextWriterStartDTDElement : out of memory!\n");
3176 xmlFree(p);
3177 return -1;
3178 }
3179 p->state = XML_TEXTWRITER_DTD_ELEM;
3180
3181 xmlListPushFront(writer->nodes, p);
3182
Daniel Veillard500a1de2004-03-22 15:22:58 +00003183 if (writer->indent) {
3184 count = xmlTextWriterWriteIndent(writer);
3185 if (count < 0)
3186 return -1;
3187 sum += count;
3188 }
3189
Daniel Veillard1d211e22003-10-20 22:32:39 +00003190 count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3191 if (count < 0)
3192 return -1;
3193 sum += count;
3194 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3195 if (count < 0)
3196 return -1;
3197 sum += count;
3198
3199 return sum;
3200}
3201
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003202/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003203 * xmlTextWriterEndDTDElement:
3204 * @writer: the xmlTextWriterPtr
3205 *
3206 * End an xml DTD element.
3207 *
3208 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3209 */
3210int
3211xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3212{
3213 int count;
3214 int sum;
3215 xmlLinkPtr lk;
3216 xmlTextWriterStackEntry *p;
3217
3218 if (writer == NULL)
3219 return -1;
3220
3221 sum = 0;
3222 lk = xmlListFront(writer->nodes);
3223 if (lk == 0)
3224 return -1;
3225
3226 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3227 if (p == 0)
3228 return -1;
3229
3230 switch (p->state) {
3231 case XML_TEXTWRITER_DTD_ELEM:
3232 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3233 count = xmlOutputBufferWriteString(writer->out, ">");
3234 if (count < 0)
3235 return -1;
3236 sum += count;
3237 break;
3238 default:
3239 return -1;
3240 }
3241
3242 if (writer->indent) {
3243 count = xmlOutputBufferWriteString(writer->out, "\n");
3244 if (count < 0)
3245 return -1;
3246 sum += count;
3247 }
3248
3249 xmlListPopFront(writer->nodes);
3250 return sum;
3251}
3252
3253/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003254 * xmlTextWriterWriteFormatDTDElement:
3255 * @writer: the xmlTextWriterPtr
3256 * @name: the name of the DTD element
3257 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003258 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003259 *
3260 * Write a formatted DTD element.
3261 *
3262 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3263 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003264int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003265xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3266 const xmlChar * name,
3267 const char *format, ...)
3268{
3269 int rc;
3270 va_list ap;
3271
3272 va_start(ap, format);
3273
3274 rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3275
3276 va_end(ap);
3277 return rc;
3278}
3279
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003280/**
3281 * xmlTextWriterWriteVFormatDTDElement:
3282 * @writer: the xmlTextWriterPtr
3283 * @name: the name of the DTD element
3284 * @format: format string (see printf)
3285 * @argptr: pointer to the first member of the variable argument list.
3286 *
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 Veillard1d211e22003-10-20 22:32:39 +00003291int
3292xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3293 const xmlChar * name,
3294 const char *format, va_list argptr)
3295{
3296 int rc;
3297 xmlChar *buf;
3298
3299 if (writer == NULL)
3300 return -1;
3301
3302 buf = xmlTextWriterVSprintf(format, argptr);
3303 if (buf == 0)
3304 return 0;
3305
3306 rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3307
3308 xmlFree(buf);
3309 return rc;
3310}
3311
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003312/**
3313 * xmlTextWriterWriteDTDElement:
3314 * @writer: the xmlTextWriterPtr
3315 * @name: the name of the DTD element
3316 * @content: content of the element
3317 *
3318 * Write a DTD element.
3319 *
3320 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3321 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003322int
3323xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3324 const xmlChar * name, const xmlChar * content)
3325{
3326 int count;
3327 int sum;
3328
3329 if (content == NULL)
3330 return -1;
3331
3332 sum = 0;
3333 count = xmlTextWriterStartDTDElement(writer, name);
3334 if (count == -1)
3335 return -1;
3336 sum += count;
3337
Daniel Veillard1d211e22003-10-20 22:32:39 +00003338 count = xmlTextWriterWriteString(writer, content);
3339 if (count == -1)
3340 return -1;
3341 sum += count;
3342
3343 count = xmlTextWriterEndDTDElement(writer);
3344 if (count == -1)
3345 return -1;
3346 sum += count;
3347
3348 return sum;
3349}
3350
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003351/**
3352 * xmlTextWriterStartDTDAttlist:
3353 * @writer: the xmlTextWriterPtr
3354 * @name: the name of the DTD ATTLIST
3355 *
3356 * Start an xml DTD ATTLIST.
3357 *
3358 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3359 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003360int
3361xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3362{
3363 int count;
3364 int sum;
3365 xmlLinkPtr lk;
3366 xmlTextWriterStackEntry *p;
3367
3368 if (writer == NULL || name == NULL || *name == '\0')
3369 return -1;
3370
3371 sum = 0;
3372 lk = xmlListFront(writer->nodes);
3373 if (lk == 0) {
3374 return -1;
3375 }
3376
3377 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003378 if (p != 0) {
3379 switch (p->state) {
3380 case XML_TEXTWRITER_DTD:
3381 count = xmlOutputBufferWriteString(writer->out, " [");
3382 if (count < 0)
3383 return -1;
3384 sum += count;
3385 if (writer->indent) {
3386 count = xmlOutputBufferWriteString(writer->out, "\n");
3387 if (count < 0)
3388 return -1;
3389 sum += count;
3390 }
3391 p->state = XML_TEXTWRITER_DTD_TEXT;
3392 /* fallthrough */
3393 case XML_TEXTWRITER_DTD_TEXT:
3394 case XML_TEXTWRITER_NONE:
3395 break;
3396 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003397 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003398 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003399 }
3400
3401 p = (xmlTextWriterStackEntry *)
3402 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3403 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003404 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003405 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3406 return -1;
3407 }
3408
3409 p->name = xmlStrdup(name);
3410 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003411 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003412 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3413 xmlFree(p);
3414 return -1;
3415 }
3416 p->state = XML_TEXTWRITER_DTD_ATTL;
3417
3418 xmlListPushFront(writer->nodes, p);
3419
Daniel Veillard500a1de2004-03-22 15:22:58 +00003420 if (writer->indent) {
3421 count = xmlTextWriterWriteIndent(writer);
3422 if (count < 0)
3423 return -1;
3424 sum += count;
3425 }
3426
Daniel Veillard1d211e22003-10-20 22:32:39 +00003427 count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3428 if (count < 0)
3429 return -1;
3430 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +00003431 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003432 if (count < 0)
3433 return -1;
3434 sum += count;
3435
3436 return sum;
3437}
3438
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003439/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003440 * xmlTextWriterEndDTDAttlist:
3441 * @writer: the xmlTextWriterPtr
3442 *
3443 * End an xml DTD attribute list.
3444 *
3445 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3446 */
3447int
3448xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3449{
3450 int count;
3451 int sum;
3452 xmlLinkPtr lk;
3453 xmlTextWriterStackEntry *p;
3454
3455 if (writer == NULL)
3456 return -1;
3457
3458 sum = 0;
3459 lk = xmlListFront(writer->nodes);
3460 if (lk == 0)
3461 return -1;
3462
3463 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3464 if (p == 0)
3465 return -1;
3466
3467 switch (p->state) {
3468 case XML_TEXTWRITER_DTD_ATTL:
3469 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3470 count = xmlOutputBufferWriteString(writer->out, ">");
3471 if (count < 0)
3472 return -1;
3473 sum += count;
3474 break;
3475 default:
3476 return -1;
3477 }
3478
3479 if (writer->indent) {
3480 count = xmlOutputBufferWriteString(writer->out, "\n");
3481 if (count < 0)
3482 return -1;
3483 sum += count;
3484 }
3485
3486 xmlListPopFront(writer->nodes);
3487 return sum;
3488}
3489
3490/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003491 * xmlTextWriterWriteFormatDTDAttlist:
3492 * @writer: the xmlTextWriterPtr
3493 * @name: the name of the DTD ATTLIST
3494 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003495 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003496 *
3497 * Write a formatted DTD ATTLIST.
3498 *
3499 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3500 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003501int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003502xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3503 const xmlChar * name,
3504 const char *format, ...)
3505{
3506 int rc;
3507 va_list ap;
3508
3509 va_start(ap, format);
3510
3511 rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3512
3513 va_end(ap);
3514 return rc;
3515}
3516
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003517/**
3518 * xmlTextWriterWriteVFormatDTDAttlist:
3519 * @writer: the xmlTextWriterPtr
3520 * @name: the name of the DTD ATTLIST
3521 * @format: format string (see printf)
3522 * @argptr: pointer to the first member of the variable argument list.
3523 *
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 Veillard1d211e22003-10-20 22:32:39 +00003528int
3529xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3530 const xmlChar * name,
3531 const char *format, va_list argptr)
3532{
3533 int rc;
3534 xmlChar *buf;
3535
3536 if (writer == NULL)
3537 return -1;
3538
3539 buf = xmlTextWriterVSprintf(format, argptr);
3540 if (buf == 0)
3541 return 0;
3542
3543 rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3544
3545 xmlFree(buf);
3546 return rc;
3547}
3548
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003549/**
3550 * xmlTextWriterWriteDTDAttlist:
3551 * @writer: the xmlTextWriterPtr
3552 * @name: the name of the DTD ATTLIST
3553 * @content: content of the ATTLIST
3554 *
3555 * Write a DTD ATTLIST.
3556 *
3557 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3558 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003559int
3560xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3561 const xmlChar * name, const xmlChar * content)
3562{
3563 int count;
3564 int sum;
3565
3566 if (content == NULL)
3567 return -1;
3568
3569 sum = 0;
3570 count = xmlTextWriterStartDTDAttlist(writer, name);
3571 if (count == -1)
3572 return -1;
3573 sum += count;
3574
Daniel Veillard1d211e22003-10-20 22:32:39 +00003575 count = xmlTextWriterWriteString(writer, content);
3576 if (count == -1)
3577 return -1;
3578 sum += count;
3579
3580 count = xmlTextWriterEndDTDAttlist(writer);
3581 if (count == -1)
3582 return -1;
3583 sum += count;
3584
3585 return sum;
3586}
3587
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003588/**
3589 * xmlTextWriterStartDTDEntity:
3590 * @writer: the xmlTextWriterPtr
3591 * @pe: TRUE if this is a parameter entity, FALSE if not
3592 * @name: the name of the DTD ATTLIST
3593 *
3594 * Start an xml DTD ATTLIST.
3595 *
3596 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3597 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003598int
3599xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3600 int pe, const xmlChar * name)
3601{
3602 int count;
3603 int sum;
3604 xmlLinkPtr lk;
3605 xmlTextWriterStackEntry *p;
3606
3607 if (writer == NULL || name == NULL || *name == '\0')
3608 return -1;
3609
3610 sum = 0;
3611 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003612 if (lk != 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00003613
Daniel Veillard500a1de2004-03-22 15:22:58 +00003614 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3615 if (p != 0) {
3616 switch (p->state) {
3617 case XML_TEXTWRITER_DTD:
3618 count = xmlOutputBufferWriteString(writer->out, " [");
3619 if (count < 0)
3620 return -1;
3621 sum += count;
3622 if (writer->indent) {
3623 count =
3624 xmlOutputBufferWriteString(writer->out, "\n");
3625 if (count < 0)
3626 return -1;
3627 sum += count;
3628 }
3629 p->state = XML_TEXTWRITER_DTD_TEXT;
3630 /* fallthrough */
3631 case XML_TEXTWRITER_DTD_TEXT:
3632 case XML_TEXTWRITER_NONE:
3633 break;
3634 default:
3635 return -1;
3636 }
3637 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003638 }
3639
3640 p = (xmlTextWriterStackEntry *)
3641 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3642 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003643 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003644 "xmlTextWriterStartDTDElement : out of memory!\n");
3645 return -1;
3646 }
3647
3648 p->name = xmlStrdup(name);
3649 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003650 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003651 "xmlTextWriterStartDTDElement : out of memory!\n");
3652 xmlFree(p);
3653 return -1;
3654 }
Daniel Veillard500a1de2004-03-22 15:22:58 +00003655
3656 if (pe != 0)
3657 p->state = XML_TEXTWRITER_DTD_PENT;
3658 else
3659 p->state = XML_TEXTWRITER_DTD_ENTY;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003660
3661 xmlListPushFront(writer->nodes, p);
3662
Daniel Veillard500a1de2004-03-22 15:22:58 +00003663 if (writer->indent) {
3664 count = xmlTextWriterWriteIndent(writer);
3665 if (count < 0)
3666 return -1;
3667 sum += count;
3668 }
3669
Daniel Veillard1d211e22003-10-20 22:32:39 +00003670 count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3671 if (count < 0)
3672 return -1;
3673 sum += count;
3674
3675 if (pe != 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00003676 count = xmlOutputBufferWriteString(writer->out, "% ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003677 if (count < 0)
3678 return -1;
3679 sum += count;
3680 }
3681
Daniel Veillardab69f362004-02-17 11:40:32 +00003682 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003683 if (count < 0)
3684 return -1;
3685 sum += count;
3686
3687 return sum;
3688}
3689
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003690/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003691 * xmlTextWriterEndDTDEntity:
3692 * @writer: the xmlTextWriterPtr
3693 *
3694 * End an xml DTD entity.
3695 *
3696 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3697 */
3698int
3699xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3700{
3701 int count;
3702 int sum;
3703 xmlLinkPtr lk;
3704 xmlTextWriterStackEntry *p;
3705
3706 if (writer == NULL)
3707 return -1;
3708
3709 sum = 0;
3710 lk = xmlListFront(writer->nodes);
3711 if (lk == 0)
3712 return -1;
3713
3714 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3715 if (p == 0)
3716 return -1;
3717
3718 switch (p->state) {
3719 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3720 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3721 if (count < 0)
3722 return -1;
3723 sum += count;
3724 case XML_TEXTWRITER_DTD_ENTY:
3725 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard500a1de2004-03-22 15:22:58 +00003726 count = xmlOutputBufferWriteString(writer->out, ">");
3727 if (count < 0)
3728 return -1;
3729 sum += count;
3730 break;
3731 default:
3732 return -1;
3733 }
3734
3735 if (writer->indent) {
3736 count = xmlOutputBufferWriteString(writer->out, "\n");
3737 if (count < 0)
3738 return -1;
3739 sum += count;
3740 }
3741
3742 xmlListPopFront(writer->nodes);
3743 return sum;
3744}
3745
3746/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003747 * xmlTextWriterWriteFormatDTDInternalEntity:
3748 * @writer: the xmlTextWriterPtr
3749 * @pe: TRUE if this is a parameter entity, FALSE if not
3750 * @name: the name of the DTD entity
3751 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003752 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003753 *
3754 * Write a formatted DTD internal entity.
3755 *
3756 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3757 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003758int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003759xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3760 int pe,
3761 const xmlChar * name,
3762 const char *format, ...)
3763{
3764 int rc;
3765 va_list ap;
3766
3767 va_start(ap, format);
3768
3769 rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3770 format, ap);
3771
3772 va_end(ap);
3773 return rc;
3774}
3775
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003776/**
3777 * xmlTextWriterWriteVFormatDTDInternalEntity:
3778 * @writer: the xmlTextWriterPtr
3779 * @pe: TRUE if this is a parameter entity, FALSE if not
3780 * @name: the name of the DTD entity
3781 * @format: format string (see printf)
3782 * @argptr: pointer to the first member of the variable argument list.
3783 *
3784 * Write a formatted DTD internal entity.
3785 *
3786 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3787 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003788int
3789xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3790 int pe,
3791 const xmlChar * name,
3792 const char *format,
3793 va_list argptr)
3794{
3795 int rc;
3796 xmlChar *buf;
3797
3798 if (writer == NULL)
3799 return -1;
3800
3801 buf = xmlTextWriterVSprintf(format, argptr);
3802 if (buf == 0)
3803 return 0;
3804
3805 rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3806
3807 xmlFree(buf);
3808 return rc;
3809}
3810
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003811/**
3812 * xmlTextWriterWriteDTDEntity:
3813 * @writer: the xmlTextWriterPtr
3814 * @pe: TRUE if this is a parameter entity, FALSE if not
3815 * @name: the name of the DTD entity
3816 * @pubid: the public identifier, which is an alternative to the system identifier
3817 * @sysid: the system identifier, which is the URI of the DTD
3818 * @ndataid: the xml notation name.
3819 * @content: content of the entity
3820 *
3821 * Write a DTD entity.
3822 *
3823 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3824 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003825int
3826xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3827 int pe,
3828 const xmlChar * name,
3829 const xmlChar * pubid,
3830 const xmlChar * sysid,
3831 const xmlChar * ndataid,
3832 const xmlChar * content)
3833{
Daniel Veillard500a1de2004-03-22 15:22:58 +00003834 if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003835 return -1;
3836 if ((pe != 0) && (ndataid != NULL))
3837 return -1;
3838
Daniel Veillard500a1de2004-03-22 15:22:58 +00003839 if ((pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003840 return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3841 content);
3842
3843 return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3844 sysid, ndataid);
3845}
3846
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003847/**
3848 * xmlTextWriterWriteDTDInternalEntity:
3849 * @writer: the xmlTextWriterPtr
3850 * @pe: TRUE if this is a parameter entity, FALSE if not
3851 * @name: the name of the DTD entity
3852 * @content: content of the entity
3853 *
3854 * Write a DTD internal entity.
3855 *
3856 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3857 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003858int
3859xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3860 int pe,
3861 const xmlChar * name,
3862 const xmlChar * content)
3863{
3864 int count;
3865 int sum;
3866
3867 if ((name == NULL) || (*name == '\0') || (content == NULL))
3868 return -1;
3869
3870 sum = 0;
3871 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3872 if (count == -1)
3873 return -1;
3874 sum += count;
3875
Daniel Veillard1d211e22003-10-20 22:32:39 +00003876 count = xmlTextWriterWriteString(writer, content);
3877 if (count == -1)
3878 return -1;
3879 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003880
3881 count = xmlTextWriterEndDTDEntity(writer);
3882 if (count == -1)
3883 return -1;
3884 sum += count;
3885
3886 return sum;
3887}
3888
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003889/**
3890 * xmlTextWriterWriteDTDExternalEntity:
3891 * @writer: the xmlTextWriterPtr
3892 * @pe: TRUE if this is a parameter entity, FALSE if not
3893 * @name: the name of the DTD entity
3894 * @pubid: the public identifier, which is an alternative to the system identifier
3895 * @sysid: the system identifier, which is the URI of the DTD
3896 * @ndataid: the xml notation name.
3897 *
Daniel Veillard500a1de2004-03-22 15:22:58 +00003898 * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003899 *
3900 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3901 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003902int
3903xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3904 int pe,
3905 const xmlChar * name,
3906 const xmlChar * pubid,
3907 const xmlChar * sysid,
3908 const xmlChar * ndataid)
3909{
3910 int count;
3911 int sum;
3912
Daniel Veillard500a1de2004-03-22 15:22:58 +00003913 if (((pubid == NULL) && (sysid == NULL)))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003914 return -1;
3915 if ((pe != 0) && (ndataid != NULL))
3916 return -1;
3917
3918 sum = 0;
3919 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3920 if (count == -1)
3921 return -1;
3922 sum += count;
3923
Daniel Veillard500a1de2004-03-22 15:22:58 +00003924 count =
3925 xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3926 ndataid);
3927 if (count < 0)
3928 return -1;
3929 sum += count;
3930
3931 count = xmlTextWriterEndDTDEntity(writer);
3932 if (count == -1)
3933 return -1;
3934 sum += count;
3935
3936 return sum;
3937}
3938
3939/**
3940 * xmlTextWriterWriteDTDExternalEntityContents:
3941 * @writer: the xmlTextWriterPtr
3942 * @pubid: the public identifier, which is an alternative to the system identifier
3943 * @sysid: the system identifier, which is the URI of the DTD
3944 * @ndataid: the xml notation name.
3945 *
3946 * Write the contents of a DTD external entity.
3947 *
3948 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3949 */
3950int
3951xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3952 const xmlChar * pubid,
3953 const xmlChar * sysid,
3954 const xmlChar * ndataid)
3955{
3956 int count;
3957 int sum;
3958 xmlLinkPtr lk;
3959 xmlTextWriterStackEntry *p;
3960
3961 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003962 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003963 "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3964 return -1;
3965 }
3966
3967 sum = 0;
3968 lk = xmlListFront(writer->nodes);
3969 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003970 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003971 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
3972 return -1;
3973 }
3974
3975 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3976 if (p == 0)
3977 return -1;
3978
3979 switch (p->state) {
3980 case XML_TEXTWRITER_DTD_ENTY:
3981 break;
3982 case XML_TEXTWRITER_DTD_PENT:
3983 if (ndataid != NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003984 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003985 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
3986 return -1;
3987 }
3988 break;
3989 default:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003990 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003991 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
3992 return -1;
3993 }
3994
Daniel Veillard1d211e22003-10-20 22:32:39 +00003995 if (pubid != 0) {
3996 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003997 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003998 "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003999 return -1;
4000 }
4001
4002 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4003 if (count < 0)
4004 return -1;
4005 sum += count;
4006
4007 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4008 if (count < 0)
4009 return -1;
4010 sum += count;
4011
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004012 count =
4013 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004014 if (count < 0)
4015 return -1;
4016 sum += count;
4017
4018 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4019 if (count < 0)
4020 return -1;
4021 sum += count;
4022 }
4023
4024 if (sysid != 0) {
4025 if (pubid == 0) {
4026 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4027 if (count < 0)
4028 return -1;
4029 sum += count;
4030 }
4031
4032 count = xmlOutputBufferWriteString(writer->out, " ");
4033 if (count < 0)
4034 return -1;
4035 sum += count;
4036
4037 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4038 if (count < 0)
4039 return -1;
4040 sum += count;
4041
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004042 count =
4043 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004044 if (count < 0)
4045 return -1;
4046 sum += count;
4047
4048 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4049 if (count < 0)
4050 return -1;
4051 sum += count;
4052 }
4053
4054 if (ndataid != NULL) {
4055 count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4056 if (count < 0)
4057 return -1;
4058 sum += count;
4059
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004060 count =
4061 xmlOutputBufferWriteString(writer->out,
4062 (const char *) ndataid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004063 if (count < 0)
4064 return -1;
4065 sum += count;
4066 }
4067
Daniel Veillard1d211e22003-10-20 22:32:39 +00004068 return sum;
4069}
4070
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004071/**
4072 * xmlTextWriterWriteDTDNotation:
4073 * @writer: the xmlTextWriterPtr
4074 * @name: the name of the xml notation
4075 * @pubid: the public identifier, which is an alternative to the system identifier
4076 * @sysid: the system identifier, which is the URI of the DTD
4077 *
4078 * Write a DTD entity.
4079 *
4080 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4081 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00004082int
4083xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4084 const xmlChar * name,
4085 const xmlChar * pubid, const xmlChar * sysid)
4086{
4087 int count;
4088 int sum;
4089 xmlLinkPtr lk;
4090 xmlTextWriterStackEntry *p;
4091
4092 if (writer == NULL || name == NULL || *name == '\0')
4093 return -1;
4094
4095 sum = 0;
4096 lk = xmlListFront(writer->nodes);
4097 if (lk == 0) {
4098 return -1;
4099 }
4100
4101 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00004102 if (p != 0) {
4103 switch (p->state) {
4104 case XML_TEXTWRITER_DTD:
4105 count = xmlOutputBufferWriteString(writer->out, " [");
4106 if (count < 0)
4107 return -1;
4108 sum += count;
4109 if (writer->indent) {
4110 count = xmlOutputBufferWriteString(writer->out, "\n");
4111 if (count < 0)
4112 return -1;
4113 sum += count;
4114 }
4115 p->state = XML_TEXTWRITER_DTD_TEXT;
4116 /* fallthrough */
4117 case XML_TEXTWRITER_DTD_TEXT:
4118 break;
4119 default:
4120 return -1;
4121 }
4122 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00004123
Daniel Veillard500a1de2004-03-22 15:22:58 +00004124 if (writer->indent) {
4125 count = xmlTextWriterWriteIndent(writer);
4126 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004127 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004128 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004129 }
4130
4131 count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4132 if (count < 0)
4133 return -1;
4134 sum += count;
4135 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4136 if (count < 0)
4137 return -1;
4138 sum += count;
4139
4140 if (pubid != 0) {
4141 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4142 if (count < 0)
4143 return -1;
4144 sum += count;
4145 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4146 if (count < 0)
4147 return -1;
4148 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004149 count =
4150 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004151 if (count < 0)
4152 return -1;
4153 sum += count;
4154 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4155 if (count < 0)
4156 return -1;
4157 sum += count;
4158 }
4159
4160 if (sysid != 0) {
4161 if (pubid == 0) {
4162 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4163 if (count < 0)
4164 return -1;
4165 sum += count;
4166 }
4167 count = xmlOutputBufferWriteString(writer->out, " ");
4168 if (count < 0)
4169 return -1;
4170 sum += count;
4171 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4172 if (count < 0)
4173 return -1;
4174 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004175 count =
4176 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004177 if (count < 0)
4178 return -1;
4179 sum += count;
4180 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4181 if (count < 0)
4182 return -1;
4183 sum += count;
4184 }
4185
4186 count = xmlOutputBufferWriteString(writer->out, ">");
4187 if (count < 0)
4188 return -1;
4189 sum += count;
4190
4191 return sum;
4192}
4193
4194/**
4195 * xmlTextWriterFlush:
4196 * @writer: the xmlTextWriterPtr
4197 *
4198 * Flush the output buffer.
4199 *
4200 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4201 */
4202int
4203xmlTextWriterFlush(xmlTextWriterPtr writer)
4204{
4205 int count;
4206
4207 if (writer == NULL)
4208 return -1;
4209
4210 if (writer->out == NULL)
4211 count = 0;
4212 else
4213 count = xmlOutputBufferFlush(writer->out);
4214
4215 return count;
4216}
4217
4218/**
4219 * misc
4220 */
4221
4222/**
4223 * xmlFreeTextWriterStackEntry:
4224 * @lk: the xmlLinkPtr
4225 *
4226 * Free callback for the xmlList.
4227 */
4228static void
4229xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4230{
4231 xmlTextWriterStackEntry *p;
4232
4233 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4234 if (p == 0)
4235 return;
4236
4237 if (p->name != 0)
4238 xmlFree(p->name);
4239 xmlFree(p);
4240}
4241
4242/**
4243 * xmlCmpTextWriterStackEntry:
4244 * @data0: the first data
4245 * @data1: the second data
4246 *
4247 * Compare callback for the xmlList.
4248 *
4249 * Returns -1, 0, 1
4250 */
4251static int
4252xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4253{
4254 xmlTextWriterStackEntry *p0;
4255 xmlTextWriterStackEntry *p1;
4256
4257 if (data0 == data1)
4258 return 0;
4259
4260 if (data0 == 0)
4261 return -1;
4262
4263 if (data1 == 0)
4264 return 1;
4265
4266 p0 = (xmlTextWriterStackEntry *) data0;
4267 p1 = (xmlTextWriterStackEntry *) data1;
4268
4269 return xmlStrcmp(p0->name, p1->name);
4270}
4271
4272/**
4273 * misc
4274 */
4275
4276/**
Rob Richardsb8769d62007-06-08 08:50:47 +00004277 * xmlTextWriterOutputNSDecl:
4278 * @writer: the xmlTextWriterPtr
4279 *
4280 * Output the current namespace declarations.
4281 */
4282static int
4283xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4284{
4285 xmlLinkPtr lk;
4286 xmlTextWriterNsStackEntry *np;
4287 int count;
4288 int sum;
4289
4290 sum = 0;
4291 while (!xmlListEmpty(writer->nsstack)) {
4292 xmlChar *namespaceURI = NULL;
4293 xmlChar *prefix = NULL;
4294
4295 lk = xmlListFront(writer->nsstack);
4296 np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4297
4298 if (np != 0) {
4299 namespaceURI = xmlStrdup(np->uri);
4300 prefix = xmlStrdup(np->prefix);
4301 }
4302
4303 xmlListPopFront(writer->nsstack);
4304
4305 if (np != 0) {
4306 count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4307 xmlFree(namespaceURI);
4308 xmlFree(prefix);
4309
4310 if (count < 0) {
4311 xmlListDelete(writer->nsstack);
4312 writer->nsstack = NULL;
4313 return -1;
4314 }
4315 sum += count;
4316 }
4317 }
4318 return sum;
4319}
4320
4321/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004322 * xmlFreeTextWriterNsStackEntry:
4323 * @lk: the xmlLinkPtr
4324 *
4325 * Free callback for the xmlList.
4326 */
4327static void
4328xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4329{
4330 xmlTextWriterNsStackEntry *p;
4331
4332 p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4333 if (p == 0)
4334 return;
4335
4336 if (p->prefix != 0)
4337 xmlFree(p->prefix);
4338 if (p->uri != 0)
4339 xmlFree(p->uri);
4340
4341 xmlFree(p);
4342}
4343
4344/**
4345 * xmlCmpTextWriterNsStackEntry:
4346 * @data0: the first data
4347 * @data1: the second data
4348 *
4349 * Compare callback for the xmlList.
4350 *
4351 * Returns -1, 0, 1
4352 */
4353static int
4354xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4355{
4356 xmlTextWriterNsStackEntry *p0;
4357 xmlTextWriterNsStackEntry *p1;
4358 int rc;
4359
4360 if (data0 == data1)
4361 return 0;
4362
4363 if (data0 == 0)
4364 return -1;
4365
4366 if (data1 == 0)
4367 return 1;
4368
4369 p0 = (xmlTextWriterNsStackEntry *) data0;
4370 p1 = (xmlTextWriterNsStackEntry *) data1;
4371
4372 rc = xmlStrcmp(p0->prefix, p1->prefix);
4373
Rob Richardsb8769d62007-06-08 08:50:47 +00004374 if ((rc != 0) || (p0->elem != p1->elem))
4375 rc = -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004376
4377 return rc;
4378}
4379
4380/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004381 * xmlTextWriterWriteDocCallback:
4382 * @context: the xmlBufferPtr
4383 * @str: the data to write
4384 * @len: the length of the data
4385 *
4386 * Write callback for the xmlOutputBuffer with target xmlBuffer
4387 *
4388 * Returns -1, 0, 1
4389 */
4390static int
4391xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
4392{
4393 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4394 int rc;
4395
Daniel Veillard1d913862003-11-21 00:28:39 +00004396 if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004397 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004398 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4399 rc);
4400 return -1;
4401 }
4402
4403 return len;
4404}
4405
4406/**
4407 * xmlTextWriterCloseDocCallback:
4408 * @context: the xmlBufferPtr
4409 *
4410 * Close callback for the xmlOutputBuffer with target xmlBuffer
4411 *
4412 * Returns -1, 0, 1
4413 */
4414static int
4415xmlTextWriterCloseDocCallback(void *context)
4416{
4417 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4418 int rc;
4419
4420 if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004421 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004422 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4423 rc);
4424 return -1;
4425 }
4426
4427 return 0;
4428}
4429
4430/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004431 * xmlTextWriterVSprintf:
4432 * @format: see printf
4433 * @argptr: pointer to the first member of the variable argument list.
4434 *
4435 * Utility function for formatted output
4436 *
4437 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4438 */
4439static xmlChar *
4440xmlTextWriterVSprintf(const char *format, va_list argptr)
4441{
4442 int size;
4443 int count;
4444 xmlChar *buf;
William M. Brackf4caa5e2005-10-20 09:04:05 +00004445 va_list locarg;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004446
4447 size = BUFSIZ;
4448 buf = (xmlChar *) xmlMalloc(size);
4449 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004450 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004451 "xmlTextWriterVSprintf : out of memory!\n");
4452 return NULL;
4453 }
4454
William M. Brackf4caa5e2005-10-20 09:04:05 +00004455 VA_COPY(locarg, argptr);
4456 while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004457 || (count == size - 1) || (count == size) || (count > size)) {
William M. Brackf4caa5e2005-10-20 09:04:05 +00004458 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004459 xmlFree(buf);
4460 size += BUFSIZ;
4461 buf = (xmlChar *) xmlMalloc(size);
4462 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004463 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004464 "xmlTextWriterVSprintf : out of memory!\n");
4465 return NULL;
4466 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004467 VA_COPY(locarg, argptr);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004468 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004469 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004470
4471 return buf;
4472}
4473
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004474/**
4475 * xmlTextWriterStartDocumentCallback:
4476 * @ctx: the user data (XML parser context)
4477 *
4478 * called at the start of document processing.
4479 */
4480static void
4481xmlTextWriterStartDocumentCallback(void *ctx)
4482{
4483 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4484 xmlDocPtr doc;
4485
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004486 if (ctxt->html) {
4487#ifdef LIBXML_HTML_ENABLED
4488 if (ctxt->myDoc == NULL)
4489 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4490 if (ctxt->myDoc == NULL) {
4491 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4492 ctxt->sax->error(ctxt->userData,
4493 "SAX.startDocument(): out of memory\n");
4494 ctxt->errNo = XML_ERR_NO_MEMORY;
4495 ctxt->instate = XML_PARSER_EOF;
4496 ctxt->disableSAX = 1;
4497 return;
4498 }
4499#else
Daniel Veillardd0cf7f62004-11-09 16:17:02 +00004500 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004501 "libxml2 built without HTML support\n");
4502 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4503 ctxt->instate = XML_PARSER_EOF;
4504 ctxt->disableSAX = 1;
4505 return;
4506#endif
4507 } else {
4508 doc = ctxt->myDoc;
4509 if (doc == NULL)
4510 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4511 if (doc != NULL) {
4512 if (doc->children == NULL) {
4513 if (ctxt->encoding != NULL)
4514 doc->encoding = xmlStrdup(ctxt->encoding);
4515 else
4516 doc->encoding = NULL;
4517 doc->standalone = ctxt->standalone;
4518 }
4519 } else {
4520 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4521 ctxt->sax->error(ctxt->userData,
4522 "SAX.startDocument(): out of memory\n");
4523 ctxt->errNo = XML_ERR_NO_MEMORY;
4524 ctxt->instate = XML_PARSER_EOF;
4525 ctxt->disableSAX = 1;
4526 return;
4527 }
4528 }
4529 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4530 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4531 ctxt->myDoc->URL =
4532 xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4533 if (ctxt->myDoc->URL == NULL)
4534 ctxt->myDoc->URL =
4535 xmlStrdup((const xmlChar *) ctxt->input->filename);
4536 }
4537}
4538
Daniel Veillard2cca4462004-01-02 20:04:23 +00004539/**
4540 * xmlTextWriterSetIndent:
4541 * @writer: the xmlTextWriterPtr
4542 * @indent: do indentation?
4543 *
4544 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4545 *
4546 * Returns -1 on error or 0 otherwise.
4547 */
4548int
Daniel Veillardab69f362004-02-17 11:40:32 +00004549xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004550{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004551 if ((writer == NULL) || (indent < 0))
Daniel Veillardab69f362004-02-17 11:40:32 +00004552 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004553
Daniel Veillardab69f362004-02-17 11:40:32 +00004554 writer->indent = indent;
4555 writer->doindent = 1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004556
Daniel Veillardab69f362004-02-17 11:40:32 +00004557 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004558}
4559
4560/**
4561 * xmlTextWriterSetIndentString:
4562 * @writer: the xmlTextWriterPtr
4563 * @str: the xmlChar string
4564 *
4565 * Set string indentation.
4566 *
4567 * Returns -1 on error or 0 otherwise.
4568 */
4569int
Daniel Veillardab69f362004-02-17 11:40:32 +00004570xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004571{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004572 if ((writer == NULL) || (!str))
Daniel Veillardab69f362004-02-17 11:40:32 +00004573 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004574
Daniel Veillardab69f362004-02-17 11:40:32 +00004575 if (writer->ichar != NULL)
4576 xmlFree(writer->ichar);
4577 writer->ichar = xmlStrdup(str);
4578
4579 if (!writer->ichar)
4580 return -1;
4581 else
4582 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004583}
4584
4585/**
4586 * xmlTextWriterWriteIndent:
4587 * @writer: the xmlTextWriterPtr
4588 *
4589 * Write indent string.
4590 *
4591 * Returns -1 on error or the number of strings written.
Daniel Veillardab69f362004-02-17 11:40:32 +00004592 */
Daniel Veillard2cca4462004-01-02 20:04:23 +00004593static int
Daniel Veillardab69f362004-02-17 11:40:32 +00004594xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004595{
Daniel Veillardab69f362004-02-17 11:40:32 +00004596 int lksize;
4597 int i;
4598 int ret;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004599
Daniel Veillardab69f362004-02-17 11:40:32 +00004600 lksize = xmlListSize(writer->nodes);
4601 if (lksize < 1)
4602 return (-1); /* list is empty */
4603 for (i = 0; i < (lksize - 1); i++) {
4604 ret = xmlOutputBufferWriteString(writer->out,
4605 (const char *) writer->ichar);
4606 if (ret == -1)
4607 return (-1);
4608 }
4609
4610 return (lksize - 1);
Daniel Veillard2cca4462004-01-02 20:04:23 +00004611}
4612
Daniel Veillard500a1de2004-03-22 15:22:58 +00004613/**
4614 * xmlTextWriterHandleStateDependencies:
4615 * @writer: the xmlTextWriterPtr
4616 * @p: the xmlTextWriterStackEntry
4617 *
4618 * Write state dependent strings.
4619 *
4620 * Returns -1 on error or the number of characters written.
4621 */
4622static int
4623xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4624 xmlTextWriterStackEntry * p)
4625{
4626 int count;
4627 int sum;
4628 char extra[3];
4629
4630 if (writer == NULL)
4631 return -1;
4632
4633 if (p == NULL)
4634 return 0;
4635
4636 sum = 0;
4637 extra[0] = extra[1] = extra[2] = '\0';
4638 if (p != 0) {
4639 sum = 0;
4640 switch (p->state) {
4641 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00004642 /* Output namespace declarations */
4643 count = xmlTextWriterOutputNSDecl(writer);
4644 if (count < 0)
4645 return -1;
4646 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004647 extra[0] = '>';
4648 p->state = XML_TEXTWRITER_TEXT;
4649 break;
4650 case XML_TEXTWRITER_PI:
4651 extra[0] = ' ';
4652 p->state = XML_TEXTWRITER_PI_TEXT;
4653 break;
4654 case XML_TEXTWRITER_DTD:
4655 extra[0] = ' ';
4656 extra[1] = '[';
4657 p->state = XML_TEXTWRITER_DTD_TEXT;
4658 break;
4659 case XML_TEXTWRITER_DTD_ELEM:
4660 extra[0] = ' ';
4661 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4662 break;
4663 case XML_TEXTWRITER_DTD_ATTL:
4664 extra[0] = ' ';
4665 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4666 break;
4667 case XML_TEXTWRITER_DTD_ENTY:
4668 case XML_TEXTWRITER_DTD_PENT:
4669 extra[0] = ' ';
4670 extra[1] = writer->qchar;
4671 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4672 break;
4673 default:
4674 break;
4675 }
4676 }
4677
4678 if (*extra != '\0') {
4679 count = xmlOutputBufferWriteString(writer->out, extra);
4680 if (count < 0)
4681 return -1;
4682 sum += count;
4683 }
4684
4685 return sum;
4686}
4687
Daniel Veillard5d4644e2005-04-01 13:11:58 +00004688#define bottom_xmlwriter
4689#include "elfgcchack.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +00004690#endif