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