blob: b88de3ad08e33e0a2bd50822d205634a19fc8d5a [file] [log] [blame]
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001
Daniel Veillard1d211e22003-10-20 22:32:39 +00002/*
3 * xmlwriter.c: XML text writer implementation
4 *
5 * For license and disclaimer see the license and disclaimer of
6 * libxml2.
7 *
8 * alfred@mickautsch.de
9 */
10
Igor Zlatkovicb23de5a2003-11-27 18:36:46 +000011#define IN_LIBXML
William M. Brackc1099be2007-01-31 18:38:56 +000012#include "libxml.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +000013#include <string.h>
Daniel Veillard1d211e22003-10-20 22:32:39 +000014
Daniel Veillard1d211e22003-10-20 22:32:39 +000015#include <libxml/xmlmemory.h>
16#include <libxml/parser.h>
Daniel Veillard5841f0e2003-11-20 11:59:09 +000017#include <libxml/uri.h>
18#include <libxml/HTMLtree.h>
Daniel Veillard1d211e22003-10-20 22:32:39 +000019
20#ifdef LIBXML_WRITER_ENABLED
21
22#include <libxml/xmlwriter.h>
23
24#define B64LINELEN 72
25#define B64CRLF "\r\n"
26
27/*
William M. Brackf4caa5e2005-10-20 09:04:05 +000028 * The following VA_COPY was coded following an example in
29 * the Samba project. It may not be sufficient for some
30 * esoteric implementations of va_list (i.e. it may need
31 * something involving a memcpy) but (hopefully) will be
32 * sufficient for libxml2.
33 */
34#ifndef VA_COPY
35 #ifdef HAVE_VA_COPY
36 #define VA_COPY(dest, src) va_copy(dest, src)
37 #else
38 #ifdef HAVE___VA_COPY
39 #define VA_COPY(dest,src) __va_copy(dest, src)
40 #else
41 #define VA_COPY(dest,src) (dest) = (src)
42 #endif
43 #endif
44#endif
45
46/*
Daniel Veillard1d211e22003-10-20 22:32:39 +000047 * Types are kept private
48 */
49typedef enum {
50 XML_TEXTWRITER_NONE = 0,
51 XML_TEXTWRITER_NAME,
52 XML_TEXTWRITER_ATTRIBUTE,
53 XML_TEXTWRITER_TEXT,
54 XML_TEXTWRITER_PI,
55 XML_TEXTWRITER_PI_TEXT,
56 XML_TEXTWRITER_CDATA,
57 XML_TEXTWRITER_DTD,
58 XML_TEXTWRITER_DTD_TEXT,
59 XML_TEXTWRITER_DTD_ELEM,
Daniel Veillard500a1de2004-03-22 15:22:58 +000060 XML_TEXTWRITER_DTD_ELEM_TEXT,
Daniel Veillard1d211e22003-10-20 22:32:39 +000061 XML_TEXTWRITER_DTD_ATTL,
Daniel Veillard500a1de2004-03-22 15:22:58 +000062 XML_TEXTWRITER_DTD_ATTL_TEXT,
63 XML_TEXTWRITER_DTD_ENTY, /* entity */
64 XML_TEXTWRITER_DTD_ENTY_TEXT,
65 XML_TEXTWRITER_DTD_PENT, /* parameter entity */
William M. Brack87640d52004-04-17 14:58:15 +000066 XML_TEXTWRITER_COMMENT
Daniel Veillard1d211e22003-10-20 22:32:39 +000067} xmlTextWriterState;
68
69typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
70
71struct _xmlTextWriterStackEntry {
72 xmlChar *name;
73 xmlTextWriterState state;
74};
75
76typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
77struct _xmlTextWriterNsStackEntry {
78 xmlChar *prefix;
79 xmlChar *uri;
80 xmlLinkPtr elem;
81};
82
83struct _xmlTextWriter {
Daniel Veillardab69f362004-02-17 11:40:32 +000084 xmlOutputBufferPtr out; /* output buffer */
85 xmlListPtr nodes; /* element name stack */
86 xmlListPtr nsstack; /* name spaces stack */
Daniel Veillard1d211e22003-10-20 22:32:39 +000087 int level;
Daniel Veillardab69f362004-02-17 11:40:32 +000088 int indent; /* enable indent */
89 int doindent; /* internal indent flag */
90 xmlChar *ichar; /* indent character */
91 char qchar; /* character used for quoting attribute values */
Daniel Veillard20c5e782004-01-21 09:57:31 +000092 xmlParserCtxtPtr ctxt;
Daniel Veillarda521d282004-11-09 14:59:59 +000093 int no_doc_free;
Rob Richards9db68f02006-08-16 22:48:51 +000094 xmlDocPtr doc;
Daniel Veillard1d211e22003-10-20 22:32:39 +000095};
96
97static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
98static int xmlCmpTextWriterStackEntry(const void *data0,
99 const void *data1);
Rob Richardsb8769d62007-06-08 08:50:47 +0000100static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000101static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
102static int xmlCmpTextWriterNsStackEntry(const void *data0,
103 const void *data1);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000104static int xmlTextWriterWriteDocCallback(void *context,
105 const xmlChar * str, int len);
106static int xmlTextWriterCloseDocCallback(void *context);
107
Daniel Veillard1d211e22003-10-20 22:32:39 +0000108static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);
109static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
110 const unsigned char *data);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000111static void xmlTextWriterStartDocumentCallback(void *ctx);
Daniel Veillardab69f362004-02-17 11:40:32 +0000112static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000113static int
114 xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
115 xmlTextWriterStackEntry * p);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000116
117/**
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000118 * xmlWriterErrMsg:
119 * @ctxt: a writer context
120 * @error: the error number
121 * @msg: the error message
122 *
123 * Handle a writer error
124 */
125static void
126xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,
127 const char *msg)
128{
129 if (ctxt != NULL) {
130 __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
131 NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
132 NULL, 0, NULL, NULL, NULL, 0, 0, msg);
133 } else {
134 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
135 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, msg);
136 }
137}
138
139/**
140 * xmlWriterErrMsgInt:
141 * @ctxt: a writer context
142 * @error: the error number
143 * @msg: the error message
144 * @val: an int
145 *
146 * Handle a writer error
147 */
148static void
149xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,
150 const char *msg, int val)
151{
152 if (ctxt != NULL) {
153 __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
154 NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
155 NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
156 } else {
157 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
158 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
159 }
160}
161
162/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000163 * xmlNewTextWriter:
164 * @out: an xmlOutputBufferPtr
165 *
166 * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
Daniel Veillardd5cc0f72004-11-06 19:24:28 +0000167 * NOTE: the @out parameter will be deallocated when the writer is closed
168 * (if the call succeed.)
Daniel Veillard1d211e22003-10-20 22:32:39 +0000169 *
170 * Returns the new xmlTextWriterPtr or NULL in case of error
171 */
172xmlTextWriterPtr
173xmlNewTextWriter(xmlOutputBufferPtr out)
174{
175 xmlTextWriterPtr ret;
176
177 ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
178 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000179 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000180 "xmlNewTextWriter : out of memory!\n");
181 return NULL;
182 }
183 memset(ret, 0, (size_t) sizeof(xmlTextWriter));
184
185 ret->nodes = xmlListCreate((xmlListDeallocator)
186 xmlFreeTextWriterStackEntry,
187 (xmlListDataCompare)
188 xmlCmpTextWriterStackEntry);
189 if (ret->nodes == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000190 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000191 "xmlNewTextWriter : out of memory!\n");
192 xmlFree(ret);
193 return NULL;
194 }
195
196 ret->nsstack = xmlListCreate((xmlListDeallocator)
197 xmlFreeTextWriterNsStackEntry,
198 (xmlListDataCompare)
199 xmlCmpTextWriterNsStackEntry);
200 if (ret->nsstack == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000201 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000202 "xmlNewTextWriter : out of memory!\n");
Daniel Veillard500a1de2004-03-22 15:22:58 +0000203 xmlListDelete(ret->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000204 xmlFree(ret);
205 return NULL;
206 }
207
208 ret->out = out;
Daniel Veillardab69f362004-02-17 11:40:32 +0000209 ret->ichar = xmlStrdup(BAD_CAST " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000210 ret->qchar = '"';
211
Daniel Veillard500a1de2004-03-22 15:22:58 +0000212 if (!ret->ichar) {
213 xmlListDelete(ret->nodes);
214 xmlListDelete(ret->nsstack);
215 xmlFree(ret);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000216 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000217 "xmlNewTextWriter : out of memory!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000218 return NULL;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000219 }
Rob Richards9db68f02006-08-16 22:48:51 +0000220
221 ret->doc = xmlNewDoc(NULL);
222
Daniel Veillarda521d282004-11-09 14:59:59 +0000223 ret->no_doc_free = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000224
Daniel Veillard1d211e22003-10-20 22:32:39 +0000225 return ret;
226}
227
228/**
229 * xmlNewTextWriterFilename:
230 * @uri: the URI of the resource for the output
231 * @compression: compress the output?
232 *
233 * Create a new xmlNewTextWriter structure with @uri as output
234 *
235 * Returns the new xmlTextWriterPtr or NULL in case of error
236 */
237xmlTextWriterPtr
238xmlNewTextWriterFilename(const char *uri, int compression)
239{
240 xmlTextWriterPtr ret;
241 xmlOutputBufferPtr out;
242
243 out = xmlOutputBufferCreateFilename(uri, NULL, compression);
244 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000245 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000246 "xmlNewTextWriterFilename : out of memory!\n");
247 return NULL;
248 }
249
250 ret = xmlNewTextWriter(out);
251 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000252 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000253 "xmlNewTextWriterFilename : out of memory!\n");
254 xmlOutputBufferClose(out);
255 return NULL;
256 }
257
Daniel Veillard2cca4462004-01-02 20:04:23 +0000258 ret->indent = 0;
259 ret->doindent = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000260 return ret;
261}
262
263/**
264 * xmlNewTextWriterMemory:
265 * @buf: xmlBufferPtr
266 * @compression: compress the output?
267 *
268 * Create a new xmlNewTextWriter structure with @buf as output
269 * TODO: handle compression
270 *
271 * Returns the new xmlTextWriterPtr or NULL in case of error
272 */
273xmlTextWriterPtr
274xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
275{
276 xmlTextWriterPtr ret;
277 xmlOutputBufferPtr out;
278
279/*::todo handle compression */
Rob Richardsa44f2342005-11-09 18:03:45 +0000280 out = xmlOutputBufferCreateBuffer(buf, NULL);
281
Daniel Veillard1d211e22003-10-20 22:32:39 +0000282 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000283 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000284 "xmlNewTextWriterMemory : out of memory!\n");
285 return NULL;
286 }
287
288 ret = xmlNewTextWriter(out);
289 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000290 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000291 "xmlNewTextWriterMemory : out of memory!\n");
292 xmlOutputBufferClose(out);
293 return NULL;
294 }
295
296 return ret;
297}
298
299/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000300 * xmlNewTextWriterPushParser:
301 * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
302 * @compression: compress the output?
303 *
304 * Create a new xmlNewTextWriter structure with @ctxt as output
Daniel Veillardd5cc0f72004-11-06 19:24:28 +0000305 * NOTE: the @ctxt context will be freed with the resulting writer
306 * (if the call succeeds).
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000307 * TODO: handle compression
308 *
309 * Returns the new xmlTextWriterPtr or NULL in case of error
310 */
311xmlTextWriterPtr
Daniel Veillard1d913862003-11-21 00:28:39 +0000312xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
313 int compression ATTRIBUTE_UNUSED)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000314{
315 xmlTextWriterPtr ret;
316 xmlOutputBufferPtr out;
317
Daniel Veillard500a1de2004-03-22 15:22:58 +0000318 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000319 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000320 "xmlNewTextWriterPushParser : invalid context!\n");
321 return NULL;
322 }
323
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000324 out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
325 xmlTextWriterWriteDocCallback,
326 (xmlOutputCloseCallback)
327 xmlTextWriterCloseDocCallback,
328 (void *) ctxt, NULL);
329 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000330 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000331 "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
332 return NULL;
333 }
334
335 ret = xmlNewTextWriter(out);
336 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000337 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000338 "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
339 xmlOutputBufferClose(out);
340 return NULL;
341 }
342
Daniel Veillard20c5e782004-01-21 09:57:31 +0000343 ret->ctxt = ctxt;
344
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000345 return ret;
346}
347
348/**
349 * xmlNewTextWriterDoc:
350 * @doc: address of a xmlDocPtr to hold the new XML document tree
351 * @compression: compress the output?
352 *
353 * Create a new xmlNewTextWriter structure with @*doc as output
354 *
355 * Returns the new xmlTextWriterPtr or NULL in case of error
356 */
357xmlTextWriterPtr
358xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
359{
360 xmlTextWriterPtr ret;
361 xmlSAXHandler saxHandler;
362 xmlParserCtxtPtr ctxt;
363
364 memset(&saxHandler, '\0', sizeof(saxHandler));
365 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
366 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
367 saxHandler.startElement = xmlSAX2StartElement;
368 saxHandler.endElement = xmlSAX2EndElement;
369
370 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
371 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000372 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000373 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
374 return NULL;
375 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000376 /*
377 * For some reason this seems to completely break if node names
378 * are interned.
379 */
380 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000381
Daniel Veillard1d913862003-11-21 00:28:39 +0000382 ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000383 if (ctxt->myDoc == NULL) {
384 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000385 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000386 "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
387 return NULL;
388 }
389
390 ret = xmlNewTextWriterPushParser(ctxt, compression);
391 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000392 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000393 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
394 return NULL;
395 }
396
Daniel Veillard500a1de2004-03-22 15:22:58 +0000397 xmlSetDocCompressMode(ctxt->myDoc, compression);
398
Daniel Veillarda521d282004-11-09 14:59:59 +0000399 if (doc != NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000400 *doc = ctxt->myDoc;
Daniel Veillarda521d282004-11-09 14:59:59 +0000401 ret->no_doc_free = 1;
402 }
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000403
404 return ret;
405}
406
407/**
408 * xmlNewTextWriterTree:
409 * @doc: xmlDocPtr
410 * @node: xmlNodePtr or NULL for doc->children
411 * @compression: compress the output?
412 *
413 * Create a new xmlNewTextWriter structure with @doc as output
414 * starting at @node
415 *
416 * Returns the new xmlTextWriterPtr or NULL in case of error
417 */
418xmlTextWriterPtr
419xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
420{
421 xmlTextWriterPtr ret;
422 xmlSAXHandler saxHandler;
423 xmlParserCtxtPtr ctxt;
424
425 if (doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000426 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000427 "xmlNewTextWriterTree : invalid document tree!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000428 return NULL;
429 }
430
431 memset(&saxHandler, '\0', sizeof(saxHandler));
432 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
433 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
434 saxHandler.startElement = xmlSAX2StartElement;
435 saxHandler.endElement = xmlSAX2EndElement;
436
437 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
438 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000439 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000440 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
441 return NULL;
442 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000443 /*
444 * For some reason this seems to completely break if node names
445 * are interned.
446 */
447 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000448
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000449 ret = xmlNewTextWriterPushParser(ctxt, compression);
450 if (ret == NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000451 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000452 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000453 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
454 return NULL;
455 }
456
Daniel Veillard500a1de2004-03-22 15:22:58 +0000457 ctxt->myDoc = doc;
458 ctxt->node = node;
Daniel Veillarda521d282004-11-09 14:59:59 +0000459 ret->no_doc_free = 1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000460
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000461 xmlSetDocCompressMode(doc, compression);
462
463 return ret;
464}
465
466/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000467 * xmlFreeTextWriter:
468 * @writer: the xmlTextWriterPtr
469 *
470 * Deallocate all the resources associated to the writer
471 */
472void
473xmlFreeTextWriter(xmlTextWriterPtr writer)
474{
475 if (writer == NULL)
476 return;
477
478 if (writer->out != NULL)
479 xmlOutputBufferClose(writer->out);
480
481 if (writer->nodes != NULL)
482 xmlListDelete(writer->nodes);
483
484 if (writer->nsstack != NULL)
485 xmlListDelete(writer->nsstack);
486
Daniel Veillarda521d282004-11-09 14:59:59 +0000487 if (writer->ctxt != NULL) {
488 if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
489 xmlFreeDoc(writer->ctxt->myDoc);
490 writer->ctxt->myDoc = NULL;
491 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000492 xmlFreeParserCtxt(writer->ctxt);
Daniel Veillarda521d282004-11-09 14:59:59 +0000493 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000494
Rob Richards9db68f02006-08-16 22:48:51 +0000495 if (writer->doc != NULL)
496 xmlFreeDoc(writer->doc);
497
Daniel Veillard4773df22004-01-23 13:15:13 +0000498 if (writer->ichar != NULL)
499 xmlFree(writer->ichar);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000500 xmlFree(writer);
501}
502
503/**
504 * xmlTextWriterStartDocument:
505 * @writer: the xmlTextWriterPtr
506 * @version: the xml version ("1.0") or NULL for default ("1.0")
507 * @encoding: the encoding or NULL for default
508 * @standalone: "yes" or "no" or NULL for default
509 *
510 * Start a new xml document
511 *
512 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
513 */
514int
515xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
516 const char *encoding, const char *standalone)
517{
518 int count;
519 int sum;
520 xmlLinkPtr lk;
521 xmlCharEncodingHandlerPtr encoder;
522
Daniel Veillard500a1de2004-03-22 15:22:58 +0000523 if ((writer == NULL) || (writer->out == NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000524 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000525 "xmlTextWriterStartDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000526 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000527 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000528
529 lk = xmlListFront(writer->nodes);
530 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000531 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000532 "xmlTextWriterStartDocument : not allowed in this context!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000533 return -1;
534 }
535
536 encoder = NULL;
537 if (encoding != NULL) {
538 encoder = xmlFindCharEncodingHandler(encoding);
539 if (encoder == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000540 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000541 "xmlTextWriterStartDocument : out of memory!\n");
542 return -1;
543 }
544 }
545
546 writer->out->encoder = encoder;
547 if (encoder != NULL) {
Daniel Veillardcaa19512007-07-04 15:42:46 +0000548 if (writer->out->conv == NULL) {
549 writer->out->conv = xmlBufferCreateSize(4000);
550 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000551 xmlCharEncOutFunc(encoder, writer->out->conv, NULL);
Rob Richards9db68f02006-08-16 22:48:51 +0000552 if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
553 writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000554 } else
555 writer->out->conv = NULL;
556
557 sum = 0;
558 count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
559 if (count < 0)
560 return -1;
561 sum += count;
562 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
563 if (count < 0)
564 return -1;
565 sum += count;
566 if (version != 0)
567 count = xmlOutputBufferWriteString(writer->out, version);
568 else
569 count = xmlOutputBufferWriteString(writer->out, "1.0");
570 if (count < 0)
571 return -1;
572 sum += count;
573 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
574 if (count < 0)
575 return -1;
576 sum += count;
577 if (writer->out->encoder != 0) {
578 count = xmlOutputBufferWriteString(writer->out, " encoding=");
579 if (count < 0)
580 return -1;
581 sum += count;
582 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
583 if (count < 0)
584 return -1;
585 sum += count;
586 count =
587 xmlOutputBufferWriteString(writer->out,
588 writer->out->encoder->name);
589 if (count < 0)
590 return -1;
591 sum += count;
592 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
593 if (count < 0)
594 return -1;
595 sum += count;
596 }
597
598 if (standalone != 0) {
599 count = xmlOutputBufferWriteString(writer->out, " standalone=");
600 if (count < 0)
601 return -1;
602 sum += count;
603 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
604 if (count < 0)
605 return -1;
606 sum += count;
607 count = xmlOutputBufferWriteString(writer->out, standalone);
608 if (count < 0)
609 return -1;
610 sum += count;
611 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
612 if (count < 0)
613 return -1;
614 sum += count;
615 }
616
617 count = xmlOutputBufferWriteString(writer->out, "?>\n");
618 if (count < 0)
619 return -1;
620 sum += count;
621
622 return sum;
623}
624
625/**
626 * xmlTextWriterEndDocument:
627 * @writer: the xmlTextWriterPtr
628 *
Daniel Veillard3ff24112008-02-13 10:17:41 +0000629 * End an xml document. All open elements are closed, and
630 * the content is flushed to the output.
Daniel Veillard1d211e22003-10-20 22:32:39 +0000631 *
Daniel Veillard3ff24112008-02-13 10:17:41 +0000632 * Returns the bytes written or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +0000633 */
634int
635xmlTextWriterEndDocument(xmlTextWriterPtr writer)
636{
637 int count;
638 int sum;
639 xmlLinkPtr lk;
640 xmlTextWriterStackEntry *p;
641
Daniel Veillard500a1de2004-03-22 15:22:58 +0000642 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000643 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000644 "xmlTextWriterEndDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000645 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000646 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000647
648 sum = 0;
649 while ((lk = xmlListFront(writer->nodes)) != NULL) {
650 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
651 if (p == 0)
652 break;
653 switch (p->state) {
654 case XML_TEXTWRITER_NAME:
655 case XML_TEXTWRITER_ATTRIBUTE:
656 case XML_TEXTWRITER_TEXT:
657 count = xmlTextWriterEndElement(writer);
658 if (count < 0)
659 return -1;
660 sum += count;
661 break;
662 case XML_TEXTWRITER_PI:
663 case XML_TEXTWRITER_PI_TEXT:
664 count = xmlTextWriterEndPI(writer);
665 if (count < 0)
666 return -1;
667 sum += count;
668 break;
669 case XML_TEXTWRITER_CDATA:
670 count = xmlTextWriterEndCDATA(writer);
671 if (count < 0)
672 return -1;
673 sum += count;
674 break;
675 case XML_TEXTWRITER_DTD:
Daniel Veillard500a1de2004-03-22 15:22:58 +0000676 case XML_TEXTWRITER_DTD_TEXT:
677 case XML_TEXTWRITER_DTD_ELEM:
678 case XML_TEXTWRITER_DTD_ELEM_TEXT:
679 case XML_TEXTWRITER_DTD_ATTL:
680 case XML_TEXTWRITER_DTD_ATTL_TEXT:
681 case XML_TEXTWRITER_DTD_ENTY:
682 case XML_TEXTWRITER_DTD_ENTY_TEXT:
683 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard1d211e22003-10-20 22:32:39 +0000684 count = xmlTextWriterEndDTD(writer);
685 if (count < 0)
686 return -1;
687 sum += count;
688 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000689 case XML_TEXTWRITER_COMMENT:
690 count = xmlTextWriterEndComment(writer);
691 if (count < 0)
692 return -1;
693 sum += count;
694 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000695 default:
Daniel Veillardab69f362004-02-17 11:40:32 +0000696 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000697 }
698 }
699
Daniel Veillard2cca4462004-01-02 20:04:23 +0000700 if (!writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000701 count = xmlOutputBufferWriteString(writer->out, "\n");
702 if (count < 0)
703 return -1;
704 sum += count;
705 }
Daniel Veillard3ff24112008-02-13 10:17:41 +0000706
707 sum += xmlTextWriterFlush(writer);
708
Daniel Veillardab69f362004-02-17 11:40:32 +0000709 return sum;
710}
711
Daniel Veillardab69f362004-02-17 11:40:32 +0000712/**
713 * xmlTextWriterStartComment:
714 * @writer: the xmlTextWriterPtr
715 *
716 * Start an xml comment.
717 *
718 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
719 */
720int
721xmlTextWriterStartComment(xmlTextWriterPtr writer)
722{
723 int count;
724 int sum;
725 xmlLinkPtr lk;
726 xmlTextWriterStackEntry *p;
727
Daniel Veillard500a1de2004-03-22 15:22:58 +0000728 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000729 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000730 "xmlTextWriterStartComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000731 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000732 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000733
734 sum = 0;
735 lk = xmlListFront(writer->nodes);
736 if (lk != 0) {
737 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
738 if (p != 0) {
739 switch (p->state) {
740 case XML_TEXTWRITER_TEXT:
741 case XML_TEXTWRITER_NONE:
742 break;
743 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000744 /* Output namespace declarations */
745 count = xmlTextWriterOutputNSDecl(writer);
746 if (count < 0)
747 return -1;
748 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000749 count = xmlOutputBufferWriteString(writer->out, ">");
750 if (count < 0)
751 return -1;
752 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000753 if (writer->indent) {
754 count =
755 xmlOutputBufferWriteString(writer->out, "\n");
756 if (count < 0)
757 return -1;
758 sum += count;
759 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000760 p->state = XML_TEXTWRITER_TEXT;
761 break;
762 default:
763 return -1;
764 }
765 }
766 }
767
768 p = (xmlTextWriterStackEntry *)
769 xmlMalloc(sizeof(xmlTextWriterStackEntry));
770 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000771 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillardab69f362004-02-17 11:40:32 +0000772 "xmlTextWriterStartElement : out of memory!\n");
773 return -1;
774 }
775
Daniel Veillard75e389d2005-07-29 22:02:24 +0000776 p->name = NULL;
Daniel Veillardab69f362004-02-17 11:40:32 +0000777 p->state = XML_TEXTWRITER_COMMENT;
778
779 xmlListPushFront(writer->nodes, p);
780
781 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000782 count = xmlTextWriterWriteIndent(writer);
783 if (count < 0)
784 return -1;
785 sum += count;
786 }
787
788 count = xmlOutputBufferWriteString(writer->out, "<!--");
789 if (count < 0)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000790 return -1;
791 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000792
793 return sum;
794}
795
796/**
797 * xmlTextWriterEndComment:
798 * @writer: the xmlTextWriterPtr
799 *
800 * End the current xml coment.
801 *
802 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
803 */
804int
805xmlTextWriterEndComment(xmlTextWriterPtr writer)
806{
807 int count;
808 int sum;
809 xmlLinkPtr lk;
810 xmlTextWriterStackEntry *p;
811
Daniel Veillard500a1de2004-03-22 15:22:58 +0000812 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000813 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000814 "xmlTextWriterEndComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000815 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000816 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000817
818 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000819 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000820 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000821 "xmlTextWriterEndComment : not allowed in this context!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000822 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000823 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000824
825 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
826 if (p == 0)
827 return -1;
828
829 sum = 0;
830 switch (p->state) {
831 case XML_TEXTWRITER_COMMENT:
832 count = xmlOutputBufferWriteString(writer->out, "-->");
833 if (count < 0)
834 return -1;
835 sum += count;
836 break;
837 default:
838 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +0000839 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000840
841 if (writer->indent) {
842 count = xmlOutputBufferWriteString(writer->out, "\n");
843 if (count < 0)
844 return -1;
845 sum += count;
846 }
847
848 xmlListPopFront(writer->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000849 return sum;
850}
851
852/**
853 * xmlTextWriterWriteFormatComment:
854 * @writer: the xmlTextWriterPtr
855 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +0000856 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +0000857 *
858 * Write an xml comment.
859 *
860 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
861 */
Daniel Veillardffa3c742005-07-21 13:24:09 +0000862int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +0000863xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
864 const char *format, ...)
865{
866 int rc;
867 va_list ap;
868
869 va_start(ap, format);
870
871 rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
872
873 va_end(ap);
874 return rc;
875}
876
877/**
878 * xmlTextWriterWriteVFormatComment:
879 * @writer: the xmlTextWriterPtr
880 * @format: format string (see printf)
881 * @argptr: pointer to the first member of the variable argument list.
882 *
883 * Write an xml comment.
884 *
885 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
886 */
887int
888xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
889 const char *format, va_list argptr)
890{
891 int rc;
892 xmlChar *buf;
893
Daniel Veillard500a1de2004-03-22 15:22:58 +0000894 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000895 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000896 "xmlTextWriterWriteVFormatComment : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000897 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000898 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000899
900 buf = xmlTextWriterVSprintf(format, argptr);
901 if (buf == 0)
902 return 0;
903
904 rc = xmlTextWriterWriteComment(writer, buf);
905
906 xmlFree(buf);
907 return rc;
908}
909
910/**
911 * xmlTextWriterWriteComment:
912 * @writer: the xmlTextWriterPtr
913 * @content: comment string
914 *
915 * Write an xml comment.
916 *
917 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
918 */
919int
920xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
921{
922 int count;
923 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000924
925 sum = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000926 count = xmlTextWriterStartComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000927 if (count < 0)
928 return -1;
929 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000930 count = xmlTextWriterWriteString(writer, content);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000931 if (count < 0)
932 return -1;
933 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000934 count = xmlTextWriterEndComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000935 if (count < 0)
936 return -1;
937 sum += count;
938
939 return sum;
940}
941
942/**
943 * xmlTextWriterStartElement:
944 * @writer: the xmlTextWriterPtr
945 * @name: element name
946 *
947 * Start an xml element.
948 *
949 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
950 */
951int
952xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
953{
954 int count;
955 int sum;
956 xmlLinkPtr lk;
957 xmlTextWriterStackEntry *p;
958
959 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
960 return -1;
961
962 sum = 0;
963 lk = xmlListFront(writer->nodes);
964 if (lk != 0) {
965 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
966 if (p != 0) {
967 switch (p->state) {
968 case XML_TEXTWRITER_PI:
969 case XML_TEXTWRITER_PI_TEXT:
970 return -1;
971 case XML_TEXTWRITER_NONE:
972 break;
Daniel Veillard614fdc12005-02-23 14:05:37 +0000973 case XML_TEXTWRITER_ATTRIBUTE:
974 count = xmlTextWriterEndAttribute(writer);
975 if (count < 0)
976 return -1;
977 sum += count;
978 /* fallthrough */
Daniel Veillard1d211e22003-10-20 22:32:39 +0000979 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000980 /* Output namespace declarations */
981 count = xmlTextWriterOutputNSDecl(writer);
982 if (count < 0)
983 return -1;
984 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000985 count = xmlOutputBufferWriteString(writer->out, ">");
986 if (count < 0)
987 return -1;
988 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000989 if (writer->indent)
990 count =
991 xmlOutputBufferWriteString(writer->out, "\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000992 p->state = XML_TEXTWRITER_TEXT;
993 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000994 default:
995 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000996 }
997 }
998 }
999
1000 p = (xmlTextWriterStackEntry *)
1001 xmlMalloc(sizeof(xmlTextWriterStackEntry));
1002 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001003 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001004 "xmlTextWriterStartElement : out of memory!\n");
1005 return -1;
1006 }
1007
1008 p->name = xmlStrdup(name);
1009 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001010 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001011 "xmlTextWriterStartElement : out of memory!\n");
1012 xmlFree(p);
1013 return -1;
1014 }
1015 p->state = XML_TEXTWRITER_NAME;
1016
1017 xmlListPushFront(writer->nodes, p);
1018
Daniel Veillardab69f362004-02-17 11:40:32 +00001019 if (writer->indent) {
1020 count = xmlTextWriterWriteIndent(writer);
1021 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001022 }
1023
Daniel Veillard1d211e22003-10-20 22:32:39 +00001024 count = xmlOutputBufferWriteString(writer->out, "<");
1025 if (count < 0)
1026 return -1;
1027 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001028 count =
1029 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001030 if (count < 0)
1031 return -1;
1032 sum += count;
1033
1034 return sum;
1035}
1036
1037/**
1038 * xmlTextWriterStartElementNS:
1039 * @writer: the xmlTextWriterPtr
1040 * @prefix: namespace prefix or NULL
1041 * @name: element local name
1042 * @namespaceURI: namespace URI or NULL
1043 *
1044 * Start an xml element with namespace support.
1045 *
1046 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1047 */
1048int
1049xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
1050 const xmlChar * prefix, const xmlChar * name,
1051 const xmlChar * namespaceURI)
1052{
1053 int count;
1054 int sum;
1055 xmlChar *buf;
1056
1057 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1058 return -1;
1059
Daniel Veillard75e389d2005-07-29 22:02:24 +00001060 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001061 if (prefix != 0) {
1062 buf = xmlStrdup(prefix);
1063 buf = xmlStrcat(buf, BAD_CAST ":");
1064 }
1065 buf = xmlStrcat(buf, name);
1066
1067 sum = 0;
1068 count = xmlTextWriterStartElement(writer, buf);
1069 xmlFree(buf);
1070 if (count < 0)
1071 return -1;
1072 sum += count;
1073
1074 if (namespaceURI != 0) {
Rob Richardsb8769d62007-06-08 08:50:47 +00001075 xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
1076 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1077 if (p == 0) {
1078 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1079 "xmlTextWriterStartElementNS : out of memory!\n");
1080 return -1;
1081 }
1082
Daniel Veillard1d211e22003-10-20 22:32:39 +00001083 buf = xmlStrdup(BAD_CAST "xmlns");
1084 if (prefix != 0) {
1085 buf = xmlStrcat(buf, BAD_CAST ":");
1086 buf = xmlStrcat(buf, prefix);
1087 }
1088
Rob Richardsb8769d62007-06-08 08:50:47 +00001089 p->prefix = buf;
1090 p->uri = xmlStrdup(namespaceURI);
1091 if (p->uri == 0) {
1092 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1093 "xmlTextWriterStartElementNS : out of memory!\n");
1094 xmlFree(p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001095 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001096 }
1097 p->elem = xmlListFront(writer->nodes);
1098
1099 xmlListPushFront(writer->nsstack, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001100 }
1101
1102 return sum;
1103}
1104
1105/**
1106 * xmlTextWriterEndElement:
1107 * @writer: the xmlTextWriterPtr
1108 *
1109 * End the current xml element.
1110 *
1111 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1112 */
1113int
1114xmlTextWriterEndElement(xmlTextWriterPtr writer)
1115{
1116 int count;
1117 int sum;
1118 xmlLinkPtr lk;
1119 xmlTextWriterStackEntry *p;
1120
1121 if (writer == NULL)
1122 return -1;
1123
1124 lk = xmlListFront(writer->nodes);
Rob Richardsb8769d62007-06-08 08:50:47 +00001125 if (lk == 0) {
1126 xmlListDelete(writer->nsstack);
1127 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001128 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001129 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001130
1131 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Rob Richardsb8769d62007-06-08 08:50:47 +00001132 if (p == 0) {
1133 xmlListDelete(writer->nsstack);
1134 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001135 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001136 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001137
1138 sum = 0;
1139 switch (p->state) {
1140 case XML_TEXTWRITER_ATTRIBUTE:
1141 count = xmlTextWriterEndAttribute(writer);
Rob Richardsb8769d62007-06-08 08:50:47 +00001142 if (count < 0) {
1143 xmlListDelete(writer->nsstack);
1144 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001145 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001146 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001147 sum += count;
1148 /* fallthrough */
1149 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001150 /* Output namespace declarations */
1151 count = xmlTextWriterOutputNSDecl(writer);
1152 if (count < 0)
1153 return -1;
1154 sum += count;
1155
Daniel Veillardab69f362004-02-17 11:40:32 +00001156 if (writer->indent) /* next element needs indent */
1157 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001158 count = xmlOutputBufferWriteString(writer->out, "/>");
1159 if (count < 0)
1160 return -1;
1161 sum += count;
1162 break;
1163 case XML_TEXTWRITER_TEXT:
Daniel Veillardab69f362004-02-17 11:40:32 +00001164 if ((writer->indent) && (writer->doindent)) {
1165 count = xmlTextWriterWriteIndent(writer);
1166 sum += count;
1167 writer->doindent = 1;
1168 } else
1169 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001170 count = xmlOutputBufferWriteString(writer->out, "</");
1171 if (count < 0)
1172 return -1;
1173 sum += count;
1174 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001175 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001176 if (count < 0)
1177 return -1;
1178 sum += count;
1179 count = xmlOutputBufferWriteString(writer->out, ">");
1180 if (count < 0)
1181 return -1;
1182 sum += count;
1183 break;
1184 default:
1185 return -1;
1186 }
1187
Daniel Veillard2cca4462004-01-02 20:04:23 +00001188 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001189 count = xmlOutputBufferWriteString(writer->out, "\n");
1190 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001191 }
1192
Daniel Veillard1d211e22003-10-20 22:32:39 +00001193 xmlListPopFront(writer->nodes);
1194 return sum;
1195}
1196
1197/**
1198 * xmlTextWriterFullEndElement:
1199 * @writer: the xmlTextWriterPtr
1200 *
1201 * End the current xml element. Writes an end tag even if the element is empty
1202 *
1203 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1204 */
1205int
1206xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1207{
1208 int count;
1209 int sum;
1210 xmlLinkPtr lk;
1211 xmlTextWriterStackEntry *p;
1212
1213 if (writer == NULL)
1214 return -1;
1215
1216 lk = xmlListFront(writer->nodes);
1217 if (lk == 0)
1218 return -1;
1219
1220 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1221 if (p == 0)
1222 return -1;
1223
1224 sum = 0;
1225 switch (p->state) {
1226 case XML_TEXTWRITER_ATTRIBUTE:
1227 count = xmlTextWriterEndAttribute(writer);
1228 if (count < 0)
1229 return -1;
1230 sum += count;
1231 /* fallthrough */
1232 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001233 /* Output namespace declarations */
1234 count = xmlTextWriterOutputNSDecl(writer);
1235 if (count < 0)
1236 return -1;
1237 sum += count;
1238
Daniel Veillard1d211e22003-10-20 22:32:39 +00001239 count = xmlOutputBufferWriteString(writer->out, ">");
1240 if (count < 0)
1241 return -1;
1242 sum += count;
Rob Richards5a7d8bd2008-12-27 13:17:43 +00001243 if (writer->indent)
1244 writer->doindent = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001245 /* fallthrough */
1246 case XML_TEXTWRITER_TEXT:
Rob Richards5a7d8bd2008-12-27 13:17:43 +00001247 if ((writer->indent) && (writer->doindent)) {
1248 count = xmlTextWriterWriteIndent(writer);
1249 sum += count;
1250 writer->doindent = 1;
1251 } else
1252 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001253 count = xmlOutputBufferWriteString(writer->out, "</");
1254 if (count < 0)
1255 return -1;
1256 sum += count;
1257 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001258 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001259 if (count < 0)
1260 return -1;
1261 sum += count;
1262 count = xmlOutputBufferWriteString(writer->out, ">");
1263 if (count < 0)
1264 return -1;
1265 sum += count;
1266 break;
1267 default:
1268 return -1;
1269 }
1270
Daniel Veillard7e26fb42008-01-09 02:19:50 +00001271 if (writer->indent) {
1272 count = xmlOutputBufferWriteString(writer->out, "\n");
1273 sum += count;
1274 }
1275
Daniel Veillard1d211e22003-10-20 22:32:39 +00001276 xmlListPopFront(writer->nodes);
1277 return sum;
1278}
1279
1280/**
1281 * xmlTextWriterWriteFormatRaw:
1282 * @writer: the xmlTextWriterPtr
1283 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001284 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001285 *
1286 * Write a formatted raw xml text.
1287 *
1288 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1289 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001290int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001291xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1292 ...)
1293{
1294 int rc;
1295 va_list ap;
1296
1297 va_start(ap, format);
1298
1299 rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1300
1301 va_end(ap);
1302 return rc;
1303}
1304
1305/**
1306 * xmlTextWriterWriteVFormatRaw:
1307 * @writer: the xmlTextWriterPtr
1308 * @format: format string (see printf)
1309 * @argptr: pointer to the first member of the variable argument list.
1310 *
1311 * Write a formatted raw xml text.
1312 *
1313 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1314 */
1315int
1316xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1317 va_list argptr)
1318{
1319 int rc;
1320 xmlChar *buf;
1321
1322 if (writer == NULL)
1323 return -1;
1324
1325 buf = xmlTextWriterVSprintf(format, argptr);
1326 if (buf == 0)
1327 return 0;
1328
1329 rc = xmlTextWriterWriteRaw(writer, buf);
1330
1331 xmlFree(buf);
1332 return rc;
1333}
1334
1335/**
Daniel Veillard1e906612003-12-05 14:57:46 +00001336 * xmlTextWriterWriteRawLen:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001337 * @writer: the xmlTextWriterPtr
1338 * @content: text string
1339 * @len: length of the text string
1340 *
1341 * Write an xml text.
1342 * TODO: what about entities and special chars??
1343 *
1344 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1345 */
1346int
1347xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1348 int len)
1349{
1350 int count;
1351 int sum;
1352 xmlLinkPtr lk;
1353 xmlTextWriterStackEntry *p;
1354
Daniel Veillard500a1de2004-03-22 15:22:58 +00001355 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001356 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001357 "xmlTextWriterWriteRawLen : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001358 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001359 }
1360
Daniel Veillarde43cc572004-11-03 11:50:29 +00001361 if ((content == NULL) || (len < 0)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001362 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001363 "xmlTextWriterWriteRawLen : invalid content!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001364 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001365 }
1366
1367 sum = 0;
1368 lk = xmlListFront(writer->nodes);
1369 if (lk != 0) {
1370 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1371 count = xmlTextWriterHandleStateDependencies(writer, p);
1372 if (count < 0)
1373 return -1;
1374 sum += count;
1375 }
1376
1377 if (writer->indent)
1378 writer->doindent = 0;
1379
1380 if (content != NULL) {
1381 count =
1382 xmlOutputBufferWrite(writer->out, len, (const char *) content);
1383 if (count < 0)
1384 return -1;
1385 sum += count;
1386 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001387
1388 return sum;
1389}
1390
1391/**
1392 * xmlTextWriterWriteRaw:
1393 * @writer: the xmlTextWriterPtr
1394 * @content: text string
1395 *
1396 * Write a raw xml text.
1397 *
1398 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1399 */
1400int
1401xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1402{
1403 return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1404}
1405
1406/**
1407 * xmlTextWriterWriteFormatString:
1408 * @writer: the xmlTextWriterPtr
1409 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001410 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001411 *
1412 * Write a formatted xml text.
1413 *
1414 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1415 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001416int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001417xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1418 ...)
1419{
1420 int rc;
1421 va_list ap;
1422
Daniel Veillarde43cc572004-11-03 11:50:29 +00001423 if ((writer == NULL) || (format == NULL))
1424 return -1;
1425
Daniel Veillard1d211e22003-10-20 22:32:39 +00001426 va_start(ap, format);
1427
1428 rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1429
1430 va_end(ap);
1431 return rc;
1432}
1433
1434/**
1435 * xmlTextWriterWriteVFormatString:
1436 * @writer: the xmlTextWriterPtr
1437 * @format: format string (see printf)
1438 * @argptr: pointer to the first member of the variable argument list.
1439 *
1440 * Write a formatted xml text.
1441 *
1442 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1443 */
1444int
1445xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1446 const char *format, va_list argptr)
1447{
1448 int rc;
1449 xmlChar *buf;
1450
Daniel Veillarde43cc572004-11-03 11:50:29 +00001451 if ((writer == NULL) || (format == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001452 return -1;
1453
1454 buf = xmlTextWriterVSprintf(format, argptr);
1455 if (buf == 0)
1456 return 0;
1457
1458 rc = xmlTextWriterWriteString(writer, buf);
1459
1460 xmlFree(buf);
1461 return rc;
1462}
1463
1464/**
1465 * xmlTextWriterWriteString:
1466 * @writer: the xmlTextWriterPtr
1467 * @content: text string
1468 *
1469 * Write an xml text.
1470 *
1471 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1472 */
1473int
1474xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1475{
Daniel Veillard500a1de2004-03-22 15:22:58 +00001476 int count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001477 int sum;
1478 xmlLinkPtr lk;
1479 xmlTextWriterStackEntry *p;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001480 xmlChar *buf;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001481
Daniel Veillarde43cc572004-11-03 11:50:29 +00001482 if ((writer == NULL) || (content == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001483 return -1;
1484
Daniel Veillard1d211e22003-10-20 22:32:39 +00001485 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001486 buf = (xmlChar *) content;
1487 lk = xmlListFront(writer->nodes);
1488 if (lk != 0) {
1489 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1490 if (p != 0) {
1491 switch (p->state) {
1492 case XML_TEXTWRITER_NAME:
1493 case XML_TEXTWRITER_TEXT:
Daniel Veillard62040be2004-05-17 03:17:26 +00001494#if 0
1495 buf = NULL;
1496 xmlOutputBufferWriteEscape(writer->out, content, NULL);
1497#endif
Daniel Veillard500a1de2004-03-22 15:22:58 +00001498 buf = xmlEncodeSpecialChars(NULL, content);
1499 break;
1500 case XML_TEXTWRITER_ATTRIBUTE:
1501 buf = NULL;
Rob Richards9db68f02006-08-16 22:48:51 +00001502 xmlAttrSerializeTxtContent(writer->out->buffer, writer->doc,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001503 NULL, content);
1504 break;
William M. Brack87640d52004-04-17 14:58:15 +00001505 default:
1506 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001507 }
1508 }
1509 }
1510
1511 if (buf != NULL) {
1512 count = xmlTextWriterWriteRaw(writer, buf);
1513 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001514 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001515 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001516
Daniel Veillard500a1de2004-03-22 15:22:58 +00001517 if (buf != content) /* buf was allocated by us, so free it */
1518 xmlFree(buf);
William M. Bracka9c612c2004-02-01 10:04:05 +00001519 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001520
1521 return sum;
1522}
1523
1524/**
1525 * xmlOutputBufferWriteBase64:
1526 * @out: the xmlOutputBufferPtr
1527 * @data: binary data
1528 * @len: the number of bytes to encode
1529 *
1530 * Write base64 encoded data to an xmlOutputBuffer.
1531 * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1532 *
1533 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1534 */
1535static int
1536xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1537 const unsigned char *data)
1538{
1539 static unsigned char dtable[64] =
William M. Brack47a31882004-09-11 16:09:09 +00001540 {'A','B','C','D','E','F','G','H','I','J','K','L','M',
1541 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1542 'a','b','c','d','e','f','g','h','i','j','k','l','m',
1543 'n','o','p','q','r','s','t','u','v','w','x','y','z',
1544 '0','1','2','3','4','5','6','7','8','9','+','/'};
1545
Daniel Veillard1d211e22003-10-20 22:32:39 +00001546 int i;
1547 int linelen;
1548 int count;
1549 int sum;
1550
Daniel Veillarde43cc572004-11-03 11:50:29 +00001551 if ((out == NULL) || (len < 0) || (data == NULL))
1552 return(-1);
1553
Daniel Veillard1d211e22003-10-20 22:32:39 +00001554 linelen = 0;
1555 sum = 0;
1556
1557 i = 0;
1558 while (1) {
1559 unsigned char igroup[3];
1560 unsigned char ogroup[4];
1561 int c;
1562 int n;
1563
1564 igroup[0] = igroup[1] = igroup[2] = 0;
1565 for (n = 0; n < 3 && i < len; n++, i++) {
1566 c = data[i];
1567 igroup[n] = (unsigned char) c;
1568 }
1569
1570 if (n > 0) {
1571 ogroup[0] = dtable[igroup[0] >> 2];
1572 ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1573 ogroup[2] =
1574 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1575 ogroup[3] = dtable[igroup[2] & 0x3F];
1576
1577 if (n < 3) {
1578 ogroup[3] = '=';
1579 if (n < 2) {
1580 ogroup[2] = '=';
1581 }
1582 }
1583
1584 if (linelen >= B64LINELEN) {
1585 count = xmlOutputBufferWrite(out, 2, B64CRLF);
1586 if (count == -1)
1587 return -1;
1588 sum += count;
1589 linelen = 0;
1590 }
1591 count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1592 if (count == -1)
1593 return -1;
1594 sum += count;
1595
1596 linelen += 4;
1597 }
Daniel Veillard929714b2003-10-22 12:34:36 +00001598
1599 if (i >= len)
1600 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001601 }
1602
Daniel Veillard1d211e22003-10-20 22:32:39 +00001603 return sum;
1604}
1605
1606/**
1607 * xmlTextWriterWriteBase64:
1608 * @writer: the xmlTextWriterPtr
1609 * @data: binary data
1610 * @start: the position within the data of the first byte to encode
1611 * @len: the number of bytes to encode
1612 *
1613 * Write an base64 encoded xml text.
1614 *
1615 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1616 */
1617int
Daniel Veillardab69f362004-02-17 11:40:32 +00001618xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001619 int start, int len)
1620{
1621 int count;
1622 int sum;
1623 xmlLinkPtr lk;
1624 xmlTextWriterStackEntry *p;
1625
Daniel Veillarde43cc572004-11-03 11:50:29 +00001626 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001627 return -1;
1628
Daniel Veillard1d211e22003-10-20 22:32:39 +00001629 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001630 lk = xmlListFront(writer->nodes);
1631 if (lk != 0) {
1632 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1633 if (p != 0) {
1634 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001635 if (count < 0)
1636 return -1;
1637 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001638 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001639 }
1640
Daniel Veillardab69f362004-02-17 11:40:32 +00001641 if (writer->indent)
1642 writer->doindent = 0;
1643
Daniel Veillard1d211e22003-10-20 22:32:39 +00001644 count =
1645 xmlOutputBufferWriteBase64(writer->out, len,
1646 (unsigned char *) data + start);
1647 if (count < 0)
1648 return -1;
1649 sum += count;
1650
1651 return sum;
1652}
1653
1654/**
1655 * xmlOutputBufferWriteBinHex:
1656 * @out: the xmlOutputBufferPtr
1657 * @data: binary data
1658 * @len: the number of bytes to encode
1659 *
1660 * Write hqx encoded data to an xmlOutputBuffer.
1661 * ::todo
1662 *
William M. Brack47a31882004-09-11 16:09:09 +00001663 * Returns the bytes written (may be 0 because of buffering)
1664 * or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +00001665 */
1666static int
Daniel Veillardab69f362004-02-17 11:40:32 +00001667xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1668 int len, const unsigned char *data)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001669{
Daniel Veillardab69f362004-02-17 11:40:32 +00001670 int count;
1671 int sum;
William M. Brack47a31882004-09-11 16:09:09 +00001672 static char hex[16] =
1673 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
Daniel Veillardab69f362004-02-17 11:40:32 +00001674 int i;
1675
Daniel Veillarde43cc572004-11-03 11:50:29 +00001676 if ((out == NULL) || (data == NULL) || (len < 0)) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001677 return -1;
1678 }
1679
1680 sum = 0;
1681 for (i = 0; i < len; i++) {
1682 count =
1683 xmlOutputBufferWrite(out, 1,
1684 (const char *) &hex[data[i] >> 4]);
1685 if (count == -1)
1686 return -1;
1687 sum += count;
1688 count =
1689 xmlOutputBufferWrite(out, 1,
1690 (const char *) &hex[data[i] & 0xF]);
1691 if (count == -1)
1692 return -1;
1693 sum += count;
1694 }
1695
1696 return sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001697}
1698
1699/**
1700 * xmlTextWriterWriteBinHex:
1701 * @writer: the xmlTextWriterPtr
1702 * @data: binary data
1703 * @start: the position within the data of the first byte to encode
1704 * @len: the number of bytes to encode
1705 *
1706 * Write a BinHex encoded xml text.
1707 *
1708 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1709 */
1710int
Daniel Veillardab69f362004-02-17 11:40:32 +00001711xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001712 int start, int len)
1713{
1714 int count;
1715 int sum;
1716 xmlLinkPtr lk;
1717 xmlTextWriterStackEntry *p;
1718
Daniel Veillarde43cc572004-11-03 11:50:29 +00001719 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001720 return -1;
1721
Daniel Veillard1d211e22003-10-20 22:32:39 +00001722 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001723 lk = xmlListFront(writer->nodes);
1724 if (lk != 0) {
1725 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1726 if (p != 0) {
1727 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001728 if (count < 0)
1729 return -1;
1730 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001731 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001732 }
1733
Daniel Veillardab69f362004-02-17 11:40:32 +00001734 if (writer->indent)
1735 writer->doindent = 0;
1736
Daniel Veillard1d211e22003-10-20 22:32:39 +00001737 count =
1738 xmlOutputBufferWriteBinHex(writer->out, len,
1739 (unsigned char *) data + start);
1740 if (count < 0)
1741 return -1;
1742 sum += count;
1743
1744 return sum;
1745}
1746
1747/**
1748 * xmlTextWriterStartAttribute:
1749 * @writer: the xmlTextWriterPtr
1750 * @name: element name
1751 *
1752 * Start an xml attribute.
1753 *
1754 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1755 */
1756int
1757xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1758{
1759 int count;
1760 int sum;
1761 xmlLinkPtr lk;
1762 xmlTextWriterStackEntry *p;
1763
1764 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1765 return -1;
1766
1767 sum = 0;
1768 lk = xmlListFront(writer->nodes);
1769 if (lk == 0)
1770 return -1;
1771
1772 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1773 if (p == 0)
1774 return -1;
1775
1776 switch (p->state) {
1777 case XML_TEXTWRITER_ATTRIBUTE:
1778 count = xmlTextWriterEndAttribute(writer);
1779 if (count < 0)
1780 return -1;
1781 sum += count;
1782 /* fallthrough */
1783 case XML_TEXTWRITER_NAME:
1784 count = xmlOutputBufferWriteString(writer->out, " ");
1785 if (count < 0)
1786 return -1;
1787 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001788 count =
1789 xmlOutputBufferWriteString(writer->out,
1790 (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001791 if (count < 0)
1792 return -1;
1793 sum += count;
1794 count = xmlOutputBufferWriteString(writer->out, "=");
1795 if (count < 0)
1796 return -1;
1797 sum += count;
1798 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1799 if (count < 0)
1800 return -1;
1801 sum += count;
1802 p->state = XML_TEXTWRITER_ATTRIBUTE;
1803 break;
1804 default:
1805 return -1;
1806 }
1807
1808 return sum;
1809}
1810
1811/**
1812 * xmlTextWriterStartAttributeNS:
1813 * @writer: the xmlTextWriterPtr
1814 * @prefix: namespace prefix or NULL
1815 * @name: element local name
1816 * @namespaceURI: namespace URI or NULL
1817 *
1818 * Start an xml attribute with namespace support.
1819 *
1820 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1821 */
1822int
1823xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1824 const xmlChar * prefix, const xmlChar * name,
1825 const xmlChar * namespaceURI)
1826{
1827 int count;
1828 int sum;
1829 xmlChar *buf;
1830 xmlTextWriterNsStackEntry *p;
1831
1832 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1833 return -1;
1834
Rob Richardsb8769d62007-06-08 08:50:47 +00001835 /* Handle namespace first in case of error */
1836 if (namespaceURI != 0) {
1837 xmlTextWriterNsStackEntry nsentry, *curns;
1838
1839 buf = xmlStrdup(BAD_CAST "xmlns");
1840 if (prefix != 0) {
1841 buf = xmlStrcat(buf, BAD_CAST ":");
1842 buf = xmlStrcat(buf, prefix);
1843 }
1844
1845 nsentry.prefix = buf;
1846 nsentry.uri = (xmlChar *)namespaceURI;
1847 nsentry.elem = xmlListFront(writer->nodes);
1848
1849 curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
1850 (void *)&nsentry);
1851 if ((curns != NULL)) {
1852 xmlFree(buf);
1853 if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
1854 /* Namespace already defined on element skip */
1855 buf = NULL;
1856 } else {
1857 /* Prefix mismatch so error out */
1858 return -1;
1859 }
1860 }
1861
1862 /* Do not add namespace decl to list - it is already there */
1863 if (buf != NULL) {
1864 p = (xmlTextWriterNsStackEntry *)
1865 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1866 if (p == 0) {
1867 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1868 "xmlTextWriterStartAttributeNS : out of memory!\n");
1869 return -1;
1870 }
1871
1872 p->prefix = buf;
1873 p->uri = xmlStrdup(namespaceURI);
1874 if (p->uri == 0) {
1875 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1876 "xmlTextWriterStartAttributeNS : out of memory!\n");
1877 xmlFree(p);
1878 return -1;
1879 }
1880 p->elem = xmlListFront(writer->nodes);
1881
1882 xmlListPushFront(writer->nsstack, p);
1883 }
1884 }
1885
Daniel Veillard75e389d2005-07-29 22:02:24 +00001886 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001887 if (prefix != 0) {
1888 buf = xmlStrdup(prefix);
1889 buf = xmlStrcat(buf, BAD_CAST ":");
1890 }
1891 buf = xmlStrcat(buf, name);
1892
1893 sum = 0;
1894 count = xmlTextWriterStartAttribute(writer, buf);
1895 xmlFree(buf);
1896 if (count < 0)
1897 return -1;
1898 sum += count;
1899
Daniel Veillard1d211e22003-10-20 22:32:39 +00001900 return sum;
1901}
1902
1903/**
1904 * xmlTextWriterEndAttribute:
1905 * @writer: the xmlTextWriterPtr
1906 *
1907 * End the current xml element.
1908 *
1909 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1910 */
1911int
1912xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1913{
1914 int count;
1915 int sum;
1916 xmlLinkPtr lk;
1917 xmlTextWriterStackEntry *p;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001918
1919 if (writer == NULL)
1920 return -1;
1921
1922 lk = xmlListFront(writer->nodes);
1923 if (lk == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001924 return -1;
1925 }
1926
1927 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1928 if (p == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001929 return -1;
1930 }
1931
1932 sum = 0;
1933 switch (p->state) {
1934 case XML_TEXTWRITER_ATTRIBUTE:
1935 p->state = XML_TEXTWRITER_NAME;
1936
1937 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1938 if (count < 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001939 return -1;
1940 }
1941 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001942 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001943 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001944 return -1;
1945 }
1946
1947 return sum;
1948}
1949
1950/**
1951 * xmlTextWriterWriteFormatAttribute:
1952 * @writer: the xmlTextWriterPtr
1953 * @name: attribute name
1954 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001955 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001956 *
1957 * Write a formatted xml attribute.
1958 *
1959 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1960 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001961int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001962xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1963 const xmlChar * name, const char *format,
1964 ...)
1965{
1966 int rc;
1967 va_list ap;
1968
1969 va_start(ap, format);
1970
1971 rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1972
1973 va_end(ap);
1974 return rc;
1975}
1976
1977/**
1978 * xmlTextWriterWriteVFormatAttribute:
1979 * @writer: the xmlTextWriterPtr
1980 * @name: attribute name
1981 * @format: format string (see printf)
1982 * @argptr: pointer to the first member of the variable argument list.
1983 *
1984 * Write a formatted xml attribute.
1985 *
1986 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1987 */
1988int
1989xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
1990 const xmlChar * name,
1991 const char *format, va_list argptr)
1992{
1993 int rc;
1994 xmlChar *buf;
1995
1996 if (writer == NULL)
1997 return -1;
1998
1999 buf = xmlTextWriterVSprintf(format, argptr);
2000 if (buf == 0)
2001 return 0;
2002
2003 rc = xmlTextWriterWriteAttribute(writer, name, buf);
2004
2005 xmlFree(buf);
2006 return rc;
2007}
2008
2009/**
2010 * xmlTextWriterWriteAttribute:
2011 * @writer: the xmlTextWriterPtr
2012 * @name: attribute name
2013 * @content: attribute content
2014 *
2015 * Write an xml attribute.
2016 *
2017 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2018 */
2019int
2020xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
2021 const xmlChar * content)
2022{
2023 int count;
2024 int sum;
2025
2026 sum = 0;
2027 count = xmlTextWriterStartAttribute(writer, name);
2028 if (count < 0)
2029 return -1;
2030 sum += count;
2031 count = xmlTextWriterWriteString(writer, content);
2032 if (count < 0)
2033 return -1;
2034 sum += count;
2035 count = xmlTextWriterEndAttribute(writer);
2036 if (count < 0)
2037 return -1;
2038 sum += count;
2039
2040 return sum;
2041}
2042
2043/**
2044 * xmlTextWriterWriteFormatAttributeNS:
2045 * @writer: the xmlTextWriterPtr
2046 * @prefix: namespace prefix
2047 * @name: attribute local name
2048 * @namespaceURI: namespace URI
2049 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002050 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002051 *
2052 * Write a formatted xml attribute.with namespace support
2053 *
2054 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2055 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002056int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002057xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
2058 const xmlChar * prefix,
2059 const xmlChar * name,
2060 const xmlChar * namespaceURI,
2061 const char *format, ...)
2062{
2063 int rc;
2064 va_list ap;
2065
2066 va_start(ap, format);
2067
2068 rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
2069 namespaceURI, format, ap);
2070
2071 va_end(ap);
2072 return rc;
2073}
2074
2075/**
2076 * xmlTextWriterWriteVFormatAttributeNS:
2077 * @writer: the xmlTextWriterPtr
2078 * @prefix: namespace prefix
2079 * @name: attribute local name
2080 * @namespaceURI: namespace URI
2081 * @format: format string (see printf)
2082 * @argptr: pointer to the first member of the variable argument list.
2083 *
2084 * Write a formatted xml attribute.with namespace support
2085 *
2086 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2087 */
2088int
2089xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
2090 const xmlChar * prefix,
2091 const xmlChar * name,
2092 const xmlChar * namespaceURI,
2093 const char *format, va_list argptr)
2094{
2095 int rc;
2096 xmlChar *buf;
2097
2098 if (writer == NULL)
2099 return -1;
2100
2101 buf = xmlTextWriterVSprintf(format, argptr);
2102 if (buf == 0)
2103 return 0;
2104
2105 rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
2106 buf);
2107
2108 xmlFree(buf);
2109 return rc;
2110}
2111
2112/**
2113 * xmlTextWriterWriteAttributeNS:
2114 * @writer: the xmlTextWriterPtr
2115 * @prefix: namespace prefix
2116 * @name: attribute local name
2117 * @namespaceURI: namespace URI
2118 * @content: attribute content
2119 *
2120 * Write an xml attribute.
2121 *
2122 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2123 */
2124int
2125xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
2126 const xmlChar * prefix, const xmlChar * name,
2127 const xmlChar * namespaceURI,
2128 const xmlChar * content)
2129{
2130 int count;
2131 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002132
2133 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2134 return -1;
2135
Daniel Veillard1d211e22003-10-20 22:32:39 +00002136 sum = 0;
Rob Richardsb8769d62007-06-08 08:50:47 +00002137 count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
2138 if (count < 0)
2139 return -1;
2140 sum += count;
2141 count = xmlTextWriterWriteString(writer, content);
2142 if (count < 0)
2143 return -1;
2144 sum += count;
2145 count = xmlTextWriterEndAttribute(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002146 if (count < 0)
2147 return -1;
2148 sum += count;
2149
Daniel Veillard1d211e22003-10-20 22:32:39 +00002150 return sum;
2151}
2152
2153/**
2154 * xmlTextWriterWriteFormatElement:
2155 * @writer: the xmlTextWriterPtr
2156 * @name: element name
2157 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002158 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002159 *
2160 * Write a formatted xml element.
2161 *
2162 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2163 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002164int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002165xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2166 const xmlChar * name, const char *format,
2167 ...)
2168{
2169 int rc;
2170 va_list ap;
2171
2172 va_start(ap, format);
2173
2174 rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2175
2176 va_end(ap);
2177 return rc;
2178}
2179
2180/**
2181 * xmlTextWriterWriteVFormatElement:
2182 * @writer: the xmlTextWriterPtr
2183 * @name: element name
2184 * @format: format string (see printf)
2185 * @argptr: pointer to the first member of the variable argument list.
2186 *
2187 * Write a formatted xml element.
2188 *
2189 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2190 */
2191int
2192xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2193 const xmlChar * name, const char *format,
2194 va_list argptr)
2195{
2196 int rc;
2197 xmlChar *buf;
2198
2199 if (writer == NULL)
2200 return -1;
2201
2202 buf = xmlTextWriterVSprintf(format, argptr);
2203 if (buf == 0)
2204 return 0;
2205
2206 rc = xmlTextWriterWriteElement(writer, name, buf);
2207
2208 xmlFree(buf);
2209 return rc;
2210}
2211
2212/**
2213 * xmlTextWriterWriteElement:
2214 * @writer: the xmlTextWriterPtr
2215 * @name: element name
2216 * @content: element content
2217 *
2218 * Write an xml element.
2219 *
2220 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2221 */
2222int
2223xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2224 const xmlChar * content)
2225{
2226 int count;
2227 int sum;
2228
2229 sum = 0;
2230 count = xmlTextWriterStartElement(writer, name);
2231 if (count == -1)
2232 return -1;
2233 sum += count;
2234 count = xmlTextWriterWriteString(writer, content);
2235 if (count == -1)
2236 return -1;
2237 sum += count;
2238 count = xmlTextWriterEndElement(writer);
2239 if (count == -1)
2240 return -1;
2241 sum += count;
2242
2243 return sum;
2244}
2245
2246/**
2247 * xmlTextWriterWriteFormatElementNS:
2248 * @writer: the xmlTextWriterPtr
2249 * @prefix: namespace prefix
2250 * @name: element local name
2251 * @namespaceURI: namespace URI
2252 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002253 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002254 *
2255 * Write a formatted xml element with namespace support.
2256 *
2257 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2258 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002259int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002260xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2261 const xmlChar * prefix,
2262 const xmlChar * name,
2263 const xmlChar * namespaceURI,
2264 const char *format, ...)
2265{
2266 int rc;
2267 va_list ap;
2268
2269 va_start(ap, format);
2270
2271 rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2272 namespaceURI, format, ap);
2273
2274 va_end(ap);
2275 return rc;
2276}
2277
2278/**
2279 * xmlTextWriterWriteVFormatElementNS:
2280 * @writer: the xmlTextWriterPtr
2281 * @prefix: namespace prefix
2282 * @name: element local name
2283 * @namespaceURI: namespace URI
2284 * @format: format string (see printf)
2285 * @argptr: pointer to the first member of the variable argument list.
2286 *
2287 * Write a formatted xml element with namespace support.
2288 *
2289 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2290 */
2291int
2292xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2293 const xmlChar * prefix,
2294 const xmlChar * name,
2295 const xmlChar * namespaceURI,
2296 const char *format, va_list argptr)
2297{
2298 int rc;
2299 xmlChar *buf;
2300
2301 if (writer == NULL)
2302 return -1;
2303
2304 buf = xmlTextWriterVSprintf(format, argptr);
2305 if (buf == 0)
2306 return 0;
2307
2308 rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2309 buf);
2310
2311 xmlFree(buf);
2312 return rc;
2313}
2314
2315/**
2316 * xmlTextWriterWriteElementNS:
2317 * @writer: the xmlTextWriterPtr
2318 * @prefix: namespace prefix
2319 * @name: element local name
2320 * @namespaceURI: namespace URI
2321 * @content: element content
2322 *
2323 * Write an xml element with namespace support.
2324 *
2325 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2326 */
2327int
2328xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2329 const xmlChar * prefix, const xmlChar * name,
2330 const xmlChar * namespaceURI,
2331 const xmlChar * content)
2332{
2333 int count;
2334 int sum;
2335
2336 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2337 return -1;
2338
2339 sum = 0;
2340 count =
2341 xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2342 if (count < 0)
2343 return -1;
2344 sum += count;
2345 count = xmlTextWriterWriteString(writer, content);
2346 if (count == -1)
2347 return -1;
2348 sum += count;
2349 count = xmlTextWriterEndElement(writer);
2350 if (count == -1)
2351 return -1;
2352 sum += count;
2353
2354 return sum;
2355}
2356
2357/**
2358 * xmlTextWriterStartPI:
2359 * @writer: the xmlTextWriterPtr
2360 * @target: PI target
2361 *
2362 * Start an xml PI.
2363 *
2364 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2365 */
2366int
2367xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2368{
2369 int count;
2370 int sum;
2371 xmlLinkPtr lk;
2372 xmlTextWriterStackEntry *p;
2373
2374 if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2375 return -1;
2376
2377 if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002378 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002379 "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2380 return -1;
2381 }
2382
2383 sum = 0;
2384 lk = xmlListFront(writer->nodes);
2385 if (lk != 0) {
2386 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2387 if (p != 0) {
2388 switch (p->state) {
2389 case XML_TEXTWRITER_ATTRIBUTE:
2390 count = xmlTextWriterEndAttribute(writer);
2391 if (count < 0)
2392 return -1;
2393 sum += count;
2394 /* fallthrough */
2395 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002396 /* Output namespace declarations */
2397 count = xmlTextWriterOutputNSDecl(writer);
2398 if (count < 0)
2399 return -1;
2400 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002401 count = xmlOutputBufferWriteString(writer->out, ">");
2402 if (count < 0)
2403 return -1;
2404 sum += count;
2405 p->state = XML_TEXTWRITER_TEXT;
2406 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00002407 case XML_TEXTWRITER_NONE:
2408 case XML_TEXTWRITER_TEXT:
2409 case XML_TEXTWRITER_DTD:
2410 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002411 case XML_TEXTWRITER_PI:
2412 case XML_TEXTWRITER_PI_TEXT:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002413 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002414 "xmlTextWriterStartPI : nested PI!\n");
2415 return -1;
2416 default:
2417 return -1;
2418 }
2419 }
2420 }
2421
2422 p = (xmlTextWriterStackEntry *)
2423 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2424 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002425 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002426 "xmlTextWriterStartPI : out of memory!\n");
2427 return -1;
2428 }
2429
2430 p->name = xmlStrdup(target);
2431 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002432 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002433 "xmlTextWriterStartPI : out of memory!\n");
2434 xmlFree(p);
2435 return -1;
2436 }
2437 p->state = XML_TEXTWRITER_PI;
2438
2439 xmlListPushFront(writer->nodes, p);
2440
2441 count = xmlOutputBufferWriteString(writer->out, "<?");
2442 if (count < 0)
2443 return -1;
2444 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002445 count =
2446 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002447 if (count < 0)
2448 return -1;
2449 sum += count;
2450
2451 return sum;
2452}
2453
2454/**
2455 * xmlTextWriterEndPI:
2456 * @writer: the xmlTextWriterPtr
2457 *
2458 * End the current xml PI.
2459 *
2460 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2461 */
2462int
2463xmlTextWriterEndPI(xmlTextWriterPtr writer)
2464{
2465 int count;
2466 int sum;
2467 xmlLinkPtr lk;
2468 xmlTextWriterStackEntry *p;
2469
2470 if (writer == NULL)
2471 return -1;
2472
2473 lk = xmlListFront(writer->nodes);
2474 if (lk == 0)
2475 return 0;
2476
2477 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2478 if (p == 0)
2479 return 0;
2480
2481 sum = 0;
2482 switch (p->state) {
2483 case XML_TEXTWRITER_PI:
2484 case XML_TEXTWRITER_PI_TEXT:
2485 count = xmlOutputBufferWriteString(writer->out, "?>");
2486 if (count < 0)
2487 return -1;
2488 sum += count;
2489 break;
2490 default:
2491 return -1;
2492 }
2493
Daniel Veillard02c1f232006-04-27 08:10:25 +00002494 if (writer->indent) {
2495 count = xmlOutputBufferWriteString(writer->out, "\n");
2496 if (count < 0)
2497 return -1;
2498 sum += count;
2499 }
2500
Daniel Veillard1d211e22003-10-20 22:32:39 +00002501 xmlListPopFront(writer->nodes);
2502 return sum;
2503}
2504
2505/**
2506 * xmlTextWriterWriteFormatPI:
2507 * @writer: the xmlTextWriterPtr
2508 * @target: PI target
2509 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002510 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002511 *
2512 * Write a formatted PI.
2513 *
2514 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2515 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002516int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002517xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2518 const char *format, ...)
2519{
2520 int rc;
2521 va_list ap;
2522
2523 va_start(ap, format);
2524
2525 rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2526
2527 va_end(ap);
2528 return rc;
2529}
2530
2531/**
2532 * xmlTextWriterWriteVFormatPI:
2533 * @writer: the xmlTextWriterPtr
2534 * @target: PI target
2535 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002536 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002537 *
2538 * Write a formatted xml PI.
2539 *
2540 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2541 */
2542int
2543xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2544 const xmlChar * target, const char *format,
2545 va_list argptr)
2546{
2547 int rc;
2548 xmlChar *buf;
2549
2550 if (writer == NULL)
2551 return -1;
2552
2553 buf = xmlTextWriterVSprintf(format, argptr);
2554 if (buf == 0)
2555 return 0;
2556
2557 rc = xmlTextWriterWritePI(writer, target, buf);
2558
2559 xmlFree(buf);
2560 return rc;
2561}
2562
2563/**
2564 * xmlTextWriterWritePI:
2565 * @writer: the xmlTextWriterPtr
2566 * @target: PI target
2567 * @content: PI content
2568 *
2569 * Write an xml PI.
2570 *
2571 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2572 */
2573int
2574xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2575 const xmlChar * content)
2576{
2577 int count;
2578 int sum;
2579
2580 sum = 0;
2581 count = xmlTextWriterStartPI(writer, target);
2582 if (count == -1)
2583 return -1;
2584 sum += count;
2585 if (content != 0) {
2586 count = xmlTextWriterWriteString(writer, content);
2587 if (count == -1)
2588 return -1;
2589 sum += count;
2590 }
2591 count = xmlTextWriterEndPI(writer);
2592 if (count == -1)
2593 return -1;
2594 sum += count;
2595
2596 return sum;
2597}
2598
2599/**
2600 * xmlTextWriterStartCDATA:
2601 * @writer: the xmlTextWriterPtr
2602 *
2603 * Start an xml CDATA section.
2604 *
2605 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2606 */
2607int
2608xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2609{
2610 int count;
2611 int sum;
2612 xmlLinkPtr lk;
2613 xmlTextWriterStackEntry *p;
2614
2615 if (writer == NULL)
2616 return -1;
2617
2618 sum = 0;
2619 lk = xmlListFront(writer->nodes);
2620 if (lk != 0) {
2621 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2622 if (p != 0) {
2623 switch (p->state) {
2624 case XML_TEXTWRITER_NONE:
Daniel Veillardccc476f2008-03-04 13:19:49 +00002625 case XML_TEXTWRITER_TEXT:
Daniel Veillard1d211e22003-10-20 22:32:39 +00002626 case XML_TEXTWRITER_PI:
2627 case XML_TEXTWRITER_PI_TEXT:
2628 break;
2629 case XML_TEXTWRITER_ATTRIBUTE:
2630 count = xmlTextWriterEndAttribute(writer);
2631 if (count < 0)
2632 return -1;
2633 sum += count;
2634 /* fallthrough */
2635 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002636 /* Output namespace declarations */
2637 count = xmlTextWriterOutputNSDecl(writer);
2638 if (count < 0)
2639 return -1;
2640 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002641 count = xmlOutputBufferWriteString(writer->out, ">");
2642 if (count < 0)
2643 return -1;
2644 sum += count;
2645 p->state = XML_TEXTWRITER_TEXT;
2646 break;
2647 case XML_TEXTWRITER_CDATA:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002648 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002649 "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2650 return -1;
2651 default:
2652 return -1;
2653 }
2654 }
2655 }
2656
2657 p = (xmlTextWriterStackEntry *)
2658 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2659 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002660 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002661 "xmlTextWriterStartCDATA : out of memory!\n");
2662 return -1;
2663 }
2664
Daniel Veillard75e389d2005-07-29 22:02:24 +00002665 p->name = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002666 p->state = XML_TEXTWRITER_CDATA;
2667
2668 xmlListPushFront(writer->nodes, p);
2669
2670 count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2671 if (count < 0)
2672 return -1;
2673 sum += count;
2674
2675 return sum;
2676}
2677
2678/**
2679 * xmlTextWriterEndCDATA:
2680 * @writer: the xmlTextWriterPtr
2681 *
2682 * End an xml CDATA section.
2683 *
2684 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2685 */
2686int
2687xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2688{
2689 int count;
2690 int sum;
2691 xmlLinkPtr lk;
2692 xmlTextWriterStackEntry *p;
2693
2694 if (writer == NULL)
2695 return -1;
2696
2697 lk = xmlListFront(writer->nodes);
2698 if (lk == 0)
2699 return -1;
2700
2701 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2702 if (p == 0)
2703 return -1;
2704
2705 sum = 0;
2706 switch (p->state) {
2707 case XML_TEXTWRITER_CDATA:
2708 count = xmlOutputBufferWriteString(writer->out, "]]>");
2709 if (count < 0)
2710 return -1;
2711 sum += count;
2712 break;
2713 default:
2714 return -1;
2715 }
2716
2717 xmlListPopFront(writer->nodes);
2718 return sum;
2719}
2720
2721/**
2722 * xmlTextWriterWriteFormatCDATA:
2723 * @writer: the xmlTextWriterPtr
2724 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002725 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002726 *
2727 * Write a formatted xml CDATA.
2728 *
2729 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2730 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002731int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002732xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2733 ...)
2734{
2735 int rc;
2736 va_list ap;
2737
2738 va_start(ap, format);
2739
2740 rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2741
2742 va_end(ap);
2743 return rc;
2744}
2745
2746/**
2747 * xmlTextWriterWriteVFormatCDATA:
2748 * @writer: the xmlTextWriterPtr
2749 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002750 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002751 *
2752 * Write a formatted xml CDATA.
2753 *
2754 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2755 */
2756int
2757xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2758 va_list argptr)
2759{
2760 int rc;
2761 xmlChar *buf;
2762
2763 if (writer == NULL)
2764 return -1;
2765
2766 buf = xmlTextWriterVSprintf(format, argptr);
2767 if (buf == 0)
2768 return 0;
2769
2770 rc = xmlTextWriterWriteCDATA(writer, buf);
2771
2772 xmlFree(buf);
2773 return rc;
2774}
2775
2776/**
2777 * xmlTextWriterWriteCDATA:
2778 * @writer: the xmlTextWriterPtr
2779 * @content: CDATA content
2780 *
2781 * Write an xml CDATA.
2782 *
2783 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2784 */
2785int
2786xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2787{
2788 int count;
2789 int sum;
2790
2791 sum = 0;
2792 count = xmlTextWriterStartCDATA(writer);
2793 if (count == -1)
2794 return -1;
2795 sum += count;
2796 if (content != 0) {
2797 count = xmlTextWriterWriteString(writer, content);
2798 if (count == -1)
2799 return -1;
2800 sum += count;
2801 }
2802 count = xmlTextWriterEndCDATA(writer);
2803 if (count == -1)
2804 return -1;
2805 sum += count;
2806
2807 return sum;
2808}
2809
2810/**
2811 * xmlTextWriterStartDTD:
2812 * @writer: the xmlTextWriterPtr
2813 * @name: the name of the DTD
2814 * @pubid: the public identifier, which is an alternative to the system identifier
2815 * @sysid: the system identifier, which is the URI of the DTD
2816 *
2817 * Start an xml DTD.
2818 *
2819 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2820 */
2821int
2822xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2823 const xmlChar * name,
2824 const xmlChar * pubid, const xmlChar * sysid)
2825{
2826 int count;
2827 int sum;
2828 xmlLinkPtr lk;
2829 xmlTextWriterStackEntry *p;
2830
2831 if (writer == NULL || name == NULL || *name == '\0')
2832 return -1;
2833
2834 sum = 0;
2835 lk = xmlListFront(writer->nodes);
Daniel Veillardab69f362004-02-17 11:40:32 +00002836 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002837 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002838 "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2839 return -1;
2840 }
2841
2842 p = (xmlTextWriterStackEntry *)
2843 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2844 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002845 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002846 "xmlTextWriterStartDTD : out of memory!\n");
2847 return -1;
2848 }
2849
2850 p->name = xmlStrdup(name);
2851 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002852 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002853 "xmlTextWriterStartDTD : out of memory!\n");
2854 xmlFree(p);
2855 return -1;
2856 }
2857 p->state = XML_TEXTWRITER_DTD;
2858
2859 xmlListPushFront(writer->nodes, p);
2860
2861 count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2862 if (count < 0)
2863 return -1;
2864 sum += count;
2865 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2866 if (count < 0)
2867 return -1;
2868 sum += count;
2869
2870 if (pubid != 0) {
2871 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002872 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002873 "xmlTextWriterStartDTD : system identifier needed!\n");
2874 return -1;
2875 }
2876
Daniel Veillard500a1de2004-03-22 15:22:58 +00002877 if (writer->indent)
2878 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2879 else
2880 count = xmlOutputBufferWrite(writer->out, 1, " ");
2881 if (count < 0)
2882 return -1;
2883 sum += count;
2884
2885 count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2886 if (count < 0)
2887 return -1;
2888 sum += count;
2889
2890 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002891 if (count < 0)
2892 return -1;
2893 sum += count;
2894
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002895 count =
2896 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002897 if (count < 0)
2898 return -1;
2899 sum += count;
2900
Daniel Veillard500a1de2004-03-22 15:22:58 +00002901 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002902 if (count < 0)
2903 return -1;
2904 sum += count;
2905 }
2906
2907 if (sysid != 0) {
2908 if (pubid == 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00002909 if (writer->indent)
2910 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2911 else
2912 count = xmlOutputBufferWrite(writer->out, 1, " ");
2913 if (count < 0)
2914 return -1;
2915 sum += count;
2916 count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2917 if (count < 0)
2918 return -1;
2919 sum += count;
Rob Richardsffe47fe2005-12-09 17:52:21 +00002920 } else {
2921 if (writer->indent)
Daniel Veillard500a1de2004-03-22 15:22:58 +00002922 count = xmlOutputBufferWriteString(writer->out, "\n ");
Rob Richardsffe47fe2005-12-09 17:52:21 +00002923 else
2924 count = xmlOutputBufferWrite(writer->out, 1, " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00002925 if (count < 0)
2926 return -1;
2927 sum += count;
2928 }
2929
Daniel Veillard500a1de2004-03-22 15:22:58 +00002930 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002931 if (count < 0)
2932 return -1;
2933 sum += count;
2934
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002935 count =
2936 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002937 if (count < 0)
2938 return -1;
2939 sum += count;
2940
Daniel Veillard500a1de2004-03-22 15:22:58 +00002941 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002942 if (count < 0)
2943 return -1;
2944 sum += count;
2945 }
2946
2947 return sum;
2948}
2949
2950/**
2951 * xmlTextWriterEndDTD:
2952 * @writer: the xmlTextWriterPtr
2953 *
2954 * End an xml DTD.
2955 *
2956 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2957 */
2958int
2959xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2960{
Daniel Veillard500a1de2004-03-22 15:22:58 +00002961 int loop;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002962 int count;
2963 int sum;
2964 xmlLinkPtr lk;
2965 xmlTextWriterStackEntry *p;
2966
2967 if (writer == NULL)
2968 return -1;
2969
2970 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002971 loop = 1;
2972 while (loop) {
2973 lk = xmlListFront(writer->nodes);
2974 if (lk == NULL)
Daniel Veillard1d211e22003-10-20 22:32:39 +00002975 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002976 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2977 if (p == 0)
2978 break;
2979 switch (p->state) {
2980 case XML_TEXTWRITER_DTD_TEXT:
2981 count = xmlOutputBufferWriteString(writer->out, "]");
2982 if (count < 0)
2983 return -1;
2984 sum += count;
2985 /* fallthrough */
2986 case XML_TEXTWRITER_DTD:
2987 count = xmlOutputBufferWriteString(writer->out, ">");
2988
2989 if (writer->indent) {
2990 if (count < 0)
2991 return -1;
2992 sum += count;
2993 count = xmlOutputBufferWriteString(writer->out, "\n");
2994 }
2995
2996 xmlListPopFront(writer->nodes);
2997 break;
2998 case XML_TEXTWRITER_DTD_ELEM:
2999 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3000 count = xmlTextWriterEndDTDElement(writer);
3001 break;
3002 case XML_TEXTWRITER_DTD_ATTL:
3003 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3004 count = xmlTextWriterEndDTDAttlist(writer);
3005 break;
3006 case XML_TEXTWRITER_DTD_ENTY:
3007 case XML_TEXTWRITER_DTD_PENT:
3008 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3009 count = xmlTextWriterEndDTDEntity(writer);
3010 break;
3011 case XML_TEXTWRITER_COMMENT:
3012 count = xmlTextWriterEndComment(writer);
3013 break;
3014 default:
3015 loop = 0;
3016 continue;
3017 }
3018
3019 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00003020 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003021 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003022 }
3023
Daniel Veillard1d211e22003-10-20 22:32:39 +00003024 return sum;
3025}
3026
3027/**
3028 * xmlTextWriterWriteFormatDTD:
3029 * @writer: the xmlTextWriterPtr
3030 * @name: the name of the DTD
3031 * @pubid: the public identifier, which is an alternative to the system identifier
3032 * @sysid: the system identifier, which is the URI of the DTD
3033 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003034 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00003035 *
3036 * Write a DTD with a formatted markup declarations part.
3037 *
3038 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3039 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003040int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003041xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3042 const xmlChar * name,
3043 const xmlChar * pubid,
3044 const xmlChar * sysid, const char *format, ...)
3045{
3046 int rc;
3047 va_list ap;
3048
3049 va_start(ap, format);
3050
3051 rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3052 ap);
3053
3054 va_end(ap);
3055 return rc;
3056}
3057
3058/**
3059 * xmlTextWriterWriteVFormatDTD:
3060 * @writer: the xmlTextWriterPtr
3061 * @name: the name of the DTD
3062 * @pubid: the public identifier, which is an alternative to the system identifier
3063 * @sysid: the system identifier, which is the URI of the DTD
3064 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003065 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00003066 *
3067 * Write a DTD with a formatted markup declarations part.
3068 *
3069 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3070 */
3071int
3072xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3073 const xmlChar * name,
3074 const xmlChar * pubid,
3075 const xmlChar * sysid,
3076 const char *format, va_list argptr)
3077{
3078 int rc;
3079 xmlChar *buf;
3080
3081 if (writer == NULL)
3082 return -1;
3083
3084 buf = xmlTextWriterVSprintf(format, argptr);
3085 if (buf == 0)
3086 return 0;
3087
3088 rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3089
3090 xmlFree(buf);
3091 return rc;
3092}
3093
3094/**
3095 * xmlTextWriterWriteDTD:
3096 * @writer: the xmlTextWriterPtr
3097 * @name: the name of the DTD
3098 * @pubid: the public identifier, which is an alternative to the system identifier
3099 * @sysid: the system identifier, which is the URI of the DTD
William M. Brackb1d53162003-11-18 06:54:40 +00003100 * @subset: string content of the DTD
Daniel Veillard1d211e22003-10-20 22:32:39 +00003101 *
3102 * Write a DTD.
3103 *
3104 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3105 */
3106int
3107xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3108 const xmlChar * name,
3109 const xmlChar * pubid,
3110 const xmlChar * sysid, const xmlChar * subset)
3111{
3112 int count;
3113 int sum;
3114
3115 sum = 0;
3116 count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3117 if (count == -1)
3118 return -1;
3119 sum += count;
3120 if (subset != 0) {
3121 count = xmlTextWriterWriteString(writer, subset);
3122 if (count == -1)
3123 return -1;
3124 sum += count;
3125 }
3126 count = xmlTextWriterEndDTD(writer);
3127 if (count == -1)
3128 return -1;
3129 sum += count;
3130
3131 return sum;
3132}
3133
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003134/**
3135 * xmlTextWriterStartDTDElement:
3136 * @writer: the xmlTextWriterPtr
3137 * @name: the name of the DTD element
3138 *
3139 * Start an xml DTD element.
3140 *
3141 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3142 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003143int
3144xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3145{
3146 int count;
3147 int sum;
3148 xmlLinkPtr lk;
3149 xmlTextWriterStackEntry *p;
3150
3151 if (writer == NULL || name == NULL || *name == '\0')
3152 return -1;
3153
3154 sum = 0;
3155 lk = xmlListFront(writer->nodes);
3156 if (lk == 0) {
3157 return -1;
3158 }
3159
3160 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003161 if (p != 0) {
3162 switch (p->state) {
3163 case XML_TEXTWRITER_DTD:
3164 count = xmlOutputBufferWriteString(writer->out, " [");
3165 if (count < 0)
3166 return -1;
3167 sum += count;
3168 if (writer->indent) {
3169 count = xmlOutputBufferWriteString(writer->out, "\n");
3170 if (count < 0)
3171 return -1;
3172 sum += count;
3173 }
3174 p->state = XML_TEXTWRITER_DTD_TEXT;
3175 /* fallthrough */
3176 case XML_TEXTWRITER_DTD_TEXT:
3177 case XML_TEXTWRITER_NONE:
3178 break;
3179 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003180 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003181 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003182 }
3183
3184 p = (xmlTextWriterStackEntry *)
3185 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3186 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003187 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003188 "xmlTextWriterStartDTDElement : out of memory!\n");
3189 return -1;
3190 }
3191
3192 p->name = xmlStrdup(name);
3193 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003194 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003195 "xmlTextWriterStartDTDElement : out of memory!\n");
3196 xmlFree(p);
3197 return -1;
3198 }
3199 p->state = XML_TEXTWRITER_DTD_ELEM;
3200
3201 xmlListPushFront(writer->nodes, p);
3202
Daniel Veillard500a1de2004-03-22 15:22:58 +00003203 if (writer->indent) {
3204 count = xmlTextWriterWriteIndent(writer);
3205 if (count < 0)
3206 return -1;
3207 sum += count;
3208 }
3209
Daniel Veillard1d211e22003-10-20 22:32:39 +00003210 count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3211 if (count < 0)
3212 return -1;
3213 sum += count;
3214 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3215 if (count < 0)
3216 return -1;
3217 sum += count;
3218
3219 return sum;
3220}
3221
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003222/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003223 * xmlTextWriterEndDTDElement:
3224 * @writer: the xmlTextWriterPtr
3225 *
3226 * End an xml DTD element.
3227 *
3228 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3229 */
3230int
3231xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3232{
3233 int count;
3234 int sum;
3235 xmlLinkPtr lk;
3236 xmlTextWriterStackEntry *p;
3237
3238 if (writer == NULL)
3239 return -1;
3240
3241 sum = 0;
3242 lk = xmlListFront(writer->nodes);
3243 if (lk == 0)
3244 return -1;
3245
3246 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3247 if (p == 0)
3248 return -1;
3249
3250 switch (p->state) {
3251 case XML_TEXTWRITER_DTD_ELEM:
3252 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3253 count = xmlOutputBufferWriteString(writer->out, ">");
3254 if (count < 0)
3255 return -1;
3256 sum += count;
3257 break;
3258 default:
3259 return -1;
3260 }
3261
3262 if (writer->indent) {
3263 count = xmlOutputBufferWriteString(writer->out, "\n");
3264 if (count < 0)
3265 return -1;
3266 sum += count;
3267 }
3268
3269 xmlListPopFront(writer->nodes);
3270 return sum;
3271}
3272
3273/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003274 * xmlTextWriterWriteFormatDTDElement:
3275 * @writer: the xmlTextWriterPtr
3276 * @name: the name of the DTD element
3277 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003278 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003279 *
3280 * Write a formatted DTD element.
3281 *
3282 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3283 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003284int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003285xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3286 const xmlChar * name,
3287 const char *format, ...)
3288{
3289 int rc;
3290 va_list ap;
3291
3292 va_start(ap, format);
3293
3294 rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3295
3296 va_end(ap);
3297 return rc;
3298}
3299
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003300/**
3301 * xmlTextWriterWriteVFormatDTDElement:
3302 * @writer: the xmlTextWriterPtr
3303 * @name: the name of the DTD element
3304 * @format: format string (see printf)
3305 * @argptr: pointer to the first member of the variable argument list.
3306 *
3307 * Write a formatted DTD element.
3308 *
3309 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3310 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003311int
3312xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3313 const xmlChar * name,
3314 const char *format, va_list argptr)
3315{
3316 int rc;
3317 xmlChar *buf;
3318
3319 if (writer == NULL)
3320 return -1;
3321
3322 buf = xmlTextWriterVSprintf(format, argptr);
3323 if (buf == 0)
3324 return 0;
3325
3326 rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3327
3328 xmlFree(buf);
3329 return rc;
3330}
3331
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003332/**
3333 * xmlTextWriterWriteDTDElement:
3334 * @writer: the xmlTextWriterPtr
3335 * @name: the name of the DTD element
3336 * @content: content of the element
3337 *
3338 * Write a DTD element.
3339 *
3340 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3341 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003342int
3343xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3344 const xmlChar * name, const xmlChar * content)
3345{
3346 int count;
3347 int sum;
3348
3349 if (content == NULL)
3350 return -1;
3351
3352 sum = 0;
3353 count = xmlTextWriterStartDTDElement(writer, name);
3354 if (count == -1)
3355 return -1;
3356 sum += count;
3357
Daniel Veillard1d211e22003-10-20 22:32:39 +00003358 count = xmlTextWriterWriteString(writer, content);
3359 if (count == -1)
3360 return -1;
3361 sum += count;
3362
3363 count = xmlTextWriterEndDTDElement(writer);
3364 if (count == -1)
3365 return -1;
3366 sum += count;
3367
3368 return sum;
3369}
3370
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003371/**
3372 * xmlTextWriterStartDTDAttlist:
3373 * @writer: the xmlTextWriterPtr
3374 * @name: the name of the DTD ATTLIST
3375 *
3376 * Start an xml DTD ATTLIST.
3377 *
3378 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3379 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003380int
3381xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3382{
3383 int count;
3384 int sum;
3385 xmlLinkPtr lk;
3386 xmlTextWriterStackEntry *p;
3387
3388 if (writer == NULL || name == NULL || *name == '\0')
3389 return -1;
3390
3391 sum = 0;
3392 lk = xmlListFront(writer->nodes);
3393 if (lk == 0) {
3394 return -1;
3395 }
3396
3397 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003398 if (p != 0) {
3399 switch (p->state) {
3400 case XML_TEXTWRITER_DTD:
3401 count = xmlOutputBufferWriteString(writer->out, " [");
3402 if (count < 0)
3403 return -1;
3404 sum += count;
3405 if (writer->indent) {
3406 count = xmlOutputBufferWriteString(writer->out, "\n");
3407 if (count < 0)
3408 return -1;
3409 sum += count;
3410 }
3411 p->state = XML_TEXTWRITER_DTD_TEXT;
3412 /* fallthrough */
3413 case XML_TEXTWRITER_DTD_TEXT:
3414 case XML_TEXTWRITER_NONE:
3415 break;
3416 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003417 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003418 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003419 }
3420
3421 p = (xmlTextWriterStackEntry *)
3422 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3423 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003424 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003425 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3426 return -1;
3427 }
3428
3429 p->name = xmlStrdup(name);
3430 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003431 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003432 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3433 xmlFree(p);
3434 return -1;
3435 }
3436 p->state = XML_TEXTWRITER_DTD_ATTL;
3437
3438 xmlListPushFront(writer->nodes, p);
3439
Daniel Veillard500a1de2004-03-22 15:22:58 +00003440 if (writer->indent) {
3441 count = xmlTextWriterWriteIndent(writer);
3442 if (count < 0)
3443 return -1;
3444 sum += count;
3445 }
3446
Daniel Veillard1d211e22003-10-20 22:32:39 +00003447 count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3448 if (count < 0)
3449 return -1;
3450 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +00003451 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003452 if (count < 0)
3453 return -1;
3454 sum += count;
3455
3456 return sum;
3457}
3458
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003459/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003460 * xmlTextWriterEndDTDAttlist:
3461 * @writer: the xmlTextWriterPtr
3462 *
3463 * End an xml DTD attribute list.
3464 *
3465 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3466 */
3467int
3468xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3469{
3470 int count;
3471 int sum;
3472 xmlLinkPtr lk;
3473 xmlTextWriterStackEntry *p;
3474
3475 if (writer == NULL)
3476 return -1;
3477
3478 sum = 0;
3479 lk = xmlListFront(writer->nodes);
3480 if (lk == 0)
3481 return -1;
3482
3483 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3484 if (p == 0)
3485 return -1;
3486
3487 switch (p->state) {
3488 case XML_TEXTWRITER_DTD_ATTL:
3489 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3490 count = xmlOutputBufferWriteString(writer->out, ">");
3491 if (count < 0)
3492 return -1;
3493 sum += count;
3494 break;
3495 default:
3496 return -1;
3497 }
3498
3499 if (writer->indent) {
3500 count = xmlOutputBufferWriteString(writer->out, "\n");
3501 if (count < 0)
3502 return -1;
3503 sum += count;
3504 }
3505
3506 xmlListPopFront(writer->nodes);
3507 return sum;
3508}
3509
3510/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003511 * xmlTextWriterWriteFormatDTDAttlist:
3512 * @writer: the xmlTextWriterPtr
3513 * @name: the name of the DTD ATTLIST
3514 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003515 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003516 *
3517 * Write a formatted DTD ATTLIST.
3518 *
3519 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3520 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003521int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003522xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3523 const xmlChar * name,
3524 const char *format, ...)
3525{
3526 int rc;
3527 va_list ap;
3528
3529 va_start(ap, format);
3530
3531 rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3532
3533 va_end(ap);
3534 return rc;
3535}
3536
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003537/**
3538 * xmlTextWriterWriteVFormatDTDAttlist:
3539 * @writer: the xmlTextWriterPtr
3540 * @name: the name of the DTD ATTLIST
3541 * @format: format string (see printf)
3542 * @argptr: pointer to the first member of the variable argument list.
3543 *
3544 * Write a formatted DTD ATTLIST.
3545 *
3546 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3547 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003548int
3549xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3550 const xmlChar * name,
3551 const char *format, va_list argptr)
3552{
3553 int rc;
3554 xmlChar *buf;
3555
3556 if (writer == NULL)
3557 return -1;
3558
3559 buf = xmlTextWriterVSprintf(format, argptr);
3560 if (buf == 0)
3561 return 0;
3562
3563 rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3564
3565 xmlFree(buf);
3566 return rc;
3567}
3568
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003569/**
3570 * xmlTextWriterWriteDTDAttlist:
3571 * @writer: the xmlTextWriterPtr
3572 * @name: the name of the DTD ATTLIST
3573 * @content: content of the ATTLIST
3574 *
3575 * Write a DTD ATTLIST.
3576 *
3577 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3578 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003579int
3580xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3581 const xmlChar * name, const xmlChar * content)
3582{
3583 int count;
3584 int sum;
3585
3586 if (content == NULL)
3587 return -1;
3588
3589 sum = 0;
3590 count = xmlTextWriterStartDTDAttlist(writer, name);
3591 if (count == -1)
3592 return -1;
3593 sum += count;
3594
Daniel Veillard1d211e22003-10-20 22:32:39 +00003595 count = xmlTextWriterWriteString(writer, content);
3596 if (count == -1)
3597 return -1;
3598 sum += count;
3599
3600 count = xmlTextWriterEndDTDAttlist(writer);
3601 if (count == -1)
3602 return -1;
3603 sum += count;
3604
3605 return sum;
3606}
3607
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003608/**
3609 * xmlTextWriterStartDTDEntity:
3610 * @writer: the xmlTextWriterPtr
3611 * @pe: TRUE if this is a parameter entity, FALSE if not
3612 * @name: the name of the DTD ATTLIST
3613 *
3614 * Start an xml DTD ATTLIST.
3615 *
3616 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3617 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003618int
3619xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3620 int pe, const xmlChar * name)
3621{
3622 int count;
3623 int sum;
3624 xmlLinkPtr lk;
3625 xmlTextWriterStackEntry *p;
3626
3627 if (writer == NULL || name == NULL || *name == '\0')
3628 return -1;
3629
3630 sum = 0;
3631 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003632 if (lk != 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00003633
Daniel Veillard500a1de2004-03-22 15:22:58 +00003634 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3635 if (p != 0) {
3636 switch (p->state) {
3637 case XML_TEXTWRITER_DTD:
3638 count = xmlOutputBufferWriteString(writer->out, " [");
3639 if (count < 0)
3640 return -1;
3641 sum += count;
3642 if (writer->indent) {
3643 count =
3644 xmlOutputBufferWriteString(writer->out, "\n");
3645 if (count < 0)
3646 return -1;
3647 sum += count;
3648 }
3649 p->state = XML_TEXTWRITER_DTD_TEXT;
3650 /* fallthrough */
3651 case XML_TEXTWRITER_DTD_TEXT:
3652 case XML_TEXTWRITER_NONE:
3653 break;
3654 default:
3655 return -1;
3656 }
3657 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003658 }
3659
3660 p = (xmlTextWriterStackEntry *)
3661 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3662 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003663 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003664 "xmlTextWriterStartDTDElement : out of memory!\n");
3665 return -1;
3666 }
3667
3668 p->name = xmlStrdup(name);
3669 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003670 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003671 "xmlTextWriterStartDTDElement : out of memory!\n");
3672 xmlFree(p);
3673 return -1;
3674 }
Daniel Veillard500a1de2004-03-22 15:22:58 +00003675
3676 if (pe != 0)
3677 p->state = XML_TEXTWRITER_DTD_PENT;
3678 else
3679 p->state = XML_TEXTWRITER_DTD_ENTY;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003680
3681 xmlListPushFront(writer->nodes, p);
3682
Daniel Veillard500a1de2004-03-22 15:22:58 +00003683 if (writer->indent) {
3684 count = xmlTextWriterWriteIndent(writer);
3685 if (count < 0)
3686 return -1;
3687 sum += count;
3688 }
3689
Daniel Veillard1d211e22003-10-20 22:32:39 +00003690 count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3691 if (count < 0)
3692 return -1;
3693 sum += count;
3694
3695 if (pe != 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00003696 count = xmlOutputBufferWriteString(writer->out, "% ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003697 if (count < 0)
3698 return -1;
3699 sum += count;
3700 }
3701
Daniel Veillardab69f362004-02-17 11:40:32 +00003702 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003703 if (count < 0)
3704 return -1;
3705 sum += count;
3706
3707 return sum;
3708}
3709
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003710/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003711 * xmlTextWriterEndDTDEntity:
3712 * @writer: the xmlTextWriterPtr
3713 *
3714 * End an xml DTD entity.
3715 *
3716 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3717 */
3718int
3719xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3720{
3721 int count;
3722 int sum;
3723 xmlLinkPtr lk;
3724 xmlTextWriterStackEntry *p;
3725
3726 if (writer == NULL)
3727 return -1;
3728
3729 sum = 0;
3730 lk = xmlListFront(writer->nodes);
3731 if (lk == 0)
3732 return -1;
3733
3734 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3735 if (p == 0)
3736 return -1;
3737
3738 switch (p->state) {
3739 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3740 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3741 if (count < 0)
3742 return -1;
3743 sum += count;
3744 case XML_TEXTWRITER_DTD_ENTY:
3745 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard500a1de2004-03-22 15:22:58 +00003746 count = xmlOutputBufferWriteString(writer->out, ">");
3747 if (count < 0)
3748 return -1;
3749 sum += count;
3750 break;
3751 default:
3752 return -1;
3753 }
3754
3755 if (writer->indent) {
3756 count = xmlOutputBufferWriteString(writer->out, "\n");
3757 if (count < 0)
3758 return -1;
3759 sum += count;
3760 }
3761
3762 xmlListPopFront(writer->nodes);
3763 return sum;
3764}
3765
3766/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003767 * xmlTextWriterWriteFormatDTDInternalEntity:
3768 * @writer: the xmlTextWriterPtr
3769 * @pe: TRUE if this is a parameter entity, FALSE if not
3770 * @name: the name of the DTD entity
3771 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003772 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003773 *
3774 * Write a formatted DTD internal entity.
3775 *
3776 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3777 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003778int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003779xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3780 int pe,
3781 const xmlChar * name,
3782 const char *format, ...)
3783{
3784 int rc;
3785 va_list ap;
3786
3787 va_start(ap, format);
3788
3789 rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3790 format, ap);
3791
3792 va_end(ap);
3793 return rc;
3794}
3795
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003796/**
3797 * xmlTextWriterWriteVFormatDTDInternalEntity:
3798 * @writer: the xmlTextWriterPtr
3799 * @pe: TRUE if this is a parameter entity, FALSE if not
3800 * @name: the name of the DTD entity
3801 * @format: format string (see printf)
3802 * @argptr: pointer to the first member of the variable argument list.
3803 *
3804 * Write a formatted DTD internal entity.
3805 *
3806 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3807 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003808int
3809xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3810 int pe,
3811 const xmlChar * name,
3812 const char *format,
3813 va_list argptr)
3814{
3815 int rc;
3816 xmlChar *buf;
3817
3818 if (writer == NULL)
3819 return -1;
3820
3821 buf = xmlTextWriterVSprintf(format, argptr);
3822 if (buf == 0)
3823 return 0;
3824
3825 rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3826
3827 xmlFree(buf);
3828 return rc;
3829}
3830
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003831/**
3832 * xmlTextWriterWriteDTDEntity:
3833 * @writer: the xmlTextWriterPtr
3834 * @pe: TRUE if this is a parameter entity, FALSE if not
3835 * @name: the name of the DTD entity
3836 * @pubid: the public identifier, which is an alternative to the system identifier
3837 * @sysid: the system identifier, which is the URI of the DTD
3838 * @ndataid: the xml notation name.
3839 * @content: content of the entity
3840 *
3841 * Write a DTD entity.
3842 *
3843 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3844 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003845int
3846xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3847 int pe,
3848 const xmlChar * name,
3849 const xmlChar * pubid,
3850 const xmlChar * sysid,
3851 const xmlChar * ndataid,
3852 const xmlChar * content)
3853{
Daniel Veillard500a1de2004-03-22 15:22:58 +00003854 if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003855 return -1;
3856 if ((pe != 0) && (ndataid != NULL))
3857 return -1;
3858
Daniel Veillard500a1de2004-03-22 15:22:58 +00003859 if ((pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003860 return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3861 content);
3862
3863 return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3864 sysid, ndataid);
3865}
3866
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003867/**
3868 * xmlTextWriterWriteDTDInternalEntity:
3869 * @writer: the xmlTextWriterPtr
3870 * @pe: TRUE if this is a parameter entity, FALSE if not
3871 * @name: the name of the DTD entity
3872 * @content: content of the entity
3873 *
3874 * Write a DTD internal entity.
3875 *
3876 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3877 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003878int
3879xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3880 int pe,
3881 const xmlChar * name,
3882 const xmlChar * content)
3883{
3884 int count;
3885 int sum;
3886
3887 if ((name == NULL) || (*name == '\0') || (content == NULL))
3888 return -1;
3889
3890 sum = 0;
3891 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3892 if (count == -1)
3893 return -1;
3894 sum += count;
3895
Daniel Veillard1d211e22003-10-20 22:32:39 +00003896 count = xmlTextWriterWriteString(writer, content);
3897 if (count == -1)
3898 return -1;
3899 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003900
3901 count = xmlTextWriterEndDTDEntity(writer);
3902 if (count == -1)
3903 return -1;
3904 sum += count;
3905
3906 return sum;
3907}
3908
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003909/**
3910 * xmlTextWriterWriteDTDExternalEntity:
3911 * @writer: the xmlTextWriterPtr
3912 * @pe: TRUE if this is a parameter entity, FALSE if not
3913 * @name: the name of the DTD entity
3914 * @pubid: the public identifier, which is an alternative to the system identifier
3915 * @sysid: the system identifier, which is the URI of the DTD
3916 * @ndataid: the xml notation name.
3917 *
Daniel Veillard500a1de2004-03-22 15:22:58 +00003918 * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003919 *
3920 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3921 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003922int
3923xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3924 int pe,
3925 const xmlChar * name,
3926 const xmlChar * pubid,
3927 const xmlChar * sysid,
3928 const xmlChar * ndataid)
3929{
3930 int count;
3931 int sum;
3932
Daniel Veillard500a1de2004-03-22 15:22:58 +00003933 if (((pubid == NULL) && (sysid == NULL)))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003934 return -1;
3935 if ((pe != 0) && (ndataid != NULL))
3936 return -1;
3937
3938 sum = 0;
3939 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3940 if (count == -1)
3941 return -1;
3942 sum += count;
3943
Daniel Veillard500a1de2004-03-22 15:22:58 +00003944 count =
3945 xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3946 ndataid);
3947 if (count < 0)
3948 return -1;
3949 sum += count;
3950
3951 count = xmlTextWriterEndDTDEntity(writer);
3952 if (count == -1)
3953 return -1;
3954 sum += count;
3955
3956 return sum;
3957}
3958
3959/**
3960 * xmlTextWriterWriteDTDExternalEntityContents:
3961 * @writer: the xmlTextWriterPtr
3962 * @pubid: the public identifier, which is an alternative to the system identifier
3963 * @sysid: the system identifier, which is the URI of the DTD
3964 * @ndataid: the xml notation name.
3965 *
3966 * Write the contents of a DTD external entity.
3967 *
3968 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3969 */
3970int
3971xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3972 const xmlChar * pubid,
3973 const xmlChar * sysid,
3974 const xmlChar * ndataid)
3975{
3976 int count;
3977 int sum;
3978 xmlLinkPtr lk;
3979 xmlTextWriterStackEntry *p;
3980
3981 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003982 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003983 "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3984 return -1;
3985 }
3986
3987 sum = 0;
3988 lk = xmlListFront(writer->nodes);
3989 if (lk == 0) {
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
3995 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3996 if (p == 0)
3997 return -1;
3998
3999 switch (p->state) {
4000 case XML_TEXTWRITER_DTD_ENTY:
4001 break;
4002 case XML_TEXTWRITER_DTD_PENT:
4003 if (ndataid != NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004004 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004005 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
4006 return -1;
4007 }
4008 break;
4009 default:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004010 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004011 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4012 return -1;
4013 }
4014
Daniel Veillard1d211e22003-10-20 22:32:39 +00004015 if (pubid != 0) {
4016 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004017 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004018 "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00004019 return -1;
4020 }
4021
4022 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4023 if (count < 0)
4024 return -1;
4025 sum += count;
4026
4027 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4028 if (count < 0)
4029 return -1;
4030 sum += count;
4031
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004032 count =
4033 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004034 if (count < 0)
4035 return -1;
4036 sum += count;
4037
4038 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4039 if (count < 0)
4040 return -1;
4041 sum += count;
4042 }
4043
4044 if (sysid != 0) {
4045 if (pubid == 0) {
4046 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4047 if (count < 0)
4048 return -1;
4049 sum += count;
4050 }
4051
4052 count = xmlOutputBufferWriteString(writer->out, " ");
4053 if (count < 0)
4054 return -1;
4055 sum += count;
4056
4057 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4058 if (count < 0)
4059 return -1;
4060 sum += count;
4061
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004062 count =
4063 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004064 if (count < 0)
4065 return -1;
4066 sum += count;
4067
4068 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4069 if (count < 0)
4070 return -1;
4071 sum += count;
4072 }
4073
4074 if (ndataid != NULL) {
4075 count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4076 if (count < 0)
4077 return -1;
4078 sum += count;
4079
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004080 count =
4081 xmlOutputBufferWriteString(writer->out,
4082 (const char *) ndataid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004083 if (count < 0)
4084 return -1;
4085 sum += count;
4086 }
4087
Daniel Veillard1d211e22003-10-20 22:32:39 +00004088 return sum;
4089}
4090
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004091/**
4092 * xmlTextWriterWriteDTDNotation:
4093 * @writer: the xmlTextWriterPtr
4094 * @name: the name of the xml notation
4095 * @pubid: the public identifier, which is an alternative to the system identifier
4096 * @sysid: the system identifier, which is the URI of the DTD
4097 *
4098 * Write a DTD entity.
4099 *
4100 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4101 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00004102int
4103xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4104 const xmlChar * name,
4105 const xmlChar * pubid, const xmlChar * sysid)
4106{
4107 int count;
4108 int sum;
4109 xmlLinkPtr lk;
4110 xmlTextWriterStackEntry *p;
4111
4112 if (writer == NULL || name == NULL || *name == '\0')
4113 return -1;
4114
4115 sum = 0;
4116 lk = xmlListFront(writer->nodes);
4117 if (lk == 0) {
4118 return -1;
4119 }
4120
4121 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00004122 if (p != 0) {
4123 switch (p->state) {
4124 case XML_TEXTWRITER_DTD:
4125 count = xmlOutputBufferWriteString(writer->out, " [");
4126 if (count < 0)
4127 return -1;
4128 sum += count;
4129 if (writer->indent) {
4130 count = xmlOutputBufferWriteString(writer->out, "\n");
4131 if (count < 0)
4132 return -1;
4133 sum += count;
4134 }
4135 p->state = XML_TEXTWRITER_DTD_TEXT;
4136 /* fallthrough */
4137 case XML_TEXTWRITER_DTD_TEXT:
4138 break;
4139 default:
4140 return -1;
4141 }
4142 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00004143
Daniel Veillard500a1de2004-03-22 15:22:58 +00004144 if (writer->indent) {
4145 count = xmlTextWriterWriteIndent(writer);
4146 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004147 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004148 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004149 }
4150
4151 count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4152 if (count < 0)
4153 return -1;
4154 sum += count;
4155 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4156 if (count < 0)
4157 return -1;
4158 sum += count;
4159
4160 if (pubid != 0) {
4161 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4162 if (count < 0)
4163 return -1;
4164 sum += count;
4165 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4166 if (count < 0)
4167 return -1;
4168 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004169 count =
4170 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004171 if (count < 0)
4172 return -1;
4173 sum += count;
4174 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4175 if (count < 0)
4176 return -1;
4177 sum += count;
4178 }
4179
4180 if (sysid != 0) {
4181 if (pubid == 0) {
4182 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4183 if (count < 0)
4184 return -1;
4185 sum += count;
4186 }
4187 count = xmlOutputBufferWriteString(writer->out, " ");
4188 if (count < 0)
4189 return -1;
4190 sum += count;
4191 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4192 if (count < 0)
4193 return -1;
4194 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004195 count =
4196 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004197 if (count < 0)
4198 return -1;
4199 sum += count;
4200 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4201 if (count < 0)
4202 return -1;
4203 sum += count;
4204 }
4205
4206 count = xmlOutputBufferWriteString(writer->out, ">");
4207 if (count < 0)
4208 return -1;
4209 sum += count;
4210
4211 return sum;
4212}
4213
4214/**
4215 * xmlTextWriterFlush:
4216 * @writer: the xmlTextWriterPtr
4217 *
4218 * Flush the output buffer.
4219 *
4220 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4221 */
4222int
4223xmlTextWriterFlush(xmlTextWriterPtr writer)
4224{
4225 int count;
4226
4227 if (writer == NULL)
4228 return -1;
4229
4230 if (writer->out == NULL)
4231 count = 0;
4232 else
4233 count = xmlOutputBufferFlush(writer->out);
4234
4235 return count;
4236}
4237
4238/**
4239 * misc
4240 */
4241
4242/**
4243 * xmlFreeTextWriterStackEntry:
4244 * @lk: the xmlLinkPtr
4245 *
4246 * Free callback for the xmlList.
4247 */
4248static void
4249xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4250{
4251 xmlTextWriterStackEntry *p;
4252
4253 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4254 if (p == 0)
4255 return;
4256
4257 if (p->name != 0)
4258 xmlFree(p->name);
4259 xmlFree(p);
4260}
4261
4262/**
4263 * xmlCmpTextWriterStackEntry:
4264 * @data0: the first data
4265 * @data1: the second data
4266 *
4267 * Compare callback for the xmlList.
4268 *
4269 * Returns -1, 0, 1
4270 */
4271static int
4272xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4273{
4274 xmlTextWriterStackEntry *p0;
4275 xmlTextWriterStackEntry *p1;
4276
4277 if (data0 == data1)
4278 return 0;
4279
4280 if (data0 == 0)
4281 return -1;
4282
4283 if (data1 == 0)
4284 return 1;
4285
4286 p0 = (xmlTextWriterStackEntry *) data0;
4287 p1 = (xmlTextWriterStackEntry *) data1;
4288
4289 return xmlStrcmp(p0->name, p1->name);
4290}
4291
4292/**
4293 * misc
4294 */
4295
4296/**
Rob Richardsb8769d62007-06-08 08:50:47 +00004297 * xmlTextWriterOutputNSDecl:
4298 * @writer: the xmlTextWriterPtr
4299 *
4300 * Output the current namespace declarations.
4301 */
4302static int
4303xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4304{
4305 xmlLinkPtr lk;
4306 xmlTextWriterNsStackEntry *np;
4307 int count;
4308 int sum;
4309
4310 sum = 0;
4311 while (!xmlListEmpty(writer->nsstack)) {
4312 xmlChar *namespaceURI = NULL;
4313 xmlChar *prefix = NULL;
4314
4315 lk = xmlListFront(writer->nsstack);
4316 np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4317
4318 if (np != 0) {
4319 namespaceURI = xmlStrdup(np->uri);
4320 prefix = xmlStrdup(np->prefix);
4321 }
4322
4323 xmlListPopFront(writer->nsstack);
4324
4325 if (np != 0) {
4326 count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4327 xmlFree(namespaceURI);
4328 xmlFree(prefix);
4329
4330 if (count < 0) {
4331 xmlListDelete(writer->nsstack);
4332 writer->nsstack = NULL;
4333 return -1;
4334 }
4335 sum += count;
4336 }
4337 }
4338 return sum;
4339}
4340
4341/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004342 * xmlFreeTextWriterNsStackEntry:
4343 * @lk: the xmlLinkPtr
4344 *
4345 * Free callback for the xmlList.
4346 */
4347static void
4348xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4349{
4350 xmlTextWriterNsStackEntry *p;
4351
4352 p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4353 if (p == 0)
4354 return;
4355
4356 if (p->prefix != 0)
4357 xmlFree(p->prefix);
4358 if (p->uri != 0)
4359 xmlFree(p->uri);
4360
4361 xmlFree(p);
4362}
4363
4364/**
4365 * xmlCmpTextWriterNsStackEntry:
4366 * @data0: the first data
4367 * @data1: the second data
4368 *
4369 * Compare callback for the xmlList.
4370 *
4371 * Returns -1, 0, 1
4372 */
4373static int
4374xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4375{
4376 xmlTextWriterNsStackEntry *p0;
4377 xmlTextWriterNsStackEntry *p1;
4378 int rc;
4379
4380 if (data0 == data1)
4381 return 0;
4382
4383 if (data0 == 0)
4384 return -1;
4385
4386 if (data1 == 0)
4387 return 1;
4388
4389 p0 = (xmlTextWriterNsStackEntry *) data0;
4390 p1 = (xmlTextWriterNsStackEntry *) data1;
4391
4392 rc = xmlStrcmp(p0->prefix, p1->prefix);
4393
Rob Richardsb8769d62007-06-08 08:50:47 +00004394 if ((rc != 0) || (p0->elem != p1->elem))
4395 rc = -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004396
4397 return rc;
4398}
4399
4400/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004401 * xmlTextWriterWriteDocCallback:
4402 * @context: the xmlBufferPtr
4403 * @str: the data to write
4404 * @len: the length of the data
4405 *
4406 * Write callback for the xmlOutputBuffer with target xmlBuffer
4407 *
4408 * Returns -1, 0, 1
4409 */
4410static int
4411xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
4412{
4413 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4414 int rc;
4415
Daniel Veillard1d913862003-11-21 00:28:39 +00004416 if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004417 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004418 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4419 rc);
4420 return -1;
4421 }
4422
4423 return len;
4424}
4425
4426/**
4427 * xmlTextWriterCloseDocCallback:
4428 * @context: the xmlBufferPtr
4429 *
4430 * Close callback for the xmlOutputBuffer with target xmlBuffer
4431 *
4432 * Returns -1, 0, 1
4433 */
4434static int
4435xmlTextWriterCloseDocCallback(void *context)
4436{
4437 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4438 int rc;
4439
4440 if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004441 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004442 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4443 rc);
4444 return -1;
4445 }
4446
4447 return 0;
4448}
4449
4450/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004451 * xmlTextWriterVSprintf:
4452 * @format: see printf
4453 * @argptr: pointer to the first member of the variable argument list.
4454 *
4455 * Utility function for formatted output
4456 *
4457 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4458 */
4459static xmlChar *
4460xmlTextWriterVSprintf(const char *format, va_list argptr)
4461{
4462 int size;
4463 int count;
4464 xmlChar *buf;
William M. Brackf4caa5e2005-10-20 09:04:05 +00004465 va_list locarg;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004466
4467 size = BUFSIZ;
4468 buf = (xmlChar *) xmlMalloc(size);
4469 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004470 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004471 "xmlTextWriterVSprintf : out of memory!\n");
4472 return NULL;
4473 }
4474
William M. Brackf4caa5e2005-10-20 09:04:05 +00004475 VA_COPY(locarg, argptr);
4476 while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004477 || (count == size - 1) || (count == size) || (count > size)) {
William M. Brackf4caa5e2005-10-20 09:04:05 +00004478 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004479 xmlFree(buf);
4480 size += BUFSIZ;
4481 buf = (xmlChar *) xmlMalloc(size);
4482 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004483 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004484 "xmlTextWriterVSprintf : out of memory!\n");
4485 return NULL;
4486 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004487 VA_COPY(locarg, argptr);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004488 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004489 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004490
4491 return buf;
4492}
4493
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004494/**
4495 * xmlTextWriterStartDocumentCallback:
4496 * @ctx: the user data (XML parser context)
4497 *
4498 * called at the start of document processing.
4499 */
4500static void
4501xmlTextWriterStartDocumentCallback(void *ctx)
4502{
4503 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4504 xmlDocPtr doc;
4505
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004506 if (ctxt->html) {
4507#ifdef LIBXML_HTML_ENABLED
4508 if (ctxt->myDoc == NULL)
4509 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4510 if (ctxt->myDoc == NULL) {
4511 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4512 ctxt->sax->error(ctxt->userData,
4513 "SAX.startDocument(): out of memory\n");
4514 ctxt->errNo = XML_ERR_NO_MEMORY;
4515 ctxt->instate = XML_PARSER_EOF;
4516 ctxt->disableSAX = 1;
4517 return;
4518 }
4519#else
Daniel Veillardd0cf7f62004-11-09 16:17:02 +00004520 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004521 "libxml2 built without HTML support\n");
4522 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4523 ctxt->instate = XML_PARSER_EOF;
4524 ctxt->disableSAX = 1;
4525 return;
4526#endif
4527 } else {
4528 doc = ctxt->myDoc;
4529 if (doc == NULL)
4530 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4531 if (doc != NULL) {
4532 if (doc->children == NULL) {
4533 if (ctxt->encoding != NULL)
4534 doc->encoding = xmlStrdup(ctxt->encoding);
4535 else
4536 doc->encoding = NULL;
4537 doc->standalone = ctxt->standalone;
4538 }
4539 } else {
4540 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4541 ctxt->sax->error(ctxt->userData,
4542 "SAX.startDocument(): out of memory\n");
4543 ctxt->errNo = XML_ERR_NO_MEMORY;
4544 ctxt->instate = XML_PARSER_EOF;
4545 ctxt->disableSAX = 1;
4546 return;
4547 }
4548 }
4549 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4550 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4551 ctxt->myDoc->URL =
4552 xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4553 if (ctxt->myDoc->URL == NULL)
4554 ctxt->myDoc->URL =
4555 xmlStrdup((const xmlChar *) ctxt->input->filename);
4556 }
4557}
4558
Daniel Veillard2cca4462004-01-02 20:04:23 +00004559/**
4560 * xmlTextWriterSetIndent:
4561 * @writer: the xmlTextWriterPtr
4562 * @indent: do indentation?
4563 *
4564 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4565 *
4566 * Returns -1 on error or 0 otherwise.
4567 */
4568int
Daniel Veillardab69f362004-02-17 11:40:32 +00004569xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004570{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004571 if ((writer == NULL) || (indent < 0))
Daniel Veillardab69f362004-02-17 11:40:32 +00004572 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004573
Daniel Veillardab69f362004-02-17 11:40:32 +00004574 writer->indent = indent;
4575 writer->doindent = 1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004576
Daniel Veillardab69f362004-02-17 11:40:32 +00004577 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004578}
4579
4580/**
4581 * xmlTextWriterSetIndentString:
4582 * @writer: the xmlTextWriterPtr
4583 * @str: the xmlChar string
4584 *
4585 * Set string indentation.
4586 *
4587 * Returns -1 on error or 0 otherwise.
4588 */
4589int
Daniel Veillardab69f362004-02-17 11:40:32 +00004590xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004591{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004592 if ((writer == NULL) || (!str))
Daniel Veillardab69f362004-02-17 11:40:32 +00004593 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004594
Daniel Veillardab69f362004-02-17 11:40:32 +00004595 if (writer->ichar != NULL)
4596 xmlFree(writer->ichar);
4597 writer->ichar = xmlStrdup(str);
4598
4599 if (!writer->ichar)
4600 return -1;
4601 else
4602 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004603}
4604
4605/**
4606 * xmlTextWriterWriteIndent:
4607 * @writer: the xmlTextWriterPtr
4608 *
4609 * Write indent string.
4610 *
4611 * Returns -1 on error or the number of strings written.
Daniel Veillardab69f362004-02-17 11:40:32 +00004612 */
Daniel Veillard2cca4462004-01-02 20:04:23 +00004613static int
Daniel Veillardab69f362004-02-17 11:40:32 +00004614xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004615{
Daniel Veillardab69f362004-02-17 11:40:32 +00004616 int lksize;
4617 int i;
4618 int ret;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004619
Daniel Veillardab69f362004-02-17 11:40:32 +00004620 lksize = xmlListSize(writer->nodes);
4621 if (lksize < 1)
4622 return (-1); /* list is empty */
4623 for (i = 0; i < (lksize - 1); i++) {
4624 ret = xmlOutputBufferWriteString(writer->out,
4625 (const char *) writer->ichar);
4626 if (ret == -1)
4627 return (-1);
4628 }
4629
4630 return (lksize - 1);
Daniel Veillard2cca4462004-01-02 20:04:23 +00004631}
4632
Daniel Veillard500a1de2004-03-22 15:22:58 +00004633/**
4634 * xmlTextWriterHandleStateDependencies:
4635 * @writer: the xmlTextWriterPtr
4636 * @p: the xmlTextWriterStackEntry
4637 *
4638 * Write state dependent strings.
4639 *
4640 * Returns -1 on error or the number of characters written.
4641 */
4642static int
4643xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4644 xmlTextWriterStackEntry * p)
4645{
4646 int count;
4647 int sum;
4648 char extra[3];
4649
4650 if (writer == NULL)
4651 return -1;
4652
4653 if (p == NULL)
4654 return 0;
4655
4656 sum = 0;
4657 extra[0] = extra[1] = extra[2] = '\0';
4658 if (p != 0) {
4659 sum = 0;
4660 switch (p->state) {
4661 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00004662 /* Output namespace declarations */
4663 count = xmlTextWriterOutputNSDecl(writer);
4664 if (count < 0)
4665 return -1;
4666 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004667 extra[0] = '>';
4668 p->state = XML_TEXTWRITER_TEXT;
4669 break;
4670 case XML_TEXTWRITER_PI:
4671 extra[0] = ' ';
4672 p->state = XML_TEXTWRITER_PI_TEXT;
4673 break;
4674 case XML_TEXTWRITER_DTD:
4675 extra[0] = ' ';
4676 extra[1] = '[';
4677 p->state = XML_TEXTWRITER_DTD_TEXT;
4678 break;
4679 case XML_TEXTWRITER_DTD_ELEM:
4680 extra[0] = ' ';
4681 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4682 break;
4683 case XML_TEXTWRITER_DTD_ATTL:
4684 extra[0] = ' ';
4685 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4686 break;
4687 case XML_TEXTWRITER_DTD_ENTY:
4688 case XML_TEXTWRITER_DTD_PENT:
4689 extra[0] = ' ';
4690 extra[1] = writer->qchar;
4691 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4692 break;
4693 default:
4694 break;
4695 }
4696 }
4697
4698 if (*extra != '\0') {
4699 count = xmlOutputBufferWriteString(writer->out, extra);
4700 if (count < 0)
4701 return -1;
4702 sum += count;
4703 }
4704
4705 return sum;
4706}
4707
Daniel Veillard5d4644e2005-04-01 13:11:58 +00004708#define bottom_xmlwriter
4709#include "elfgcchack.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +00004710#endif