blob: 2e21d1baf59ba6b6651f7911f76c90fa01ef434d [file] [log] [blame]
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001
Daniel Veillard1d211e22003-10-20 22:32:39 +00002/*
3 * xmlwriter.c: XML text writer implementation
4 *
5 * For license and disclaimer see the license and disclaimer of
6 * libxml2.
7 *
8 * alfred@mickautsch.de
9 */
10
Igor Zlatkovicb23de5a2003-11-27 18:36:46 +000011#define IN_LIBXML
William M. Brackc1099be2007-01-31 18:38:56 +000012#include "libxml.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +000013#include <string.h>
Daniel Veillard1d211e22003-10-20 22:32:39 +000014
Daniel Veillard1d211e22003-10-20 22:32:39 +000015#include <libxml/xmlmemory.h>
16#include <libxml/parser.h>
Daniel Veillard5841f0e2003-11-20 11:59:09 +000017#include <libxml/uri.h>
18#include <libxml/HTMLtree.h>
Daniel Veillard1d211e22003-10-20 22:32:39 +000019
20#ifdef LIBXML_WRITER_ENABLED
21
22#include <libxml/xmlwriter.h>
23
Daniel Veillarddbf54112012-07-16 14:54:45 +080024#include "buf.h"
25#include "enc.h"
26#include "save.h"
27
Daniel Veillard1d211e22003-10-20 22:32:39 +000028#define B64LINELEN 72
29#define B64CRLF "\r\n"
30
31/*
William M. Brackf4caa5e2005-10-20 09:04:05 +000032 * The following VA_COPY was coded following an example in
33 * the Samba project. It may not be sufficient for some
Patrick Monnerat0f7a26d2013-12-12 15:04:43 +080034 * esoteric implementations of va_list but (hopefully) will
35 * be sufficient for libxml2.
William M. Brackf4caa5e2005-10-20 09:04:05 +000036 */
37#ifndef VA_COPY
38 #ifdef HAVE_VA_COPY
39 #define VA_COPY(dest, src) va_copy(dest, src)
40 #else
41 #ifdef HAVE___VA_COPY
42 #define VA_COPY(dest,src) __va_copy(dest, src)
43 #else
Patrick Monnerat0f7a26d2013-12-12 15:04:43 +080044 #ifndef VA_LIST_IS_ARRAY
45 #define VA_COPY(dest,src) (dest) = (src)
46 #else
47 #include <string.h>
48 #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
49 #endif
William M. Brackf4caa5e2005-10-20 09:04:05 +000050 #endif
51 #endif
52#endif
53
54/*
Daniel Veillard1d211e22003-10-20 22:32:39 +000055 * Types are kept private
56 */
57typedef enum {
58 XML_TEXTWRITER_NONE = 0,
59 XML_TEXTWRITER_NAME,
60 XML_TEXTWRITER_ATTRIBUTE,
61 XML_TEXTWRITER_TEXT,
62 XML_TEXTWRITER_PI,
63 XML_TEXTWRITER_PI_TEXT,
64 XML_TEXTWRITER_CDATA,
65 XML_TEXTWRITER_DTD,
66 XML_TEXTWRITER_DTD_TEXT,
67 XML_TEXTWRITER_DTD_ELEM,
Daniel Veillard500a1de2004-03-22 15:22:58 +000068 XML_TEXTWRITER_DTD_ELEM_TEXT,
Daniel Veillard1d211e22003-10-20 22:32:39 +000069 XML_TEXTWRITER_DTD_ATTL,
Daniel Veillard500a1de2004-03-22 15:22:58 +000070 XML_TEXTWRITER_DTD_ATTL_TEXT,
71 XML_TEXTWRITER_DTD_ENTY, /* entity */
72 XML_TEXTWRITER_DTD_ENTY_TEXT,
73 XML_TEXTWRITER_DTD_PENT, /* parameter entity */
William M. Brack87640d52004-04-17 14:58:15 +000074 XML_TEXTWRITER_COMMENT
Daniel Veillard1d211e22003-10-20 22:32:39 +000075} xmlTextWriterState;
76
77typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
78
79struct _xmlTextWriterStackEntry {
80 xmlChar *name;
81 xmlTextWriterState state;
82};
83
84typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
85struct _xmlTextWriterNsStackEntry {
86 xmlChar *prefix;
87 xmlChar *uri;
88 xmlLinkPtr elem;
89};
90
91struct _xmlTextWriter {
Daniel Veillardab69f362004-02-17 11:40:32 +000092 xmlOutputBufferPtr out; /* output buffer */
93 xmlListPtr nodes; /* element name stack */
94 xmlListPtr nsstack; /* name spaces stack */
Daniel Veillard1d211e22003-10-20 22:32:39 +000095 int level;
Daniel Veillardab69f362004-02-17 11:40:32 +000096 int indent; /* enable indent */
97 int doindent; /* internal indent flag */
98 xmlChar *ichar; /* indent character */
99 char qchar; /* character used for quoting attribute values */
Daniel Veillard20c5e782004-01-21 09:57:31 +0000100 xmlParserCtxtPtr ctxt;
Daniel Veillarda521d282004-11-09 14:59:59 +0000101 int no_doc_free;
Rob Richards9db68f02006-08-16 22:48:51 +0000102 xmlDocPtr doc;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000103};
104
105static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
106static int xmlCmpTextWriterStackEntry(const void *data0,
107 const void *data1);
Rob Richardsb8769d62007-06-08 08:50:47 +0000108static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000109static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
110static int xmlCmpTextWriterNsStackEntry(const void *data0,
111 const void *data1);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000112static int xmlTextWriterWriteDocCallback(void *context,
113 const xmlChar * str, int len);
114static int xmlTextWriterCloseDocCallback(void *context);
115
Daniel Veillard1d211e22003-10-20 22:32:39 +0000116static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);
117static 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 */
156static void
157xmlWriterErrMsgInt(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
193 ret->nodes = xmlListCreate((xmlListDeallocator)
194 xmlFreeTextWriterStackEntry,
195 (xmlListDataCompare)
196 xmlCmpTextWriterStackEntry);
197 if (ret->nodes == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000198 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000199 "xmlNewTextWriter : out of memory!\n");
200 xmlFree(ret);
201 return NULL;
202 }
203
204 ret->nsstack = xmlListCreate((xmlListDeallocator)
205 xmlFreeTextWriterNsStackEntry,
206 (xmlListDataCompare)
207 xmlCmpTextWriterNsStackEntry);
208 if (ret->nsstack == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000209 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000210 "xmlNewTextWriter : out of memory!\n");
Daniel Veillard500a1de2004-03-22 15:22:58 +0000211 xmlListDelete(ret->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000212 xmlFree(ret);
213 return NULL;
214 }
215
216 ret->out = out;
Daniel Veillardab69f362004-02-17 11:40:32 +0000217 ret->ichar = xmlStrdup(BAD_CAST " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000218 ret->qchar = '"';
219
Daniel Veillard500a1de2004-03-22 15:22:58 +0000220 if (!ret->ichar) {
221 xmlListDelete(ret->nodes);
222 xmlListDelete(ret->nsstack);
223 xmlFree(ret);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000224 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000225 "xmlNewTextWriter : out of memory!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000226 return NULL;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000227 }
Rob Richards9db68f02006-08-16 22:48:51 +0000228
229 ret->doc = xmlNewDoc(NULL);
230
Daniel Veillarda521d282004-11-09 14:59:59 +0000231 ret->no_doc_free = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000232
Daniel Veillard1d211e22003-10-20 22:32:39 +0000233 return ret;
234}
235
236/**
237 * xmlNewTextWriterFilename:
238 * @uri: the URI of the resource for the output
239 * @compression: compress the output?
240 *
241 * Create a new xmlNewTextWriter structure with @uri as output
242 *
243 * Returns the new xmlTextWriterPtr or NULL in case of error
244 */
245xmlTextWriterPtr
246xmlNewTextWriterFilename(const char *uri, int compression)
247{
248 xmlTextWriterPtr ret;
249 xmlOutputBufferPtr out;
250
251 out = xmlOutputBufferCreateFilename(uri, NULL, compression);
252 if (out == NULL) {
Rob Richards798743a2009-06-19 13:54:25 -0400253 xmlWriterErrMsg(NULL, XML_IO_EIO,
254 "xmlNewTextWriterFilename : cannot open uri\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000255 return NULL;
256 }
257
258 ret = xmlNewTextWriter(out);
259 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000260 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000261 "xmlNewTextWriterFilename : out of memory!\n");
262 xmlOutputBufferClose(out);
263 return NULL;
264 }
265
Daniel Veillard2cca4462004-01-02 20:04:23 +0000266 ret->indent = 0;
267 ret->doindent = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000268 return ret;
269}
270
271/**
272 * xmlNewTextWriterMemory:
273 * @buf: xmlBufferPtr
274 * @compression: compress the output?
275 *
276 * Create a new xmlNewTextWriter structure with @buf as output
277 * TODO: handle compression
278 *
279 * Returns the new xmlTextWriterPtr or NULL in case of error
280 */
281xmlTextWriterPtr
282xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
283{
284 xmlTextWriterPtr ret;
285 xmlOutputBufferPtr out;
286
287/*::todo handle compression */
Rob Richardsa44f2342005-11-09 18:03:45 +0000288 out = xmlOutputBufferCreateBuffer(buf, NULL);
289
Daniel Veillard1d211e22003-10-20 22:32:39 +0000290 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000291 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000292 "xmlNewTextWriterMemory : out of memory!\n");
293 return NULL;
294 }
295
296 ret = xmlNewTextWriter(out);
297 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000298 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000299 "xmlNewTextWriterMemory : out of memory!\n");
300 xmlOutputBufferClose(out);
301 return NULL;
302 }
303
304 return ret;
305}
306
307/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000308 * xmlNewTextWriterPushParser:
309 * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
310 * @compression: compress the output?
311 *
312 * Create a new xmlNewTextWriter structure with @ctxt as output
Daniel Veillardd5cc0f72004-11-06 19:24:28 +0000313 * NOTE: the @ctxt context will be freed with the resulting writer
314 * (if the call succeeds).
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000315 * TODO: handle compression
316 *
317 * Returns the new xmlTextWriterPtr or NULL in case of error
318 */
319xmlTextWriterPtr
Daniel Veillard1d913862003-11-21 00:28:39 +0000320xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
321 int compression ATTRIBUTE_UNUSED)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000322{
323 xmlTextWriterPtr ret;
324 xmlOutputBufferPtr out;
325
Daniel Veillard500a1de2004-03-22 15:22:58 +0000326 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000327 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000328 "xmlNewTextWriterPushParser : invalid context!\n");
329 return NULL;
330 }
331
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000332 out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
333 xmlTextWriterWriteDocCallback,
334 (xmlOutputCloseCallback)
335 xmlTextWriterCloseDocCallback,
336 (void *) ctxt, NULL);
337 if (out == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000338 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000339 "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
340 return NULL;
341 }
342
343 ret = xmlNewTextWriter(out);
344 if (ret == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000345 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000346 "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
347 xmlOutputBufferClose(out);
348 return NULL;
349 }
350
Daniel Veillard20c5e782004-01-21 09:57:31 +0000351 ret->ctxt = ctxt;
352
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000353 return ret;
354}
355
356/**
357 * xmlNewTextWriterDoc:
358 * @doc: address of a xmlDocPtr to hold the new XML document tree
359 * @compression: compress the output?
360 *
361 * Create a new xmlNewTextWriter structure with @*doc as output
362 *
363 * Returns the new xmlTextWriterPtr or NULL in case of error
364 */
365xmlTextWriterPtr
366xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
367{
368 xmlTextWriterPtr ret;
369 xmlSAXHandler saxHandler;
370 xmlParserCtxtPtr ctxt;
371
372 memset(&saxHandler, '\0', sizeof(saxHandler));
373 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
374 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
375 saxHandler.startElement = xmlSAX2StartElement;
376 saxHandler.endElement = xmlSAX2EndElement;
377
378 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
379 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000380 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillardeb0a0b22009-02-20 08:19:53 +0000381 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000382 return NULL;
383 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000384 /*
385 * For some reason this seems to completely break if node names
386 * are interned.
387 */
388 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000389
Daniel Veillard1d913862003-11-21 00:28:39 +0000390 ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000391 if (ctxt->myDoc == NULL) {
392 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000393 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000394 "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
395 return NULL;
396 }
397
398 ret = xmlNewTextWriterPushParser(ctxt, compression);
399 if (ret == NULL) {
Daniel Veillardeb0a0b22009-02-20 08:19:53 +0000400 xmlFreeDoc(ctxt->myDoc);
401 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000402 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillardeb0a0b22009-02-20 08:19:53 +0000403 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000404 return NULL;
405 }
406
Daniel Veillard500a1de2004-03-22 15:22:58 +0000407 xmlSetDocCompressMode(ctxt->myDoc, compression);
408
Daniel Veillarda521d282004-11-09 14:59:59 +0000409 if (doc != NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000410 *doc = ctxt->myDoc;
Daniel Veillarda521d282004-11-09 14:59:59 +0000411 ret->no_doc_free = 1;
412 }
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000413
414 return ret;
415}
416
417/**
418 * xmlNewTextWriterTree:
419 * @doc: xmlDocPtr
420 * @node: xmlNodePtr or NULL for doc->children
421 * @compression: compress the output?
422 *
423 * Create a new xmlNewTextWriter structure with @doc as output
424 * starting at @node
425 *
426 * Returns the new xmlTextWriterPtr or NULL in case of error
427 */
428xmlTextWriterPtr
429xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
430{
431 xmlTextWriterPtr ret;
432 xmlSAXHandler saxHandler;
433 xmlParserCtxtPtr ctxt;
434
435 if (doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000436 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000437 "xmlNewTextWriterTree : invalid document tree!\n");
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000438 return NULL;
439 }
440
441 memset(&saxHandler, '\0', sizeof(saxHandler));
442 xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
443 saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
444 saxHandler.startElement = xmlSAX2StartElement;
445 saxHandler.endElement = xmlSAX2EndElement;
446
447 ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
448 if (ctxt == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000449 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000450 "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
451 return NULL;
452 }
Daniel Veillard03a53c32004-10-26 16:06:51 +0000453 /*
454 * For some reason this seems to completely break if node names
455 * are interned.
456 */
457 ctxt->dictNames = 0;
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000458
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000459 ret = xmlNewTextWriterPushParser(ctxt, compression);
460 if (ret == NULL) {
Daniel Veillard500a1de2004-03-22 15:22:58 +0000461 xmlFreeParserCtxt(ctxt);
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000462 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000463 "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
464 return NULL;
465 }
466
Daniel Veillard500a1de2004-03-22 15:22:58 +0000467 ctxt->myDoc = doc;
468 ctxt->node = node;
Daniel Veillarda521d282004-11-09 14:59:59 +0000469 ret->no_doc_free = 1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000470
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000471 xmlSetDocCompressMode(doc, compression);
472
473 return ret;
474}
475
476/**
Daniel Veillard1d211e22003-10-20 22:32:39 +0000477 * xmlFreeTextWriter:
478 * @writer: the xmlTextWriterPtr
479 *
480 * Deallocate all the resources associated to the writer
481 */
482void
483xmlFreeTextWriter(xmlTextWriterPtr writer)
484{
485 if (writer == NULL)
486 return;
487
488 if (writer->out != NULL)
489 xmlOutputBufferClose(writer->out);
490
491 if (writer->nodes != NULL)
492 xmlListDelete(writer->nodes);
493
494 if (writer->nsstack != NULL)
495 xmlListDelete(writer->nsstack);
496
Daniel Veillarda521d282004-11-09 14:59:59 +0000497 if (writer->ctxt != NULL) {
498 if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
499 xmlFreeDoc(writer->ctxt->myDoc);
500 writer->ctxt->myDoc = NULL;
501 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000502 xmlFreeParserCtxt(writer->ctxt);
Daniel Veillarda521d282004-11-09 14:59:59 +0000503 }
Daniel Veillard20c5e782004-01-21 09:57:31 +0000504
Rob Richards9db68f02006-08-16 22:48:51 +0000505 if (writer->doc != NULL)
506 xmlFreeDoc(writer->doc);
507
Daniel Veillard4773df22004-01-23 13:15:13 +0000508 if (writer->ichar != NULL)
509 xmlFree(writer->ichar);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000510 xmlFree(writer);
511}
512
513/**
514 * xmlTextWriterStartDocument:
515 * @writer: the xmlTextWriterPtr
516 * @version: the xml version ("1.0") or NULL for default ("1.0")
517 * @encoding: the encoding or NULL for default
518 * @standalone: "yes" or "no" or NULL for default
519 *
520 * Start a new xml document
521 *
522 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
523 */
524int
525xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
526 const char *encoding, const char *standalone)
527{
528 int count;
529 int sum;
530 xmlLinkPtr lk;
531 xmlCharEncodingHandlerPtr encoder;
532
Daniel Veillard500a1de2004-03-22 15:22:58 +0000533 if ((writer == NULL) || (writer->out == NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000534 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000535 "xmlTextWriterStartDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000536 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000537 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000538
539 lk = xmlListFront(writer->nodes);
540 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000541 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000542 "xmlTextWriterStartDocument : not allowed in this context!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000543 return -1;
544 }
545
546 encoder = NULL;
547 if (encoding != NULL) {
548 encoder = xmlFindCharEncodingHandler(encoding);
549 if (encoder == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000550 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +0000551 "xmlTextWriterStartDocument : out of memory!\n");
552 return -1;
553 }
554 }
555
556 writer->out->encoder = encoder;
557 if (encoder != NULL) {
Daniel Veillardcaa19512007-07-04 15:42:46 +0000558 if (writer->out->conv == NULL) {
Daniel Veillarddbf54112012-07-16 14:54:45 +0800559 writer->out->conv = xmlBufCreateSize(4000);
Daniel Veillardcaa19512007-07-04 15:42:46 +0000560 }
Daniel Veillarddbf54112012-07-16 14:54:45 +0800561 xmlCharEncOutput(writer->out, 1);
Rob Richards9db68f02006-08-16 22:48:51 +0000562 if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
563 writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000564 } else
565 writer->out->conv = NULL;
566
567 sum = 0;
568 count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
569 if (count < 0)
570 return -1;
571 sum += count;
572 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
573 if (count < 0)
574 return -1;
575 sum += count;
576 if (version != 0)
577 count = xmlOutputBufferWriteString(writer->out, version);
578 else
579 count = xmlOutputBufferWriteString(writer->out, "1.0");
580 if (count < 0)
581 return -1;
582 sum += count;
583 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
584 if (count < 0)
585 return -1;
586 sum += count;
587 if (writer->out->encoder != 0) {
588 count = xmlOutputBufferWriteString(writer->out, " encoding=");
589 if (count < 0)
590 return -1;
591 sum += count;
592 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
593 if (count < 0)
594 return -1;
595 sum += count;
596 count =
597 xmlOutputBufferWriteString(writer->out,
598 writer->out->encoder->name);
599 if (count < 0)
600 return -1;
601 sum += count;
602 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
603 if (count < 0)
604 return -1;
605 sum += count;
606 }
607
608 if (standalone != 0) {
609 count = xmlOutputBufferWriteString(writer->out, " standalone=");
610 if (count < 0)
611 return -1;
612 sum += count;
613 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
614 if (count < 0)
615 return -1;
616 sum += count;
617 count = xmlOutputBufferWriteString(writer->out, standalone);
618 if (count < 0)
619 return -1;
620 sum += count;
621 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
622 if (count < 0)
623 return -1;
624 sum += count;
625 }
626
627 count = xmlOutputBufferWriteString(writer->out, "?>\n");
628 if (count < 0)
629 return -1;
630 sum += count;
631
632 return sum;
633}
634
635/**
636 * xmlTextWriterEndDocument:
637 * @writer: the xmlTextWriterPtr
638 *
Daniel Veillard3ff24112008-02-13 10:17:41 +0000639 * End an xml document. All open elements are closed, and
640 * the content is flushed to the output.
Daniel Veillard1d211e22003-10-20 22:32:39 +0000641 *
Daniel Veillard3ff24112008-02-13 10:17:41 +0000642 * Returns the bytes written or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +0000643 */
644int
645xmlTextWriterEndDocument(xmlTextWriterPtr writer)
646{
647 int count;
648 int sum;
649 xmlLinkPtr lk;
650 xmlTextWriterStackEntry *p;
651
Daniel Veillard500a1de2004-03-22 15:22:58 +0000652 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000653 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000654 "xmlTextWriterEndDocument : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000655 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000656 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000657
658 sum = 0;
659 while ((lk = xmlListFront(writer->nodes)) != NULL) {
660 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
661 if (p == 0)
662 break;
663 switch (p->state) {
664 case XML_TEXTWRITER_NAME:
665 case XML_TEXTWRITER_ATTRIBUTE:
666 case XML_TEXTWRITER_TEXT:
667 count = xmlTextWriterEndElement(writer);
668 if (count < 0)
669 return -1;
670 sum += count;
671 break;
672 case XML_TEXTWRITER_PI:
673 case XML_TEXTWRITER_PI_TEXT:
674 count = xmlTextWriterEndPI(writer);
675 if (count < 0)
676 return -1;
677 sum += count;
678 break;
679 case XML_TEXTWRITER_CDATA:
680 count = xmlTextWriterEndCDATA(writer);
681 if (count < 0)
682 return -1;
683 sum += count;
684 break;
685 case XML_TEXTWRITER_DTD:
Daniel Veillard500a1de2004-03-22 15:22:58 +0000686 case XML_TEXTWRITER_DTD_TEXT:
687 case XML_TEXTWRITER_DTD_ELEM:
688 case XML_TEXTWRITER_DTD_ELEM_TEXT:
689 case XML_TEXTWRITER_DTD_ATTL:
690 case XML_TEXTWRITER_DTD_ATTL_TEXT:
691 case XML_TEXTWRITER_DTD_ENTY:
692 case XML_TEXTWRITER_DTD_ENTY_TEXT:
693 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard1d211e22003-10-20 22:32:39 +0000694 count = xmlTextWriterEndDTD(writer);
695 if (count < 0)
696 return -1;
697 sum += count;
698 break;
Daniel Veillardab69f362004-02-17 11:40:32 +0000699 case XML_TEXTWRITER_COMMENT:
700 count = xmlTextWriterEndComment(writer);
701 if (count < 0)
702 return -1;
703 sum += count;
704 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000705 default:
Daniel Veillardab69f362004-02-17 11:40:32 +0000706 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000707 }
708 }
709
Daniel Veillard2cca4462004-01-02 20:04:23 +0000710 if (!writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000711 count = xmlOutputBufferWriteString(writer->out, "\n");
712 if (count < 0)
713 return -1;
714 sum += count;
715 }
Daniel Veillard3ff24112008-02-13 10:17:41 +0000716
717 sum += xmlTextWriterFlush(writer);
718
Daniel Veillardab69f362004-02-17 11:40:32 +0000719 return sum;
720}
721
Daniel Veillardab69f362004-02-17 11:40:32 +0000722/**
723 * xmlTextWriterStartComment:
724 * @writer: the xmlTextWriterPtr
725 *
726 * Start an xml comment.
727 *
728 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
729 */
730int
731xmlTextWriterStartComment(xmlTextWriterPtr writer)
732{
733 int count;
734 int sum;
735 xmlLinkPtr lk;
736 xmlTextWriterStackEntry *p;
737
Daniel Veillard500a1de2004-03-22 15:22:58 +0000738 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000739 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000740 "xmlTextWriterStartComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000741 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000742 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000743
744 sum = 0;
745 lk = xmlListFront(writer->nodes);
746 if (lk != 0) {
747 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
748 if (p != 0) {
749 switch (p->state) {
750 case XML_TEXTWRITER_TEXT:
751 case XML_TEXTWRITER_NONE:
752 break;
753 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000754 /* Output namespace declarations */
755 count = xmlTextWriterOutputNSDecl(writer);
756 if (count < 0)
757 return -1;
758 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000759 count = xmlOutputBufferWriteString(writer->out, ">");
760 if (count < 0)
761 return -1;
762 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000763 if (writer->indent) {
764 count =
765 xmlOutputBufferWriteString(writer->out, "\n");
766 if (count < 0)
767 return -1;
768 sum += count;
769 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000770 p->state = XML_TEXTWRITER_TEXT;
771 break;
772 default:
773 return -1;
774 }
775 }
776 }
777
778 p = (xmlTextWriterStackEntry *)
779 xmlMalloc(sizeof(xmlTextWriterStackEntry));
780 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000781 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillardab69f362004-02-17 11:40:32 +0000782 "xmlTextWriterStartElement : out of memory!\n");
783 return -1;
784 }
785
Daniel Veillard75e389d2005-07-29 22:02:24 +0000786 p->name = NULL;
Daniel Veillardab69f362004-02-17 11:40:32 +0000787 p->state = XML_TEXTWRITER_COMMENT;
788
789 xmlListPushFront(writer->nodes, p);
790
791 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +0000792 count = xmlTextWriterWriteIndent(writer);
793 if (count < 0)
794 return -1;
795 sum += count;
796 }
797
798 count = xmlOutputBufferWriteString(writer->out, "<!--");
799 if (count < 0)
Daniel Veillard5841f0e2003-11-20 11:59:09 +0000800 return -1;
801 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000802
803 return sum;
804}
805
806/**
807 * xmlTextWriterEndComment:
808 * @writer: the xmlTextWriterPtr
809 *
810 * End the current xml coment.
811 *
812 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
813 */
814int
815xmlTextWriterEndComment(xmlTextWriterPtr writer)
816{
817 int count;
818 int sum;
819 xmlLinkPtr lk;
820 xmlTextWriterStackEntry *p;
821
Daniel Veillard500a1de2004-03-22 15:22:58 +0000822 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000823 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000824 "xmlTextWriterEndComment : invalid writer!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000825 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000826 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000827
828 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000829 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000830 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000831 "xmlTextWriterEndComment : not allowed in this context!\n");
Daniel Veillardab69f362004-02-17 11:40:32 +0000832 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000833 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000834
835 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
836 if (p == 0)
837 return -1;
838
839 sum = 0;
840 switch (p->state) {
841 case XML_TEXTWRITER_COMMENT:
842 count = xmlOutputBufferWriteString(writer->out, "-->");
843 if (count < 0)
844 return -1;
845 sum += count;
846 break;
847 default:
848 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +0000849 }
Daniel Veillardab69f362004-02-17 11:40:32 +0000850
851 if (writer->indent) {
852 count = xmlOutputBufferWriteString(writer->out, "\n");
853 if (count < 0)
854 return -1;
855 sum += count;
856 }
857
858 xmlListPopFront(writer->nodes);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000859 return sum;
860}
861
862/**
863 * xmlTextWriterWriteFormatComment:
864 * @writer: the xmlTextWriterPtr
865 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +0000866 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +0000867 *
868 * Write an xml comment.
869 *
870 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
871 */
Daniel Veillardffa3c742005-07-21 13:24:09 +0000872int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +0000873xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
874 const char *format, ...)
875{
876 int rc;
877 va_list ap;
878
879 va_start(ap, format);
880
881 rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
882
883 va_end(ap);
884 return rc;
885}
886
887/**
888 * xmlTextWriterWriteVFormatComment:
889 * @writer: the xmlTextWriterPtr
890 * @format: format string (see printf)
891 * @argptr: pointer to the first member of the variable argument list.
892 *
893 * Write an xml comment.
894 *
895 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
896 */
897int
898xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
899 const char *format, va_list argptr)
900{
901 int rc;
902 xmlChar *buf;
903
Daniel Veillard500a1de2004-03-22 15:22:58 +0000904 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000905 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +0000906 "xmlTextWriterWriteVFormatComment : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +0000907 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000908 }
Daniel Veillard1d211e22003-10-20 22:32:39 +0000909
910 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +0000911 if (buf == NULL)
912 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000913
914 rc = xmlTextWriterWriteComment(writer, buf);
915
916 xmlFree(buf);
917 return rc;
918}
919
920/**
921 * xmlTextWriterWriteComment:
922 * @writer: the xmlTextWriterPtr
923 * @content: comment string
924 *
925 * Write an xml comment.
926 *
927 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
928 */
929int
930xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
931{
932 int count;
933 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000934
935 sum = 0;
Daniel Veillardab69f362004-02-17 11:40:32 +0000936 count = xmlTextWriterStartComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000937 if (count < 0)
938 return -1;
939 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000940 count = xmlTextWriterWriteString(writer, content);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000941 if (count < 0)
942 return -1;
943 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000944 count = xmlTextWriterEndComment(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +0000945 if (count < 0)
946 return -1;
947 sum += count;
948
949 return sum;
950}
951
952/**
953 * xmlTextWriterStartElement:
954 * @writer: the xmlTextWriterPtr
955 * @name: element name
956 *
957 * Start an xml element.
958 *
959 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
960 */
961int
962xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
963{
964 int count;
965 int sum;
966 xmlLinkPtr lk;
967 xmlTextWriterStackEntry *p;
968
969 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
970 return -1;
971
972 sum = 0;
973 lk = xmlListFront(writer->nodes);
974 if (lk != 0) {
975 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
976 if (p != 0) {
977 switch (p->state) {
978 case XML_TEXTWRITER_PI:
979 case XML_TEXTWRITER_PI_TEXT:
980 return -1;
981 case XML_TEXTWRITER_NONE:
982 break;
Daniel Veillard614fdc12005-02-23 14:05:37 +0000983 case XML_TEXTWRITER_ATTRIBUTE:
984 count = xmlTextWriterEndAttribute(writer);
985 if (count < 0)
986 return -1;
987 sum += count;
988 /* fallthrough */
Daniel Veillard1d211e22003-10-20 22:32:39 +0000989 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +0000990 /* Output namespace declarations */
991 count = xmlTextWriterOutputNSDecl(writer);
992 if (count < 0)
993 return -1;
994 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000995 count = xmlOutputBufferWriteString(writer->out, ">");
996 if (count < 0)
997 return -1;
998 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +0000999 if (writer->indent)
1000 count =
1001 xmlOutputBufferWriteString(writer->out, "\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001002 p->state = XML_TEXTWRITER_TEXT;
1003 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00001004 default:
1005 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001006 }
1007 }
1008 }
1009
1010 p = (xmlTextWriterStackEntry *)
1011 xmlMalloc(sizeof(xmlTextWriterStackEntry));
1012 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001013 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001014 "xmlTextWriterStartElement : out of memory!\n");
1015 return -1;
1016 }
1017
1018 p->name = xmlStrdup(name);
1019 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001020 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001021 "xmlTextWriterStartElement : out of memory!\n");
1022 xmlFree(p);
1023 return -1;
1024 }
1025 p->state = XML_TEXTWRITER_NAME;
1026
1027 xmlListPushFront(writer->nodes, p);
1028
Daniel Veillardab69f362004-02-17 11:40:32 +00001029 if (writer->indent) {
1030 count = xmlTextWriterWriteIndent(writer);
1031 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001032 }
1033
Daniel Veillard1d211e22003-10-20 22:32:39 +00001034 count = xmlOutputBufferWriteString(writer->out, "<");
1035 if (count < 0)
1036 return -1;
1037 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001038 count =
1039 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001040 if (count < 0)
1041 return -1;
1042 sum += count;
1043
1044 return sum;
1045}
1046
1047/**
1048 * xmlTextWriterStartElementNS:
1049 * @writer: the xmlTextWriterPtr
1050 * @prefix: namespace prefix or NULL
1051 * @name: element local name
1052 * @namespaceURI: namespace URI or NULL
1053 *
1054 * Start an xml element with namespace support.
1055 *
1056 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1057 */
1058int
1059xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
1060 const xmlChar * prefix, const xmlChar * name,
1061 const xmlChar * namespaceURI)
1062{
1063 int count;
1064 int sum;
1065 xmlChar *buf;
1066
1067 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1068 return -1;
1069
Daniel Veillard75e389d2005-07-29 22:02:24 +00001070 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001071 if (prefix != 0) {
1072 buf = xmlStrdup(prefix);
1073 buf = xmlStrcat(buf, BAD_CAST ":");
1074 }
1075 buf = xmlStrcat(buf, name);
1076
1077 sum = 0;
1078 count = xmlTextWriterStartElement(writer, buf);
1079 xmlFree(buf);
1080 if (count < 0)
1081 return -1;
1082 sum += count;
1083
1084 if (namespaceURI != 0) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001085 xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
Rob Richardsb8769d62007-06-08 08:50:47 +00001086 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1087 if (p == 0) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001088 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Rob Richardsb8769d62007-06-08 08:50:47 +00001089 "xmlTextWriterStartElementNS : out of memory!\n");
1090 return -1;
1091 }
1092
Daniel Veillard1d211e22003-10-20 22:32:39 +00001093 buf = xmlStrdup(BAD_CAST "xmlns");
1094 if (prefix != 0) {
1095 buf = xmlStrcat(buf, BAD_CAST ":");
1096 buf = xmlStrcat(buf, prefix);
1097 }
1098
Rob Richardsb8769d62007-06-08 08:50:47 +00001099 p->prefix = buf;
1100 p->uri = xmlStrdup(namespaceURI);
1101 if (p->uri == 0) {
1102 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1103 "xmlTextWriterStartElementNS : out of memory!\n");
1104 xmlFree(p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001105 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001106 }
1107 p->elem = xmlListFront(writer->nodes);
1108
1109 xmlListPushFront(writer->nsstack, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001110 }
1111
1112 return sum;
1113}
1114
1115/**
1116 * xmlTextWriterEndElement:
1117 * @writer: the xmlTextWriterPtr
1118 *
1119 * End the current xml element.
1120 *
1121 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1122 */
1123int
1124xmlTextWriterEndElement(xmlTextWriterPtr writer)
1125{
1126 int count;
1127 int sum;
1128 xmlLinkPtr lk;
1129 xmlTextWriterStackEntry *p;
1130
1131 if (writer == NULL)
1132 return -1;
1133
1134 lk = xmlListFront(writer->nodes);
Rob Richardsb8769d62007-06-08 08:50:47 +00001135 if (lk == 0) {
1136 xmlListDelete(writer->nsstack);
1137 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001138 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001139 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001140
1141 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Rob Richardsb8769d62007-06-08 08:50:47 +00001142 if (p == 0) {
1143 xmlListDelete(writer->nsstack);
1144 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001145 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001146 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001147
1148 sum = 0;
1149 switch (p->state) {
1150 case XML_TEXTWRITER_ATTRIBUTE:
1151 count = xmlTextWriterEndAttribute(writer);
Rob Richardsb8769d62007-06-08 08:50:47 +00001152 if (count < 0) {
1153 xmlListDelete(writer->nsstack);
1154 writer->nsstack = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001155 return -1;
Rob Richardsb8769d62007-06-08 08:50:47 +00001156 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001157 sum += count;
1158 /* fallthrough */
1159 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001160 /* Output namespace declarations */
1161 count = xmlTextWriterOutputNSDecl(writer);
1162 if (count < 0)
1163 return -1;
1164 sum += count;
1165
Daniel Veillardab69f362004-02-17 11:40:32 +00001166 if (writer->indent) /* next element needs indent */
1167 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001168 count = xmlOutputBufferWriteString(writer->out, "/>");
1169 if (count < 0)
1170 return -1;
1171 sum += count;
1172 break;
1173 case XML_TEXTWRITER_TEXT:
Daniel Veillardab69f362004-02-17 11:40:32 +00001174 if ((writer->indent) && (writer->doindent)) {
1175 count = xmlTextWriterWriteIndent(writer);
1176 sum += count;
1177 writer->doindent = 1;
1178 } else
1179 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001180 count = xmlOutputBufferWriteString(writer->out, "</");
1181 if (count < 0)
1182 return -1;
1183 sum += count;
1184 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001185 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001186 if (count < 0)
1187 return -1;
1188 sum += count;
1189 count = xmlOutputBufferWriteString(writer->out, ">");
1190 if (count < 0)
1191 return -1;
1192 sum += count;
1193 break;
1194 default:
1195 return -1;
1196 }
1197
Daniel Veillard2cca4462004-01-02 20:04:23 +00001198 if (writer->indent) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001199 count = xmlOutputBufferWriteString(writer->out, "\n");
1200 sum += count;
Daniel Veillard2cca4462004-01-02 20:04:23 +00001201 }
1202
Daniel Veillard1d211e22003-10-20 22:32:39 +00001203 xmlListPopFront(writer->nodes);
1204 return sum;
1205}
1206
1207/**
1208 * xmlTextWriterFullEndElement:
1209 * @writer: the xmlTextWriterPtr
1210 *
1211 * End the current xml element. Writes an end tag even if the element is empty
1212 *
1213 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1214 */
1215int
1216xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1217{
1218 int count;
1219 int sum;
1220 xmlLinkPtr lk;
1221 xmlTextWriterStackEntry *p;
1222
1223 if (writer == NULL)
1224 return -1;
1225
1226 lk = xmlListFront(writer->nodes);
1227 if (lk == 0)
1228 return -1;
1229
1230 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1231 if (p == 0)
1232 return -1;
1233
1234 sum = 0;
1235 switch (p->state) {
1236 case XML_TEXTWRITER_ATTRIBUTE:
1237 count = xmlTextWriterEndAttribute(writer);
1238 if (count < 0)
1239 return -1;
1240 sum += count;
1241 /* fallthrough */
1242 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00001243 /* Output namespace declarations */
1244 count = xmlTextWriterOutputNSDecl(writer);
1245 if (count < 0)
1246 return -1;
1247 sum += count;
1248
Daniel Veillard1d211e22003-10-20 22:32:39 +00001249 count = xmlOutputBufferWriteString(writer->out, ">");
1250 if (count < 0)
1251 return -1;
1252 sum += count;
Rob Richards5a7d8bd2008-12-27 13:17:43 +00001253 if (writer->indent)
1254 writer->doindent = 0;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001255 /* fallthrough */
1256 case XML_TEXTWRITER_TEXT:
Rob Richards5a7d8bd2008-12-27 13:17:43 +00001257 if ((writer->indent) && (writer->doindent)) {
1258 count = xmlTextWriterWriteIndent(writer);
1259 sum += count;
1260 writer->doindent = 1;
1261 } else
1262 writer->doindent = 1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001263 count = xmlOutputBufferWriteString(writer->out, "</");
1264 if (count < 0)
1265 return -1;
1266 sum += count;
1267 count = xmlOutputBufferWriteString(writer->out,
Daniel Veillardab69f362004-02-17 11:40:32 +00001268 (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001269 if (count < 0)
1270 return -1;
1271 sum += count;
1272 count = xmlOutputBufferWriteString(writer->out, ">");
1273 if (count < 0)
1274 return -1;
1275 sum += count;
1276 break;
1277 default:
1278 return -1;
1279 }
1280
Daniel Veillard7e26fb42008-01-09 02:19:50 +00001281 if (writer->indent) {
1282 count = xmlOutputBufferWriteString(writer->out, "\n");
1283 sum += count;
1284 }
1285
Daniel Veillard1d211e22003-10-20 22:32:39 +00001286 xmlListPopFront(writer->nodes);
1287 return sum;
1288}
1289
1290/**
1291 * xmlTextWriterWriteFormatRaw:
1292 * @writer: the xmlTextWriterPtr
1293 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001294 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001295 *
1296 * Write a formatted raw xml text.
1297 *
1298 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1299 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001300int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001301xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1302 ...)
1303{
1304 int rc;
1305 va_list ap;
1306
1307 va_start(ap, format);
1308
1309 rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1310
1311 va_end(ap);
1312 return rc;
1313}
1314
1315/**
1316 * xmlTextWriterWriteVFormatRaw:
1317 * @writer: the xmlTextWriterPtr
1318 * @format: format string (see printf)
1319 * @argptr: pointer to the first member of the variable argument list.
1320 *
1321 * Write a formatted raw xml text.
1322 *
1323 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1324 */
1325int
1326xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1327 va_list argptr)
1328{
1329 int rc;
1330 xmlChar *buf;
1331
1332 if (writer == NULL)
1333 return -1;
1334
1335 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00001336 if (buf == NULL)
1337 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001338
1339 rc = xmlTextWriterWriteRaw(writer, buf);
1340
1341 xmlFree(buf);
1342 return rc;
1343}
1344
1345/**
Daniel Veillard1e906612003-12-05 14:57:46 +00001346 * xmlTextWriterWriteRawLen:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001347 * @writer: the xmlTextWriterPtr
1348 * @content: text string
1349 * @len: length of the text string
1350 *
1351 * Write an xml text.
1352 * TODO: what about entities and special chars??
1353 *
1354 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1355 */
1356int
1357xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1358 int len)
1359{
1360 int count;
1361 int sum;
1362 xmlLinkPtr lk;
1363 xmlTextWriterStackEntry *p;
1364
Daniel Veillard500a1de2004-03-22 15:22:58 +00001365 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001366 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001367 "xmlTextWriterWriteRawLen : invalid writer!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001368 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001369 }
1370
Daniel Veillarde43cc572004-11-03 11:50:29 +00001371 if ((content == NULL) || (len < 0)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001372 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00001373 "xmlTextWriterWriteRawLen : invalid content!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00001374 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001375 }
1376
1377 sum = 0;
1378 lk = xmlListFront(writer->nodes);
1379 if (lk != 0) {
1380 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1381 count = xmlTextWriterHandleStateDependencies(writer, p);
1382 if (count < 0)
1383 return -1;
1384 sum += count;
1385 }
1386
1387 if (writer->indent)
1388 writer->doindent = 0;
1389
1390 if (content != NULL) {
1391 count =
1392 xmlOutputBufferWrite(writer->out, len, (const char *) content);
1393 if (count < 0)
1394 return -1;
1395 sum += count;
1396 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001397
1398 return sum;
1399}
1400
1401/**
1402 * xmlTextWriterWriteRaw:
1403 * @writer: the xmlTextWriterPtr
1404 * @content: text string
1405 *
1406 * Write a raw xml text.
1407 *
1408 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1409 */
1410int
1411xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1412{
1413 return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1414}
1415
1416/**
1417 * xmlTextWriterWriteFormatString:
1418 * @writer: the xmlTextWriterPtr
1419 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001420 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001421 *
1422 * Write a formatted xml text.
1423 *
1424 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1425 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001426int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001427xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1428 ...)
1429{
1430 int rc;
1431 va_list ap;
1432
Daniel Veillarde43cc572004-11-03 11:50:29 +00001433 if ((writer == NULL) || (format == NULL))
1434 return -1;
1435
Daniel Veillard1d211e22003-10-20 22:32:39 +00001436 va_start(ap, format);
1437
1438 rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1439
1440 va_end(ap);
1441 return rc;
1442}
1443
1444/**
1445 * xmlTextWriterWriteVFormatString:
1446 * @writer: the xmlTextWriterPtr
1447 * @format: format string (see printf)
1448 * @argptr: pointer to the first member of the variable argument list.
1449 *
1450 * Write a formatted xml text.
1451 *
1452 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1453 */
1454int
1455xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1456 const char *format, va_list argptr)
1457{
1458 int rc;
1459 xmlChar *buf;
1460
Daniel Veillarde43cc572004-11-03 11:50:29 +00001461 if ((writer == NULL) || (format == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001462 return -1;
1463
1464 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00001465 if (buf == NULL)
1466 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001467
1468 rc = xmlTextWriterWriteString(writer, buf);
1469
1470 xmlFree(buf);
1471 return rc;
1472}
1473
1474/**
1475 * xmlTextWriterWriteString:
1476 * @writer: the xmlTextWriterPtr
1477 * @content: text string
1478 *
1479 * Write an xml text.
1480 *
1481 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1482 */
1483int
1484xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1485{
Daniel Veillard500a1de2004-03-22 15:22:58 +00001486 int count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001487 int sum;
1488 xmlLinkPtr lk;
1489 xmlTextWriterStackEntry *p;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001490 xmlChar *buf;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001491
Daniel Veillarde43cc572004-11-03 11:50:29 +00001492 if ((writer == NULL) || (content == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001493 return -1;
1494
Daniel Veillard1d211e22003-10-20 22:32:39 +00001495 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001496 buf = (xmlChar *) content;
1497 lk = xmlListFront(writer->nodes);
1498 if (lk != 0) {
1499 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1500 if (p != 0) {
1501 switch (p->state) {
1502 case XML_TEXTWRITER_NAME:
1503 case XML_TEXTWRITER_TEXT:
Daniel Veillard62040be2004-05-17 03:17:26 +00001504#if 0
1505 buf = NULL;
1506 xmlOutputBufferWriteEscape(writer->out, content, NULL);
1507#endif
Daniel Veillard500a1de2004-03-22 15:22:58 +00001508 buf = xmlEncodeSpecialChars(NULL, content);
1509 break;
1510 case XML_TEXTWRITER_ATTRIBUTE:
1511 buf = NULL;
Daniel Veillarddbf54112012-07-16 14:54:45 +08001512 xmlBufAttrSerializeTxtContent(writer->out->buffer,
1513 writer->doc, NULL, content);
Daniel Veillard500a1de2004-03-22 15:22:58 +00001514 break;
William M. Brack87640d52004-04-17 14:58:15 +00001515 default:
1516 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001517 }
1518 }
1519 }
1520
1521 if (buf != NULL) {
1522 count = xmlTextWriterWriteRaw(writer, buf);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001523
Daniel Veillard500a1de2004-03-22 15:22:58 +00001524 if (buf != content) /* buf was allocated by us, so free it */
1525 xmlFree(buf);
Daniel Veillardeb0a0b22009-02-20 08:19:53 +00001526
1527 if (count < 0)
1528 return -1;
1529 sum += count;
William M. Bracka9c612c2004-02-01 10:04:05 +00001530 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001531
1532 return sum;
1533}
1534
1535/**
1536 * xmlOutputBufferWriteBase64:
1537 * @out: the xmlOutputBufferPtr
1538 * @data: binary data
1539 * @len: the number of bytes to encode
1540 *
1541 * Write base64 encoded data to an xmlOutputBuffer.
1542 * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1543 *
1544 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1545 */
1546static int
1547xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1548 const unsigned char *data)
1549{
1550 static unsigned char dtable[64] =
William M. Brack47a31882004-09-11 16:09:09 +00001551 {'A','B','C','D','E','F','G','H','I','J','K','L','M',
1552 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1553 'a','b','c','d','e','f','g','h','i','j','k','l','m',
1554 'n','o','p','q','r','s','t','u','v','w','x','y','z',
1555 '0','1','2','3','4','5','6','7','8','9','+','/'};
1556
Daniel Veillard1d211e22003-10-20 22:32:39 +00001557 int i;
1558 int linelen;
1559 int count;
1560 int sum;
1561
Daniel Veillarde43cc572004-11-03 11:50:29 +00001562 if ((out == NULL) || (len < 0) || (data == NULL))
1563 return(-1);
1564
Daniel Veillard1d211e22003-10-20 22:32:39 +00001565 linelen = 0;
1566 sum = 0;
1567
1568 i = 0;
1569 while (1) {
1570 unsigned char igroup[3];
1571 unsigned char ogroup[4];
1572 int c;
1573 int n;
1574
1575 igroup[0] = igroup[1] = igroup[2] = 0;
1576 for (n = 0; n < 3 && i < len; n++, i++) {
1577 c = data[i];
1578 igroup[n] = (unsigned char) c;
1579 }
1580
1581 if (n > 0) {
1582 ogroup[0] = dtable[igroup[0] >> 2];
1583 ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1584 ogroup[2] =
1585 dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1586 ogroup[3] = dtable[igroup[2] & 0x3F];
1587
1588 if (n < 3) {
1589 ogroup[3] = '=';
1590 if (n < 2) {
1591 ogroup[2] = '=';
1592 }
1593 }
1594
1595 if (linelen >= B64LINELEN) {
1596 count = xmlOutputBufferWrite(out, 2, B64CRLF);
1597 if (count == -1)
1598 return -1;
1599 sum += count;
1600 linelen = 0;
1601 }
1602 count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1603 if (count == -1)
1604 return -1;
1605 sum += count;
1606
1607 linelen += 4;
1608 }
Daniel Veillard929714b2003-10-22 12:34:36 +00001609
1610 if (i >= len)
1611 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001612 }
1613
Daniel Veillard1d211e22003-10-20 22:32:39 +00001614 return sum;
1615}
1616
1617/**
1618 * xmlTextWriterWriteBase64:
1619 * @writer: the xmlTextWriterPtr
1620 * @data: binary data
1621 * @start: the position within the data of the first byte to encode
1622 * @len: the number of bytes to encode
1623 *
1624 * Write an base64 encoded xml text.
1625 *
1626 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1627 */
1628int
Daniel Veillardab69f362004-02-17 11:40:32 +00001629xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001630 int start, int len)
1631{
1632 int count;
1633 int sum;
1634 xmlLinkPtr lk;
1635 xmlTextWriterStackEntry *p;
1636
Daniel Veillarde43cc572004-11-03 11:50:29 +00001637 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001638 return -1;
1639
Daniel Veillard1d211e22003-10-20 22:32:39 +00001640 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001641 lk = xmlListFront(writer->nodes);
1642 if (lk != 0) {
1643 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1644 if (p != 0) {
1645 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001646 if (count < 0)
1647 return -1;
1648 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001649 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001650 }
1651
Daniel Veillardab69f362004-02-17 11:40:32 +00001652 if (writer->indent)
1653 writer->doindent = 0;
1654
Daniel Veillard1d211e22003-10-20 22:32:39 +00001655 count =
1656 xmlOutputBufferWriteBase64(writer->out, len,
1657 (unsigned char *) data + start);
1658 if (count < 0)
1659 return -1;
1660 sum += count;
1661
1662 return sum;
1663}
1664
1665/**
1666 * xmlOutputBufferWriteBinHex:
1667 * @out: the xmlOutputBufferPtr
1668 * @data: binary data
1669 * @len: the number of bytes to encode
1670 *
1671 * Write hqx encoded data to an xmlOutputBuffer.
1672 * ::todo
1673 *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001674 * Returns the bytes written (may be 0 because of buffering)
William M. Brack47a31882004-09-11 16:09:09 +00001675 * or -1 in case of error
Daniel Veillard1d211e22003-10-20 22:32:39 +00001676 */
1677static int
Daniel Veillardab69f362004-02-17 11:40:32 +00001678xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1679 int len, const unsigned char *data)
Daniel Veillard1d211e22003-10-20 22:32:39 +00001680{
Daniel Veillardab69f362004-02-17 11:40:32 +00001681 int count;
1682 int sum;
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001683 static char hex[16] =
1684 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
Daniel Veillardab69f362004-02-17 11:40:32 +00001685 int i;
1686
Daniel Veillarde43cc572004-11-03 11:50:29 +00001687 if ((out == NULL) || (data == NULL) || (len < 0)) {
Daniel Veillardab69f362004-02-17 11:40:32 +00001688 return -1;
1689 }
1690
1691 sum = 0;
1692 for (i = 0; i < len; i++) {
1693 count =
1694 xmlOutputBufferWrite(out, 1,
1695 (const char *) &hex[data[i] >> 4]);
1696 if (count == -1)
1697 return -1;
1698 sum += count;
1699 count =
1700 xmlOutputBufferWrite(out, 1,
1701 (const char *) &hex[data[i] & 0xF]);
1702 if (count == -1)
1703 return -1;
1704 sum += count;
1705 }
1706
1707 return sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001708}
1709
1710/**
1711 * xmlTextWriterWriteBinHex:
1712 * @writer: the xmlTextWriterPtr
1713 * @data: binary data
1714 * @start: the position within the data of the first byte to encode
1715 * @len: the number of bytes to encode
1716 *
1717 * Write a BinHex encoded xml text.
1718 *
1719 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1720 */
1721int
Daniel Veillardab69f362004-02-17 11:40:32 +00001722xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
Daniel Veillard1d211e22003-10-20 22:32:39 +00001723 int start, int len)
1724{
1725 int count;
1726 int sum;
1727 xmlLinkPtr lk;
1728 xmlTextWriterStackEntry *p;
1729
Daniel Veillarde43cc572004-11-03 11:50:29 +00001730 if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
Daniel Veillard1d211e22003-10-20 22:32:39 +00001731 return -1;
1732
Daniel Veillard1d211e22003-10-20 22:32:39 +00001733 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001734 lk = xmlListFront(writer->nodes);
1735 if (lk != 0) {
1736 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1737 if (p != 0) {
1738 count = xmlTextWriterHandleStateDependencies(writer, p);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001739 if (count < 0)
1740 return -1;
1741 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001742 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00001743 }
1744
Daniel Veillardab69f362004-02-17 11:40:32 +00001745 if (writer->indent)
1746 writer->doindent = 0;
1747
Daniel Veillard1d211e22003-10-20 22:32:39 +00001748 count =
1749 xmlOutputBufferWriteBinHex(writer->out, len,
1750 (unsigned char *) data + start);
1751 if (count < 0)
1752 return -1;
1753 sum += count;
1754
1755 return sum;
1756}
1757
1758/**
1759 * xmlTextWriterStartAttribute:
1760 * @writer: the xmlTextWriterPtr
1761 * @name: element name
1762 *
1763 * Start an xml attribute.
1764 *
1765 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1766 */
1767int
1768xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1769{
1770 int count;
1771 int sum;
1772 xmlLinkPtr lk;
1773 xmlTextWriterStackEntry *p;
1774
1775 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1776 return -1;
1777
1778 sum = 0;
1779 lk = xmlListFront(writer->nodes);
1780 if (lk == 0)
1781 return -1;
1782
1783 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1784 if (p == 0)
1785 return -1;
1786
1787 switch (p->state) {
1788 case XML_TEXTWRITER_ATTRIBUTE:
1789 count = xmlTextWriterEndAttribute(writer);
1790 if (count < 0)
1791 return -1;
1792 sum += count;
1793 /* fallthrough */
1794 case XML_TEXTWRITER_NAME:
1795 count = xmlOutputBufferWriteString(writer->out, " ");
1796 if (count < 0)
1797 return -1;
1798 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00001799 count =
1800 xmlOutputBufferWriteString(writer->out,
1801 (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00001802 if (count < 0)
1803 return -1;
1804 sum += count;
1805 count = xmlOutputBufferWriteString(writer->out, "=");
1806 if (count < 0)
1807 return -1;
1808 sum += count;
1809 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1810 if (count < 0)
1811 return -1;
1812 sum += count;
1813 p->state = XML_TEXTWRITER_ATTRIBUTE;
1814 break;
1815 default:
1816 return -1;
1817 }
1818
1819 return sum;
1820}
1821
1822/**
1823 * xmlTextWriterStartAttributeNS:
1824 * @writer: the xmlTextWriterPtr
1825 * @prefix: namespace prefix or NULL
1826 * @name: element local name
1827 * @namespaceURI: namespace URI or NULL
1828 *
1829 * Start an xml attribute with namespace support.
1830 *
1831 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1832 */
1833int
1834xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1835 const xmlChar * prefix, const xmlChar * name,
1836 const xmlChar * namespaceURI)
1837{
1838 int count;
1839 int sum;
1840 xmlChar *buf;
1841 xmlTextWriterNsStackEntry *p;
1842
1843 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1844 return -1;
1845
Rob Richardsb8769d62007-06-08 08:50:47 +00001846 /* Handle namespace first in case of error */
1847 if (namespaceURI != 0) {
1848 xmlTextWriterNsStackEntry nsentry, *curns;
1849
1850 buf = xmlStrdup(BAD_CAST "xmlns");
1851 if (prefix != 0) {
1852 buf = xmlStrcat(buf, BAD_CAST ":");
1853 buf = xmlStrcat(buf, prefix);
1854 }
1855
1856 nsentry.prefix = buf;
1857 nsentry.uri = (xmlChar *)namespaceURI;
1858 nsentry.elem = xmlListFront(writer->nodes);
1859
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001860 curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
Rob Richardsb8769d62007-06-08 08:50:47 +00001861 (void *)&nsentry);
1862 if ((curns != NULL)) {
1863 xmlFree(buf);
1864 if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
1865 /* Namespace already defined on element skip */
1866 buf = NULL;
1867 } else {
1868 /* Prefix mismatch so error out */
1869 return -1;
1870 }
1871 }
1872
1873 /* Do not add namespace decl to list - it is already there */
1874 if (buf != NULL) {
1875 p = (xmlTextWriterNsStackEntry *)
1876 xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1877 if (p == 0) {
1878 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1879 "xmlTextWriterStartAttributeNS : out of memory!\n");
1880 return -1;
1881 }
1882
1883 p->prefix = buf;
1884 p->uri = xmlStrdup(namespaceURI);
1885 if (p->uri == 0) {
1886 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1887 "xmlTextWriterStartAttributeNS : out of memory!\n");
1888 xmlFree(p);
1889 return -1;
1890 }
1891 p->elem = xmlListFront(writer->nodes);
1892
1893 xmlListPushFront(writer->nsstack, p);
1894 }
1895 }
1896
Daniel Veillard75e389d2005-07-29 22:02:24 +00001897 buf = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001898 if (prefix != 0) {
1899 buf = xmlStrdup(prefix);
1900 buf = xmlStrcat(buf, BAD_CAST ":");
1901 }
1902 buf = xmlStrcat(buf, name);
1903
1904 sum = 0;
1905 count = xmlTextWriterStartAttribute(writer, buf);
1906 xmlFree(buf);
1907 if (count < 0)
1908 return -1;
1909 sum += count;
1910
Daniel Veillard1d211e22003-10-20 22:32:39 +00001911 return sum;
1912}
1913
1914/**
1915 * xmlTextWriterEndAttribute:
1916 * @writer: the xmlTextWriterPtr
1917 *
1918 * End the current xml element.
1919 *
1920 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1921 */
1922int
1923xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1924{
1925 int count;
1926 int sum;
1927 xmlLinkPtr lk;
1928 xmlTextWriterStackEntry *p;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001929
1930 if (writer == NULL)
1931 return -1;
1932
1933 lk = xmlListFront(writer->nodes);
1934 if (lk == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001935 return -1;
1936 }
1937
1938 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1939 if (p == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001940 return -1;
1941 }
1942
1943 sum = 0;
1944 switch (p->state) {
1945 case XML_TEXTWRITER_ATTRIBUTE:
1946 p->state = XML_TEXTWRITER_NAME;
1947
1948 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1949 if (count < 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001950 return -1;
1951 }
1952 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001953 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001954 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00001955 return -1;
1956 }
1957
1958 return sum;
1959}
1960
1961/**
1962 * xmlTextWriterWriteFormatAttribute:
1963 * @writer: the xmlTextWriterPtr
1964 * @name: attribute name
1965 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00001966 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00001967 *
1968 * Write a formatted xml attribute.
1969 *
1970 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1971 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00001972int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00001973xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1974 const xmlChar * name, const char *format,
1975 ...)
1976{
1977 int rc;
1978 va_list ap;
1979
1980 va_start(ap, format);
1981
1982 rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1983
1984 va_end(ap);
1985 return rc;
1986}
1987
1988/**
1989 * xmlTextWriterWriteVFormatAttribute:
1990 * @writer: the xmlTextWriterPtr
1991 * @name: attribute name
1992 * @format: format string (see printf)
1993 * @argptr: pointer to the first member of the variable argument list.
1994 *
1995 * Write a formatted xml attribute.
1996 *
1997 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1998 */
1999int
2000xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
2001 const xmlChar * name,
2002 const char *format, va_list argptr)
2003{
2004 int rc;
2005 xmlChar *buf;
2006
2007 if (writer == NULL)
2008 return -1;
2009
2010 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002011 if (buf == NULL)
2012 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002013
2014 rc = xmlTextWriterWriteAttribute(writer, name, buf);
2015
2016 xmlFree(buf);
2017 return rc;
2018}
2019
2020/**
2021 * xmlTextWriterWriteAttribute:
2022 * @writer: the xmlTextWriterPtr
2023 * @name: attribute name
2024 * @content: attribute content
2025 *
2026 * Write an xml attribute.
2027 *
2028 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2029 */
2030int
2031xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
2032 const xmlChar * content)
2033{
2034 int count;
2035 int sum;
2036
2037 sum = 0;
2038 count = xmlTextWriterStartAttribute(writer, name);
2039 if (count < 0)
2040 return -1;
2041 sum += count;
2042 count = xmlTextWriterWriteString(writer, content);
2043 if (count < 0)
2044 return -1;
2045 sum += count;
2046 count = xmlTextWriterEndAttribute(writer);
2047 if (count < 0)
2048 return -1;
2049 sum += count;
2050
2051 return sum;
2052}
2053
2054/**
2055 * xmlTextWriterWriteFormatAttributeNS:
2056 * @writer: the xmlTextWriterPtr
2057 * @prefix: namespace prefix
2058 * @name: attribute local name
2059 * @namespaceURI: namespace URI
2060 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002061 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002062 *
2063 * Write a formatted xml attribute.with namespace support
2064 *
2065 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2066 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002067int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002068xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
2069 const xmlChar * prefix,
2070 const xmlChar * name,
2071 const xmlChar * namespaceURI,
2072 const char *format, ...)
2073{
2074 int rc;
2075 va_list ap;
2076
2077 va_start(ap, format);
2078
2079 rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
2080 namespaceURI, format, ap);
2081
2082 va_end(ap);
2083 return rc;
2084}
2085
2086/**
2087 * xmlTextWriterWriteVFormatAttributeNS:
2088 * @writer: the xmlTextWriterPtr
2089 * @prefix: namespace prefix
2090 * @name: attribute local name
2091 * @namespaceURI: namespace URI
2092 * @format: format string (see printf)
2093 * @argptr: pointer to the first member of the variable argument list.
2094 *
2095 * Write a formatted xml attribute.with namespace support
2096 *
2097 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2098 */
2099int
2100xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
2101 const xmlChar * prefix,
2102 const xmlChar * name,
2103 const xmlChar * namespaceURI,
2104 const char *format, va_list argptr)
2105{
2106 int rc;
2107 xmlChar *buf;
2108
2109 if (writer == NULL)
2110 return -1;
2111
2112 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002113 if (buf == NULL)
2114 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002115
2116 rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
2117 buf);
2118
2119 xmlFree(buf);
2120 return rc;
2121}
2122
2123/**
2124 * xmlTextWriterWriteAttributeNS:
2125 * @writer: the xmlTextWriterPtr
2126 * @prefix: namespace prefix
2127 * @name: attribute local name
2128 * @namespaceURI: namespace URI
2129 * @content: attribute content
2130 *
2131 * Write an xml attribute.
2132 *
2133 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2134 */
2135int
2136xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
2137 const xmlChar * prefix, const xmlChar * name,
2138 const xmlChar * namespaceURI,
2139 const xmlChar * content)
2140{
2141 int count;
2142 int sum;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002143
2144 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2145 return -1;
2146
Daniel Veillard1d211e22003-10-20 22:32:39 +00002147 sum = 0;
Rob Richardsb8769d62007-06-08 08:50:47 +00002148 count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
2149 if (count < 0)
2150 return -1;
2151 sum += count;
2152 count = xmlTextWriterWriteString(writer, content);
2153 if (count < 0)
2154 return -1;
2155 sum += count;
2156 count = xmlTextWriterEndAttribute(writer);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002157 if (count < 0)
2158 return -1;
2159 sum += count;
2160
Daniel Veillard1d211e22003-10-20 22:32:39 +00002161 return sum;
2162}
2163
2164/**
2165 * xmlTextWriterWriteFormatElement:
2166 * @writer: the xmlTextWriterPtr
2167 * @name: element name
2168 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002169 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002170 *
2171 * Write a formatted xml element.
2172 *
2173 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2174 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002175int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002176xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2177 const xmlChar * name, const char *format,
2178 ...)
2179{
2180 int rc;
2181 va_list ap;
2182
2183 va_start(ap, format);
2184
2185 rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2186
2187 va_end(ap);
2188 return rc;
2189}
2190
2191/**
2192 * xmlTextWriterWriteVFormatElement:
2193 * @writer: the xmlTextWriterPtr
2194 * @name: element name
2195 * @format: format string (see printf)
2196 * @argptr: pointer to the first member of the variable argument list.
2197 *
2198 * Write a formatted xml element.
2199 *
2200 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2201 */
2202int
2203xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2204 const xmlChar * name, const char *format,
2205 va_list argptr)
2206{
2207 int rc;
2208 xmlChar *buf;
2209
2210 if (writer == NULL)
2211 return -1;
2212
2213 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002214 if (buf == NULL)
2215 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002216
2217 rc = xmlTextWriterWriteElement(writer, name, buf);
2218
2219 xmlFree(buf);
2220 return rc;
2221}
2222
2223/**
2224 * xmlTextWriterWriteElement:
2225 * @writer: the xmlTextWriterPtr
2226 * @name: element name
2227 * @content: element content
2228 *
2229 * Write an xml element.
2230 *
2231 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2232 */
2233int
2234xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2235 const xmlChar * content)
2236{
2237 int count;
2238 int sum;
2239
2240 sum = 0;
2241 count = xmlTextWriterStartElement(writer, name);
2242 if (count == -1)
2243 return -1;
2244 sum += count;
2245 count = xmlTextWriterWriteString(writer, content);
2246 if (count == -1)
2247 return -1;
2248 sum += count;
2249 count = xmlTextWriterEndElement(writer);
2250 if (count == -1)
2251 return -1;
2252 sum += count;
2253
2254 return sum;
2255}
2256
2257/**
2258 * xmlTextWriterWriteFormatElementNS:
2259 * @writer: the xmlTextWriterPtr
2260 * @prefix: namespace prefix
2261 * @name: element local name
2262 * @namespaceURI: namespace URI
2263 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002264 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002265 *
2266 * Write a formatted xml element with namespace support.
2267 *
2268 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2269 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002270int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002271xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2272 const xmlChar * prefix,
2273 const xmlChar * name,
2274 const xmlChar * namespaceURI,
2275 const char *format, ...)
2276{
2277 int rc;
2278 va_list ap;
2279
2280 va_start(ap, format);
2281
2282 rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2283 namespaceURI, format, ap);
2284
2285 va_end(ap);
2286 return rc;
2287}
2288
2289/**
2290 * xmlTextWriterWriteVFormatElementNS:
2291 * @writer: the xmlTextWriterPtr
2292 * @prefix: namespace prefix
2293 * @name: element local name
2294 * @namespaceURI: namespace URI
2295 * @format: format string (see printf)
2296 * @argptr: pointer to the first member of the variable argument list.
2297 *
2298 * Write a formatted xml element with namespace support.
2299 *
2300 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2301 */
2302int
2303xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2304 const xmlChar * prefix,
2305 const xmlChar * name,
2306 const xmlChar * namespaceURI,
2307 const char *format, va_list argptr)
2308{
2309 int rc;
2310 xmlChar *buf;
2311
2312 if (writer == NULL)
2313 return -1;
2314
2315 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002316 if (buf == NULL)
2317 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002318
2319 rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2320 buf);
2321
2322 xmlFree(buf);
2323 return rc;
2324}
2325
2326/**
2327 * xmlTextWriterWriteElementNS:
2328 * @writer: the xmlTextWriterPtr
2329 * @prefix: namespace prefix
2330 * @name: element local name
2331 * @namespaceURI: namespace URI
2332 * @content: element content
2333 *
2334 * Write an xml element with namespace support.
2335 *
2336 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2337 */
2338int
2339xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2340 const xmlChar * prefix, const xmlChar * name,
2341 const xmlChar * namespaceURI,
2342 const xmlChar * content)
2343{
2344 int count;
2345 int sum;
2346
2347 if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2348 return -1;
2349
2350 sum = 0;
2351 count =
2352 xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2353 if (count < 0)
2354 return -1;
2355 sum += count;
2356 count = xmlTextWriterWriteString(writer, content);
2357 if (count == -1)
2358 return -1;
2359 sum += count;
2360 count = xmlTextWriterEndElement(writer);
2361 if (count == -1)
2362 return -1;
2363 sum += count;
2364
2365 return sum;
2366}
2367
2368/**
2369 * xmlTextWriterStartPI:
2370 * @writer: the xmlTextWriterPtr
2371 * @target: PI target
2372 *
2373 * Start an xml PI.
2374 *
2375 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2376 */
2377int
2378xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2379{
2380 int count;
2381 int sum;
2382 xmlLinkPtr lk;
2383 xmlTextWriterStackEntry *p;
2384
2385 if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2386 return -1;
2387
2388 if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002389 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002390 "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2391 return -1;
2392 }
2393
2394 sum = 0;
2395 lk = xmlListFront(writer->nodes);
2396 if (lk != 0) {
2397 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2398 if (p != 0) {
2399 switch (p->state) {
2400 case XML_TEXTWRITER_ATTRIBUTE:
2401 count = xmlTextWriterEndAttribute(writer);
2402 if (count < 0)
2403 return -1;
2404 sum += count;
2405 /* fallthrough */
2406 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002407 /* Output namespace declarations */
2408 count = xmlTextWriterOutputNSDecl(writer);
2409 if (count < 0)
2410 return -1;
2411 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002412 count = xmlOutputBufferWriteString(writer->out, ">");
2413 if (count < 0)
2414 return -1;
2415 sum += count;
2416 p->state = XML_TEXTWRITER_TEXT;
2417 break;
Daniel Veillardab69f362004-02-17 11:40:32 +00002418 case XML_TEXTWRITER_NONE:
2419 case XML_TEXTWRITER_TEXT:
2420 case XML_TEXTWRITER_DTD:
2421 break;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002422 case XML_TEXTWRITER_PI:
2423 case XML_TEXTWRITER_PI_TEXT:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002424 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002425 "xmlTextWriterStartPI : nested PI!\n");
2426 return -1;
2427 default:
2428 return -1;
2429 }
2430 }
2431 }
2432
2433 p = (xmlTextWriterStackEntry *)
2434 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2435 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002436 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002437 "xmlTextWriterStartPI : out of memory!\n");
2438 return -1;
2439 }
2440
2441 p->name = xmlStrdup(target);
2442 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002443 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002444 "xmlTextWriterStartPI : out of memory!\n");
2445 xmlFree(p);
2446 return -1;
2447 }
2448 p->state = XML_TEXTWRITER_PI;
2449
2450 xmlListPushFront(writer->nodes, p);
2451
2452 count = xmlOutputBufferWriteString(writer->out, "<?");
2453 if (count < 0)
2454 return -1;
2455 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002456 count =
2457 xmlOutputBufferWriteString(writer->out, (const char *) p->name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002458 if (count < 0)
2459 return -1;
2460 sum += count;
2461
2462 return sum;
2463}
2464
2465/**
2466 * xmlTextWriterEndPI:
2467 * @writer: the xmlTextWriterPtr
2468 *
2469 * End the current xml PI.
2470 *
2471 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2472 */
2473int
2474xmlTextWriterEndPI(xmlTextWriterPtr writer)
2475{
2476 int count;
2477 int sum;
2478 xmlLinkPtr lk;
2479 xmlTextWriterStackEntry *p;
2480
2481 if (writer == NULL)
2482 return -1;
2483
2484 lk = xmlListFront(writer->nodes);
2485 if (lk == 0)
2486 return 0;
2487
2488 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2489 if (p == 0)
2490 return 0;
2491
2492 sum = 0;
2493 switch (p->state) {
2494 case XML_TEXTWRITER_PI:
2495 case XML_TEXTWRITER_PI_TEXT:
2496 count = xmlOutputBufferWriteString(writer->out, "?>");
2497 if (count < 0)
2498 return -1;
2499 sum += count;
2500 break;
2501 default:
2502 return -1;
2503 }
2504
Daniel Veillard02c1f232006-04-27 08:10:25 +00002505 if (writer->indent) {
2506 count = xmlOutputBufferWriteString(writer->out, "\n");
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002507 if (count < 0)
2508 return -1;
Daniel Veillard02c1f232006-04-27 08:10:25 +00002509 sum += count;
2510 }
2511
Daniel Veillard1d211e22003-10-20 22:32:39 +00002512 xmlListPopFront(writer->nodes);
2513 return sum;
2514}
2515
2516/**
2517 * xmlTextWriterWriteFormatPI:
2518 * @writer: the xmlTextWriterPtr
2519 * @target: PI target
2520 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002521 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002522 *
2523 * Write a formatted PI.
2524 *
2525 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2526 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002527int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002528xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2529 const char *format, ...)
2530{
2531 int rc;
2532 va_list ap;
2533
2534 va_start(ap, format);
2535
2536 rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2537
2538 va_end(ap);
2539 return rc;
2540}
2541
2542/**
2543 * xmlTextWriterWriteVFormatPI:
2544 * @writer: the xmlTextWriterPtr
2545 * @target: PI target
2546 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002547 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002548 *
2549 * Write a formatted xml PI.
2550 *
2551 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2552 */
2553int
2554xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2555 const xmlChar * target, const char *format,
2556 va_list argptr)
2557{
2558 int rc;
2559 xmlChar *buf;
2560
2561 if (writer == NULL)
2562 return -1;
2563
2564 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002565 if (buf == NULL)
2566 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002567
2568 rc = xmlTextWriterWritePI(writer, target, buf);
2569
2570 xmlFree(buf);
2571 return rc;
2572}
2573
2574/**
2575 * xmlTextWriterWritePI:
2576 * @writer: the xmlTextWriterPtr
2577 * @target: PI target
2578 * @content: PI content
2579 *
2580 * Write an xml PI.
2581 *
2582 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2583 */
2584int
2585xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2586 const xmlChar * content)
2587{
2588 int count;
2589 int sum;
2590
2591 sum = 0;
2592 count = xmlTextWriterStartPI(writer, target);
2593 if (count == -1)
2594 return -1;
2595 sum += count;
2596 if (content != 0) {
2597 count = xmlTextWriterWriteString(writer, content);
2598 if (count == -1)
2599 return -1;
2600 sum += count;
2601 }
2602 count = xmlTextWriterEndPI(writer);
2603 if (count == -1)
2604 return -1;
2605 sum += count;
2606
2607 return sum;
2608}
2609
2610/**
2611 * xmlTextWriterStartCDATA:
2612 * @writer: the xmlTextWriterPtr
2613 *
2614 * Start an xml CDATA section.
2615 *
2616 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2617 */
2618int
2619xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2620{
2621 int count;
2622 int sum;
2623 xmlLinkPtr lk;
2624 xmlTextWriterStackEntry *p;
2625
2626 if (writer == NULL)
2627 return -1;
2628
2629 sum = 0;
2630 lk = xmlListFront(writer->nodes);
2631 if (lk != 0) {
2632 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2633 if (p != 0) {
2634 switch (p->state) {
2635 case XML_TEXTWRITER_NONE:
Daniel Veillardccc476f2008-03-04 13:19:49 +00002636 case XML_TEXTWRITER_TEXT:
Daniel Veillard1d211e22003-10-20 22:32:39 +00002637 case XML_TEXTWRITER_PI:
2638 case XML_TEXTWRITER_PI_TEXT:
2639 break;
2640 case XML_TEXTWRITER_ATTRIBUTE:
2641 count = xmlTextWriterEndAttribute(writer);
2642 if (count < 0)
2643 return -1;
2644 sum += count;
2645 /* fallthrough */
2646 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00002647 /* Output namespace declarations */
2648 count = xmlTextWriterOutputNSDecl(writer);
2649 if (count < 0)
2650 return -1;
2651 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002652 count = xmlOutputBufferWriteString(writer->out, ">");
2653 if (count < 0)
2654 return -1;
2655 sum += count;
2656 p->state = XML_TEXTWRITER_TEXT;
2657 break;
2658 case XML_TEXTWRITER_CDATA:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002659 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002660 "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2661 return -1;
2662 default:
2663 return -1;
2664 }
2665 }
2666 }
2667
2668 p = (xmlTextWriterStackEntry *)
2669 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2670 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002671 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002672 "xmlTextWriterStartCDATA : out of memory!\n");
2673 return -1;
2674 }
2675
Daniel Veillard75e389d2005-07-29 22:02:24 +00002676 p->name = NULL;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002677 p->state = XML_TEXTWRITER_CDATA;
2678
2679 xmlListPushFront(writer->nodes, p);
2680
2681 count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2682 if (count < 0)
2683 return -1;
2684 sum += count;
2685
2686 return sum;
2687}
2688
2689/**
2690 * xmlTextWriterEndCDATA:
2691 * @writer: the xmlTextWriterPtr
2692 *
2693 * End an xml CDATA section.
2694 *
2695 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2696 */
2697int
2698xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2699{
2700 int count;
2701 int sum;
2702 xmlLinkPtr lk;
2703 xmlTextWriterStackEntry *p;
2704
2705 if (writer == NULL)
2706 return -1;
2707
2708 lk = xmlListFront(writer->nodes);
2709 if (lk == 0)
2710 return -1;
2711
2712 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2713 if (p == 0)
2714 return -1;
2715
2716 sum = 0;
2717 switch (p->state) {
2718 case XML_TEXTWRITER_CDATA:
2719 count = xmlOutputBufferWriteString(writer->out, "]]>");
2720 if (count < 0)
2721 return -1;
2722 sum += count;
2723 break;
2724 default:
2725 return -1;
2726 }
2727
2728 xmlListPopFront(writer->nodes);
2729 return sum;
2730}
2731
2732/**
2733 * xmlTextWriterWriteFormatCDATA:
2734 * @writer: the xmlTextWriterPtr
2735 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00002736 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00002737 *
2738 * Write a formatted xml CDATA.
2739 *
2740 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2741 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00002742int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00002743xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2744 ...)
2745{
2746 int rc;
2747 va_list ap;
2748
2749 va_start(ap, format);
2750
2751 rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2752
2753 va_end(ap);
2754 return rc;
2755}
2756
2757/**
2758 * xmlTextWriterWriteVFormatCDATA:
2759 * @writer: the xmlTextWriterPtr
2760 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002761 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00002762 *
2763 * Write a formatted xml CDATA.
2764 *
2765 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2766 */
2767int
2768xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2769 va_list argptr)
2770{
2771 int rc;
2772 xmlChar *buf;
2773
2774 if (writer == NULL)
2775 return -1;
2776
2777 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00002778 if (buf == NULL)
2779 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002780
2781 rc = xmlTextWriterWriteCDATA(writer, buf);
2782
2783 xmlFree(buf);
2784 return rc;
2785}
2786
2787/**
2788 * xmlTextWriterWriteCDATA:
2789 * @writer: the xmlTextWriterPtr
2790 * @content: CDATA content
2791 *
2792 * Write an xml CDATA.
2793 *
2794 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2795 */
2796int
2797xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2798{
2799 int count;
2800 int sum;
2801
2802 sum = 0;
2803 count = xmlTextWriterStartCDATA(writer);
2804 if (count == -1)
2805 return -1;
2806 sum += count;
2807 if (content != 0) {
2808 count = xmlTextWriterWriteString(writer, content);
2809 if (count == -1)
2810 return -1;
2811 sum += count;
2812 }
2813 count = xmlTextWriterEndCDATA(writer);
2814 if (count == -1)
2815 return -1;
2816 sum += count;
2817
2818 return sum;
2819}
2820
2821/**
2822 * xmlTextWriterStartDTD:
2823 * @writer: the xmlTextWriterPtr
2824 * @name: the name of the DTD
2825 * @pubid: the public identifier, which is an alternative to the system identifier
2826 * @sysid: the system identifier, which is the URI of the DTD
2827 *
2828 * Start an xml DTD.
2829 *
2830 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2831 */
2832int
2833xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2834 const xmlChar * name,
2835 const xmlChar * pubid, const xmlChar * sysid)
2836{
2837 int count;
2838 int sum;
2839 xmlLinkPtr lk;
2840 xmlTextWriterStackEntry *p;
2841
2842 if (writer == NULL || name == NULL || *name == '\0')
2843 return -1;
2844
2845 sum = 0;
2846 lk = xmlListFront(writer->nodes);
Daniel Veillardab69f362004-02-17 11:40:32 +00002847 if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002848 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002849 "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2850 return -1;
2851 }
2852
2853 p = (xmlTextWriterStackEntry *)
2854 xmlMalloc(sizeof(xmlTextWriterStackEntry));
2855 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002856 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002857 "xmlTextWriterStartDTD : out of memory!\n");
2858 return -1;
2859 }
2860
2861 p->name = xmlStrdup(name);
2862 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002863 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002864 "xmlTextWriterStartDTD : out of memory!\n");
2865 xmlFree(p);
2866 return -1;
2867 }
2868 p->state = XML_TEXTWRITER_DTD;
2869
2870 xmlListPushFront(writer->nodes, p);
2871
2872 count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2873 if (count < 0)
2874 return -1;
2875 sum += count;
2876 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2877 if (count < 0)
2878 return -1;
2879 sum += count;
2880
2881 if (pubid != 0) {
2882 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002883 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard1d211e22003-10-20 22:32:39 +00002884 "xmlTextWriterStartDTD : system identifier needed!\n");
2885 return -1;
2886 }
2887
Daniel Veillard500a1de2004-03-22 15:22:58 +00002888 if (writer->indent)
2889 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2890 else
2891 count = xmlOutputBufferWrite(writer->out, 1, " ");
2892 if (count < 0)
2893 return -1;
2894 sum += count;
2895
2896 count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2897 if (count < 0)
2898 return -1;
2899 sum += count;
2900
2901 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002902 if (count < 0)
2903 return -1;
2904 sum += count;
2905
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002906 count =
2907 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002908 if (count < 0)
2909 return -1;
2910 sum += count;
2911
Daniel Veillard500a1de2004-03-22 15:22:58 +00002912 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002913 if (count < 0)
2914 return -1;
2915 sum += count;
2916 }
2917
2918 if (sysid != 0) {
2919 if (pubid == 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00002920 if (writer->indent)
2921 count = xmlOutputBufferWrite(writer->out, 1, "\n");
2922 else
2923 count = xmlOutputBufferWrite(writer->out, 1, " ");
2924 if (count < 0)
2925 return -1;
2926 sum += count;
2927 count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2928 if (count < 0)
2929 return -1;
2930 sum += count;
Rob Richardsffe47fe2005-12-09 17:52:21 +00002931 } else {
2932 if (writer->indent)
Daniel Veillard500a1de2004-03-22 15:22:58 +00002933 count = xmlOutputBufferWriteString(writer->out, "\n ");
Rob Richardsffe47fe2005-12-09 17:52:21 +00002934 else
2935 count = xmlOutputBufferWrite(writer->out, 1, " ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00002936 if (count < 0)
2937 return -1;
2938 sum += count;
2939 }
2940
Daniel Veillard500a1de2004-03-22 15:22:58 +00002941 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002942 if (count < 0)
2943 return -1;
2944 sum += count;
2945
Daniel Veillard5841f0e2003-11-20 11:59:09 +00002946 count =
2947 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002948 if (count < 0)
2949 return -1;
2950 sum += count;
2951
Daniel Veillard500a1de2004-03-22 15:22:58 +00002952 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
Daniel Veillard1d211e22003-10-20 22:32:39 +00002953 if (count < 0)
2954 return -1;
2955 sum += count;
2956 }
2957
2958 return sum;
2959}
2960
2961/**
2962 * xmlTextWriterEndDTD:
2963 * @writer: the xmlTextWriterPtr
2964 *
2965 * End an xml DTD.
2966 *
2967 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2968 */
2969int
2970xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2971{
Daniel Veillard500a1de2004-03-22 15:22:58 +00002972 int loop;
Daniel Veillard1d211e22003-10-20 22:32:39 +00002973 int count;
2974 int sum;
2975 xmlLinkPtr lk;
2976 xmlTextWriterStackEntry *p;
2977
2978 if (writer == NULL)
2979 return -1;
2980
2981 sum = 0;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002982 loop = 1;
2983 while (loop) {
2984 lk = xmlListFront(writer->nodes);
2985 if (lk == NULL)
Daniel Veillard1d211e22003-10-20 22:32:39 +00002986 break;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002987 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2988 if (p == 0)
2989 break;
2990 switch (p->state) {
2991 case XML_TEXTWRITER_DTD_TEXT:
2992 count = xmlOutputBufferWriteString(writer->out, "]");
2993 if (count < 0)
2994 return -1;
2995 sum += count;
2996 /* fallthrough */
2997 case XML_TEXTWRITER_DTD:
2998 count = xmlOutputBufferWriteString(writer->out, ">");
2999
3000 if (writer->indent) {
3001 if (count < 0)
3002 return -1;
3003 sum += count;
3004 count = xmlOutputBufferWriteString(writer->out, "\n");
3005 }
3006
3007 xmlListPopFront(writer->nodes);
3008 break;
3009 case XML_TEXTWRITER_DTD_ELEM:
3010 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3011 count = xmlTextWriterEndDTDElement(writer);
3012 break;
3013 case XML_TEXTWRITER_DTD_ATTL:
3014 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3015 count = xmlTextWriterEndDTDAttlist(writer);
3016 break;
3017 case XML_TEXTWRITER_DTD_ENTY:
3018 case XML_TEXTWRITER_DTD_PENT:
3019 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3020 count = xmlTextWriterEndDTDEntity(writer);
3021 break;
3022 case XML_TEXTWRITER_COMMENT:
3023 count = xmlTextWriterEndComment(writer);
3024 break;
3025 default:
3026 loop = 0;
3027 continue;
3028 }
3029
3030 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00003031 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003032 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003033 }
3034
Daniel Veillard1d211e22003-10-20 22:32:39 +00003035 return sum;
3036}
3037
3038/**
3039 * xmlTextWriterWriteFormatDTD:
3040 * @writer: the xmlTextWriterPtr
3041 * @name: the name of the DTD
3042 * @pubid: the public identifier, which is an alternative to the system identifier
3043 * @sysid: the system identifier, which is the URI of the DTD
3044 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003045 * @...: extra parameters for the format
Daniel Veillard1d211e22003-10-20 22:32:39 +00003046 *
3047 * Write a DTD with a formatted markup declarations part.
3048 *
3049 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3050 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003051int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003052xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3053 const xmlChar * name,
3054 const xmlChar * pubid,
3055 const xmlChar * sysid, const char *format, ...)
3056{
3057 int rc;
3058 va_list ap;
3059
3060 va_start(ap, format);
3061
3062 rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3063 ap);
3064
3065 va_end(ap);
3066 return rc;
3067}
3068
3069/**
3070 * xmlTextWriterWriteVFormatDTD:
3071 * @writer: the xmlTextWriterPtr
3072 * @name: the name of the DTD
3073 * @pubid: the public identifier, which is an alternative to the system identifier
3074 * @sysid: the system identifier, which is the URI of the DTD
3075 * @format: format string (see printf)
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003076 * @argptr: pointer to the first member of the variable argument list.
Daniel Veillard1d211e22003-10-20 22:32:39 +00003077 *
3078 * Write a DTD with a formatted markup declarations part.
3079 *
3080 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3081 */
3082int
3083xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3084 const xmlChar * name,
3085 const xmlChar * pubid,
3086 const xmlChar * sysid,
3087 const char *format, va_list argptr)
3088{
3089 int rc;
3090 xmlChar *buf;
3091
3092 if (writer == NULL)
3093 return -1;
3094
3095 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003096 if (buf == NULL)
3097 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003098
3099 rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3100
3101 xmlFree(buf);
3102 return rc;
3103}
3104
3105/**
3106 * xmlTextWriterWriteDTD:
3107 * @writer: the xmlTextWriterPtr
3108 * @name: the name of the DTD
3109 * @pubid: the public identifier, which is an alternative to the system identifier
3110 * @sysid: the system identifier, which is the URI of the DTD
William M. Brackb1d53162003-11-18 06:54:40 +00003111 * @subset: string content of the DTD
Daniel Veillard1d211e22003-10-20 22:32:39 +00003112 *
3113 * Write a DTD.
3114 *
3115 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3116 */
3117int
3118xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3119 const xmlChar * name,
3120 const xmlChar * pubid,
3121 const xmlChar * sysid, const xmlChar * subset)
3122{
3123 int count;
3124 int sum;
3125
3126 sum = 0;
3127 count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3128 if (count == -1)
3129 return -1;
3130 sum += count;
3131 if (subset != 0) {
3132 count = xmlTextWriterWriteString(writer, subset);
3133 if (count == -1)
3134 return -1;
3135 sum += count;
3136 }
3137 count = xmlTextWriterEndDTD(writer);
3138 if (count == -1)
3139 return -1;
3140 sum += count;
3141
3142 return sum;
3143}
3144
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003145/**
3146 * xmlTextWriterStartDTDElement:
3147 * @writer: the xmlTextWriterPtr
3148 * @name: the name of the DTD element
3149 *
3150 * Start an xml DTD element.
3151 *
3152 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3153 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003154int
3155xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3156{
3157 int count;
3158 int sum;
3159 xmlLinkPtr lk;
3160 xmlTextWriterStackEntry *p;
3161
3162 if (writer == NULL || name == NULL || *name == '\0')
3163 return -1;
3164
3165 sum = 0;
3166 lk = xmlListFront(writer->nodes);
3167 if (lk == 0) {
3168 return -1;
3169 }
3170
3171 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003172 if (p != 0) {
3173 switch (p->state) {
3174 case XML_TEXTWRITER_DTD:
3175 count = xmlOutputBufferWriteString(writer->out, " [");
3176 if (count < 0)
3177 return -1;
3178 sum += count;
3179 if (writer->indent) {
3180 count = xmlOutputBufferWriteString(writer->out, "\n");
3181 if (count < 0)
3182 return -1;
3183 sum += count;
3184 }
3185 p->state = XML_TEXTWRITER_DTD_TEXT;
3186 /* fallthrough */
3187 case XML_TEXTWRITER_DTD_TEXT:
3188 case XML_TEXTWRITER_NONE:
3189 break;
3190 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003191 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003192 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003193 }
3194
3195 p = (xmlTextWriterStackEntry *)
3196 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3197 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003198 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003199 "xmlTextWriterStartDTDElement : out of memory!\n");
3200 return -1;
3201 }
3202
3203 p->name = xmlStrdup(name);
3204 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003205 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003206 "xmlTextWriterStartDTDElement : out of memory!\n");
3207 xmlFree(p);
3208 return -1;
3209 }
3210 p->state = XML_TEXTWRITER_DTD_ELEM;
3211
3212 xmlListPushFront(writer->nodes, p);
3213
Daniel Veillard500a1de2004-03-22 15:22:58 +00003214 if (writer->indent) {
3215 count = xmlTextWriterWriteIndent(writer);
3216 if (count < 0)
3217 return -1;
3218 sum += count;
3219 }
3220
Daniel Veillard1d211e22003-10-20 22:32:39 +00003221 count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3222 if (count < 0)
3223 return -1;
3224 sum += count;
3225 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3226 if (count < 0)
3227 return -1;
3228 sum += count;
3229
3230 return sum;
3231}
3232
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003233/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003234 * xmlTextWriterEndDTDElement:
3235 * @writer: the xmlTextWriterPtr
3236 *
3237 * End an xml DTD element.
3238 *
3239 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3240 */
3241int
3242xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3243{
3244 int count;
3245 int sum;
3246 xmlLinkPtr lk;
3247 xmlTextWriterStackEntry *p;
3248
3249 if (writer == NULL)
3250 return -1;
3251
3252 sum = 0;
3253 lk = xmlListFront(writer->nodes);
3254 if (lk == 0)
3255 return -1;
3256
3257 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3258 if (p == 0)
3259 return -1;
3260
3261 switch (p->state) {
3262 case XML_TEXTWRITER_DTD_ELEM:
3263 case XML_TEXTWRITER_DTD_ELEM_TEXT:
3264 count = xmlOutputBufferWriteString(writer->out, ">");
3265 if (count < 0)
3266 return -1;
3267 sum += count;
3268 break;
3269 default:
3270 return -1;
3271 }
3272
3273 if (writer->indent) {
3274 count = xmlOutputBufferWriteString(writer->out, "\n");
3275 if (count < 0)
3276 return -1;
3277 sum += count;
3278 }
3279
3280 xmlListPopFront(writer->nodes);
3281 return sum;
3282}
3283
3284/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003285 * xmlTextWriterWriteFormatDTDElement:
3286 * @writer: the xmlTextWriterPtr
3287 * @name: the name of the DTD element
3288 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003289 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003290 *
3291 * Write a formatted DTD element.
3292 *
3293 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3294 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003295int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003296xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3297 const xmlChar * name,
3298 const char *format, ...)
3299{
3300 int rc;
3301 va_list ap;
3302
3303 va_start(ap, format);
3304
3305 rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3306
3307 va_end(ap);
3308 return rc;
3309}
3310
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003311/**
3312 * xmlTextWriterWriteVFormatDTDElement:
3313 * @writer: the xmlTextWriterPtr
3314 * @name: the name of the DTD element
3315 * @format: format string (see printf)
3316 * @argptr: pointer to the first member of the variable argument list.
3317 *
3318 * Write a formatted DTD element.
3319 *
3320 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3321 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003322int
3323xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3324 const xmlChar * name,
3325 const char *format, va_list argptr)
3326{
3327 int rc;
3328 xmlChar *buf;
3329
3330 if (writer == NULL)
3331 return -1;
3332
3333 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003334 if (buf == NULL)
3335 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003336
3337 rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3338
3339 xmlFree(buf);
3340 return rc;
3341}
3342
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003343/**
3344 * xmlTextWriterWriteDTDElement:
3345 * @writer: the xmlTextWriterPtr
3346 * @name: the name of the DTD element
3347 * @content: content of the element
3348 *
3349 * Write a DTD element.
3350 *
3351 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3352 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003353int
3354xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3355 const xmlChar * name, const xmlChar * content)
3356{
3357 int count;
3358 int sum;
3359
3360 if (content == NULL)
3361 return -1;
3362
3363 sum = 0;
3364 count = xmlTextWriterStartDTDElement(writer, name);
3365 if (count == -1)
3366 return -1;
3367 sum += count;
3368
Daniel Veillard1d211e22003-10-20 22:32:39 +00003369 count = xmlTextWriterWriteString(writer, content);
3370 if (count == -1)
3371 return -1;
3372 sum += count;
3373
3374 count = xmlTextWriterEndDTDElement(writer);
3375 if (count == -1)
3376 return -1;
3377 sum += count;
3378
3379 return sum;
3380}
3381
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003382/**
3383 * xmlTextWriterStartDTDAttlist:
3384 * @writer: the xmlTextWriterPtr
3385 * @name: the name of the DTD ATTLIST
3386 *
3387 * Start an xml DTD ATTLIST.
3388 *
3389 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3390 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003391int
3392xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3393{
3394 int count;
3395 int sum;
3396 xmlLinkPtr lk;
3397 xmlTextWriterStackEntry *p;
3398
3399 if (writer == NULL || name == NULL || *name == '\0')
3400 return -1;
3401
3402 sum = 0;
3403 lk = xmlListFront(writer->nodes);
3404 if (lk == 0) {
3405 return -1;
3406 }
3407
3408 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003409 if (p != 0) {
3410 switch (p->state) {
3411 case XML_TEXTWRITER_DTD:
3412 count = xmlOutputBufferWriteString(writer->out, " [");
3413 if (count < 0)
3414 return -1;
3415 sum += count;
3416 if (writer->indent) {
3417 count = xmlOutputBufferWriteString(writer->out, "\n");
3418 if (count < 0)
3419 return -1;
3420 sum += count;
3421 }
3422 p->state = XML_TEXTWRITER_DTD_TEXT;
3423 /* fallthrough */
3424 case XML_TEXTWRITER_DTD_TEXT:
3425 case XML_TEXTWRITER_NONE:
3426 break;
3427 default:
Daniel Veillard1d211e22003-10-20 22:32:39 +00003428 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003429 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003430 }
3431
3432 p = (xmlTextWriterStackEntry *)
3433 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3434 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003435 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003436 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3437 return -1;
3438 }
3439
3440 p->name = xmlStrdup(name);
3441 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003442 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003443 "xmlTextWriterStartDTDAttlist : out of memory!\n");
3444 xmlFree(p);
3445 return -1;
3446 }
3447 p->state = XML_TEXTWRITER_DTD_ATTL;
3448
3449 xmlListPushFront(writer->nodes, p);
3450
Daniel Veillard500a1de2004-03-22 15:22:58 +00003451 if (writer->indent) {
3452 count = xmlTextWriterWriteIndent(writer);
3453 if (count < 0)
3454 return -1;
3455 sum += count;
3456 }
3457
Daniel Veillard1d211e22003-10-20 22:32:39 +00003458 count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3459 if (count < 0)
3460 return -1;
3461 sum += count;
Daniel Veillardab69f362004-02-17 11:40:32 +00003462 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003463 if (count < 0)
3464 return -1;
3465 sum += count;
3466
3467 return sum;
3468}
3469
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003470/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003471 * xmlTextWriterEndDTDAttlist:
3472 * @writer: the xmlTextWriterPtr
3473 *
3474 * End an xml DTD attribute list.
3475 *
3476 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3477 */
3478int
3479xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3480{
3481 int count;
3482 int sum;
3483 xmlLinkPtr lk;
3484 xmlTextWriterStackEntry *p;
3485
3486 if (writer == NULL)
3487 return -1;
3488
3489 sum = 0;
3490 lk = xmlListFront(writer->nodes);
3491 if (lk == 0)
3492 return -1;
3493
3494 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3495 if (p == 0)
3496 return -1;
3497
3498 switch (p->state) {
3499 case XML_TEXTWRITER_DTD_ATTL:
3500 case XML_TEXTWRITER_DTD_ATTL_TEXT:
3501 count = xmlOutputBufferWriteString(writer->out, ">");
3502 if (count < 0)
3503 return -1;
3504 sum += count;
3505 break;
3506 default:
3507 return -1;
3508 }
3509
3510 if (writer->indent) {
3511 count = xmlOutputBufferWriteString(writer->out, "\n");
3512 if (count < 0)
3513 return -1;
3514 sum += count;
3515 }
3516
3517 xmlListPopFront(writer->nodes);
3518 return sum;
3519}
3520
3521/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003522 * xmlTextWriterWriteFormatDTDAttlist:
3523 * @writer: the xmlTextWriterPtr
3524 * @name: the name of the DTD ATTLIST
3525 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003526 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003527 *
3528 * Write a formatted DTD ATTLIST.
3529 *
3530 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3531 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003532int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003533xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3534 const xmlChar * name,
3535 const char *format, ...)
3536{
3537 int rc;
3538 va_list ap;
3539
3540 va_start(ap, format);
3541
3542 rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3543
3544 va_end(ap);
3545 return rc;
3546}
3547
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003548/**
3549 * xmlTextWriterWriteVFormatDTDAttlist:
3550 * @writer: the xmlTextWriterPtr
3551 * @name: the name of the DTD ATTLIST
3552 * @format: format string (see printf)
3553 * @argptr: pointer to the first member of the variable argument list.
3554 *
3555 * Write a formatted DTD ATTLIST.
3556 *
3557 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3558 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003559int
3560xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3561 const xmlChar * name,
3562 const char *format, va_list argptr)
3563{
3564 int rc;
3565 xmlChar *buf;
3566
3567 if (writer == NULL)
3568 return -1;
3569
3570 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003571 if (buf == NULL)
3572 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003573
3574 rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3575
3576 xmlFree(buf);
3577 return rc;
3578}
3579
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003580/**
3581 * xmlTextWriterWriteDTDAttlist:
3582 * @writer: the xmlTextWriterPtr
3583 * @name: the name of the DTD ATTLIST
3584 * @content: content of the ATTLIST
3585 *
3586 * Write a DTD ATTLIST.
3587 *
3588 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3589 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003590int
3591xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3592 const xmlChar * name, const xmlChar * content)
3593{
3594 int count;
3595 int sum;
3596
3597 if (content == NULL)
3598 return -1;
3599
3600 sum = 0;
3601 count = xmlTextWriterStartDTDAttlist(writer, name);
3602 if (count == -1)
3603 return -1;
3604 sum += count;
3605
Daniel Veillard1d211e22003-10-20 22:32:39 +00003606 count = xmlTextWriterWriteString(writer, content);
3607 if (count == -1)
3608 return -1;
3609 sum += count;
3610
3611 count = xmlTextWriterEndDTDAttlist(writer);
3612 if (count == -1)
3613 return -1;
3614 sum += count;
3615
3616 return sum;
3617}
3618
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003619/**
3620 * xmlTextWriterStartDTDEntity:
3621 * @writer: the xmlTextWriterPtr
3622 * @pe: TRUE if this is a parameter entity, FALSE if not
3623 * @name: the name of the DTD ATTLIST
3624 *
3625 * Start an xml DTD ATTLIST.
3626 *
3627 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3628 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003629int
3630xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3631 int pe, const xmlChar * name)
3632{
3633 int count;
3634 int sum;
3635 xmlLinkPtr lk;
3636 xmlTextWriterStackEntry *p;
3637
3638 if (writer == NULL || name == NULL || *name == '\0')
3639 return -1;
3640
3641 sum = 0;
3642 lk = xmlListFront(writer->nodes);
Daniel Veillard500a1de2004-03-22 15:22:58 +00003643 if (lk != 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00003644
Daniel Veillard500a1de2004-03-22 15:22:58 +00003645 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3646 if (p != 0) {
3647 switch (p->state) {
3648 case XML_TEXTWRITER_DTD:
3649 count = xmlOutputBufferWriteString(writer->out, " [");
3650 if (count < 0)
3651 return -1;
3652 sum += count;
3653 if (writer->indent) {
3654 count =
3655 xmlOutputBufferWriteString(writer->out, "\n");
3656 if (count < 0)
3657 return -1;
3658 sum += count;
3659 }
3660 p->state = XML_TEXTWRITER_DTD_TEXT;
3661 /* fallthrough */
3662 case XML_TEXTWRITER_DTD_TEXT:
3663 case XML_TEXTWRITER_NONE:
3664 break;
3665 default:
3666 return -1;
3667 }
3668 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00003669 }
3670
3671 p = (xmlTextWriterStackEntry *)
3672 xmlMalloc(sizeof(xmlTextWriterStackEntry));
3673 if (p == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003674 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003675 "xmlTextWriterStartDTDElement : out of memory!\n");
3676 return -1;
3677 }
3678
3679 p->name = xmlStrdup(name);
3680 if (p->name == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003681 xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00003682 "xmlTextWriterStartDTDElement : out of memory!\n");
3683 xmlFree(p);
3684 return -1;
3685 }
Daniel Veillard500a1de2004-03-22 15:22:58 +00003686
3687 if (pe != 0)
3688 p->state = XML_TEXTWRITER_DTD_PENT;
3689 else
3690 p->state = XML_TEXTWRITER_DTD_ENTY;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003691
3692 xmlListPushFront(writer->nodes, p);
3693
Daniel Veillard500a1de2004-03-22 15:22:58 +00003694 if (writer->indent) {
3695 count = xmlTextWriterWriteIndent(writer);
3696 if (count < 0)
3697 return -1;
3698 sum += count;
3699 }
3700
Daniel Veillard1d211e22003-10-20 22:32:39 +00003701 count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3702 if (count < 0)
3703 return -1;
3704 sum += count;
3705
3706 if (pe != 0) {
Daniel Veillard500a1de2004-03-22 15:22:58 +00003707 count = xmlOutputBufferWriteString(writer->out, "% ");
Daniel Veillard1d211e22003-10-20 22:32:39 +00003708 if (count < 0)
3709 return -1;
3710 sum += count;
3711 }
3712
Daniel Veillardab69f362004-02-17 11:40:32 +00003713 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
Daniel Veillard1d211e22003-10-20 22:32:39 +00003714 if (count < 0)
3715 return -1;
3716 sum += count;
3717
3718 return sum;
3719}
3720
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003721/**
Daniel Veillard500a1de2004-03-22 15:22:58 +00003722 * xmlTextWriterEndDTDEntity:
3723 * @writer: the xmlTextWriterPtr
3724 *
3725 * End an xml DTD entity.
3726 *
3727 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3728 */
3729int
3730xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3731{
3732 int count;
3733 int sum;
3734 xmlLinkPtr lk;
3735 xmlTextWriterStackEntry *p;
3736
3737 if (writer == NULL)
3738 return -1;
3739
3740 sum = 0;
3741 lk = xmlListFront(writer->nodes);
3742 if (lk == 0)
3743 return -1;
3744
3745 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3746 if (p == 0)
3747 return -1;
3748
3749 switch (p->state) {
3750 case XML_TEXTWRITER_DTD_ENTY_TEXT:
3751 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3752 if (count < 0)
3753 return -1;
3754 sum += count;
3755 case XML_TEXTWRITER_DTD_ENTY:
3756 case XML_TEXTWRITER_DTD_PENT:
Daniel Veillard500a1de2004-03-22 15:22:58 +00003757 count = xmlOutputBufferWriteString(writer->out, ">");
3758 if (count < 0)
3759 return -1;
3760 sum += count;
3761 break;
3762 default:
3763 return -1;
3764 }
3765
3766 if (writer->indent) {
3767 count = xmlOutputBufferWriteString(writer->out, "\n");
3768 if (count < 0)
3769 return -1;
3770 sum += count;
3771 }
3772
3773 xmlListPopFront(writer->nodes);
3774 return sum;
3775}
3776
3777/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003778 * xmlTextWriterWriteFormatDTDInternalEntity:
3779 * @writer: the xmlTextWriterPtr
3780 * @pe: TRUE if this is a parameter entity, FALSE if not
3781 * @name: the name of the DTD entity
3782 * @format: format string (see printf)
Daniel Veillard1d913862003-11-21 00:28:39 +00003783 * @...: extra parameters for the format
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003784 *
3785 * Write a formatted DTD internal entity.
3786 *
3787 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3788 */
Daniel Veillardffa3c742005-07-21 13:24:09 +00003789int XMLCDECL
Daniel Veillard1d211e22003-10-20 22:32:39 +00003790xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3791 int pe,
3792 const xmlChar * name,
3793 const char *format, ...)
3794{
3795 int rc;
3796 va_list ap;
3797
3798 va_start(ap, format);
3799
3800 rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3801 format, ap);
3802
3803 va_end(ap);
3804 return rc;
3805}
3806
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003807/**
3808 * xmlTextWriterWriteVFormatDTDInternalEntity:
3809 * @writer: the xmlTextWriterPtr
3810 * @pe: TRUE if this is a parameter entity, FALSE if not
3811 * @name: the name of the DTD entity
3812 * @format: format string (see printf)
3813 * @argptr: pointer to the first member of the variable argument list.
3814 *
3815 * Write a formatted DTD internal entity.
3816 *
3817 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3818 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003819int
3820xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3821 int pe,
3822 const xmlChar * name,
3823 const char *format,
3824 va_list argptr)
3825{
3826 int rc;
3827 xmlChar *buf;
3828
3829 if (writer == NULL)
3830 return -1;
3831
3832 buf = xmlTextWriterVSprintf(format, argptr);
Daniel Veillardcb0ae192009-02-20 08:40:55 +00003833 if (buf == NULL)
3834 return -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003835
3836 rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3837
3838 xmlFree(buf);
3839 return rc;
3840}
3841
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003842/**
3843 * xmlTextWriterWriteDTDEntity:
3844 * @writer: the xmlTextWriterPtr
3845 * @pe: TRUE if this is a parameter entity, FALSE if not
3846 * @name: the name of the DTD entity
3847 * @pubid: the public identifier, which is an alternative to the system identifier
3848 * @sysid: the system identifier, which is the URI of the DTD
3849 * @ndataid: the xml notation name.
3850 * @content: content of the entity
3851 *
3852 * Write a DTD entity.
3853 *
3854 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3855 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003856int
3857xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3858 int pe,
3859 const xmlChar * name,
3860 const xmlChar * pubid,
3861 const xmlChar * sysid,
3862 const xmlChar * ndataid,
3863 const xmlChar * content)
3864{
Daniel Veillard500a1de2004-03-22 15:22:58 +00003865 if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003866 return -1;
3867 if ((pe != 0) && (ndataid != NULL))
3868 return -1;
3869
Daniel Veillard500a1de2004-03-22 15:22:58 +00003870 if ((pubid == NULL) && (sysid == NULL))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003871 return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3872 content);
3873
3874 return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3875 sysid, ndataid);
3876}
3877
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003878/**
3879 * xmlTextWriterWriteDTDInternalEntity:
3880 * @writer: the xmlTextWriterPtr
3881 * @pe: TRUE if this is a parameter entity, FALSE if not
3882 * @name: the name of the DTD entity
3883 * @content: content of the entity
3884 *
3885 * Write a DTD internal entity.
3886 *
3887 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3888 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003889int
3890xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3891 int pe,
3892 const xmlChar * name,
3893 const xmlChar * content)
3894{
3895 int count;
3896 int sum;
3897
3898 if ((name == NULL) || (*name == '\0') || (content == NULL))
3899 return -1;
3900
3901 sum = 0;
3902 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3903 if (count == -1)
3904 return -1;
3905 sum += count;
3906
Daniel Veillard1d211e22003-10-20 22:32:39 +00003907 count = xmlTextWriterWriteString(writer, content);
3908 if (count == -1)
3909 return -1;
3910 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00003911
3912 count = xmlTextWriterEndDTDEntity(writer);
3913 if (count == -1)
3914 return -1;
3915 sum += count;
3916
3917 return sum;
3918}
3919
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003920/**
3921 * xmlTextWriterWriteDTDExternalEntity:
3922 * @writer: the xmlTextWriterPtr
3923 * @pe: TRUE if this is a parameter entity, FALSE if not
3924 * @name: the name of the DTD entity
3925 * @pubid: the public identifier, which is an alternative to the system identifier
3926 * @sysid: the system identifier, which is the URI of the DTD
3927 * @ndataid: the xml notation name.
3928 *
Daniel Veillard500a1de2004-03-22 15:22:58 +00003929 * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
Daniel Veillard5841f0e2003-11-20 11:59:09 +00003930 *
3931 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3932 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00003933int
3934xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3935 int pe,
3936 const xmlChar * name,
3937 const xmlChar * pubid,
3938 const xmlChar * sysid,
3939 const xmlChar * ndataid)
3940{
3941 int count;
3942 int sum;
3943
Daniel Veillard500a1de2004-03-22 15:22:58 +00003944 if (((pubid == NULL) && (sysid == NULL)))
Daniel Veillard1d211e22003-10-20 22:32:39 +00003945 return -1;
3946 if ((pe != 0) && (ndataid != NULL))
3947 return -1;
3948
3949 sum = 0;
3950 count = xmlTextWriterStartDTDEntity(writer, pe, name);
3951 if (count == -1)
3952 return -1;
3953 sum += count;
3954
Daniel Veillard500a1de2004-03-22 15:22:58 +00003955 count =
3956 xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3957 ndataid);
3958 if (count < 0)
3959 return -1;
3960 sum += count;
3961
3962 count = xmlTextWriterEndDTDEntity(writer);
3963 if (count == -1)
3964 return -1;
3965 sum += count;
3966
3967 return sum;
3968}
3969
3970/**
3971 * xmlTextWriterWriteDTDExternalEntityContents:
3972 * @writer: the xmlTextWriterPtr
3973 * @pubid: the public identifier, which is an alternative to the system identifier
3974 * @sysid: the system identifier, which is the URI of the DTD
3975 * @ndataid: the xml notation name.
3976 *
3977 * Write the contents of a DTD external entity.
3978 *
3979 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3980 */
3981int
3982xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3983 const xmlChar * pubid,
3984 const xmlChar * sysid,
3985 const xmlChar * ndataid)
3986{
3987 int count;
3988 int sum;
3989 xmlLinkPtr lk;
3990 xmlTextWriterStackEntry *p;
3991
3992 if (writer == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00003993 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00003994 "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
3995 return -1;
3996 }
3997
3998 sum = 0;
3999 lk = xmlListFront(writer->nodes);
4000 if (lk == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004001 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004002 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4003 return -1;
4004 }
4005
4006 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4007 if (p == 0)
4008 return -1;
4009
4010 switch (p->state) {
4011 case XML_TEXTWRITER_DTD_ENTY:
4012 break;
4013 case XML_TEXTWRITER_DTD_PENT:
4014 if (ndataid != NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004015 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004016 "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
4017 return -1;
4018 }
4019 break;
4020 default:
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004021 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004022 "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4023 return -1;
4024 }
4025
Daniel Veillard1d211e22003-10-20 22:32:39 +00004026 if (pubid != 0) {
4027 if (sysid == 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004028 xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
Daniel Veillard500a1de2004-03-22 15:22:58 +00004029 "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
Daniel Veillard1d211e22003-10-20 22:32:39 +00004030 return -1;
4031 }
4032
4033 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4034 if (count < 0)
4035 return -1;
4036 sum += count;
4037
4038 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4039 if (count < 0)
4040 return -1;
4041 sum += count;
4042
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004043 count =
4044 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004045 if (count < 0)
4046 return -1;
4047 sum += count;
4048
4049 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4050 if (count < 0)
4051 return -1;
4052 sum += count;
4053 }
4054
4055 if (sysid != 0) {
4056 if (pubid == 0) {
4057 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4058 if (count < 0)
4059 return -1;
4060 sum += count;
4061 }
4062
4063 count = xmlOutputBufferWriteString(writer->out, " ");
4064 if (count < 0)
4065 return -1;
4066 sum += count;
4067
4068 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4069 if (count < 0)
4070 return -1;
4071 sum += count;
4072
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004073 count =
4074 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004075 if (count < 0)
4076 return -1;
4077 sum += count;
4078
4079 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4080 if (count < 0)
4081 return -1;
4082 sum += count;
4083 }
4084
4085 if (ndataid != NULL) {
4086 count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4087 if (count < 0)
4088 return -1;
4089 sum += count;
4090
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004091 count =
4092 xmlOutputBufferWriteString(writer->out,
4093 (const char *) ndataid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004094 if (count < 0)
4095 return -1;
4096 sum += count;
4097 }
4098
Daniel Veillard1d211e22003-10-20 22:32:39 +00004099 return sum;
4100}
4101
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004102/**
4103 * xmlTextWriterWriteDTDNotation:
4104 * @writer: the xmlTextWriterPtr
4105 * @name: the name of the xml notation
4106 * @pubid: the public identifier, which is an alternative to the system identifier
4107 * @sysid: the system identifier, which is the URI of the DTD
4108 *
4109 * Write a DTD entity.
4110 *
4111 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4112 */
Daniel Veillard1d211e22003-10-20 22:32:39 +00004113int
4114xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4115 const xmlChar * name,
4116 const xmlChar * pubid, const xmlChar * sysid)
4117{
4118 int count;
4119 int sum;
4120 xmlLinkPtr lk;
4121 xmlTextWriterStackEntry *p;
4122
4123 if (writer == NULL || name == NULL || *name == '\0')
4124 return -1;
4125
4126 sum = 0;
4127 lk = xmlListFront(writer->nodes);
4128 if (lk == 0) {
4129 return -1;
4130 }
4131
4132 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
Daniel Veillard500a1de2004-03-22 15:22:58 +00004133 if (p != 0) {
4134 switch (p->state) {
4135 case XML_TEXTWRITER_DTD:
4136 count = xmlOutputBufferWriteString(writer->out, " [");
4137 if (count < 0)
4138 return -1;
4139 sum += count;
4140 if (writer->indent) {
4141 count = xmlOutputBufferWriteString(writer->out, "\n");
4142 if (count < 0)
4143 return -1;
4144 sum += count;
4145 }
4146 p->state = XML_TEXTWRITER_DTD_TEXT;
4147 /* fallthrough */
4148 case XML_TEXTWRITER_DTD_TEXT:
4149 break;
4150 default:
4151 return -1;
4152 }
4153 }
Daniel Veillard1d211e22003-10-20 22:32:39 +00004154
Daniel Veillard500a1de2004-03-22 15:22:58 +00004155 if (writer->indent) {
4156 count = xmlTextWriterWriteIndent(writer);
4157 if (count < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004158 return -1;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004159 sum += count;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004160 }
4161
4162 count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4163 if (count < 0)
4164 return -1;
4165 sum += count;
4166 count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4167 if (count < 0)
4168 return -1;
4169 sum += count;
4170
4171 if (pubid != 0) {
4172 count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4173 if (count < 0)
4174 return -1;
4175 sum += count;
4176 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4177 if (count < 0)
4178 return -1;
4179 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004180 count =
4181 xmlOutputBufferWriteString(writer->out, (const char *) pubid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004182 if (count < 0)
4183 return -1;
4184 sum += count;
4185 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4186 if (count < 0)
4187 return -1;
4188 sum += count;
4189 }
4190
4191 if (sysid != 0) {
4192 if (pubid == 0) {
4193 count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4194 if (count < 0)
4195 return -1;
4196 sum += count;
4197 }
4198 count = xmlOutputBufferWriteString(writer->out, " ");
4199 if (count < 0)
4200 return -1;
4201 sum += count;
4202 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4203 if (count < 0)
4204 return -1;
4205 sum += count;
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004206 count =
4207 xmlOutputBufferWriteString(writer->out, (const char *) sysid);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004208 if (count < 0)
4209 return -1;
4210 sum += count;
4211 count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4212 if (count < 0)
4213 return -1;
4214 sum += count;
4215 }
4216
4217 count = xmlOutputBufferWriteString(writer->out, ">");
4218 if (count < 0)
4219 return -1;
4220 sum += count;
4221
4222 return sum;
4223}
4224
4225/**
4226 * xmlTextWriterFlush:
4227 * @writer: the xmlTextWriterPtr
4228 *
4229 * Flush the output buffer.
4230 *
4231 * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4232 */
4233int
4234xmlTextWriterFlush(xmlTextWriterPtr writer)
4235{
4236 int count;
4237
4238 if (writer == NULL)
4239 return -1;
4240
4241 if (writer->out == NULL)
4242 count = 0;
4243 else
4244 count = xmlOutputBufferFlush(writer->out);
4245
4246 return count;
4247}
4248
4249/**
4250 * misc
4251 */
4252
4253/**
4254 * xmlFreeTextWriterStackEntry:
4255 * @lk: the xmlLinkPtr
4256 *
4257 * Free callback for the xmlList.
4258 */
4259static void
4260xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4261{
4262 xmlTextWriterStackEntry *p;
4263
4264 p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4265 if (p == 0)
4266 return;
4267
4268 if (p->name != 0)
4269 xmlFree(p->name);
4270 xmlFree(p);
4271}
4272
4273/**
4274 * xmlCmpTextWriterStackEntry:
4275 * @data0: the first data
4276 * @data1: the second data
4277 *
4278 * Compare callback for the xmlList.
4279 *
4280 * Returns -1, 0, 1
4281 */
4282static int
4283xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4284{
4285 xmlTextWriterStackEntry *p0;
4286 xmlTextWriterStackEntry *p1;
4287
4288 if (data0 == data1)
4289 return 0;
4290
4291 if (data0 == 0)
4292 return -1;
4293
4294 if (data1 == 0)
4295 return 1;
4296
4297 p0 = (xmlTextWriterStackEntry *) data0;
4298 p1 = (xmlTextWriterStackEntry *) data1;
4299
4300 return xmlStrcmp(p0->name, p1->name);
4301}
4302
4303/**
4304 * misc
4305 */
4306
4307/**
Rob Richardsb8769d62007-06-08 08:50:47 +00004308 * xmlTextWriterOutputNSDecl:
4309 * @writer: the xmlTextWriterPtr
4310 *
4311 * Output the current namespace declarations.
4312 */
4313static int
4314xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4315{
4316 xmlLinkPtr lk;
4317 xmlTextWriterNsStackEntry *np;
4318 int count;
4319 int sum;
4320
4321 sum = 0;
4322 while (!xmlListEmpty(writer->nsstack)) {
4323 xmlChar *namespaceURI = NULL;
4324 xmlChar *prefix = NULL;
4325
4326 lk = xmlListFront(writer->nsstack);
4327 np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4328
4329 if (np != 0) {
4330 namespaceURI = xmlStrdup(np->uri);
4331 prefix = xmlStrdup(np->prefix);
4332 }
4333
4334 xmlListPopFront(writer->nsstack);
4335
4336 if (np != 0) {
4337 count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4338 xmlFree(namespaceURI);
4339 xmlFree(prefix);
4340
4341 if (count < 0) {
4342 xmlListDelete(writer->nsstack);
4343 writer->nsstack = NULL;
4344 return -1;
4345 }
4346 sum += count;
4347 }
4348 }
4349 return sum;
4350}
4351
4352/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004353 * xmlFreeTextWriterNsStackEntry:
4354 * @lk: the xmlLinkPtr
4355 *
4356 * Free callback for the xmlList.
4357 */
4358static void
4359xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4360{
4361 xmlTextWriterNsStackEntry *p;
4362
4363 p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4364 if (p == 0)
4365 return;
4366
4367 if (p->prefix != 0)
4368 xmlFree(p->prefix);
4369 if (p->uri != 0)
4370 xmlFree(p->uri);
4371
4372 xmlFree(p);
4373}
4374
4375/**
4376 * xmlCmpTextWriterNsStackEntry:
4377 * @data0: the first data
4378 * @data1: the second data
4379 *
4380 * Compare callback for the xmlList.
4381 *
4382 * Returns -1, 0, 1
4383 */
4384static int
4385xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4386{
4387 xmlTextWriterNsStackEntry *p0;
4388 xmlTextWriterNsStackEntry *p1;
4389 int rc;
4390
4391 if (data0 == data1)
4392 return 0;
4393
4394 if (data0 == 0)
4395 return -1;
4396
4397 if (data1 == 0)
4398 return 1;
4399
4400 p0 = (xmlTextWriterNsStackEntry *) data0;
4401 p1 = (xmlTextWriterNsStackEntry *) data1;
4402
4403 rc = xmlStrcmp(p0->prefix, p1->prefix);
4404
Rob Richardsb8769d62007-06-08 08:50:47 +00004405 if ((rc != 0) || (p0->elem != p1->elem))
4406 rc = -1;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004407
4408 return rc;
4409}
4410
4411/**
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004412 * xmlTextWriterWriteDocCallback:
4413 * @context: the xmlBufferPtr
4414 * @str: the data to write
4415 * @len: the length of the data
4416 *
4417 * Write callback for the xmlOutputBuffer with target xmlBuffer
4418 *
4419 * Returns -1, 0, 1
4420 */
4421static int
4422xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
4423{
4424 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4425 int rc;
4426
Daniel Veillard1d913862003-11-21 00:28:39 +00004427 if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004428 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004429 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4430 rc);
4431 return -1;
4432 }
4433
4434 return len;
4435}
4436
4437/**
4438 * xmlTextWriterCloseDocCallback:
4439 * @context: the xmlBufferPtr
4440 *
4441 * Close callback for the xmlOutputBuffer with target xmlBuffer
4442 *
4443 * Returns -1, 0, 1
4444 */
4445static int
4446xmlTextWriterCloseDocCallback(void *context)
4447{
4448 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4449 int rc;
4450
4451 if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004452 xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004453 "xmlTextWriterWriteDocCallback : XML error %d !\n",
4454 rc);
4455 return -1;
4456 }
4457
4458 return 0;
4459}
4460
4461/**
Daniel Veillard1d211e22003-10-20 22:32:39 +00004462 * xmlTextWriterVSprintf:
4463 * @format: see printf
4464 * @argptr: pointer to the first member of the variable argument list.
4465 *
4466 * Utility function for formatted output
4467 *
4468 * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4469 */
4470static xmlChar *
4471xmlTextWriterVSprintf(const char *format, va_list argptr)
4472{
4473 int size;
4474 int count;
4475 xmlChar *buf;
William M. Brackf4caa5e2005-10-20 09:04:05 +00004476 va_list locarg;
Daniel Veillard1d211e22003-10-20 22:32:39 +00004477
4478 size = BUFSIZ;
4479 buf = (xmlChar *) xmlMalloc(size);
4480 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004481 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004482 "xmlTextWriterVSprintf : out of memory!\n");
4483 return NULL;
4484 }
4485
William M. Brackf4caa5e2005-10-20 09:04:05 +00004486 VA_COPY(locarg, argptr);
4487 while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
Daniel Veillard1d211e22003-10-20 22:32:39 +00004488 || (count == size - 1) || (count == size) || (count > size)) {
William M. Brackf4caa5e2005-10-20 09:04:05 +00004489 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004490 xmlFree(buf);
4491 size += BUFSIZ;
4492 buf = (xmlChar *) xmlMalloc(size);
4493 if (buf == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004494 xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
Daniel Veillard1d211e22003-10-20 22:32:39 +00004495 "xmlTextWriterVSprintf : out of memory!\n");
4496 return NULL;
4497 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004498 VA_COPY(locarg, argptr);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004499 }
William M. Brackf4caa5e2005-10-20 09:04:05 +00004500 va_end(locarg);
Daniel Veillard1d211e22003-10-20 22:32:39 +00004501
4502 return buf;
4503}
4504
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004505/**
4506 * xmlTextWriterStartDocumentCallback:
4507 * @ctx: the user data (XML parser context)
4508 *
4509 * called at the start of document processing.
4510 */
4511static void
4512xmlTextWriterStartDocumentCallback(void *ctx)
4513{
4514 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4515 xmlDocPtr doc;
4516
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004517 if (ctxt->html) {
4518#ifdef LIBXML_HTML_ENABLED
4519 if (ctxt->myDoc == NULL)
4520 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4521 if (ctxt->myDoc == NULL) {
4522 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4523 ctxt->sax->error(ctxt->userData,
4524 "SAX.startDocument(): out of memory\n");
4525 ctxt->errNo = XML_ERR_NO_MEMORY;
4526 ctxt->instate = XML_PARSER_EOF;
4527 ctxt->disableSAX = 1;
4528 return;
4529 }
4530#else
Daniel Veillardd0cf7f62004-11-09 16:17:02 +00004531 xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
Daniel Veillard5841f0e2003-11-20 11:59:09 +00004532 "libxml2 built without HTML support\n");
4533 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4534 ctxt->instate = XML_PARSER_EOF;
4535 ctxt->disableSAX = 1;
4536 return;
4537#endif
4538 } else {
4539 doc = ctxt->myDoc;
4540 if (doc == NULL)
4541 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4542 if (doc != NULL) {
4543 if (doc->children == NULL) {
4544 if (ctxt->encoding != NULL)
4545 doc->encoding = xmlStrdup(ctxt->encoding);
4546 else
4547 doc->encoding = NULL;
4548 doc->standalone = ctxt->standalone;
4549 }
4550 } else {
4551 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4552 ctxt->sax->error(ctxt->userData,
4553 "SAX.startDocument(): out of memory\n");
4554 ctxt->errNo = XML_ERR_NO_MEMORY;
4555 ctxt->instate = XML_PARSER_EOF;
4556 ctxt->disableSAX = 1;
4557 return;
4558 }
4559 }
4560 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4561 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4562 ctxt->myDoc->URL =
4563 xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4564 if (ctxt->myDoc->URL == NULL)
4565 ctxt->myDoc->URL =
4566 xmlStrdup((const xmlChar *) ctxt->input->filename);
4567 }
4568}
4569
Daniel Veillard2cca4462004-01-02 20:04:23 +00004570/**
4571 * xmlTextWriterSetIndent:
4572 * @writer: the xmlTextWriterPtr
4573 * @indent: do indentation?
4574 *
4575 * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4576 *
4577 * Returns -1 on error or 0 otherwise.
4578 */
4579int
Daniel Veillardab69f362004-02-17 11:40:32 +00004580xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004581{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004582 if ((writer == NULL) || (indent < 0))
Daniel Veillardab69f362004-02-17 11:40:32 +00004583 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004584
Daniel Veillardab69f362004-02-17 11:40:32 +00004585 writer->indent = indent;
4586 writer->doindent = 1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004587
Daniel Veillardab69f362004-02-17 11:40:32 +00004588 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004589}
4590
4591/**
4592 * xmlTextWriterSetIndentString:
4593 * @writer: the xmlTextWriterPtr
4594 * @str: the xmlChar string
4595 *
4596 * Set string indentation.
4597 *
4598 * Returns -1 on error or 0 otherwise.
4599 */
4600int
Daniel Veillardab69f362004-02-17 11:40:32 +00004601xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004602{
Daniel Veillarde43cc572004-11-03 11:50:29 +00004603 if ((writer == NULL) || (!str))
Daniel Veillardab69f362004-02-17 11:40:32 +00004604 return -1;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004605
Daniel Veillardab69f362004-02-17 11:40:32 +00004606 if (writer->ichar != NULL)
4607 xmlFree(writer->ichar);
4608 writer->ichar = xmlStrdup(str);
4609
4610 if (!writer->ichar)
4611 return -1;
4612 else
4613 return 0;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004614}
4615
4616/**
Csaba Raduly429d3a02012-09-11 11:50:25 +08004617 * xmlTextWriterSetQuoteChar:
4618 * @writer: the xmlTextWriterPtr
4619 * @quotechar: the quote character
4620 *
4621 * Set the character used for quoting attributes.
4622 *
4623 * Returns -1 on error or 0 otherwise.
4624 */
4625int
4626xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar)
4627{
4628 if ((writer == NULL) || ((quotechar != '\'') && (quotechar != '"')))
4629 return -1;
4630
4631 writer->qchar = quotechar;
4632
4633 return 0;
4634}
4635
4636/**
Daniel Veillard2cca4462004-01-02 20:04:23 +00004637 * xmlTextWriterWriteIndent:
4638 * @writer: the xmlTextWriterPtr
4639 *
4640 * Write indent string.
4641 *
4642 * Returns -1 on error or the number of strings written.
Daniel Veillardab69f362004-02-17 11:40:32 +00004643 */
Daniel Veillard2cca4462004-01-02 20:04:23 +00004644static int
Daniel Veillardab69f362004-02-17 11:40:32 +00004645xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
Daniel Veillard2cca4462004-01-02 20:04:23 +00004646{
Daniel Veillardab69f362004-02-17 11:40:32 +00004647 int lksize;
4648 int i;
4649 int ret;
Daniel Veillard2cca4462004-01-02 20:04:23 +00004650
Daniel Veillardab69f362004-02-17 11:40:32 +00004651 lksize = xmlListSize(writer->nodes);
4652 if (lksize < 1)
4653 return (-1); /* list is empty */
4654 for (i = 0; i < (lksize - 1); i++) {
4655 ret = xmlOutputBufferWriteString(writer->out,
4656 (const char *) writer->ichar);
4657 if (ret == -1)
4658 return (-1);
4659 }
4660
4661 return (lksize - 1);
Daniel Veillard2cca4462004-01-02 20:04:23 +00004662}
4663
Daniel Veillard500a1de2004-03-22 15:22:58 +00004664/**
4665 * xmlTextWriterHandleStateDependencies:
4666 * @writer: the xmlTextWriterPtr
4667 * @p: the xmlTextWriterStackEntry
4668 *
4669 * Write state dependent strings.
4670 *
4671 * Returns -1 on error or the number of characters written.
4672 */
4673static int
4674xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4675 xmlTextWriterStackEntry * p)
4676{
4677 int count;
4678 int sum;
4679 char extra[3];
4680
4681 if (writer == NULL)
4682 return -1;
4683
4684 if (p == NULL)
4685 return 0;
4686
4687 sum = 0;
4688 extra[0] = extra[1] = extra[2] = '\0';
4689 if (p != 0) {
4690 sum = 0;
4691 switch (p->state) {
4692 case XML_TEXTWRITER_NAME:
Rob Richardsb8769d62007-06-08 08:50:47 +00004693 /* Output namespace declarations */
4694 count = xmlTextWriterOutputNSDecl(writer);
4695 if (count < 0)
4696 return -1;
4697 sum += count;
Daniel Veillard500a1de2004-03-22 15:22:58 +00004698 extra[0] = '>';
4699 p->state = XML_TEXTWRITER_TEXT;
4700 break;
4701 case XML_TEXTWRITER_PI:
4702 extra[0] = ' ';
4703 p->state = XML_TEXTWRITER_PI_TEXT;
4704 break;
4705 case XML_TEXTWRITER_DTD:
4706 extra[0] = ' ';
4707 extra[1] = '[';
4708 p->state = XML_TEXTWRITER_DTD_TEXT;
4709 break;
4710 case XML_TEXTWRITER_DTD_ELEM:
4711 extra[0] = ' ';
4712 p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4713 break;
4714 case XML_TEXTWRITER_DTD_ATTL:
4715 extra[0] = ' ';
4716 p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4717 break;
4718 case XML_TEXTWRITER_DTD_ENTY:
4719 case XML_TEXTWRITER_DTD_PENT:
4720 extra[0] = ' ';
4721 extra[1] = writer->qchar;
4722 p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4723 break;
4724 default:
4725 break;
4726 }
4727 }
4728
4729 if (*extra != '\0') {
4730 count = xmlOutputBufferWriteString(writer->out, extra);
4731 if (count < 0)
4732 return -1;
4733 sum += count;
4734 }
4735
4736 return sum;
4737}
4738
Daniel Veillard5d4644e2005-04-01 13:11:58 +00004739#define bottom_xmlwriter
4740#include "elfgcchack.h"
Daniel Veillard1d211e22003-10-20 22:32:39 +00004741#endif