blob: 58445c84c866b5e0cda1614ff349878b5b3df2b8 [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,
Nick Wellnhofer86615e42017-11-09 17:47:47 +0100113 const char *str, int len);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000114static 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
Nick Wellnhofer86615e42017-11-09 17:47:47 +0100328 out = xmlOutputBufferCreateIO(xmlTextWriterWriteDocCallback,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000329 xmlTextWriterCloseDocCallback,
330 (void *) ctxt, NULL);
331 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000332 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000333 "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
334 return NULL;
335 }
336
337 ret = xmlNewTextWriter(out);
338 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000339 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000340 "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
341 xmlOutputBufferClose(out);
342 return NULL;
343 }
344
Daniel Veillard20c5e782004-01-21 09:57:31 +0000345 ret->ctxt = ctxt;
346
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000347 return ret;
348}
349
350/**
351 * xmlNewTextWriterDoc:
352 * @doc: address of a xmlDocPtr to hold the new XML document tree
353 * @compression: compress the output?
354 *
355 * Create a new xmlNewTextWriter structure with @*doc as output
356 *
357 * Returns the new xmlTextWriterPtr or NULL in case of error
358 */
359xmlTextWriterPtr
360xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
361{
362 xmlTextWriterPtr ret;
363 xmlSAXHandler saxHandler;
364 xmlParserCtxtPtr ctxt;
365
366 memset(&saxHandler, '\0', sizeof(saxHandler));
367 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
368 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
369 saxHandler.startElement = xmlSAX2StartElement;
370 saxHandler.endElement = xmlSAX2EndElement;
371
372 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
373 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000374 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillardeb0a0b22009-02-20 08:19:53 +0000375 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000376 return NULL;
377 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000378 /*
379 * For some reason this seems to completely break if node names
380 * are interned.
381 */
382 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000383
Daniel Veillard1d913862003-11-21 00:28:39 +0000384 ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000385 if (ctxt->myDoc == NULL) {
386 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000387 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000388 "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
389 return NULL;
390 }
391
392 ret = xmlNewTextWriterPushParser(ctxt, compression);
393 if (ret == NULL) {
Daniel Veillardeb0a0b22009-02-20 08:19:53 +0000394 xmlFreeDoc(ctxt->myDoc);
395 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000396 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillardeb0a0b22009-02-20 08:19:53 +0000397 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000398 return NULL;
399 }
400
Daniel Veillard500a1de2004-03-22 15:22:58 +0000401 xmlSetDocCompressMode(ctxt->myDoc, compression);
402
Daniel Veillarda521d282004-11-09 14:59:59 +0000403 if (doc != NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000404 *doc = ctxt->myDoc;
Daniel Veillarda521d282004-11-09 14:59:59 +0000405 ret->no_doc_free = 1;
406 }
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000407
408 return ret;
409}
410
411/**
412 * xmlNewTextWriterTree:
413 * @doc: xmlDocPtr
414 * @node: xmlNodePtr or NULL for doc->children
415 * @compression: compress the output?
416 *
417 * Create a new xmlNewTextWriter structure with @doc as output
418 * starting at @node
419 *
420 * Returns the new xmlTextWriterPtr or NULL in case of error
421 */
422xmlTextWriterPtr
423xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
424{
425 xmlTextWriterPtr ret;
426 xmlSAXHandler saxHandler;
427 xmlParserCtxtPtr ctxt;
428
429 if (doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000430 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000431 "xmlNewTextWriterTree : invalid document tree!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000432 return NULL;
433 }
434
435 memset(&saxHandler, '\0', sizeof(saxHandler));
436 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
437 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
438 saxHandler.startElement = xmlSAX2StartElement;
439 saxHandler.endElement = xmlSAX2EndElement;
440
441 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
442 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000443 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000444 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
445 return NULL;
446 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000447 /*
448 * For some reason this seems to completely break if node names
449 * are interned.
450 */
451 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000452
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000453 ret = xmlNewTextWriterPushParser(ctxt, compression);
454 if (ret == NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000455 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000456 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000457 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
458 return NULL;
459 }
460
Daniel Veillard500a1de2004-03-22 15:22:58 +0000461 ctxt->myDoc = doc;
462 ctxt->node = node;
Daniel Veillarda521d282004-11-09 14:59:59 +0000463 ret->no_doc_free = 1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000464
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000465 xmlSetDocCompressMode(doc, compression);
466
467 return ret;
468}
469
470/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000471 * xmlFreeTextWriter:
472 * @writer: the xmlTextWriterPtr
473 *
474 * Deallocate all the resources associated to the writer
475 */
476void
477xmlFreeTextWriter(xmlTextWriterPtr writer)
478{
479 if (writer == NULL)
480 return;
481
482 if (writer->out != NULL)
483 xmlOutputBufferClose(writer->out);
484
485 if (writer->nodes != NULL)
486 xmlListDelete(writer->nodes);
487
488 if (writer->nsstack != NULL)
489 xmlListDelete(writer->nsstack);
490
Daniel Veillarda521d282004-11-09 14:59:59 +0000491 if (writer->ctxt != NULL) {
492 if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
493 xmlFreeDoc(writer->ctxt->myDoc);
494 writer->ctxt->myDoc = NULL;
495 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000496 xmlFreeParserCtxt(writer->ctxt);
Daniel Veillarda521d282004-11-09 14:59:59 +0000497 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000498
Rob Richards9db68f02006-08-16 22:48:51 +0000499 if (writer->doc != NULL)
500 xmlFreeDoc(writer->doc);
501
Daniel Veillard4773df22004-01-23 13:15:13 +0000502 if (writer->ichar != NULL)
503 xmlFree(writer->ichar);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000504 xmlFree(writer);
505}
506
507/**
508 * xmlTextWriterStartDocument:
509 * @writer: the xmlTextWriterPtr
510 * @version: the xml version ("1.0") or NULL for default ("1.0")
511 * @encoding: the encoding or NULL for default
512 * @standalone: "yes" or "no" or NULL for default
513 *
514 * Start a new xml document
515 *
516 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
517 */
518int
519xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
520 const char *encoding, const char *standalone)
521{
522 int count;
523 int sum;
524 xmlLinkPtr lk;
525 xmlCharEncodingHandlerPtr encoder;
526
Daniel Veillard500a1de2004-03-22 15:22:58 +0000527 if ((writer == NULL) || (writer->out == NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000528 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000529 "xmlTextWriterStartDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000530 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000531 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000532
533 lk = xmlListFront(writer->nodes);
534 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000535 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000536 "xmlTextWriterStartDocument : not allowed in this context!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000537 return -1;
538 }
539
540 encoder = NULL;
541 if (encoding != NULL) {
542 encoder = xmlFindCharEncodingHandler(encoding);
543 if (encoder == NULL) {
Haibo Huangcfd91dc2020-07-30 23:01:33 -0700544 xmlWriterErrMsg(writer, XML_ERR_UNSUPPORTED_ENCODING,
545 "xmlTextWriterStartDocument : unsupported encoding\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000546 return -1;
547 }
548 }
549
550 writer->out->encoder = encoder;
551 if (encoder != NULL) {
Daniel Veillardcaa19512007-07-04 15:42:46 +0000552 if (writer->out->conv == NULL) {
Daniel Veillarddbf54112012-07-16 14:54:45 +0800553 writer->out->conv = xmlBufCreateSize(4000);
Daniel Veillardcaa19512007-07-04 15:42:46 +0000554 }
Daniel Veillarddbf54112012-07-16 14:54:45 +0800555 xmlCharEncOutput(writer->out, 1);
Rob Richards9db68f02006-08-16 22:48:51 +0000556 if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
557 writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000558 } else
559 writer->out->conv = NULL;
560
561 sum = 0;
562 count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
563 if (count < 0)
564 return -1;
565 sum += count;
566 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
567 if (count < 0)
568 return -1;
569 sum += count;
570 if (version != 0)
571 count = xmlOutputBufferWriteString(writer->out, version);
572 else
573 count = xmlOutputBufferWriteString(writer->out, "1.0");
574 if (count < 0)
575 return -1;
576 sum += count;
577 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
578 if (count < 0)
579 return -1;
580 sum += count;
581 if (writer->out->encoder != 0) {
582 count = xmlOutputBufferWriteString(writer->out, " encoding=");
583 if (count < 0)
584 return -1;
585 sum += count;
586 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
587 if (count < 0)
588 return -1;
589 sum += count;
590 count =
591 xmlOutputBufferWriteString(writer->out,
592 writer->out->encoder->name);
593 if (count < 0)
594 return -1;
595 sum += count;
596 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
597 if (count < 0)
598 return -1;
599 sum += count;
600 }
601
602 if (standalone != 0) {
603 count = xmlOutputBufferWriteString(writer->out, " standalone=");
604 if (count < 0)
605 return -1;
606 sum += count;
607 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
608 if (count < 0)
609 return -1;
610 sum += count;
611 count = xmlOutputBufferWriteString(writer->out, standalone);
612 if (count < 0)
613 return -1;
614 sum += count;
615 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
616 if (count < 0)
617 return -1;
618 sum += count;
619 }
620
621 count = xmlOutputBufferWriteString(writer->out, "?>\n");
622 if (count < 0)
623 return -1;
624 sum += count;
625
626 return sum;
627}
628
629/**
630 * xmlTextWriterEndDocument:
631 * @writer: the xmlTextWriterPtr
632 *
Daniel Veillard3ff24112008-02-13 10:17:41 +0000633 * End an xml document. All open elements are closed, and
634 * the content is flushed to the output.
Daniel Veillard1d211e22003-10-20 22:32:39 +0000635 *
Daniel Veillard3ff24112008-02-13 10:17:41 +0000636 * Returns the bytes written or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +0000637 */
638int
639xmlTextWriterEndDocument(xmlTextWriterPtr writer)
640{
641 int count;
642 int sum;
643 xmlLinkPtr lk;
644 xmlTextWriterStackEntry *p;
645
Daniel Veillard500a1de2004-03-22 15:22:58 +0000646 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000647 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000648 "xmlTextWriterEndDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000649 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000650 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000651
652 sum = 0;
653 while ((lk = xmlListFront(writer->nodes)) != NULL) {
654 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
655 if (p == 0)
656 break;
657 switch (p->state) {
658 case XML_TEXTWRITER_NAME:
659 case XML_TEXTWRITER_ATTRIBUTE:
660 case XML_TEXTWRITER_TEXT:
661 count = xmlTextWriterEndElement(writer);
662 if (count < 0)
663 return -1;
664 sum += count;
665 break;
666 case XML_TEXTWRITER_PI:
667 case XML_TEXTWRITER_PI_TEXT:
668 count = xmlTextWriterEndPI(writer);
669 if (count < 0)
670 return -1;
671 sum += count;
672 break;
673 case XML_TEXTWRITER_CDATA:
674 count = xmlTextWriterEndCDATA(writer);
675 if (count < 0)
676 return -1;
677 sum += count;
678 break;
679 case XML_TEXTWRITER_DTD:
Daniel Veillard500a1de2004-03-22 15:22:58 +0000680 case XML_TEXTWRITER_DTD_TEXT:
681 case XML_TEXTWRITER_DTD_ELEM:
682 case XML_TEXTWRITER_DTD_ELEM_TEXT:
683 case XML_TEXTWRITER_DTD_ATTL:
684 case XML_TEXTWRITER_DTD_ATTL_TEXT:
685 case XML_TEXTWRITER_DTD_ENTY:
686 case XML_TEXTWRITER_DTD_ENTY_TEXT:
687 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard1d211e22003-10-20 22:32:39 +0000688 count = xmlTextWriterEndDTD(writer);
689 if (count < 0)
690 return -1;
691 sum += count;
692 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000693 case XML_TEXTWRITER_COMMENT:
694 count = xmlTextWriterEndComment(writer);
695 if (count < 0)
696 return -1;
697 sum += count;
698 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000699 default:
Daniel Veillardab69f362004-02-17 11:40:32 +0000700 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000701 }
702 }
703
Daniel Veillard2cca4462004-01-02 20:04:23 +0000704 if (!writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000705 count = xmlOutputBufferWriteString(writer->out, "\n");
706 if (count < 0)
707 return -1;
708 sum += count;
709 }
Daniel Veillard3ff24112008-02-13 10:17:41 +0000710
711 sum += xmlTextWriterFlush(writer);
712
Daniel Veillardab69f362004-02-17 11:40:32 +0000713 return sum;
714}
715
Daniel Veillardab69f362004-02-17 11:40:32 +0000716/**
717 * xmlTextWriterStartComment:
718 * @writer: the xmlTextWriterPtr
719 *
720 * Start an xml comment.
721 *
722 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
723 */
724int
725xmlTextWriterStartComment(xmlTextWriterPtr writer)
726{
727 int count;
728 int sum;
729 xmlLinkPtr lk;
730 xmlTextWriterStackEntry *p;
731
Daniel Veillard500a1de2004-03-22 15:22:58 +0000732 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000733 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000734 "xmlTextWriterStartComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000735 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000736 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000737
738 sum = 0;
739 lk = xmlListFront(writer->nodes);
740 if (lk != 0) {
741 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
742 if (p != 0) {
743 switch (p->state) {
744 case XML_TEXTWRITER_TEXT:
745 case XML_TEXTWRITER_NONE:
746 break;
747 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000748 /* Output namespace declarations */
749 count = xmlTextWriterOutputNSDecl(writer);
750 if (count < 0)
751 return -1;
752 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000753 count = xmlOutputBufferWriteString(writer->out, ">");
754 if (count < 0)
755 return -1;
756 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000757 if (writer->indent) {
758 count =
759 xmlOutputBufferWriteString(writer->out, "\n");
760 if (count < 0)
761 return -1;
762 sum += count;
763 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000764 p->state = XML_TEXTWRITER_TEXT;
765 break;
766 default:
767 return -1;
768 }
769 }
770 }
771
772 p = (xmlTextWriterStackEntry *)
773 xmlMalloc(sizeof(xmlTextWriterStackEntry));
774 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000775 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillardab69f362004-02-17 11:40:32 +0000776 "xmlTextWriterStartElement : out of memory!\n");
777 return -1;
778 }
779
Daniel Veillard75e389d2005-07-29 22:02:24 +0000780 p->name = NULL;
Daniel Veillardab69f362004-02-17 11:40:32 +0000781 p->state = XML_TEXTWRITER_COMMENT;
782
783 xmlListPushFront(writer->nodes, p);
784
785 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000786 count = xmlTextWriterWriteIndent(writer);
787 if (count < 0)
788 return -1;
789 sum += count;
790 }
791
792 count = xmlOutputBufferWriteString(writer->out, "<!--");
793 if (count < 0)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000794 return -1;
795 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000796
797 return sum;
798}
799
800/**
801 * xmlTextWriterEndComment:
802 * @writer: the xmlTextWriterPtr
803 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -0700804 * End the current xml comment.
Daniel Veillardab69f362004-02-17 11:40:32 +0000805 *
806 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
807 */
808int
809xmlTextWriterEndComment(xmlTextWriterPtr writer)
810{
811 int count;
812 int sum;
813 xmlLinkPtr lk;
814 xmlTextWriterStackEntry *p;
815
Daniel Veillard500a1de2004-03-22 15:22:58 +0000816 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000817 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000818 "xmlTextWriterEndComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000819 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000820 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000821
822 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000823 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000824 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000825 "xmlTextWriterEndComment : not allowed in this context!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000826 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000827 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000828
829 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
830 if (p == 0)
831 return -1;
832
833 sum = 0;
834 switch (p->state) {
835 case XML_TEXTWRITER_COMMENT:
836 count = xmlOutputBufferWriteString(writer->out, "-->");
837 if (count < 0)
838 return -1;
839 sum += count;
840 break;
841 default:
842 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +0000843 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000844
845 if (writer->indent) {
846 count = xmlOutputBufferWriteString(writer->out, "\n");
847 if (count < 0)
848 return -1;
849 sum += count;
850 }
851
852 xmlListPopFront(writer->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000853 return sum;
854}
855
856/**
857 * xmlTextWriterWriteFormatComment:
858 * @writer: the xmlTextWriterPtr
859 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +0000860 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +0000861 *
862 * Write an xml comment.
863 *
864 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
865 */
Daniel Veillardffa3c742005-07-21 13:24:09 +0000866int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +0000867xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
868 const char *format, ...)
869{
870 int rc;
871 va_list ap;
872
873 va_start(ap, format);
874
875 rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
876
877 va_end(ap);
878 return rc;
879}
880
881/**
882 * xmlTextWriterWriteVFormatComment:
883 * @writer: the xmlTextWriterPtr
884 * @format: format string (see printf)
885 * @argptr: pointer to the first member of the variable argument list.
886 *
887 * Write an xml comment.
888 *
889 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
890 */
891int
892xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
893 const char *format, va_list argptr)
894{
895 int rc;
896 xmlChar *buf;
897
Daniel Veillard500a1de2004-03-22 15:22:58 +0000898 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000899 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000900 "xmlTextWriterWriteVFormatComment : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000901 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000902 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000903
904 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +0000905 if (buf == NULL)
906 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000907
908 rc = xmlTextWriterWriteComment(writer, buf);
909
910 xmlFree(buf);
911 return rc;
912}
913
914/**
915 * xmlTextWriterWriteComment:
916 * @writer: the xmlTextWriterPtr
917 * @content: comment string
918 *
919 * Write an xml comment.
920 *
921 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
922 */
923int
924xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
925{
926 int count;
927 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000928
929 sum = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000930 count = xmlTextWriterStartComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000931 if (count < 0)
932 return -1;
933 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000934 count = xmlTextWriterWriteString(writer, content);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000935 if (count < 0)
936 return -1;
937 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000938 count = xmlTextWriterEndComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000939 if (count < 0)
940 return -1;
941 sum += count;
942
943 return sum;
944}
945
946/**
947 * xmlTextWriterStartElement:
948 * @writer: the xmlTextWriterPtr
949 * @name: element name
950 *
951 * Start an xml element.
952 *
953 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
954 */
955int
956xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
957{
958 int count;
959 int sum;
960 xmlLinkPtr lk;
961 xmlTextWriterStackEntry *p;
962
963 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
964 return -1;
965
966 sum = 0;
967 lk = xmlListFront(writer->nodes);
968 if (lk != 0) {
969 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
970 if (p != 0) {
971 switch (p->state) {
972 case XML_TEXTWRITER_PI:
973 case XML_TEXTWRITER_PI_TEXT:
974 return -1;
975 case XML_TEXTWRITER_NONE:
976 break;
Daniel Veillard614fdc12005-02-23 14:05:37 +0000977 case XML_TEXTWRITER_ATTRIBUTE:
978 count = xmlTextWriterEndAttribute(writer);
979 if (count < 0)
980 return -1;
981 sum += count;
982 /* fallthrough */
Daniel Veillard1d211e22003-10-20 22:32:39 +0000983 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000984 /* Output namespace declarations */
985 count = xmlTextWriterOutputNSDecl(writer);
986 if (count < 0)
987 return -1;
988 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000989 count = xmlOutputBufferWriteString(writer->out, ">");
990 if (count < 0)
991 return -1;
992 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000993 if (writer->indent)
994 count =
995 xmlOutputBufferWriteString(writer->out, "\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000996 p->state = XML_TEXTWRITER_TEXT;
997 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000998 default:
999 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001000 }
1001 }
1002 }
1003
1004 p = (xmlTextWriterStackEntry *)
1005 xmlMalloc(sizeof(xmlTextWriterStackEntry));
1006 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001007 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001008 "xmlTextWriterStartElement : out of memory!\n");
1009 return -1;
1010 }
1011
1012 p->name = xmlStrdup(name);
1013 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001014 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001015 "xmlTextWriterStartElement : out of memory!\n");
1016 xmlFree(p);
1017 return -1;
1018 }
1019 p->state = XML_TEXTWRITER_NAME;
1020
1021 xmlListPushFront(writer->nodes, p);
1022
Daniel Veillardab69f362004-02-17 11:40:32 +00001023 if (writer->indent) {
1024 count = xmlTextWriterWriteIndent(writer);
1025 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001026 }
1027
Daniel Veillard1d211e22003-10-20 22:32:39 +00001028 count = xmlOutputBufferWriteString(writer->out, "<");
1029 if (count < 0)
1030 return -1;
1031 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001032 count =
1033 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001034 if (count < 0)
1035 return -1;
1036 sum += count;
1037
1038 return sum;
1039}
1040
1041/**
1042 * xmlTextWriterStartElementNS:
1043 * @writer: the xmlTextWriterPtr
1044 * @prefix: namespace prefix or NULL
1045 * @name: element local name
1046 * @namespaceURI: namespace URI or NULL
1047 *
1048 * Start an xml element with namespace support.
1049 *
1050 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1051 */
1052int
1053xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
1054 const xmlChar * prefix, const xmlChar * name,
1055 const xmlChar * namespaceURI)
1056{
1057 int count;
1058 int sum;
1059 xmlChar *buf;
1060
1061 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1062 return -1;
1063
Daniel Veillard75e389d2005-07-29 22:02:24 +00001064 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001065 if (prefix != 0) {
1066 buf = xmlStrdup(prefix);
1067 buf = xmlStrcat(buf, BAD_CAST ":");
1068 }
1069 buf = xmlStrcat(buf, name);
1070
1071 sum = 0;
1072 count = xmlTextWriterStartElement(writer, buf);
1073 xmlFree(buf);
1074 if (count < 0)
1075 return -1;
1076 sum += count;
1077
1078 if (namespaceURI != 0) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001079 xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
Rob Richardsb8769d62007-06-08 08:50:47 +00001080 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1081 if (p == 0) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001082 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Rob Richardsb8769d62007-06-08 08:50:47 +00001083 "xmlTextWriterStartElementNS : out of memory!\n");
1084 return -1;
1085 }
1086
Daniel Veillard1d211e22003-10-20 22:32:39 +00001087 buf = xmlStrdup(BAD_CAST "xmlns");
1088 if (prefix != 0) {
1089 buf = xmlStrcat(buf, BAD_CAST ":");
1090 buf = xmlStrcat(buf, prefix);
1091 }
1092
Rob Richardsb8769d62007-06-08 08:50:47 +00001093 p->prefix = buf;
1094 p->uri = xmlStrdup(namespaceURI);
1095 if (p->uri == 0) {
1096 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1097 "xmlTextWriterStartElementNS : out of memory!\n");
1098 xmlFree(p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001099 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001100 }
1101 p->elem = xmlListFront(writer->nodes);
1102
1103 xmlListPushFront(writer->nsstack, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001104 }
1105
1106 return sum;
1107}
1108
1109/**
1110 * xmlTextWriterEndElement:
1111 * @writer: the xmlTextWriterPtr
1112 *
1113 * End the current xml element.
1114 *
1115 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1116 */
1117int
1118xmlTextWriterEndElement(xmlTextWriterPtr writer)
1119{
1120 int count;
1121 int sum;
1122 xmlLinkPtr lk;
1123 xmlTextWriterStackEntry *p;
1124
1125 if (writer == NULL)
1126 return -1;
1127
1128 lk = xmlListFront(writer->nodes);
Rob Richardsb8769d62007-06-08 08:50:47 +00001129 if (lk == 0) {
1130 xmlListDelete(writer->nsstack);
1131 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001132 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001133 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001134
1135 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Rob Richardsb8769d62007-06-08 08:50:47 +00001136 if (p == 0) {
1137 xmlListDelete(writer->nsstack);
1138 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001139 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001140 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001141
1142 sum = 0;
1143 switch (p->state) {
1144 case XML_TEXTWRITER_ATTRIBUTE:
1145 count = xmlTextWriterEndAttribute(writer);
Rob Richardsb8769d62007-06-08 08:50:47 +00001146 if (count < 0) {
1147 xmlListDelete(writer->nsstack);
1148 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001149 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001150 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001151 sum += count;
1152 /* fallthrough */
1153 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001154 /* Output namespace declarations */
1155 count = xmlTextWriterOutputNSDecl(writer);
1156 if (count < 0)
1157 return -1;
1158 sum += count;
1159
Daniel Veillardab69f362004-02-17 11:40:32 +00001160 if (writer->indent) /* next element needs indent */
1161 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001162 count = xmlOutputBufferWriteString(writer->out, "/>");
1163 if (count < 0)
1164 return -1;
1165 sum += count;
1166 break;
1167 case XML_TEXTWRITER_TEXT:
Daniel Veillardab69f362004-02-17 11:40:32 +00001168 if ((writer->indent) && (writer->doindent)) {
1169 count = xmlTextWriterWriteIndent(writer);
1170 sum += count;
1171 writer->doindent = 1;
1172 } else
1173 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001174 count = xmlOutputBufferWriteString(writer->out, "</");
1175 if (count < 0)
1176 return -1;
1177 sum += count;
1178 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001179 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001180 if (count < 0)
1181 return -1;
1182 sum += count;
1183 count = xmlOutputBufferWriteString(writer->out, ">");
1184 if (count < 0)
1185 return -1;
1186 sum += count;
1187 break;
1188 default:
1189 return -1;
1190 }
1191
Daniel Veillard2cca4462004-01-02 20:04:23 +00001192 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001193 count = xmlOutputBufferWriteString(writer->out, "\n");
1194 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001195 }
1196
Daniel Veillard1d211e22003-10-20 22:32:39 +00001197 xmlListPopFront(writer->nodes);
1198 return sum;
1199}
1200
1201/**
1202 * xmlTextWriterFullEndElement:
1203 * @writer: the xmlTextWriterPtr
1204 *
1205 * End the current xml element. Writes an end tag even if the element is empty
1206 *
1207 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1208 */
1209int
1210xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1211{
1212 int count;
1213 int sum;
1214 xmlLinkPtr lk;
1215 xmlTextWriterStackEntry *p;
1216
1217 if (writer == NULL)
1218 return -1;
1219
1220 lk = xmlListFront(writer->nodes);
1221 if (lk == 0)
1222 return -1;
1223
1224 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1225 if (p == 0)
1226 return -1;
1227
1228 sum = 0;
1229 switch (p->state) {
1230 case XML_TEXTWRITER_ATTRIBUTE:
1231 count = xmlTextWriterEndAttribute(writer);
1232 if (count < 0)
1233 return -1;
1234 sum += count;
1235 /* fallthrough */
1236 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001237 /* Output namespace declarations */
1238 count = xmlTextWriterOutputNSDecl(writer);
1239 if (count < 0)
1240 return -1;
1241 sum += count;
1242
Daniel Veillard1d211e22003-10-20 22:32:39 +00001243 count = xmlOutputBufferWriteString(writer->out, ">");
1244 if (count < 0)
1245 return -1;
1246 sum += count;
Rob Richards5a7d8bd2008-12-27 13:17:43 +00001247 if (writer->indent)
1248 writer->doindent = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001249 /* fallthrough */
1250 case XML_TEXTWRITER_TEXT:
Rob Richards5a7d8bd2008-12-27 13:17:43 +00001251 if ((writer->indent) && (writer->doindent)) {
1252 count = xmlTextWriterWriteIndent(writer);
1253 sum += count;
1254 writer->doindent = 1;
1255 } else
1256 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001257 count = xmlOutputBufferWriteString(writer->out, "</");
1258 if (count < 0)
1259 return -1;
1260 sum += count;
1261 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001262 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001263 if (count < 0)
1264 return -1;
1265 sum += count;
1266 count = xmlOutputBufferWriteString(writer->out, ">");
1267 if (count < 0)
1268 return -1;
1269 sum += count;
1270 break;
1271 default:
1272 return -1;
1273 }
1274
Daniel Veillard7e26fb42008-01-09 02:19:50 +00001275 if (writer->indent) {
1276 count = xmlOutputBufferWriteString(writer->out, "\n");
1277 sum += count;
1278 }
1279
Daniel Veillard1d211e22003-10-20 22:32:39 +00001280 xmlListPopFront(writer->nodes);
1281 return sum;
1282}
1283
1284/**
1285 * xmlTextWriterWriteFormatRaw:
1286 * @writer: the xmlTextWriterPtr
1287 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001288 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001289 *
1290 * Write a formatted raw xml text.
1291 *
1292 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1293 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001294int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001295xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1296 ...)
1297{
1298 int rc;
1299 va_list ap;
1300
1301 va_start(ap, format);
1302
1303 rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1304
1305 va_end(ap);
1306 return rc;
1307}
1308
1309/**
1310 * xmlTextWriterWriteVFormatRaw:
1311 * @writer: the xmlTextWriterPtr
1312 * @format: format string (see printf)
1313 * @argptr: pointer to the first member of the variable argument list.
1314 *
1315 * Write a formatted raw xml text.
1316 *
1317 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1318 */
1319int
1320xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1321 va_list argptr)
1322{
1323 int rc;
1324 xmlChar *buf;
1325
1326 if (writer == NULL)
1327 return -1;
1328
1329 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00001330 if (buf == NULL)
1331 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001332
1333 rc = xmlTextWriterWriteRaw(writer, buf);
1334
1335 xmlFree(buf);
1336 return rc;
1337}
1338
1339/**
Daniel Veillard1e906612003-12-05 14:57:46 +00001340 * xmlTextWriterWriteRawLen:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001341 * @writer: the xmlTextWriterPtr
1342 * @content: text string
1343 * @len: length of the text string
1344 *
1345 * Write an xml text.
1346 * TODO: what about entities and special chars??
1347 *
1348 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1349 */
1350int
1351xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1352 int len)
1353{
1354 int count;
1355 int sum;
1356 xmlLinkPtr lk;
1357 xmlTextWriterStackEntry *p;
1358
Daniel Veillard500a1de2004-03-22 15:22:58 +00001359 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001360 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001361 "xmlTextWriterWriteRawLen : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001362 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001363 }
1364
Daniel Veillarde43cc572004-11-03 11:50:29 +00001365 if ((content == NULL) || (len < 0)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001366 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001367 "xmlTextWriterWriteRawLen : invalid content!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001368 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001369 }
1370
1371 sum = 0;
1372 lk = xmlListFront(writer->nodes);
1373 if (lk != 0) {
1374 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1375 count = xmlTextWriterHandleStateDependencies(writer, p);
1376 if (count < 0)
1377 return -1;
1378 sum += count;
1379 }
1380
1381 if (writer->indent)
1382 writer->doindent = 0;
1383
1384 if (content != NULL) {
1385 count =
1386 xmlOutputBufferWrite(writer->out, len, (const char *) content);
1387 if (count < 0)
1388 return -1;
1389 sum += count;
1390 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001391
1392 return sum;
1393}
1394
1395/**
1396 * xmlTextWriterWriteRaw:
1397 * @writer: the xmlTextWriterPtr
1398 * @content: text string
1399 *
1400 * Write a raw xml text.
1401 *
1402 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1403 */
1404int
1405xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1406{
1407 return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1408}
1409
1410/**
1411 * xmlTextWriterWriteFormatString:
1412 * @writer: the xmlTextWriterPtr
1413 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001414 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001415 *
1416 * Write a formatted xml text.
1417 *
1418 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1419 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001420int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001421xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1422 ...)
1423{
1424 int rc;
1425 va_list ap;
1426
Daniel Veillarde43cc572004-11-03 11:50:29 +00001427 if ((writer == NULL) || (format == NULL))
1428 return -1;
1429
Daniel Veillard1d211e22003-10-20 22:32:39 +00001430 va_start(ap, format);
1431
1432 rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1433
1434 va_end(ap);
1435 return rc;
1436}
1437
1438/**
1439 * xmlTextWriterWriteVFormatString:
1440 * @writer: the xmlTextWriterPtr
1441 * @format: format string (see printf)
1442 * @argptr: pointer to the first member of the variable argument list.
1443 *
1444 * Write a formatted xml text.
1445 *
1446 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1447 */
1448int
1449xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1450 const char *format, va_list argptr)
1451{
1452 int rc;
1453 xmlChar *buf;
1454
Daniel Veillarde43cc572004-11-03 11:50:29 +00001455 if ((writer == NULL) || (format == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001456 return -1;
1457
1458 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00001459 if (buf == NULL)
1460 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001461
1462 rc = xmlTextWriterWriteString(writer, buf);
1463
1464 xmlFree(buf);
1465 return rc;
1466}
1467
1468/**
1469 * xmlTextWriterWriteString:
1470 * @writer: the xmlTextWriterPtr
1471 * @content: text string
1472 *
1473 * Write an xml text.
1474 *
1475 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1476 */
1477int
1478xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1479{
Daniel Veillard500a1de2004-03-22 15:22:58 +00001480 int count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001481 int sum;
1482 xmlLinkPtr lk;
1483 xmlTextWriterStackEntry *p;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001484 xmlChar *buf;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001485
Daniel Veillarde43cc572004-11-03 11:50:29 +00001486 if ((writer == NULL) || (content == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001487 return -1;
1488
Daniel Veillard1d211e22003-10-20 22:32:39 +00001489 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001490 buf = (xmlChar *) content;
1491 lk = xmlListFront(writer->nodes);
1492 if (lk != 0) {
1493 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1494 if (p != 0) {
1495 switch (p->state) {
1496 case XML_TEXTWRITER_NAME:
1497 case XML_TEXTWRITER_TEXT:
Daniel Veillard62040be2004-05-17 03:17:26 +00001498#if 0
1499 buf = NULL;
1500 xmlOutputBufferWriteEscape(writer->out, content, NULL);
1501#endif
Daniel Veillard500a1de2004-03-22 15:22:58 +00001502 buf = xmlEncodeSpecialChars(NULL, content);
1503 break;
1504 case XML_TEXTWRITER_ATTRIBUTE:
1505 buf = NULL;
Daniel Veillarddbf54112012-07-16 14:54:45 +08001506 xmlBufAttrSerializeTxtContent(writer->out->buffer,
1507 writer->doc, NULL, content);
Daniel Veillard500a1de2004-03-22 15:22:58 +00001508 break;
William M. Brack87640d52004-04-17 14:58:15 +00001509 default:
1510 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001511 }
1512 }
1513 }
1514
1515 if (buf != NULL) {
1516 count = xmlTextWriterWriteRaw(writer, buf);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001517
Daniel Veillard500a1de2004-03-22 15:22:58 +00001518 if (buf != content) /* buf was allocated by us, so free it */
1519 xmlFree(buf);
Daniel Veillardeb0a0b22009-02-20 08:19:53 +00001520
1521 if (count < 0)
1522 return -1;
1523 sum += count;
William M. Bracka9c612c2004-02-01 10:04:05 +00001524 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001525
1526 return sum;
1527}
1528
1529/**
1530 * xmlOutputBufferWriteBase64:
1531 * @out: the xmlOutputBufferPtr
1532 * @data: binary data
1533 * @len: the number of bytes to encode
1534 *
1535 * Write base64 encoded data to an xmlOutputBuffer.
1536 * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1537 *
1538 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1539 */
1540static int
1541xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1542 const unsigned char *data)
1543{
1544 static unsigned char dtable[64] =
William M. Brack47a31882004-09-11 16:09:09 +00001545 {'A','B','C','D','E','F','G','H','I','J','K','L','M',
1546 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1547 '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 '0','1','2','3','4','5','6','7','8','9','+','/'};
1550
Daniel Veillard1d211e22003-10-20 22:32:39 +00001551 int i;
1552 int linelen;
1553 int count;
1554 int sum;
1555
Daniel Veillarde43cc572004-11-03 11:50:29 +00001556 if ((out == NULL) || (len < 0) || (data == NULL))
1557 return(-1);
1558
Daniel Veillard1d211e22003-10-20 22:32:39 +00001559 linelen = 0;
1560 sum = 0;
1561
1562 i = 0;
1563 while (1) {
1564 unsigned char igroup[3];
1565 unsigned char ogroup[4];
1566 int c;
1567 int n;
1568
1569 igroup[0] = igroup[1] = igroup[2] = 0;
1570 for (n = 0; n < 3 && i < len; n++, i++) {
1571 c = data[i];
1572 igroup[n] = (unsigned char) c;
1573 }
1574
1575 if (n > 0) {
1576 ogroup[0] = dtable[igroup[0] >> 2];
1577 ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1578 ogroup[2] =
1579 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1580 ogroup[3] = dtable[igroup[2] & 0x3F];
1581
1582 if (n < 3) {
1583 ogroup[3] = '=';
1584 if (n < 2) {
1585 ogroup[2] = '=';
1586 }
1587 }
1588
1589 if (linelen >= B64LINELEN) {
1590 count = xmlOutputBufferWrite(out, 2, B64CRLF);
1591 if (count == -1)
1592 return -1;
1593 sum += count;
1594 linelen = 0;
1595 }
1596 count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1597 if (count == -1)
1598 return -1;
1599 sum += count;
1600
1601 linelen += 4;
1602 }
Daniel Veillard929714b2003-10-22 12:34:36 +00001603
1604 if (i >= len)
1605 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001606 }
1607
Daniel Veillard1d211e22003-10-20 22:32:39 +00001608 return sum;
1609}
1610
1611/**
1612 * xmlTextWriterWriteBase64:
1613 * @writer: the xmlTextWriterPtr
1614 * @data: binary data
1615 * @start: the position within the data of the first byte to encode
1616 * @len: the number of bytes to encode
1617 *
1618 * Write an base64 encoded xml text.
1619 *
1620 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1621 */
1622int
Daniel Veillardab69f362004-02-17 11:40:32 +00001623xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001624 int start, int len)
1625{
1626 int count;
1627 int sum;
1628 xmlLinkPtr lk;
1629 xmlTextWriterStackEntry *p;
1630
Daniel Veillarde43cc572004-11-03 11:50:29 +00001631 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001632 return -1;
1633
Daniel Veillard1d211e22003-10-20 22:32:39 +00001634 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001635 lk = xmlListFront(writer->nodes);
1636 if (lk != 0) {
1637 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1638 if (p != 0) {
1639 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001640 if (count < 0)
1641 return -1;
1642 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001643 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001644 }
1645
Daniel Veillardab69f362004-02-17 11:40:32 +00001646 if (writer->indent)
1647 writer->doindent = 0;
1648
Daniel Veillard1d211e22003-10-20 22:32:39 +00001649 count =
1650 xmlOutputBufferWriteBase64(writer->out, len,
1651 (unsigned char *) data + start);
1652 if (count < 0)
1653 return -1;
1654 sum += count;
1655
1656 return sum;
1657}
1658
1659/**
1660 * xmlOutputBufferWriteBinHex:
1661 * @out: the xmlOutputBufferPtr
1662 * @data: binary data
1663 * @len: the number of bytes to encode
1664 *
1665 * Write hqx encoded data to an xmlOutputBuffer.
1666 * ::todo
1667 *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001668 * Returns the bytes written (may be 0 because of buffering)
William M. Brack47a31882004-09-11 16:09:09 +00001669 * or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +00001670 */
1671static int
Daniel Veillardab69f362004-02-17 11:40:32 +00001672xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1673 int len, const unsigned char *data)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001674{
Daniel Veillardab69f362004-02-17 11:40:32 +00001675 int count;
1676 int sum;
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001677 static char hex[16] =
1678 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
Daniel Veillardab69f362004-02-17 11:40:32 +00001679 int i;
1680
Daniel Veillarde43cc572004-11-03 11:50:29 +00001681 if ((out == NULL) || (data == NULL) || (len < 0)) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001682 return -1;
1683 }
1684
1685 sum = 0;
1686 for (i = 0; i < len; i++) {
1687 count =
1688 xmlOutputBufferWrite(out, 1,
1689 (const char *) &hex[data[i] >> 4]);
1690 if (count == -1)
1691 return -1;
1692 sum += count;
1693 count =
1694 xmlOutputBufferWrite(out, 1,
1695 (const char *) &hex[data[i] & 0xF]);
1696 if (count == -1)
1697 return -1;
1698 sum += count;
1699 }
1700
1701 return sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001702}
1703
1704/**
1705 * xmlTextWriterWriteBinHex:
1706 * @writer: the xmlTextWriterPtr
1707 * @data: binary data
1708 * @start: the position within the data of the first byte to encode
1709 * @len: the number of bytes to encode
1710 *
1711 * Write a BinHex encoded xml text.
1712 *
1713 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1714 */
1715int
Daniel Veillardab69f362004-02-17 11:40:32 +00001716xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001717 int start, int len)
1718{
1719 int count;
1720 int sum;
1721 xmlLinkPtr lk;
1722 xmlTextWriterStackEntry *p;
1723
Daniel Veillarde43cc572004-11-03 11:50:29 +00001724 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001725 return -1;
1726
Daniel Veillard1d211e22003-10-20 22:32:39 +00001727 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001728 lk = xmlListFront(writer->nodes);
1729 if (lk != 0) {
1730 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1731 if (p != 0) {
1732 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001733 if (count < 0)
1734 return -1;
1735 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001736 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001737 }
1738
Daniel Veillardab69f362004-02-17 11:40:32 +00001739 if (writer->indent)
1740 writer->doindent = 0;
1741
Daniel Veillard1d211e22003-10-20 22:32:39 +00001742 count =
1743 xmlOutputBufferWriteBinHex(writer->out, len,
1744 (unsigned char *) data + start);
1745 if (count < 0)
1746 return -1;
1747 sum += count;
1748
1749 return sum;
1750}
1751
1752/**
1753 * xmlTextWriterStartAttribute:
1754 * @writer: the xmlTextWriterPtr
1755 * @name: element name
1756 *
1757 * Start an xml attribute.
1758 *
1759 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1760 */
1761int
1762xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1763{
1764 int count;
1765 int sum;
1766 xmlLinkPtr lk;
1767 xmlTextWriterStackEntry *p;
1768
1769 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1770 return -1;
1771
1772 sum = 0;
1773 lk = xmlListFront(writer->nodes);
1774 if (lk == 0)
1775 return -1;
1776
1777 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1778 if (p == 0)
1779 return -1;
1780
1781 switch (p->state) {
1782 case XML_TEXTWRITER_ATTRIBUTE:
1783 count = xmlTextWriterEndAttribute(writer);
1784 if (count < 0)
1785 return -1;
1786 sum += count;
1787 /* fallthrough */
1788 case XML_TEXTWRITER_NAME:
1789 count = xmlOutputBufferWriteString(writer->out, " ");
1790 if (count < 0)
1791 return -1;
1792 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001793 count =
1794 xmlOutputBufferWriteString(writer->out,
1795 (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001796 if (count < 0)
1797 return -1;
1798 sum += count;
1799 count = xmlOutputBufferWriteString(writer->out, "=");
1800 if (count < 0)
1801 return -1;
1802 sum += count;
1803 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1804 if (count < 0)
1805 return -1;
1806 sum += count;
1807 p->state = XML_TEXTWRITER_ATTRIBUTE;
1808 break;
1809 default:
1810 return -1;
1811 }
1812
1813 return sum;
1814}
1815
1816/**
1817 * xmlTextWriterStartAttributeNS:
1818 * @writer: the xmlTextWriterPtr
1819 * @prefix: namespace prefix or NULL
1820 * @name: element local name
1821 * @namespaceURI: namespace URI or NULL
1822 *
1823 * Start an xml attribute with namespace support.
1824 *
1825 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1826 */
1827int
1828xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1829 const xmlChar * prefix, const xmlChar * name,
1830 const xmlChar * namespaceURI)
1831{
1832 int count;
1833 int sum;
1834 xmlChar *buf;
1835 xmlTextWriterNsStackEntry *p;
1836
1837 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1838 return -1;
1839
Rob Richardsb8769d62007-06-08 08:50:47 +00001840 /* Handle namespace first in case of error */
1841 if (namespaceURI != 0) {
1842 xmlTextWriterNsStackEntry nsentry, *curns;
1843
1844 buf = xmlStrdup(BAD_CAST "xmlns");
1845 if (prefix != 0) {
1846 buf = xmlStrcat(buf, BAD_CAST ":");
1847 buf = xmlStrcat(buf, prefix);
1848 }
1849
1850 nsentry.prefix = buf;
1851 nsentry.uri = (xmlChar *)namespaceURI;
1852 nsentry.elem = xmlListFront(writer->nodes);
1853
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001854 curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
Rob Richardsb8769d62007-06-08 08:50:47 +00001855 (void *)&nsentry);
1856 if ((curns != NULL)) {
1857 xmlFree(buf);
1858 if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
1859 /* Namespace already defined on element skip */
1860 buf = NULL;
1861 } else {
1862 /* Prefix mismatch so error out */
1863 return -1;
1864 }
1865 }
1866
1867 /* Do not add namespace decl to list - it is already there */
1868 if (buf != NULL) {
1869 p = (xmlTextWriterNsStackEntry *)
1870 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1871 if (p == 0) {
1872 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1873 "xmlTextWriterStartAttributeNS : out of memory!\n");
1874 return -1;
1875 }
1876
1877 p->prefix = buf;
1878 p->uri = xmlStrdup(namespaceURI);
1879 if (p->uri == 0) {
1880 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1881 "xmlTextWriterStartAttributeNS : out of memory!\n");
1882 xmlFree(p);
1883 return -1;
1884 }
1885 p->elem = xmlListFront(writer->nodes);
1886
1887 xmlListPushFront(writer->nsstack, p);
1888 }
1889 }
1890
Daniel Veillard75e389d2005-07-29 22:02:24 +00001891 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001892 if (prefix != 0) {
1893 buf = xmlStrdup(prefix);
1894 buf = xmlStrcat(buf, BAD_CAST ":");
1895 }
1896 buf = xmlStrcat(buf, name);
1897
1898 sum = 0;
1899 count = xmlTextWriterStartAttribute(writer, buf);
1900 xmlFree(buf);
1901 if (count < 0)
1902 return -1;
1903 sum += count;
1904
Daniel Veillard1d211e22003-10-20 22:32:39 +00001905 return sum;
1906}
1907
1908/**
1909 * xmlTextWriterEndAttribute:
1910 * @writer: the xmlTextWriterPtr
1911 *
1912 * End the current xml element.
1913 *
1914 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1915 */
1916int
1917xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1918{
1919 int count;
1920 int sum;
1921 xmlLinkPtr lk;
1922 xmlTextWriterStackEntry *p;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001923
1924 if (writer == NULL)
1925 return -1;
1926
1927 lk = xmlListFront(writer->nodes);
1928 if (lk == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001929 return -1;
1930 }
1931
1932 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1933 if (p == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001934 return -1;
1935 }
1936
1937 sum = 0;
1938 switch (p->state) {
1939 case XML_TEXTWRITER_ATTRIBUTE:
1940 p->state = XML_TEXTWRITER_NAME;
1941
1942 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1943 if (count < 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001944 return -1;
1945 }
1946 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001947 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001948 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001949 return -1;
1950 }
1951
1952 return sum;
1953}
1954
1955/**
1956 * xmlTextWriterWriteFormatAttribute:
1957 * @writer: the xmlTextWriterPtr
1958 * @name: attribute name
1959 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001960 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001961 *
1962 * Write a formatted xml attribute.
1963 *
1964 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1965 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001966int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001967xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1968 const xmlChar * name, const char *format,
1969 ...)
1970{
1971 int rc;
1972 va_list ap;
1973
1974 va_start(ap, format);
1975
1976 rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1977
1978 va_end(ap);
1979 return rc;
1980}
1981
1982/**
1983 * xmlTextWriterWriteVFormatAttribute:
1984 * @writer: the xmlTextWriterPtr
1985 * @name: attribute name
1986 * @format: format string (see printf)
1987 * @argptr: pointer to the first member of the variable argument list.
1988 *
1989 * Write a formatted xml attribute.
1990 *
1991 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1992 */
1993int
1994xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
1995 const xmlChar * name,
1996 const char *format, va_list argptr)
1997{
1998 int rc;
1999 xmlChar *buf;
2000
2001 if (writer == NULL)
2002 return -1;
2003
2004 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002005 if (buf == NULL)
2006 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002007
2008 rc = xmlTextWriterWriteAttribute(writer, name, buf);
2009
2010 xmlFree(buf);
2011 return rc;
2012}
2013
2014/**
2015 * xmlTextWriterWriteAttribute:
2016 * @writer: the xmlTextWriterPtr
2017 * @name: attribute name
2018 * @content: attribute content
2019 *
2020 * Write an xml attribute.
2021 *
2022 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2023 */
2024int
2025xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
2026 const xmlChar * content)
2027{
2028 int count;
2029 int sum;
2030
2031 sum = 0;
2032 count = xmlTextWriterStartAttribute(writer, name);
2033 if (count < 0)
2034 return -1;
2035 sum += count;
2036 count = xmlTextWriterWriteString(writer, content);
2037 if (count < 0)
2038 return -1;
2039 sum += count;
2040 count = xmlTextWriterEndAttribute(writer);
2041 if (count < 0)
2042 return -1;
2043 sum += count;
2044
2045 return sum;
2046}
2047
2048/**
2049 * xmlTextWriterWriteFormatAttributeNS:
2050 * @writer: the xmlTextWriterPtr
2051 * @prefix: namespace prefix
2052 * @name: attribute local name
2053 * @namespaceURI: namespace URI
2054 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002055 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002056 *
2057 * Write a formatted xml attribute.with namespace support
2058 *
2059 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2060 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002061int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002062xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
2063 const xmlChar * prefix,
2064 const xmlChar * name,
2065 const xmlChar * namespaceURI,
2066 const char *format, ...)
2067{
2068 int rc;
2069 va_list ap;
2070
2071 va_start(ap, format);
2072
2073 rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
2074 namespaceURI, format, ap);
2075
2076 va_end(ap);
2077 return rc;
2078}
2079
2080/**
2081 * xmlTextWriterWriteVFormatAttributeNS:
2082 * @writer: the xmlTextWriterPtr
2083 * @prefix: namespace prefix
2084 * @name: attribute local name
2085 * @namespaceURI: namespace URI
2086 * @format: format string (see printf)
2087 * @argptr: pointer to the first member of the variable argument list.
2088 *
2089 * Write a formatted xml attribute.with namespace support
2090 *
2091 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2092 */
2093int
2094xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
2095 const xmlChar * prefix,
2096 const xmlChar * name,
2097 const xmlChar * namespaceURI,
2098 const char *format, va_list argptr)
2099{
2100 int rc;
2101 xmlChar *buf;
2102
2103 if (writer == NULL)
2104 return -1;
2105
2106 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002107 if (buf == NULL)
2108 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002109
2110 rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
2111 buf);
2112
2113 xmlFree(buf);
2114 return rc;
2115}
2116
2117/**
2118 * xmlTextWriterWriteAttributeNS:
2119 * @writer: the xmlTextWriterPtr
2120 * @prefix: namespace prefix
2121 * @name: attribute local name
2122 * @namespaceURI: namespace URI
2123 * @content: attribute content
2124 *
2125 * Write an xml attribute.
2126 *
2127 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2128 */
2129int
2130xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
2131 const xmlChar * prefix, const xmlChar * name,
2132 const xmlChar * namespaceURI,
2133 const xmlChar * content)
2134{
2135 int count;
2136 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002137
2138 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2139 return -1;
2140
Daniel Veillard1d211e22003-10-20 22:32:39 +00002141 sum = 0;
Rob Richardsb8769d62007-06-08 08:50:47 +00002142 count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
2143 if (count < 0)
2144 return -1;
2145 sum += count;
2146 count = xmlTextWriterWriteString(writer, content);
2147 if (count < 0)
2148 return -1;
2149 sum += count;
2150 count = xmlTextWriterEndAttribute(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002151 if (count < 0)
2152 return -1;
2153 sum += count;
2154
Daniel Veillard1d211e22003-10-20 22:32:39 +00002155 return sum;
2156}
2157
2158/**
2159 * xmlTextWriterWriteFormatElement:
2160 * @writer: the xmlTextWriterPtr
2161 * @name: element name
2162 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002163 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002164 *
2165 * Write a formatted xml element.
2166 *
2167 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2168 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002169int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002170xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2171 const xmlChar * name, const char *format,
2172 ...)
2173{
2174 int rc;
2175 va_list ap;
2176
2177 va_start(ap, format);
2178
2179 rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2180
2181 va_end(ap);
2182 return rc;
2183}
2184
2185/**
2186 * xmlTextWriterWriteVFormatElement:
2187 * @writer: the xmlTextWriterPtr
2188 * @name: element name
2189 * @format: format string (see printf)
2190 * @argptr: pointer to the first member of the variable argument list.
2191 *
2192 * Write a formatted xml element.
2193 *
2194 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2195 */
2196int
2197xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2198 const xmlChar * name, const char *format,
2199 va_list argptr)
2200{
2201 int rc;
2202 xmlChar *buf;
2203
2204 if (writer == NULL)
2205 return -1;
2206
2207 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002208 if (buf == NULL)
2209 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002210
2211 rc = xmlTextWriterWriteElement(writer, name, buf);
2212
2213 xmlFree(buf);
2214 return rc;
2215}
2216
2217/**
2218 * xmlTextWriterWriteElement:
2219 * @writer: the xmlTextWriterPtr
2220 * @name: element name
2221 * @content: element content
2222 *
2223 * Write an xml element.
2224 *
2225 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2226 */
2227int
2228xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2229 const xmlChar * content)
2230{
2231 int count;
2232 int sum;
2233
2234 sum = 0;
2235 count = xmlTextWriterStartElement(writer, name);
2236 if (count == -1)
2237 return -1;
2238 sum += count;
Daniel Veillardc9ecf452014-02-08 02:22:35 +08002239 if (content != NULL) {
2240 count = xmlTextWriterWriteString(writer, content);
2241 if (count == -1)
2242 return -1;
2243 sum += count;
2244 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00002245 count = xmlTextWriterEndElement(writer);
2246 if (count == -1)
2247 return -1;
2248 sum += count;
2249
2250 return sum;
2251}
2252
2253/**
2254 * xmlTextWriterWriteFormatElementNS:
2255 * @writer: the xmlTextWriterPtr
2256 * @prefix: namespace prefix
2257 * @name: element local name
2258 * @namespaceURI: namespace URI
2259 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002260 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002261 *
2262 * Write a formatted xml element with namespace support.
2263 *
2264 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2265 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002266int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002267xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2268 const xmlChar * prefix,
2269 const xmlChar * name,
2270 const xmlChar * namespaceURI,
2271 const char *format, ...)
2272{
2273 int rc;
2274 va_list ap;
2275
2276 va_start(ap, format);
2277
2278 rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2279 namespaceURI, format, ap);
2280
2281 va_end(ap);
2282 return rc;
2283}
2284
2285/**
2286 * xmlTextWriterWriteVFormatElementNS:
2287 * @writer: the xmlTextWriterPtr
2288 * @prefix: namespace prefix
2289 * @name: element local name
2290 * @namespaceURI: namespace URI
2291 * @format: format string (see printf)
2292 * @argptr: pointer to the first member of the variable argument list.
2293 *
2294 * Write a formatted xml element with namespace support.
2295 *
2296 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2297 */
2298int
2299xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2300 const xmlChar * prefix,
2301 const xmlChar * name,
2302 const xmlChar * namespaceURI,
2303 const char *format, va_list argptr)
2304{
2305 int rc;
2306 xmlChar *buf;
2307
2308 if (writer == NULL)
2309 return -1;
2310
2311 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002312 if (buf == NULL)
2313 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002314
2315 rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2316 buf);
2317
2318 xmlFree(buf);
2319 return rc;
2320}
2321
2322/**
2323 * xmlTextWriterWriteElementNS:
2324 * @writer: the xmlTextWriterPtr
2325 * @prefix: namespace prefix
2326 * @name: element local name
2327 * @namespaceURI: namespace URI
2328 * @content: element content
2329 *
2330 * Write an xml element with namespace support.
2331 *
2332 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2333 */
2334int
2335xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2336 const xmlChar * prefix, const xmlChar * name,
2337 const xmlChar * namespaceURI,
2338 const xmlChar * content)
2339{
2340 int count;
2341 int sum;
2342
2343 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2344 return -1;
2345
2346 sum = 0;
2347 count =
2348 xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2349 if (count < 0)
2350 return -1;
2351 sum += count;
2352 count = xmlTextWriterWriteString(writer, content);
2353 if (count == -1)
2354 return -1;
2355 sum += count;
2356 count = xmlTextWriterEndElement(writer);
2357 if (count == -1)
2358 return -1;
2359 sum += count;
2360
2361 return sum;
2362}
2363
2364/**
2365 * xmlTextWriterStartPI:
2366 * @writer: the xmlTextWriterPtr
2367 * @target: PI target
2368 *
2369 * Start an xml PI.
2370 *
2371 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2372 */
2373int
2374xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2375{
2376 int count;
2377 int sum;
2378 xmlLinkPtr lk;
2379 xmlTextWriterStackEntry *p;
2380
2381 if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2382 return -1;
2383
2384 if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002385 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002386 "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2387 return -1;
2388 }
2389
2390 sum = 0;
2391 lk = xmlListFront(writer->nodes);
2392 if (lk != 0) {
2393 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2394 if (p != 0) {
2395 switch (p->state) {
2396 case XML_TEXTWRITER_ATTRIBUTE:
2397 count = xmlTextWriterEndAttribute(writer);
2398 if (count < 0)
2399 return -1;
2400 sum += count;
2401 /* fallthrough */
2402 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002403 /* Output namespace declarations */
2404 count = xmlTextWriterOutputNSDecl(writer);
2405 if (count < 0)
2406 return -1;
2407 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002408 count = xmlOutputBufferWriteString(writer->out, ">");
2409 if (count < 0)
2410 return -1;
2411 sum += count;
2412 p->state = XML_TEXTWRITER_TEXT;
2413 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00002414 case XML_TEXTWRITER_NONE:
2415 case XML_TEXTWRITER_TEXT:
2416 case XML_TEXTWRITER_DTD:
2417 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002418 case XML_TEXTWRITER_PI:
2419 case XML_TEXTWRITER_PI_TEXT:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002420 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002421 "xmlTextWriterStartPI : nested PI!\n");
2422 return -1;
2423 default:
2424 return -1;
2425 }
2426 }
2427 }
2428
2429 p = (xmlTextWriterStackEntry *)
2430 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2431 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002432 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002433 "xmlTextWriterStartPI : out of memory!\n");
2434 return -1;
2435 }
2436
2437 p->name = xmlStrdup(target);
2438 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002439 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002440 "xmlTextWriterStartPI : out of memory!\n");
2441 xmlFree(p);
2442 return -1;
2443 }
2444 p->state = XML_TEXTWRITER_PI;
2445
2446 xmlListPushFront(writer->nodes, p);
2447
2448 count = xmlOutputBufferWriteString(writer->out, "<?");
2449 if (count < 0)
2450 return -1;
2451 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002452 count =
2453 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002454 if (count < 0)
2455 return -1;
2456 sum += count;
2457
2458 return sum;
2459}
2460
2461/**
2462 * xmlTextWriterEndPI:
2463 * @writer: the xmlTextWriterPtr
2464 *
2465 * End the current xml PI.
2466 *
2467 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2468 */
2469int
2470xmlTextWriterEndPI(xmlTextWriterPtr writer)
2471{
2472 int count;
2473 int sum;
2474 xmlLinkPtr lk;
2475 xmlTextWriterStackEntry *p;
2476
2477 if (writer == NULL)
2478 return -1;
2479
2480 lk = xmlListFront(writer->nodes);
2481 if (lk == 0)
2482 return 0;
2483
2484 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2485 if (p == 0)
2486 return 0;
2487
2488 sum = 0;
2489 switch (p->state) {
2490 case XML_TEXTWRITER_PI:
2491 case XML_TEXTWRITER_PI_TEXT:
2492 count = xmlOutputBufferWriteString(writer->out, "?>");
2493 if (count < 0)
2494 return -1;
2495 sum += count;
2496 break;
2497 default:
2498 return -1;
2499 }
2500
Daniel Veillard02c1f232006-04-27 08:10:25 +00002501 if (writer->indent) {
2502 count = xmlOutputBufferWriteString(writer->out, "\n");
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002503 if (count < 0)
2504 return -1;
Daniel Veillard02c1f232006-04-27 08:10:25 +00002505 sum += count;
2506 }
2507
Daniel Veillard1d211e22003-10-20 22:32:39 +00002508 xmlListPopFront(writer->nodes);
2509 return sum;
2510}
2511
2512/**
2513 * xmlTextWriterWriteFormatPI:
2514 * @writer: the xmlTextWriterPtr
2515 * @target: PI target
2516 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002517 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002518 *
2519 * Write a formatted PI.
2520 *
2521 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2522 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002523int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002524xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2525 const char *format, ...)
2526{
2527 int rc;
2528 va_list ap;
2529
2530 va_start(ap, format);
2531
2532 rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2533
2534 va_end(ap);
2535 return rc;
2536}
2537
2538/**
2539 * xmlTextWriterWriteVFormatPI:
2540 * @writer: the xmlTextWriterPtr
2541 * @target: PI target
2542 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002543 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002544 *
2545 * Write a formatted xml PI.
2546 *
2547 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2548 */
2549int
2550xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2551 const xmlChar * target, const char *format,
2552 va_list argptr)
2553{
2554 int rc;
2555 xmlChar *buf;
2556
2557 if (writer == NULL)
2558 return -1;
2559
2560 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002561 if (buf == NULL)
2562 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002563
2564 rc = xmlTextWriterWritePI(writer, target, buf);
2565
2566 xmlFree(buf);
2567 return rc;
2568}
2569
2570/**
2571 * xmlTextWriterWritePI:
2572 * @writer: the xmlTextWriterPtr
2573 * @target: PI target
2574 * @content: PI content
2575 *
2576 * Write an xml PI.
2577 *
2578 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2579 */
2580int
2581xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2582 const xmlChar * content)
2583{
2584 int count;
2585 int sum;
2586
2587 sum = 0;
2588 count = xmlTextWriterStartPI(writer, target);
2589 if (count == -1)
2590 return -1;
2591 sum += count;
2592 if (content != 0) {
2593 count = xmlTextWriterWriteString(writer, content);
2594 if (count == -1)
2595 return -1;
2596 sum += count;
2597 }
2598 count = xmlTextWriterEndPI(writer);
2599 if (count == -1)
2600 return -1;
2601 sum += count;
2602
2603 return sum;
2604}
2605
2606/**
2607 * xmlTextWriterStartCDATA:
2608 * @writer: the xmlTextWriterPtr
2609 *
2610 * Start an xml CDATA section.
2611 *
2612 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2613 */
2614int
2615xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2616{
2617 int count;
2618 int sum;
2619 xmlLinkPtr lk;
2620 xmlTextWriterStackEntry *p;
2621
2622 if (writer == NULL)
2623 return -1;
2624
2625 sum = 0;
2626 lk = xmlListFront(writer->nodes);
2627 if (lk != 0) {
2628 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2629 if (p != 0) {
2630 switch (p->state) {
2631 case XML_TEXTWRITER_NONE:
Daniel Veillardccc476f2008-03-04 13:19:49 +00002632 case XML_TEXTWRITER_TEXT:
Daniel Veillard1d211e22003-10-20 22:32:39 +00002633 case XML_TEXTWRITER_PI:
2634 case XML_TEXTWRITER_PI_TEXT:
2635 break;
2636 case XML_TEXTWRITER_ATTRIBUTE:
2637 count = xmlTextWriterEndAttribute(writer);
2638 if (count < 0)
2639 return -1;
2640 sum += count;
2641 /* fallthrough */
2642 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002643 /* Output namespace declarations */
2644 count = xmlTextWriterOutputNSDecl(writer);
2645 if (count < 0)
2646 return -1;
2647 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002648 count = xmlOutputBufferWriteString(writer->out, ">");
2649 if (count < 0)
2650 return -1;
2651 sum += count;
2652 p->state = XML_TEXTWRITER_TEXT;
2653 break;
2654 case XML_TEXTWRITER_CDATA:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002655 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002656 "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2657 return -1;
2658 default:
2659 return -1;
2660 }
2661 }
2662 }
2663
2664 p = (xmlTextWriterStackEntry *)
2665 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2666 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002667 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002668 "xmlTextWriterStartCDATA : out of memory!\n");
2669 return -1;
2670 }
2671
Daniel Veillard75e389d2005-07-29 22:02:24 +00002672 p->name = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002673 p->state = XML_TEXTWRITER_CDATA;
2674
2675 xmlListPushFront(writer->nodes, p);
2676
2677 count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2678 if (count < 0)
2679 return -1;
2680 sum += count;
2681
2682 return sum;
2683}
2684
2685/**
2686 * xmlTextWriterEndCDATA:
2687 * @writer: the xmlTextWriterPtr
2688 *
2689 * End an xml CDATA section.
2690 *
2691 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2692 */
2693int
2694xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2695{
2696 int count;
2697 int sum;
2698 xmlLinkPtr lk;
2699 xmlTextWriterStackEntry *p;
2700
2701 if (writer == NULL)
2702 return -1;
2703
2704 lk = xmlListFront(writer->nodes);
2705 if (lk == 0)
2706 return -1;
2707
2708 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2709 if (p == 0)
2710 return -1;
2711
2712 sum = 0;
2713 switch (p->state) {
2714 case XML_TEXTWRITER_CDATA:
2715 count = xmlOutputBufferWriteString(writer->out, "]]>");
2716 if (count < 0)
2717 return -1;
2718 sum += count;
2719 break;
2720 default:
2721 return -1;
2722 }
2723
2724 xmlListPopFront(writer->nodes);
2725 return sum;
2726}
2727
2728/**
2729 * xmlTextWriterWriteFormatCDATA:
2730 * @writer: the xmlTextWriterPtr
2731 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002732 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002733 *
2734 * Write a formatted xml CDATA.
2735 *
2736 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2737 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002738int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002739xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2740 ...)
2741{
2742 int rc;
2743 va_list ap;
2744
2745 va_start(ap, format);
2746
2747 rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2748
2749 va_end(ap);
2750 return rc;
2751}
2752
2753/**
2754 * xmlTextWriterWriteVFormatCDATA:
2755 * @writer: the xmlTextWriterPtr
2756 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002757 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002758 *
2759 * Write a formatted xml CDATA.
2760 *
2761 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2762 */
2763int
2764xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2765 va_list argptr)
2766{
2767 int rc;
2768 xmlChar *buf;
2769
2770 if (writer == NULL)
2771 return -1;
2772
2773 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002774 if (buf == NULL)
2775 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002776
2777 rc = xmlTextWriterWriteCDATA(writer, buf);
2778
2779 xmlFree(buf);
2780 return rc;
2781}
2782
2783/**
2784 * xmlTextWriterWriteCDATA:
2785 * @writer: the xmlTextWriterPtr
2786 * @content: CDATA content
2787 *
2788 * Write an xml CDATA.
2789 *
2790 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2791 */
2792int
2793xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2794{
2795 int count;
2796 int sum;
2797
2798 sum = 0;
2799 count = xmlTextWriterStartCDATA(writer);
2800 if (count == -1)
2801 return -1;
2802 sum += count;
2803 if (content != 0) {
2804 count = xmlTextWriterWriteString(writer, content);
2805 if (count == -1)
2806 return -1;
2807 sum += count;
2808 }
2809 count = xmlTextWriterEndCDATA(writer);
2810 if (count == -1)
2811 return -1;
2812 sum += count;
2813
2814 return sum;
2815}
2816
2817/**
2818 * xmlTextWriterStartDTD:
2819 * @writer: the xmlTextWriterPtr
2820 * @name: the name of the DTD
2821 * @pubid: the public identifier, which is an alternative to the system identifier
2822 * @sysid: the system identifier, which is the URI of the DTD
2823 *
2824 * Start an xml DTD.
2825 *
2826 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2827 */
2828int
2829xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2830 const xmlChar * name,
2831 const xmlChar * pubid, const xmlChar * sysid)
2832{
2833 int count;
2834 int sum;
2835 xmlLinkPtr lk;
2836 xmlTextWriterStackEntry *p;
2837
2838 if (writer == NULL || name == NULL || *name == '\0')
2839 return -1;
2840
2841 sum = 0;
2842 lk = xmlListFront(writer->nodes);
Daniel Veillardab69f362004-02-17 11:40:32 +00002843 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002844 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002845 "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2846 return -1;
2847 }
2848
2849 p = (xmlTextWriterStackEntry *)
2850 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2851 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002852 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002853 "xmlTextWriterStartDTD : out of memory!\n");
2854 return -1;
2855 }
2856
2857 p->name = xmlStrdup(name);
2858 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002859 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002860 "xmlTextWriterStartDTD : out of memory!\n");
2861 xmlFree(p);
2862 return -1;
2863 }
2864 p->state = XML_TEXTWRITER_DTD;
2865
2866 xmlListPushFront(writer->nodes, p);
2867
2868 count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2869 if (count < 0)
2870 return -1;
2871 sum += count;
2872 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2873 if (count < 0)
2874 return -1;
2875 sum += count;
2876
2877 if (pubid != 0) {
2878 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002879 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002880 "xmlTextWriterStartDTD : system identifier needed!\n");
2881 return -1;
2882 }
2883
Daniel Veillard500a1de2004-03-22 15:22:58 +00002884 if (writer->indent)
2885 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2886 else
2887 count = xmlOutputBufferWrite(writer->out, 1, " ");
2888 if (count < 0)
2889 return -1;
2890 sum += count;
2891
2892 count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2893 if (count < 0)
2894 return -1;
2895 sum += count;
2896
2897 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002898 if (count < 0)
2899 return -1;
2900 sum += count;
2901
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002902 count =
2903 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002904 if (count < 0)
2905 return -1;
2906 sum += count;
2907
Daniel Veillard500a1de2004-03-22 15:22:58 +00002908 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002909 if (count < 0)
2910 return -1;
2911 sum += count;
2912 }
2913
2914 if (sysid != 0) {
2915 if (pubid == 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00002916 if (writer->indent)
2917 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2918 else
2919 count = xmlOutputBufferWrite(writer->out, 1, " ");
2920 if (count < 0)
2921 return -1;
2922 sum += count;
2923 count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2924 if (count < 0)
2925 return -1;
2926 sum += count;
Rob Richardsffe47fe2005-12-09 17:52:21 +00002927 } else {
2928 if (writer->indent)
Daniel Veillard500a1de2004-03-22 15:22:58 +00002929 count = xmlOutputBufferWriteString(writer->out, "\n ");
Rob Richardsffe47fe2005-12-09 17:52:21 +00002930 else
2931 count = xmlOutputBufferWrite(writer->out, 1, " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00002932 if (count < 0)
2933 return -1;
2934 sum += count;
2935 }
2936
Daniel Veillard500a1de2004-03-22 15:22:58 +00002937 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002938 if (count < 0)
2939 return -1;
2940 sum += count;
2941
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002942 count =
2943 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002944 if (count < 0)
2945 return -1;
2946 sum += count;
2947
Daniel Veillard500a1de2004-03-22 15:22:58 +00002948 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002949 if (count < 0)
2950 return -1;
2951 sum += count;
2952 }
2953
2954 return sum;
2955}
2956
2957/**
2958 * xmlTextWriterEndDTD:
2959 * @writer: the xmlTextWriterPtr
2960 *
2961 * End an xml DTD.
2962 *
2963 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2964 */
2965int
2966xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2967{
Daniel Veillard500a1de2004-03-22 15:22:58 +00002968 int loop;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002969 int count;
2970 int sum;
2971 xmlLinkPtr lk;
2972 xmlTextWriterStackEntry *p;
2973
2974 if (writer == NULL)
2975 return -1;
2976
2977 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002978 loop = 1;
2979 while (loop) {
2980 lk = xmlListFront(writer->nodes);
2981 if (lk == NULL)
Daniel Veillard1d211e22003-10-20 22:32:39 +00002982 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002983 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2984 if (p == 0)
2985 break;
2986 switch (p->state) {
2987 case XML_TEXTWRITER_DTD_TEXT:
2988 count = xmlOutputBufferWriteString(writer->out, "]");
2989 if (count < 0)
2990 return -1;
2991 sum += count;
2992 /* fallthrough */
2993 case XML_TEXTWRITER_DTD:
2994 count = xmlOutputBufferWriteString(writer->out, ">");
2995
2996 if (writer->indent) {
2997 if (count < 0)
2998 return -1;
2999 sum += count;
3000 count = xmlOutputBufferWriteString(writer->out, "\n");
3001 }
3002
3003 xmlListPopFront(writer->nodes);
3004 break;
3005 case XML_TEXTWRITER_DTD_ELEM:
3006 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3007 count = xmlTextWriterEndDTDElement(writer);
3008 break;
3009 case XML_TEXTWRITER_DTD_ATTL:
3010 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3011 count = xmlTextWriterEndDTDAttlist(writer);
3012 break;
3013 case XML_TEXTWRITER_DTD_ENTY:
3014 case XML_TEXTWRITER_DTD_PENT:
3015 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3016 count = xmlTextWriterEndDTDEntity(writer);
3017 break;
3018 case XML_TEXTWRITER_COMMENT:
3019 count = xmlTextWriterEndComment(writer);
3020 break;
3021 default:
3022 loop = 0;
3023 continue;
3024 }
3025
3026 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00003027 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003028 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003029 }
3030
Daniel Veillard1d211e22003-10-20 22:32:39 +00003031 return sum;
3032}
3033
3034/**
3035 * xmlTextWriterWriteFormatDTD:
3036 * @writer: the xmlTextWriterPtr
3037 * @name: the name of the DTD
3038 * @pubid: the public identifier, which is an alternative to the system identifier
3039 * @sysid: the system identifier, which is the URI of the DTD
3040 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003041 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00003042 *
3043 * Write a DTD with a formatted markup declarations part.
3044 *
3045 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3046 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003047int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003048xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3049 const xmlChar * name,
3050 const xmlChar * pubid,
3051 const xmlChar * sysid, const char *format, ...)
3052{
3053 int rc;
3054 va_list ap;
3055
3056 va_start(ap, format);
3057
3058 rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3059 ap);
3060
3061 va_end(ap);
3062 return rc;
3063}
3064
3065/**
3066 * xmlTextWriterWriteVFormatDTD:
3067 * @writer: the xmlTextWriterPtr
3068 * @name: the name of the DTD
3069 * @pubid: the public identifier, which is an alternative to the system identifier
3070 * @sysid: the system identifier, which is the URI of the DTD
3071 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003072 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00003073 *
3074 * Write a DTD with a formatted markup declarations part.
3075 *
3076 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3077 */
3078int
3079xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3080 const xmlChar * name,
3081 const xmlChar * pubid,
3082 const xmlChar * sysid,
3083 const char *format, va_list argptr)
3084{
3085 int rc;
3086 xmlChar *buf;
3087
3088 if (writer == NULL)
3089 return -1;
3090
3091 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003092 if (buf == NULL)
3093 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003094
3095 rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3096
3097 xmlFree(buf);
3098 return rc;
3099}
3100
3101/**
3102 * xmlTextWriterWriteDTD:
3103 * @writer: the xmlTextWriterPtr
3104 * @name: the name of the DTD
3105 * @pubid: the public identifier, which is an alternative to the system identifier
3106 * @sysid: the system identifier, which is the URI of the DTD
William M. Brackb1d53162003-11-18 06:54:40 +00003107 * @subset: string content of the DTD
Daniel Veillard1d211e22003-10-20 22:32:39 +00003108 *
3109 * Write a DTD.
3110 *
3111 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3112 */
3113int
3114xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3115 const xmlChar * name,
3116 const xmlChar * pubid,
3117 const xmlChar * sysid, const xmlChar * subset)
3118{
3119 int count;
3120 int sum;
3121
3122 sum = 0;
3123 count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3124 if (count == -1)
3125 return -1;
3126 sum += count;
3127 if (subset != 0) {
3128 count = xmlTextWriterWriteString(writer, subset);
3129 if (count == -1)
3130 return -1;
3131 sum += count;
3132 }
3133 count = xmlTextWriterEndDTD(writer);
3134 if (count == -1)
3135 return -1;
3136 sum += count;
3137
3138 return sum;
3139}
3140
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003141/**
3142 * xmlTextWriterStartDTDElement:
3143 * @writer: the xmlTextWriterPtr
3144 * @name: the name of the DTD element
3145 *
3146 * Start an xml DTD element.
3147 *
3148 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3149 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003150int
3151xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3152{
3153 int count;
3154 int sum;
3155 xmlLinkPtr lk;
3156 xmlTextWriterStackEntry *p;
3157
3158 if (writer == NULL || name == NULL || *name == '\0')
3159 return -1;
3160
3161 sum = 0;
3162 lk = xmlListFront(writer->nodes);
3163 if (lk == 0) {
3164 return -1;
3165 }
3166
3167 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003168 if (p != 0) {
3169 switch (p->state) {
3170 case XML_TEXTWRITER_DTD:
3171 count = xmlOutputBufferWriteString(writer->out, " [");
3172 if (count < 0)
3173 return -1;
3174 sum += count;
3175 if (writer->indent) {
3176 count = xmlOutputBufferWriteString(writer->out, "\n");
3177 if (count < 0)
3178 return -1;
3179 sum += count;
3180 }
3181 p->state = XML_TEXTWRITER_DTD_TEXT;
3182 /* fallthrough */
3183 case XML_TEXTWRITER_DTD_TEXT:
3184 case XML_TEXTWRITER_NONE:
3185 break;
3186 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003187 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003188 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003189 }
3190
3191 p = (xmlTextWriterStackEntry *)
3192 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3193 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003194 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003195 "xmlTextWriterStartDTDElement : out of memory!\n");
3196 return -1;
3197 }
3198
3199 p->name = xmlStrdup(name);
3200 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003201 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003202 "xmlTextWriterStartDTDElement : out of memory!\n");
3203 xmlFree(p);
3204 return -1;
3205 }
3206 p->state = XML_TEXTWRITER_DTD_ELEM;
3207
3208 xmlListPushFront(writer->nodes, p);
3209
Daniel Veillard500a1de2004-03-22 15:22:58 +00003210 if (writer->indent) {
3211 count = xmlTextWriterWriteIndent(writer);
3212 if (count < 0)
3213 return -1;
3214 sum += count;
3215 }
3216
Daniel Veillard1d211e22003-10-20 22:32:39 +00003217 count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3218 if (count < 0)
3219 return -1;
3220 sum += count;
3221 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3222 if (count < 0)
3223 return -1;
3224 sum += count;
3225
3226 return sum;
3227}
3228
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003229/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003230 * xmlTextWriterEndDTDElement:
3231 * @writer: the xmlTextWriterPtr
3232 *
3233 * End an xml DTD element.
3234 *
3235 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3236 */
3237int
3238xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3239{
3240 int count;
3241 int sum;
3242 xmlLinkPtr lk;
3243 xmlTextWriterStackEntry *p;
3244
3245 if (writer == NULL)
3246 return -1;
3247
3248 sum = 0;
3249 lk = xmlListFront(writer->nodes);
3250 if (lk == 0)
3251 return -1;
3252
3253 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3254 if (p == 0)
3255 return -1;
3256
3257 switch (p->state) {
3258 case XML_TEXTWRITER_DTD_ELEM:
3259 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3260 count = xmlOutputBufferWriteString(writer->out, ">");
3261 if (count < 0)
3262 return -1;
3263 sum += count;
3264 break;
3265 default:
3266 return -1;
3267 }
3268
3269 if (writer->indent) {
3270 count = xmlOutputBufferWriteString(writer->out, "\n");
3271 if (count < 0)
3272 return -1;
3273 sum += count;
3274 }
3275
3276 xmlListPopFront(writer->nodes);
3277 return sum;
3278}
3279
3280/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003281 * xmlTextWriterWriteFormatDTDElement:
3282 * @writer: the xmlTextWriterPtr
3283 * @name: the name of the DTD element
3284 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003285 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003286 *
3287 * Write a formatted DTD element.
3288 *
3289 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3290 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003291int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003292xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3293 const xmlChar * name,
3294 const char *format, ...)
3295{
3296 int rc;
3297 va_list ap;
3298
3299 va_start(ap, format);
3300
3301 rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3302
3303 va_end(ap);
3304 return rc;
3305}
3306
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003307/**
3308 * xmlTextWriterWriteVFormatDTDElement:
3309 * @writer: the xmlTextWriterPtr
3310 * @name: the name of the DTD element
3311 * @format: format string (see printf)
3312 * @argptr: pointer to the first member of the variable argument list.
3313 *
3314 * Write a formatted DTD element.
3315 *
3316 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3317 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003318int
3319xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3320 const xmlChar * name,
3321 const char *format, va_list argptr)
3322{
3323 int rc;
3324 xmlChar *buf;
3325
3326 if (writer == NULL)
3327 return -1;
3328
3329 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003330 if (buf == NULL)
3331 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003332
3333 rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3334
3335 xmlFree(buf);
3336 return rc;
3337}
3338
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003339/**
3340 * xmlTextWriterWriteDTDElement:
3341 * @writer: the xmlTextWriterPtr
3342 * @name: the name of the DTD element
3343 * @content: content of the element
3344 *
3345 * Write a DTD element.
3346 *
3347 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3348 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003349int
3350xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3351 const xmlChar * name, const xmlChar * content)
3352{
3353 int count;
3354 int sum;
3355
3356 if (content == NULL)
3357 return -1;
3358
3359 sum = 0;
3360 count = xmlTextWriterStartDTDElement(writer, name);
3361 if (count == -1)
3362 return -1;
3363 sum += count;
3364
Daniel Veillard1d211e22003-10-20 22:32:39 +00003365 count = xmlTextWriterWriteString(writer, content);
3366 if (count == -1)
3367 return -1;
3368 sum += count;
3369
3370 count = xmlTextWriterEndDTDElement(writer);
3371 if (count == -1)
3372 return -1;
3373 sum += count;
3374
3375 return sum;
3376}
3377
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003378/**
3379 * xmlTextWriterStartDTDAttlist:
3380 * @writer: the xmlTextWriterPtr
3381 * @name: the name of the DTD ATTLIST
3382 *
3383 * Start an xml DTD ATTLIST.
3384 *
3385 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3386 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003387int
3388xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3389{
3390 int count;
3391 int sum;
3392 xmlLinkPtr lk;
3393 xmlTextWriterStackEntry *p;
3394
3395 if (writer == NULL || name == NULL || *name == '\0')
3396 return -1;
3397
3398 sum = 0;
3399 lk = xmlListFront(writer->nodes);
3400 if (lk == 0) {
3401 return -1;
3402 }
3403
3404 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003405 if (p != 0) {
3406 switch (p->state) {
3407 case XML_TEXTWRITER_DTD:
3408 count = xmlOutputBufferWriteString(writer->out, " [");
3409 if (count < 0)
3410 return -1;
3411 sum += count;
3412 if (writer->indent) {
3413 count = xmlOutputBufferWriteString(writer->out, "\n");
3414 if (count < 0)
3415 return -1;
3416 sum += count;
3417 }
3418 p->state = XML_TEXTWRITER_DTD_TEXT;
3419 /* fallthrough */
3420 case XML_TEXTWRITER_DTD_TEXT:
3421 case XML_TEXTWRITER_NONE:
3422 break;
3423 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003424 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003425 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003426 }
3427
3428 p = (xmlTextWriterStackEntry *)
3429 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3430 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003431 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003432 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3433 return -1;
3434 }
3435
3436 p->name = xmlStrdup(name);
3437 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003438 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003439 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3440 xmlFree(p);
3441 return -1;
3442 }
3443 p->state = XML_TEXTWRITER_DTD_ATTL;
3444
3445 xmlListPushFront(writer->nodes, p);
3446
Daniel Veillard500a1de2004-03-22 15:22:58 +00003447 if (writer->indent) {
3448 count = xmlTextWriterWriteIndent(writer);
3449 if (count < 0)
3450 return -1;
3451 sum += count;
3452 }
3453
Daniel Veillard1d211e22003-10-20 22:32:39 +00003454 count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3455 if (count < 0)
3456 return -1;
3457 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +00003458 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003459 if (count < 0)
3460 return -1;
3461 sum += count;
3462
3463 return sum;
3464}
3465
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003466/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003467 * xmlTextWriterEndDTDAttlist:
3468 * @writer: the xmlTextWriterPtr
3469 *
3470 * End an xml DTD attribute list.
3471 *
3472 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3473 */
3474int
3475xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3476{
3477 int count;
3478 int sum;
3479 xmlLinkPtr lk;
3480 xmlTextWriterStackEntry *p;
3481
3482 if (writer == NULL)
3483 return -1;
3484
3485 sum = 0;
3486 lk = xmlListFront(writer->nodes);
3487 if (lk == 0)
3488 return -1;
3489
3490 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3491 if (p == 0)
3492 return -1;
3493
3494 switch (p->state) {
3495 case XML_TEXTWRITER_DTD_ATTL:
3496 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3497 count = xmlOutputBufferWriteString(writer->out, ">");
3498 if (count < 0)
3499 return -1;
3500 sum += count;
3501 break;
3502 default:
3503 return -1;
3504 }
3505
3506 if (writer->indent) {
3507 count = xmlOutputBufferWriteString(writer->out, "\n");
3508 if (count < 0)
3509 return -1;
3510 sum += count;
3511 }
3512
3513 xmlListPopFront(writer->nodes);
3514 return sum;
3515}
3516
3517/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003518 * xmlTextWriterWriteFormatDTDAttlist:
3519 * @writer: the xmlTextWriterPtr
3520 * @name: the name of the DTD ATTLIST
3521 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003522 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003523 *
3524 * Write a formatted DTD ATTLIST.
3525 *
3526 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3527 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003528int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003529xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3530 const xmlChar * name,
3531 const char *format, ...)
3532{
3533 int rc;
3534 va_list ap;
3535
3536 va_start(ap, format);
3537
3538 rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3539
3540 va_end(ap);
3541 return rc;
3542}
3543
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003544/**
3545 * xmlTextWriterWriteVFormatDTDAttlist:
3546 * @writer: the xmlTextWriterPtr
3547 * @name: the name of the DTD ATTLIST
3548 * @format: format string (see printf)
3549 * @argptr: pointer to the first member of the variable argument list.
3550 *
3551 * Write a formatted DTD ATTLIST.
3552 *
3553 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3554 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003555int
3556xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3557 const xmlChar * name,
3558 const char *format, va_list argptr)
3559{
3560 int rc;
3561 xmlChar *buf;
3562
3563 if (writer == NULL)
3564 return -1;
3565
3566 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003567 if (buf == NULL)
3568 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003569
3570 rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3571
3572 xmlFree(buf);
3573 return rc;
3574}
3575
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003576/**
3577 * xmlTextWriterWriteDTDAttlist:
3578 * @writer: the xmlTextWriterPtr
3579 * @name: the name of the DTD ATTLIST
3580 * @content: content of the ATTLIST
3581 *
3582 * Write a DTD ATTLIST.
3583 *
3584 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3585 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003586int
3587xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3588 const xmlChar * name, const xmlChar * content)
3589{
3590 int count;
3591 int sum;
3592
3593 if (content == NULL)
3594 return -1;
3595
3596 sum = 0;
3597 count = xmlTextWriterStartDTDAttlist(writer, name);
3598 if (count == -1)
3599 return -1;
3600 sum += count;
3601
Daniel Veillard1d211e22003-10-20 22:32:39 +00003602 count = xmlTextWriterWriteString(writer, content);
3603 if (count == -1)
3604 return -1;
3605 sum += count;
3606
3607 count = xmlTextWriterEndDTDAttlist(writer);
3608 if (count == -1)
3609 return -1;
3610 sum += count;
3611
3612 return sum;
3613}
3614
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003615/**
3616 * xmlTextWriterStartDTDEntity:
3617 * @writer: the xmlTextWriterPtr
3618 * @pe: TRUE if this is a parameter entity, FALSE if not
3619 * @name: the name of the DTD ATTLIST
3620 *
3621 * Start an xml DTD ATTLIST.
3622 *
3623 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3624 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003625int
3626xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3627 int pe, const xmlChar * name)
3628{
3629 int count;
3630 int sum;
3631 xmlLinkPtr lk;
3632 xmlTextWriterStackEntry *p;
3633
3634 if (writer == NULL || name == NULL || *name == '\0')
3635 return -1;
3636
3637 sum = 0;
3638 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003639 if (lk != 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00003640
Daniel Veillard500a1de2004-03-22 15:22:58 +00003641 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3642 if (p != 0) {
3643 switch (p->state) {
3644 case XML_TEXTWRITER_DTD:
3645 count = xmlOutputBufferWriteString(writer->out, " [");
3646 if (count < 0)
3647 return -1;
3648 sum += count;
3649 if (writer->indent) {
3650 count =
3651 xmlOutputBufferWriteString(writer->out, "\n");
3652 if (count < 0)
3653 return -1;
3654 sum += count;
3655 }
3656 p->state = XML_TEXTWRITER_DTD_TEXT;
3657 /* fallthrough */
3658 case XML_TEXTWRITER_DTD_TEXT:
3659 case XML_TEXTWRITER_NONE:
3660 break;
3661 default:
3662 return -1;
3663 }
3664 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003665 }
3666
3667 p = (xmlTextWriterStackEntry *)
3668 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3669 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003670 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003671 "xmlTextWriterStartDTDElement : out of memory!\n");
3672 return -1;
3673 }
3674
3675 p->name = xmlStrdup(name);
3676 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003677 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003678 "xmlTextWriterStartDTDElement : out of memory!\n");
3679 xmlFree(p);
3680 return -1;
3681 }
Daniel Veillard500a1de2004-03-22 15:22:58 +00003682
3683 if (pe != 0)
3684 p->state = XML_TEXTWRITER_DTD_PENT;
3685 else
3686 p->state = XML_TEXTWRITER_DTD_ENTY;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003687
3688 xmlListPushFront(writer->nodes, p);
3689
Daniel Veillard500a1de2004-03-22 15:22:58 +00003690 if (writer->indent) {
3691 count = xmlTextWriterWriteIndent(writer);
3692 if (count < 0)
3693 return -1;
3694 sum += count;
3695 }
3696
Daniel Veillard1d211e22003-10-20 22:32:39 +00003697 count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3698 if (count < 0)
3699 return -1;
3700 sum += count;
3701
3702 if (pe != 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00003703 count = xmlOutputBufferWriteString(writer->out, "% ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003704 if (count < 0)
3705 return -1;
3706 sum += count;
3707 }
3708
Daniel Veillardab69f362004-02-17 11:40:32 +00003709 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003710 if (count < 0)
3711 return -1;
3712 sum += count;
3713
3714 return sum;
3715}
3716
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003717/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003718 * xmlTextWriterEndDTDEntity:
3719 * @writer: the xmlTextWriterPtr
3720 *
3721 * End an xml DTD entity.
3722 *
3723 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3724 */
3725int
3726xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3727{
3728 int count;
3729 int sum;
3730 xmlLinkPtr lk;
3731 xmlTextWriterStackEntry *p;
3732
3733 if (writer == NULL)
3734 return -1;
3735
3736 sum = 0;
3737 lk = xmlListFront(writer->nodes);
3738 if (lk == 0)
3739 return -1;
3740
3741 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3742 if (p == 0)
3743 return -1;
3744
3745 switch (p->state) {
3746 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3747 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3748 if (count < 0)
3749 return -1;
3750 sum += count;
J. Peter Mugaasd2c329a2017-10-21 13:49:31 +02003751 /* Falls through. */
Daniel Veillard500a1de2004-03-22 15:22:58 +00003752 case XML_TEXTWRITER_DTD_ENTY:
3753 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard500a1de2004-03-22 15:22:58 +00003754 count = xmlOutputBufferWriteString(writer->out, ">");
3755 if (count < 0)
3756 return -1;
3757 sum += count;
3758 break;
3759 default:
3760 return -1;
3761 }
3762
3763 if (writer->indent) {
3764 count = xmlOutputBufferWriteString(writer->out, "\n");
3765 if (count < 0)
3766 return -1;
3767 sum += count;
3768 }
3769
3770 xmlListPopFront(writer->nodes);
3771 return sum;
3772}
3773
3774/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003775 * xmlTextWriterWriteFormatDTDInternalEntity:
3776 * @writer: the xmlTextWriterPtr
3777 * @pe: TRUE if this is a parameter entity, FALSE if not
3778 * @name: the name of the DTD entity
3779 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003780 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003781 *
3782 * Write a formatted DTD internal entity.
3783 *
3784 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3785 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003786int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003787xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3788 int pe,
3789 const xmlChar * name,
3790 const char *format, ...)
3791{
3792 int rc;
3793 va_list ap;
3794
3795 va_start(ap, format);
3796
3797 rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3798 format, ap);
3799
3800 va_end(ap);
3801 return rc;
3802}
3803
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003804/**
3805 * xmlTextWriterWriteVFormatDTDInternalEntity:
3806 * @writer: the xmlTextWriterPtr
3807 * @pe: TRUE if this is a parameter entity, FALSE if not
3808 * @name: the name of the DTD entity
3809 * @format: format string (see printf)
3810 * @argptr: pointer to the first member of the variable argument list.
3811 *
3812 * Write a formatted DTD internal entity.
3813 *
3814 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3815 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003816int
3817xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3818 int pe,
3819 const xmlChar * name,
3820 const char *format,
3821 va_list argptr)
3822{
3823 int rc;
3824 xmlChar *buf;
3825
3826 if (writer == NULL)
3827 return -1;
3828
3829 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003830 if (buf == NULL)
3831 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003832
3833 rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3834
3835 xmlFree(buf);
3836 return rc;
3837}
3838
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003839/**
3840 * xmlTextWriterWriteDTDEntity:
3841 * @writer: the xmlTextWriterPtr
3842 * @pe: TRUE if this is a parameter entity, FALSE if not
3843 * @name: the name of the DTD entity
3844 * @pubid: the public identifier, which is an alternative to the system identifier
3845 * @sysid: the system identifier, which is the URI of the DTD
3846 * @ndataid: the xml notation name.
3847 * @content: content of the entity
3848 *
3849 * Write a DTD entity.
3850 *
3851 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3852 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003853int
3854xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3855 int pe,
3856 const xmlChar * name,
3857 const xmlChar * pubid,
3858 const xmlChar * sysid,
3859 const xmlChar * ndataid,
3860 const xmlChar * content)
3861{
Daniel Veillard500a1de2004-03-22 15:22:58 +00003862 if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003863 return -1;
3864 if ((pe != 0) && (ndataid != NULL))
3865 return -1;
3866
Daniel Veillard500a1de2004-03-22 15:22:58 +00003867 if ((pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003868 return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3869 content);
3870
3871 return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3872 sysid, ndataid);
3873}
3874
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003875/**
3876 * xmlTextWriterWriteDTDInternalEntity:
3877 * @writer: the xmlTextWriterPtr
3878 * @pe: TRUE if this is a parameter entity, FALSE if not
3879 * @name: the name of the DTD entity
3880 * @content: content of the entity
3881 *
3882 * Write a DTD internal entity.
3883 *
3884 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3885 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003886int
3887xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3888 int pe,
3889 const xmlChar * name,
3890 const xmlChar * content)
3891{
3892 int count;
3893 int sum;
3894
3895 if ((name == NULL) || (*name == '\0') || (content == NULL))
3896 return -1;
3897
3898 sum = 0;
3899 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3900 if (count == -1)
3901 return -1;
3902 sum += count;
3903
Daniel Veillard1d211e22003-10-20 22:32:39 +00003904 count = xmlTextWriterWriteString(writer, content);
3905 if (count == -1)
3906 return -1;
3907 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003908
3909 count = xmlTextWriterEndDTDEntity(writer);
3910 if (count == -1)
3911 return -1;
3912 sum += count;
3913
3914 return sum;
3915}
3916
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003917/**
3918 * xmlTextWriterWriteDTDExternalEntity:
3919 * @writer: the xmlTextWriterPtr
3920 * @pe: TRUE if this is a parameter entity, FALSE if not
3921 * @name: the name of the DTD entity
3922 * @pubid: the public identifier, which is an alternative to the system identifier
3923 * @sysid: the system identifier, which is the URI of the DTD
3924 * @ndataid: the xml notation name.
3925 *
Daniel Veillard500a1de2004-03-22 15:22:58 +00003926 * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003927 *
3928 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3929 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003930int
3931xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3932 int pe,
3933 const xmlChar * name,
3934 const xmlChar * pubid,
3935 const xmlChar * sysid,
3936 const xmlChar * ndataid)
3937{
3938 int count;
3939 int sum;
3940
Daniel Veillard500a1de2004-03-22 15:22:58 +00003941 if (((pubid == NULL) && (sysid == NULL)))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003942 return -1;
3943 if ((pe != 0) && (ndataid != NULL))
3944 return -1;
3945
3946 sum = 0;
3947 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3948 if (count == -1)
3949 return -1;
3950 sum += count;
3951
Daniel Veillard500a1de2004-03-22 15:22:58 +00003952 count =
3953 xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3954 ndataid);
3955 if (count < 0)
3956 return -1;
3957 sum += count;
3958
3959 count = xmlTextWriterEndDTDEntity(writer);
3960 if (count == -1)
3961 return -1;
3962 sum += count;
3963
3964 return sum;
3965}
3966
3967/**
3968 * xmlTextWriterWriteDTDExternalEntityContents:
3969 * @writer: the xmlTextWriterPtr
3970 * @pubid: the public identifier, which is an alternative to the system identifier
3971 * @sysid: the system identifier, which is the URI of the DTD
3972 * @ndataid: the xml notation name.
3973 *
3974 * Write the contents of a DTD external entity.
3975 *
3976 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3977 */
3978int
3979xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3980 const xmlChar * pubid,
3981 const xmlChar * sysid,
3982 const xmlChar * ndataid)
3983{
3984 int count;
3985 int sum;
3986 xmlLinkPtr lk;
3987 xmlTextWriterStackEntry *p;
3988
3989 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003990 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003991 "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3992 return -1;
3993 }
3994
3995 sum = 0;
3996 lk = xmlListFront(writer->nodes);
3997 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003998 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003999 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4000 return -1;
4001 }
4002
4003 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4004 if (p == 0)
4005 return -1;
4006
4007 switch (p->state) {
4008 case XML_TEXTWRITER_DTD_ENTY:
4009 break;
4010 case XML_TEXTWRITER_DTD_PENT:
4011 if (ndataid != NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004012 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004013 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
4014 return -1;
4015 }
4016 break;
4017 default:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004018 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004019 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4020 return -1;
4021 }
4022
Daniel Veillard1d211e22003-10-20 22:32:39 +00004023 if (pubid != 0) {
4024 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004025 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004026 "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00004027 return -1;
4028 }
4029
4030 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4031 if (count < 0)
4032 return -1;
4033 sum += count;
4034
4035 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4036 if (count < 0)
4037 return -1;
4038 sum += count;
4039
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004040 count =
4041 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004042 if (count < 0)
4043 return -1;
4044 sum += count;
4045
4046 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4047 if (count < 0)
4048 return -1;
4049 sum += count;
4050 }
4051
4052 if (sysid != 0) {
4053 if (pubid == 0) {
4054 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4055 if (count < 0)
4056 return -1;
4057 sum += count;
4058 }
4059
4060 count = xmlOutputBufferWriteString(writer->out, " ");
4061 if (count < 0)
4062 return -1;
4063 sum += count;
4064
4065 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4066 if (count < 0)
4067 return -1;
4068 sum += count;
4069
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004070 count =
4071 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004072 if (count < 0)
4073 return -1;
4074 sum += count;
4075
4076 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4077 if (count < 0)
4078 return -1;
4079 sum += count;
4080 }
4081
4082 if (ndataid != NULL) {
4083 count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4084 if (count < 0)
4085 return -1;
4086 sum += count;
4087
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004088 count =
4089 xmlOutputBufferWriteString(writer->out,
4090 (const char *) ndataid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004091 if (count < 0)
4092 return -1;
4093 sum += count;
4094 }
4095
Daniel Veillard1d211e22003-10-20 22:32:39 +00004096 return sum;
4097}
4098
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004099/**
4100 * xmlTextWriterWriteDTDNotation:
4101 * @writer: the xmlTextWriterPtr
4102 * @name: the name of the xml notation
4103 * @pubid: the public identifier, which is an alternative to the system identifier
4104 * @sysid: the system identifier, which is the URI of the DTD
4105 *
4106 * Write a DTD entity.
4107 *
4108 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4109 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00004110int
4111xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4112 const xmlChar * name,
4113 const xmlChar * pubid, const xmlChar * sysid)
4114{
4115 int count;
4116 int sum;
4117 xmlLinkPtr lk;
4118 xmlTextWriterStackEntry *p;
4119
4120 if (writer == NULL || name == NULL || *name == '\0')
4121 return -1;
4122
4123 sum = 0;
4124 lk = xmlListFront(writer->nodes);
4125 if (lk == 0) {
4126 return -1;
4127 }
4128
4129 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00004130 if (p != 0) {
4131 switch (p->state) {
4132 case XML_TEXTWRITER_DTD:
4133 count = xmlOutputBufferWriteString(writer->out, " [");
4134 if (count < 0)
4135 return -1;
4136 sum += count;
4137 if (writer->indent) {
4138 count = xmlOutputBufferWriteString(writer->out, "\n");
4139 if (count < 0)
4140 return -1;
4141 sum += count;
4142 }
4143 p->state = XML_TEXTWRITER_DTD_TEXT;
4144 /* fallthrough */
4145 case XML_TEXTWRITER_DTD_TEXT:
4146 break;
4147 default:
4148 return -1;
4149 }
4150 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00004151
Daniel Veillard500a1de2004-03-22 15:22:58 +00004152 if (writer->indent) {
4153 count = xmlTextWriterWriteIndent(writer);
4154 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004155 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004156 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004157 }
4158
4159 count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4160 if (count < 0)
4161 return -1;
4162 sum += count;
4163 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4164 if (count < 0)
4165 return -1;
4166 sum += count;
4167
4168 if (pubid != 0) {
4169 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4170 if (count < 0)
4171 return -1;
4172 sum += count;
4173 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4174 if (count < 0)
4175 return -1;
4176 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004177 count =
4178 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004179 if (count < 0)
4180 return -1;
4181 sum += count;
4182 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4183 if (count < 0)
4184 return -1;
4185 sum += count;
4186 }
4187
4188 if (sysid != 0) {
4189 if (pubid == 0) {
4190 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4191 if (count < 0)
4192 return -1;
4193 sum += count;
4194 }
4195 count = xmlOutputBufferWriteString(writer->out, " ");
4196 if (count < 0)
4197 return -1;
4198 sum += count;
4199 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4200 if (count < 0)
4201 return -1;
4202 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004203 count =
4204 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004205 if (count < 0)
4206 return -1;
4207 sum += count;
4208 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4209 if (count < 0)
4210 return -1;
4211 sum += count;
4212 }
4213
4214 count = xmlOutputBufferWriteString(writer->out, ">");
4215 if (count < 0)
4216 return -1;
4217 sum += count;
4218
4219 return sum;
4220}
4221
4222/**
4223 * xmlTextWriterFlush:
4224 * @writer: the xmlTextWriterPtr
4225 *
4226 * Flush the output buffer.
4227 *
4228 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4229 */
4230int
4231xmlTextWriterFlush(xmlTextWriterPtr writer)
4232{
4233 int count;
4234
4235 if (writer == NULL)
4236 return -1;
4237
4238 if (writer->out == NULL)
4239 count = 0;
4240 else
4241 count = xmlOutputBufferFlush(writer->out);
4242
4243 return count;
4244}
4245
4246/**
4247 * misc
4248 */
4249
4250/**
4251 * xmlFreeTextWriterStackEntry:
4252 * @lk: the xmlLinkPtr
4253 *
4254 * Free callback for the xmlList.
4255 */
4256static void
4257xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4258{
4259 xmlTextWriterStackEntry *p;
4260
4261 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4262 if (p == 0)
4263 return;
4264
4265 if (p->name != 0)
4266 xmlFree(p->name);
4267 xmlFree(p);
4268}
4269
4270/**
4271 * xmlCmpTextWriterStackEntry:
4272 * @data0: the first data
4273 * @data1: the second data
4274 *
4275 * Compare callback for the xmlList.
4276 *
4277 * Returns -1, 0, 1
4278 */
4279static int
4280xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4281{
4282 xmlTextWriterStackEntry *p0;
4283 xmlTextWriterStackEntry *p1;
4284
4285 if (data0 == data1)
4286 return 0;
4287
4288 if (data0 == 0)
4289 return -1;
4290
4291 if (data1 == 0)
4292 return 1;
4293
4294 p0 = (xmlTextWriterStackEntry *) data0;
4295 p1 = (xmlTextWriterStackEntry *) data1;
4296
4297 return xmlStrcmp(p0->name, p1->name);
4298}
4299
4300/**
4301 * misc
4302 */
4303
4304/**
Rob Richardsb8769d62007-06-08 08:50:47 +00004305 * xmlTextWriterOutputNSDecl:
4306 * @writer: the xmlTextWriterPtr
4307 *
4308 * Output the current namespace declarations.
4309 */
4310static int
4311xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4312{
4313 xmlLinkPtr lk;
4314 xmlTextWriterNsStackEntry *np;
4315 int count;
4316 int sum;
4317
4318 sum = 0;
4319 while (!xmlListEmpty(writer->nsstack)) {
4320 xmlChar *namespaceURI = NULL;
4321 xmlChar *prefix = NULL;
4322
4323 lk = xmlListFront(writer->nsstack);
4324 np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4325
4326 if (np != 0) {
4327 namespaceURI = xmlStrdup(np->uri);
4328 prefix = xmlStrdup(np->prefix);
4329 }
4330
4331 xmlListPopFront(writer->nsstack);
4332
4333 if (np != 0) {
4334 count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4335 xmlFree(namespaceURI);
4336 xmlFree(prefix);
4337
4338 if (count < 0) {
4339 xmlListDelete(writer->nsstack);
4340 writer->nsstack = NULL;
4341 return -1;
4342 }
4343 sum += count;
4344 }
4345 }
4346 return sum;
4347}
4348
4349/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004350 * xmlFreeTextWriterNsStackEntry:
4351 * @lk: the xmlLinkPtr
4352 *
4353 * Free callback for the xmlList.
4354 */
4355static void
4356xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4357{
4358 xmlTextWriterNsStackEntry *p;
4359
4360 p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4361 if (p == 0)
4362 return;
4363
4364 if (p->prefix != 0)
4365 xmlFree(p->prefix);
4366 if (p->uri != 0)
4367 xmlFree(p->uri);
4368
4369 xmlFree(p);
4370}
4371
4372/**
4373 * xmlCmpTextWriterNsStackEntry:
4374 * @data0: the first data
4375 * @data1: the second data
4376 *
4377 * Compare callback for the xmlList.
4378 *
4379 * Returns -1, 0, 1
4380 */
4381static int
4382xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4383{
4384 xmlTextWriterNsStackEntry *p0;
4385 xmlTextWriterNsStackEntry *p1;
4386 int rc;
4387
4388 if (data0 == data1)
4389 return 0;
4390
4391 if (data0 == 0)
4392 return -1;
4393
4394 if (data1 == 0)
4395 return 1;
4396
4397 p0 = (xmlTextWriterNsStackEntry *) data0;
4398 p1 = (xmlTextWriterNsStackEntry *) data1;
4399
4400 rc = xmlStrcmp(p0->prefix, p1->prefix);
4401
Rob Richardsb8769d62007-06-08 08:50:47 +00004402 if ((rc != 0) || (p0->elem != p1->elem))
4403 rc = -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004404
4405 return rc;
4406}
4407
4408/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004409 * xmlTextWriterWriteDocCallback:
4410 * @context: the xmlBufferPtr
4411 * @str: the data to write
4412 * @len: the length of the data
4413 *
4414 * Write callback for the xmlOutputBuffer with target xmlBuffer
4415 *
4416 * Returns -1, 0, 1
4417 */
4418static int
Nick Wellnhofer86615e42017-11-09 17:47:47 +01004419xmlTextWriterWriteDocCallback(void *context, const char *str, int len)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004420{
4421 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4422 int rc;
4423
Nick Wellnhofer86615e42017-11-09 17:47:47 +01004424 if ((rc = xmlParseChunk(ctxt, str, len, 0)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004425 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004426 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4427 rc);
4428 return -1;
4429 }
4430
4431 return len;
4432}
4433
4434/**
4435 * xmlTextWriterCloseDocCallback:
4436 * @context: the xmlBufferPtr
4437 *
4438 * Close callback for the xmlOutputBuffer with target xmlBuffer
4439 *
4440 * Returns -1, 0, 1
4441 */
4442static int
4443xmlTextWriterCloseDocCallback(void *context)
4444{
4445 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4446 int rc;
4447
4448 if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004449 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Nick Wellnhofer86615e42017-11-09 17:47:47 +01004450 "xmlTextWriterCloseDocCallback : XML error %d !\n",
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004451 rc);
4452 return -1;
4453 }
4454
4455 return 0;
4456}
4457
4458/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004459 * xmlTextWriterVSprintf:
4460 * @format: see printf
4461 * @argptr: pointer to the first member of the variable argument list.
4462 *
4463 * Utility function for formatted output
4464 *
4465 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4466 */
4467static xmlChar *
4468xmlTextWriterVSprintf(const char *format, va_list argptr)
4469{
4470 int size;
4471 int count;
4472 xmlChar *buf;
William M. Brackf4caa5e2005-10-20 09:04:05 +00004473 va_list locarg;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004474
4475 size = BUFSIZ;
4476 buf = (xmlChar *) xmlMalloc(size);
4477 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004478 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004479 "xmlTextWriterVSprintf : out of memory!\n");
4480 return NULL;
4481 }
4482
William M. Brackf4caa5e2005-10-20 09:04:05 +00004483 VA_COPY(locarg, argptr);
4484 while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004485 || (count == size - 1) || (count == size) || (count > size)) {
William M. Brackf4caa5e2005-10-20 09:04:05 +00004486 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004487 xmlFree(buf);
4488 size += BUFSIZ;
4489 buf = (xmlChar *) xmlMalloc(size);
4490 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004491 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004492 "xmlTextWriterVSprintf : out of memory!\n");
4493 return NULL;
4494 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004495 VA_COPY(locarg, argptr);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004496 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004497 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004498
4499 return buf;
4500}
4501
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004502/**
4503 * xmlTextWriterStartDocumentCallback:
4504 * @ctx: the user data (XML parser context)
4505 *
4506 * called at the start of document processing.
4507 */
4508static void
4509xmlTextWriterStartDocumentCallback(void *ctx)
4510{
4511 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4512 xmlDocPtr doc;
4513
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004514 if (ctxt->html) {
4515#ifdef LIBXML_HTML_ENABLED
4516 if (ctxt->myDoc == NULL)
4517 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4518 if (ctxt->myDoc == NULL) {
4519 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4520 ctxt->sax->error(ctxt->userData,
4521 "SAX.startDocument(): out of memory\n");
4522 ctxt->errNo = XML_ERR_NO_MEMORY;
4523 ctxt->instate = XML_PARSER_EOF;
4524 ctxt->disableSAX = 1;
4525 return;
4526 }
4527#else
Daniel Veillardd0cf7f62004-11-09 16:17:02 +00004528 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004529 "libxml2 built without HTML support\n");
4530 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4531 ctxt->instate = XML_PARSER_EOF;
4532 ctxt->disableSAX = 1;
4533 return;
4534#endif
4535 } else {
4536 doc = ctxt->myDoc;
4537 if (doc == NULL)
4538 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4539 if (doc != NULL) {
4540 if (doc->children == NULL) {
4541 if (ctxt->encoding != NULL)
4542 doc->encoding = xmlStrdup(ctxt->encoding);
4543 else
4544 doc->encoding = NULL;
4545 doc->standalone = ctxt->standalone;
4546 }
4547 } else {
4548 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4549 ctxt->sax->error(ctxt->userData,
4550 "SAX.startDocument(): out of memory\n");
4551 ctxt->errNo = XML_ERR_NO_MEMORY;
4552 ctxt->instate = XML_PARSER_EOF;
4553 ctxt->disableSAX = 1;
4554 return;
4555 }
4556 }
4557 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4558 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4559 ctxt->myDoc->URL =
4560 xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4561 if (ctxt->myDoc->URL == NULL)
4562 ctxt->myDoc->URL =
4563 xmlStrdup((const xmlChar *) ctxt->input->filename);
4564 }
4565}
4566
Daniel Veillard2cca4462004-01-02 20:04:23 +00004567/**
4568 * xmlTextWriterSetIndent:
4569 * @writer: the xmlTextWriterPtr
4570 * @indent: do indentation?
4571 *
4572 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4573 *
4574 * Returns -1 on error or 0 otherwise.
4575 */
4576int
Daniel Veillardab69f362004-02-17 11:40:32 +00004577xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004578{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004579 if ((writer == NULL) || (indent < 0))
Daniel Veillardab69f362004-02-17 11:40:32 +00004580 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004581
Daniel Veillardab69f362004-02-17 11:40:32 +00004582 writer->indent = indent;
4583 writer->doindent = 1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004584
Daniel Veillardab69f362004-02-17 11:40:32 +00004585 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004586}
4587
4588/**
4589 * xmlTextWriterSetIndentString:
4590 * @writer: the xmlTextWriterPtr
4591 * @str: the xmlChar string
4592 *
4593 * Set string indentation.
4594 *
4595 * Returns -1 on error or 0 otherwise.
4596 */
4597int
Daniel Veillardab69f362004-02-17 11:40:32 +00004598xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004599{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004600 if ((writer == NULL) || (!str))
Daniel Veillardab69f362004-02-17 11:40:32 +00004601 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004602
Daniel Veillardab69f362004-02-17 11:40:32 +00004603 if (writer->ichar != NULL)
4604 xmlFree(writer->ichar);
4605 writer->ichar = xmlStrdup(str);
4606
4607 if (!writer->ichar)
4608 return -1;
4609 else
4610 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004611}
4612
4613/**
Csaba Raduly429d3a02012-09-11 11:50:25 +08004614 * xmlTextWriterSetQuoteChar:
4615 * @writer: the xmlTextWriterPtr
4616 * @quotechar: the quote character
4617 *
4618 * Set the character used for quoting attributes.
4619 *
4620 * Returns -1 on error or 0 otherwise.
4621 */
4622int
4623xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar)
4624{
4625 if ((writer == NULL) || ((quotechar != '\'') && (quotechar != '"')))
4626 return -1;
4627
4628 writer->qchar = quotechar;
4629
4630 return 0;
4631}
4632
4633/**
Daniel Veillard2cca4462004-01-02 20:04:23 +00004634 * xmlTextWriterWriteIndent:
4635 * @writer: the xmlTextWriterPtr
4636 *
4637 * Write indent string.
4638 *
4639 * Returns -1 on error or the number of strings written.
Daniel Veillardab69f362004-02-17 11:40:32 +00004640 */
Daniel Veillard2cca4462004-01-02 20:04:23 +00004641static int
Daniel Veillardab69f362004-02-17 11:40:32 +00004642xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004643{
Daniel Veillardab69f362004-02-17 11:40:32 +00004644 int lksize;
4645 int i;
4646 int ret;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004647
Daniel Veillardab69f362004-02-17 11:40:32 +00004648 lksize = xmlListSize(writer->nodes);
4649 if (lksize < 1)
4650 return (-1); /* list is empty */
4651 for (i = 0; i < (lksize - 1); i++) {
4652 ret = xmlOutputBufferWriteString(writer->out,
4653 (const char *) writer->ichar);
4654 if (ret == -1)
4655 return (-1);
4656 }
4657
4658 return (lksize - 1);
Daniel Veillard2cca4462004-01-02 20:04:23 +00004659}
4660
Daniel Veillard500a1de2004-03-22 15:22:58 +00004661/**
4662 * xmlTextWriterHandleStateDependencies:
4663 * @writer: the xmlTextWriterPtr
4664 * @p: the xmlTextWriterStackEntry
4665 *
4666 * Write state dependent strings.
4667 *
4668 * Returns -1 on error or the number of characters written.
4669 */
4670static int
4671xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4672 xmlTextWriterStackEntry * p)
4673{
4674 int count;
4675 int sum;
4676 char extra[3];
4677
4678 if (writer == NULL)
4679 return -1;
4680
4681 if (p == NULL)
4682 return 0;
4683
4684 sum = 0;
4685 extra[0] = extra[1] = extra[2] = '\0';
4686 if (p != 0) {
4687 sum = 0;
4688 switch (p->state) {
4689 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00004690 /* Output namespace declarations */
4691 count = xmlTextWriterOutputNSDecl(writer);
4692 if (count < 0)
4693 return -1;
4694 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004695 extra[0] = '>';
4696 p->state = XML_TEXTWRITER_TEXT;
4697 break;
4698 case XML_TEXTWRITER_PI:
4699 extra[0] = ' ';
4700 p->state = XML_TEXTWRITER_PI_TEXT;
4701 break;
4702 case XML_TEXTWRITER_DTD:
4703 extra[0] = ' ';
4704 extra[1] = '[';
4705 p->state = XML_TEXTWRITER_DTD_TEXT;
4706 break;
4707 case XML_TEXTWRITER_DTD_ELEM:
4708 extra[0] = ' ';
4709 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4710 break;
4711 case XML_TEXTWRITER_DTD_ATTL:
4712 extra[0] = ' ';
4713 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4714 break;
4715 case XML_TEXTWRITER_DTD_ENTY:
4716 case XML_TEXTWRITER_DTD_PENT:
4717 extra[0] = ' ';
4718 extra[1] = writer->qchar;
4719 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4720 break;
4721 default:
4722 break;
4723 }
4724 }
4725
4726 if (*extra != '\0') {
4727 count = xmlOutputBufferWriteString(writer->out, extra);
4728 if (count < 0)
4729 return -1;
4730 sum += count;
4731 }
4732
4733 return sum;
4734}
4735
Daniel Veillard5d4644e2005-04-01 13:11:58 +00004736#define bottom_xmlwriter
4737#include "elfgcchack.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +00004738#endif