pocxxeci 0.30.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pocxxeci might be problematic. Click here for more details.

Files changed (160) hide show
  1. package/LICENSE +19 -0
  2. package/Makefile +18 -0
  3. package/README.md +52 -0
  4. package/binding.gyp +81 -0
  5. package/index.d.ts +273 -0
  6. package/index.js +45 -0
  7. package/lib/bindings.js +1 -0
  8. package/lib/document.js +122 -0
  9. package/lib/element.js +82 -0
  10. package/lib/sax_parser.js +38 -0
  11. package/package.json +70 -0
  12. package/src/html_document.cc +7 -0
  13. package/src/html_document.h +18 -0
  14. package/src/libxmljs.cc +252 -0
  15. package/src/libxmljs.h +53 -0
  16. package/src/xml_attribute.cc +173 -0
  17. package/src/xml_attribute.h +40 -0
  18. package/src/xml_comment.cc +117 -0
  19. package/src/xml_comment.h +30 -0
  20. package/src/xml_document.cc +810 -0
  21. package/src/xml_document.h +67 -0
  22. package/src/xml_element.cc +565 -0
  23. package/src/xml_element.h +61 -0
  24. package/src/xml_namespace.cc +158 -0
  25. package/src/xml_namespace.h +39 -0
  26. package/src/xml_node.cc +761 -0
  27. package/src/xml_node.h +73 -0
  28. package/src/xml_pi.cc +161 -0
  29. package/src/xml_pi.h +34 -0
  30. package/src/xml_sax_parser.cc +424 -0
  31. package/src/xml_sax_parser.h +73 -0
  32. package/src/xml_syntax_error.cc +66 -0
  33. package/src/xml_syntax_error.h +25 -0
  34. package/src/xml_text.cc +320 -0
  35. package/src/xml_text.h +48 -0
  36. package/src/xml_textwriter.cc +315 -0
  37. package/src/xml_textwriter.h +62 -0
  38. package/src/xml_xpath_context.cc +70 -0
  39. package/src/xml_xpath_context.h +23 -0
  40. package/vendor/libxml/Copyright +23 -0
  41. package/vendor/libxml/DOCBparser.c +305 -0
  42. package/vendor/libxml/HTMLparser.c +7287 -0
  43. package/vendor/libxml/HTMLtree.c +1200 -0
  44. package/vendor/libxml/Makefile +2983 -0
  45. package/vendor/libxml/SAX.c +180 -0
  46. package/vendor/libxml/SAX2.c +3036 -0
  47. package/vendor/libxml/buf.c +1351 -0
  48. package/vendor/libxml/buf.h +72 -0
  49. package/vendor/libxml/c14n.c +2234 -0
  50. package/vendor/libxml/catalog.c +3828 -0
  51. package/vendor/libxml/chvalid.c +336 -0
  52. package/vendor/libxml/config.h +294 -0
  53. package/vendor/libxml/config.h.gch +0 -0
  54. package/vendor/libxml/debugXML.c +3423 -0
  55. package/vendor/libxml/dict.c +1298 -0
  56. package/vendor/libxml/elfgcchack.h +17818 -0
  57. package/vendor/libxml/enc.h +32 -0
  58. package/vendor/libxml/encoding.c +3975 -0
  59. package/vendor/libxml/entities.c +1163 -0
  60. package/vendor/libxml/error.c +998 -0
  61. package/vendor/libxml/globals.c +1126 -0
  62. package/vendor/libxml/hash.c +1146 -0
  63. package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
  64. package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
  65. package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
  66. package/vendor/libxml/include/libxml/Makefile +725 -0
  67. package/vendor/libxml/include/libxml/Makefile.am +54 -0
  68. package/vendor/libxml/include/libxml/Makefile.in +725 -0
  69. package/vendor/libxml/include/libxml/SAX.h +173 -0
  70. package/vendor/libxml/include/libxml/SAX2.h +178 -0
  71. package/vendor/libxml/include/libxml/c14n.h +128 -0
  72. package/vendor/libxml/include/libxml/catalog.h +182 -0
  73. package/vendor/libxml/include/libxml/chvalid.h +230 -0
  74. package/vendor/libxml/include/libxml/debugXML.h +217 -0
  75. package/vendor/libxml/include/libxml/dict.h +79 -0
  76. package/vendor/libxml/include/libxml/encoding.h +245 -0
  77. package/vendor/libxml/include/libxml/entities.h +151 -0
  78. package/vendor/libxml/include/libxml/globals.h +508 -0
  79. package/vendor/libxml/include/libxml/hash.h +236 -0
  80. package/vendor/libxml/include/libxml/list.h +137 -0
  81. package/vendor/libxml/include/libxml/nanoftp.h +163 -0
  82. package/vendor/libxml/include/libxml/nanohttp.h +81 -0
  83. package/vendor/libxml/include/libxml/parser.h +1243 -0
  84. package/vendor/libxml/include/libxml/parserInternals.h +644 -0
  85. package/vendor/libxml/include/libxml/pattern.h +100 -0
  86. package/vendor/libxml/include/libxml/relaxng.h +217 -0
  87. package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
  88. package/vendor/libxml/include/libxml/schematron.h +142 -0
  89. package/vendor/libxml/include/libxml/threads.h +89 -0
  90. package/vendor/libxml/include/libxml/tree.h +1311 -0
  91. package/vendor/libxml/include/libxml/uri.h +94 -0
  92. package/vendor/libxml/include/libxml/valid.h +458 -0
  93. package/vendor/libxml/include/libxml/xinclude.h +129 -0
  94. package/vendor/libxml/include/libxml/xlink.h +189 -0
  95. package/vendor/libxml/include/libxml/xmlIO.h +368 -0
  96. package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
  97. package/vendor/libxml/include/libxml/xmlerror.h +945 -0
  98. package/vendor/libxml/include/libxml/xmlexports.h +77 -0
  99. package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
  100. package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
  101. package/vendor/libxml/include/libxml/xmlreader.h +428 -0
  102. package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
  103. package/vendor/libxml/include/libxml/xmlsave.h +88 -0
  104. package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
  105. package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
  106. package/vendor/libxml/include/libxml/xmlstring.h +140 -0
  107. package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
  108. package/vendor/libxml/include/libxml/xmlversion.h +484 -0
  109. package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
  110. package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
  111. package/vendor/libxml/include/libxml/xpath.h +564 -0
  112. package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
  113. package/vendor/libxml/include/libxml/xpointer.h +114 -0
  114. package/vendor/libxml/include/win32config.h +122 -0
  115. package/vendor/libxml/include/wsockcompat.h +54 -0
  116. package/vendor/libxml/legacy.c +1343 -0
  117. package/vendor/libxml/libxml.h +134 -0
  118. package/vendor/libxml/list.c +779 -0
  119. package/vendor/libxml/nanoftp.c +2118 -0
  120. package/vendor/libxml/nanohttp.c +1899 -0
  121. package/vendor/libxml/parser.c +15553 -0
  122. package/vendor/libxml/parserInternals.c +2164 -0
  123. package/vendor/libxml/pattern.c +2621 -0
  124. package/vendor/libxml/relaxng.c +11101 -0
  125. package/vendor/libxml/rngparser.c +1595 -0
  126. package/vendor/libxml/runsuite.c +1157 -0
  127. package/vendor/libxml/save.h +36 -0
  128. package/vendor/libxml/schematron.c +1787 -0
  129. package/vendor/libxml/threads.c +1049 -0
  130. package/vendor/libxml/timsort.h +601 -0
  131. package/vendor/libxml/tree.c +10183 -0
  132. package/vendor/libxml/trio.c +6895 -0
  133. package/vendor/libxml/trio.h +230 -0
  134. package/vendor/libxml/triodef.h +228 -0
  135. package/vendor/libxml/trionan.c +914 -0
  136. package/vendor/libxml/trionan.h +84 -0
  137. package/vendor/libxml/triop.h +150 -0
  138. package/vendor/libxml/triostr.c +2112 -0
  139. package/vendor/libxml/triostr.h +144 -0
  140. package/vendor/libxml/uri.c +2561 -0
  141. package/vendor/libxml/valid.c +7138 -0
  142. package/vendor/libxml/xinclude.c +2657 -0
  143. package/vendor/libxml/xlink.c +183 -0
  144. package/vendor/libxml/xmlIO.c +4135 -0
  145. package/vendor/libxml/xmlcatalog.c +624 -0
  146. package/vendor/libxml/xmllint.c +3796 -0
  147. package/vendor/libxml/xmlmemory.c +1163 -0
  148. package/vendor/libxml/xmlmodule.c +468 -0
  149. package/vendor/libxml/xmlreader.c +6033 -0
  150. package/vendor/libxml/xmlregexp.c +8271 -0
  151. package/vendor/libxml/xmlsave.c +2735 -0
  152. package/vendor/libxml/xmlschemas.c +29173 -0
  153. package/vendor/libxml/xmlschemastypes.c +6276 -0
  154. package/vendor/libxml/xmlstring.c +1050 -0
  155. package/vendor/libxml/xmlunicode.c +3179 -0
  156. package/vendor/libxml/xmlwriter.c +4738 -0
  157. package/vendor/libxml/xpath.c +14734 -0
  158. package/vendor/libxml/xpointer.c +2969 -0
  159. package/vendor/libxml/xzlib.c +815 -0
  160. package/vendor/libxml/xzlib.h +19 -0
@@ -0,0 +1,2735 @@
1
+ /*
2
+ * xmlsave.c: Implementation of the document serializer
3
+ *
4
+ * See Copyright for the status of this software.
5
+ *
6
+ * daniel@veillard.com
7
+ */
8
+
9
+ #define IN_LIBXML
10
+ #include "libxml.h"
11
+
12
+ #include <string.h>
13
+ #include <libxml/xmlmemory.h>
14
+ #include <libxml/parserInternals.h>
15
+ #include <libxml/tree.h>
16
+ #include <libxml/xmlsave.h>
17
+
18
+ #define MAX_INDENT 60
19
+
20
+ #include <libxml/HTMLtree.h>
21
+
22
+ #include "buf.h"
23
+ #include "enc.h"
24
+ #include "save.h"
25
+
26
+ /************************************************************************
27
+ * *
28
+ * XHTML detection *
29
+ * *
30
+ ************************************************************************/
31
+ #define XHTML_STRICT_PUBLIC_ID BAD_CAST \
32
+ "-//W3C//DTD XHTML 1.0 Strict//EN"
33
+ #define XHTML_STRICT_SYSTEM_ID BAD_CAST \
34
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
35
+ #define XHTML_FRAME_PUBLIC_ID BAD_CAST \
36
+ "-//W3C//DTD XHTML 1.0 Frameset//EN"
37
+ #define XHTML_FRAME_SYSTEM_ID BAD_CAST \
38
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
39
+ #define XHTML_TRANS_PUBLIC_ID BAD_CAST \
40
+ "-//W3C//DTD XHTML 1.0 Transitional//EN"
41
+ #define XHTML_TRANS_SYSTEM_ID BAD_CAST \
42
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
43
+
44
+ #define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml"
45
+ /**
46
+ * xmlIsXHTML:
47
+ * @systemID: the system identifier
48
+ * @publicID: the public identifier
49
+ *
50
+ * Try to find if the document correspond to an XHTML DTD
51
+ *
52
+ * Returns 1 if true, 0 if not and -1 in case of error
53
+ */
54
+ int
55
+ xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) {
56
+ if ((systemID == NULL) && (publicID == NULL))
57
+ return(-1);
58
+ if (publicID != NULL) {
59
+ if (xmlStrEqual(publicID, XHTML_STRICT_PUBLIC_ID)) return(1);
60
+ if (xmlStrEqual(publicID, XHTML_FRAME_PUBLIC_ID)) return(1);
61
+ if (xmlStrEqual(publicID, XHTML_TRANS_PUBLIC_ID)) return(1);
62
+ }
63
+ if (systemID != NULL) {
64
+ if (xmlStrEqual(systemID, XHTML_STRICT_SYSTEM_ID)) return(1);
65
+ if (xmlStrEqual(systemID, XHTML_FRAME_SYSTEM_ID)) return(1);
66
+ if (xmlStrEqual(systemID, XHTML_TRANS_SYSTEM_ID)) return(1);
67
+ }
68
+ return(0);
69
+ }
70
+
71
+ #ifdef LIBXML_OUTPUT_ENABLED
72
+
73
+ #define TODO \
74
+ xmlGenericError(xmlGenericErrorContext, \
75
+ "Unimplemented block at %s:%d\n", \
76
+ __FILE__, __LINE__);
77
+
78
+ struct _xmlSaveCtxt {
79
+ void *_private;
80
+ int type;
81
+ int fd;
82
+ const xmlChar *filename;
83
+ const xmlChar *encoding;
84
+ xmlCharEncodingHandlerPtr handler;
85
+ xmlOutputBufferPtr buf;
86
+ int options;
87
+ int level;
88
+ int format;
89
+ char indent[MAX_INDENT + 1]; /* array for indenting output */
90
+ int indent_nr;
91
+ int indent_size;
92
+ xmlCharEncodingOutputFunc escape; /* used for element content */
93
+ xmlCharEncodingOutputFunc escapeAttr;/* used for attribute content */
94
+ };
95
+
96
+ /************************************************************************
97
+ * *
98
+ * Output error handlers *
99
+ * *
100
+ ************************************************************************/
101
+ /**
102
+ * xmlSaveErrMemory:
103
+ * @extra: extra information
104
+ *
105
+ * Handle an out of memory condition
106
+ */
107
+ static void
108
+ xmlSaveErrMemory(const char *extra)
109
+ {
110
+ __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra);
111
+ }
112
+
113
+ /**
114
+ * xmlSaveErr:
115
+ * @code: the error number
116
+ * @node: the location of the error.
117
+ * @extra: extra information
118
+ *
119
+ * Handle an out of memory condition
120
+ */
121
+ static void
122
+ xmlSaveErr(int code, xmlNodePtr node, const char *extra)
123
+ {
124
+ const char *msg = NULL;
125
+
126
+ switch(code) {
127
+ case XML_SAVE_NOT_UTF8:
128
+ msg = "string is not in UTF-8\n";
129
+ break;
130
+ case XML_SAVE_CHAR_INVALID:
131
+ msg = "invalid character value\n";
132
+ break;
133
+ case XML_SAVE_UNKNOWN_ENCODING:
134
+ msg = "unknown encoding %s\n";
135
+ break;
136
+ case XML_SAVE_NO_DOCTYPE:
137
+ msg = "document has no DOCTYPE\n";
138
+ break;
139
+ default:
140
+ msg = "unexpected error number\n";
141
+ }
142
+ __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra);
143
+ }
144
+
145
+ /************************************************************************
146
+ * *
147
+ * Special escaping routines *
148
+ * *
149
+ ************************************************************************/
150
+ static unsigned char *
151
+ xmlSerializeHexCharRef(unsigned char *out, int val) {
152
+ unsigned char *ptr;
153
+
154
+ *out++ = '&';
155
+ *out++ = '#';
156
+ *out++ = 'x';
157
+ if (val < 0x10) ptr = out;
158
+ else if (val < 0x100) ptr = out + 1;
159
+ else if (val < 0x1000) ptr = out + 2;
160
+ else if (val < 0x10000) ptr = out + 3;
161
+ else if (val < 0x100000) ptr = out + 4;
162
+ else ptr = out + 5;
163
+ out = ptr + 1;
164
+ while (val > 0) {
165
+ switch (val & 0xF) {
166
+ case 0: *ptr-- = '0'; break;
167
+ case 1: *ptr-- = '1'; break;
168
+ case 2: *ptr-- = '2'; break;
169
+ case 3: *ptr-- = '3'; break;
170
+ case 4: *ptr-- = '4'; break;
171
+ case 5: *ptr-- = '5'; break;
172
+ case 6: *ptr-- = '6'; break;
173
+ case 7: *ptr-- = '7'; break;
174
+ case 8: *ptr-- = '8'; break;
175
+ case 9: *ptr-- = '9'; break;
176
+ case 0xA: *ptr-- = 'A'; break;
177
+ case 0xB: *ptr-- = 'B'; break;
178
+ case 0xC: *ptr-- = 'C'; break;
179
+ case 0xD: *ptr-- = 'D'; break;
180
+ case 0xE: *ptr-- = 'E'; break;
181
+ case 0xF: *ptr-- = 'F'; break;
182
+ default: *ptr-- = '0'; break;
183
+ }
184
+ val >>= 4;
185
+ }
186
+ *out++ = ';';
187
+ *out = 0;
188
+ return(out);
189
+ }
190
+
191
+ /**
192
+ * xmlEscapeEntities:
193
+ * @out: a pointer to an array of bytes to store the result
194
+ * @outlen: the length of @out
195
+ * @in: a pointer to an array of unescaped UTF-8 bytes
196
+ * @inlen: the length of @in
197
+ *
198
+ * Take a block of UTF-8 chars in and escape them. Used when there is no
199
+ * encoding specified.
200
+ *
201
+ * Returns 0 if success, or -1 otherwise
202
+ * The value of @inlen after return is the number of octets consumed
203
+ * if the return value is positive, else unpredictable.
204
+ * The value of @outlen after return is the number of octets consumed.
205
+ */
206
+ static int
207
+ xmlEscapeEntities(unsigned char* out, int *outlen,
208
+ const xmlChar* in, int *inlen) {
209
+ unsigned char* outstart = out;
210
+ const unsigned char* base = in;
211
+ unsigned char* outend = out + *outlen;
212
+ const unsigned char* inend;
213
+ int val;
214
+
215
+ inend = in + (*inlen);
216
+
217
+ while ((in < inend) && (out < outend)) {
218
+ if (*in == '<') {
219
+ if (outend - out < 4) break;
220
+ *out++ = '&';
221
+ *out++ = 'l';
222
+ *out++ = 't';
223
+ *out++ = ';';
224
+ in++;
225
+ continue;
226
+ } else if (*in == '>') {
227
+ if (outend - out < 4) break;
228
+ *out++ = '&';
229
+ *out++ = 'g';
230
+ *out++ = 't';
231
+ *out++ = ';';
232
+ in++;
233
+ continue;
234
+ } else if (*in == '&') {
235
+ if (outend - out < 5) break;
236
+ *out++ = '&';
237
+ *out++ = 'a';
238
+ *out++ = 'm';
239
+ *out++ = 'p';
240
+ *out++ = ';';
241
+ in++;
242
+ continue;
243
+ } else if (((*in >= 0x20) && (*in < 0x80)) ||
244
+ (*in == '\n') || (*in == '\t')) {
245
+ /*
246
+ * default case, just copy !
247
+ */
248
+ *out++ = *in++;
249
+ continue;
250
+ } else if (*in >= 0x80) {
251
+ /*
252
+ * We assume we have UTF-8 input.
253
+ */
254
+ if (outend - out < 11) break;
255
+
256
+ if (*in < 0xC0) {
257
+ xmlSaveErr(XML_SAVE_NOT_UTF8, NULL, NULL);
258
+ in++;
259
+ goto error;
260
+ } else if (*in < 0xE0) {
261
+ if (inend - in < 2) break;
262
+ val = (in[0]) & 0x1F;
263
+ val <<= 6;
264
+ val |= (in[1]) & 0x3F;
265
+ in += 2;
266
+ } else if (*in < 0xF0) {
267
+ if (inend - in < 3) break;
268
+ val = (in[0]) & 0x0F;
269
+ val <<= 6;
270
+ val |= (in[1]) & 0x3F;
271
+ val <<= 6;
272
+ val |= (in[2]) & 0x3F;
273
+ in += 3;
274
+ } else if (*in < 0xF8) {
275
+ if (inend - in < 4) break;
276
+ val = (in[0]) & 0x07;
277
+ val <<= 6;
278
+ val |= (in[1]) & 0x3F;
279
+ val <<= 6;
280
+ val |= (in[2]) & 0x3F;
281
+ val <<= 6;
282
+ val |= (in[3]) & 0x3F;
283
+ in += 4;
284
+ } else {
285
+ xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);
286
+ in++;
287
+ goto error;
288
+ }
289
+ if (!IS_CHAR(val)) {
290
+ xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);
291
+ in++;
292
+ goto error;
293
+ }
294
+
295
+ /*
296
+ * We could do multiple things here. Just save as a char ref
297
+ */
298
+ out = xmlSerializeHexCharRef(out, val);
299
+ } else if (IS_BYTE_CHAR(*in)) {
300
+ if (outend - out < 6) break;
301
+ out = xmlSerializeHexCharRef(out, *in++);
302
+ } else {
303
+ xmlGenericError(xmlGenericErrorContext,
304
+ "xmlEscapeEntities : char out of range\n");
305
+ in++;
306
+ goto error;
307
+ }
308
+ }
309
+ *outlen = out - outstart;
310
+ *inlen = in - base;
311
+ return(0);
312
+ error:
313
+ *outlen = out - outstart;
314
+ *inlen = in - base;
315
+ return(-1);
316
+ }
317
+
318
+ /************************************************************************
319
+ * *
320
+ * Allocation and deallocation *
321
+ * *
322
+ ************************************************************************/
323
+ /**
324
+ * xmlSaveCtxtInit:
325
+ * @ctxt: the saving context
326
+ *
327
+ * Initialize a saving context
328
+ */
329
+ static void
330
+ xmlSaveCtxtInit(xmlSaveCtxtPtr ctxt)
331
+ {
332
+ int i;
333
+ int len;
334
+
335
+ if (ctxt == NULL) return;
336
+ if ((ctxt->encoding == NULL) && (ctxt->escape == NULL))
337
+ ctxt->escape = xmlEscapeEntities;
338
+ len = xmlStrlen((xmlChar *)xmlTreeIndentString);
339
+ if ((xmlTreeIndentString == NULL) || (len == 0)) {
340
+ memset(&ctxt->indent[0], 0, MAX_INDENT + 1);
341
+ } else {
342
+ ctxt->indent_size = len;
343
+ ctxt->indent_nr = MAX_INDENT / ctxt->indent_size;
344
+ for (i = 0;i < ctxt->indent_nr;i++)
345
+ memcpy(&ctxt->indent[i * ctxt->indent_size], xmlTreeIndentString,
346
+ ctxt->indent_size);
347
+ ctxt->indent[ctxt->indent_nr * ctxt->indent_size] = 0;
348
+ }
349
+
350
+ if (xmlSaveNoEmptyTags) {
351
+ ctxt->options |= XML_SAVE_NO_EMPTY;
352
+ }
353
+ }
354
+
355
+ /**
356
+ * xmlFreeSaveCtxt:
357
+ *
358
+ * Free a saving context, destroying the output in any remaining buffer
359
+ */
360
+ static void
361
+ xmlFreeSaveCtxt(xmlSaveCtxtPtr ctxt)
362
+ {
363
+ if (ctxt == NULL) return;
364
+ if (ctxt->encoding != NULL)
365
+ xmlFree((char *) ctxt->encoding);
366
+ if (ctxt->buf != NULL)
367
+ xmlOutputBufferClose(ctxt->buf);
368
+ xmlFree(ctxt);
369
+ }
370
+
371
+ /**
372
+ * xmlNewSaveCtxt:
373
+ *
374
+ * Create a new saving context
375
+ *
376
+ * Returns the new structure or NULL in case of error
377
+ */
378
+ static xmlSaveCtxtPtr
379
+ xmlNewSaveCtxt(const char *encoding, int options)
380
+ {
381
+ xmlSaveCtxtPtr ret;
382
+
383
+ ret = (xmlSaveCtxtPtr) xmlMalloc(sizeof(xmlSaveCtxt));
384
+ if (ret == NULL) {
385
+ xmlSaveErrMemory("creating saving context");
386
+ return ( NULL );
387
+ }
388
+ memset(ret, 0, sizeof(xmlSaveCtxt));
389
+
390
+ if (encoding != NULL) {
391
+ ret->handler = xmlFindCharEncodingHandler(encoding);
392
+ if (ret->handler == NULL) {
393
+ xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
394
+ xmlFreeSaveCtxt(ret);
395
+ return(NULL);
396
+ }
397
+ ret->encoding = xmlStrdup((const xmlChar *)encoding);
398
+ ret->escape = NULL;
399
+ }
400
+ xmlSaveCtxtInit(ret);
401
+
402
+ /*
403
+ * Use the options
404
+ */
405
+
406
+ /* Re-check this option as it may already have been set */
407
+ if ((ret->options & XML_SAVE_NO_EMPTY) && ! (options & XML_SAVE_NO_EMPTY)) {
408
+ options |= XML_SAVE_NO_EMPTY;
409
+ }
410
+
411
+ ret->options = options;
412
+ if (options & XML_SAVE_FORMAT)
413
+ ret->format = 1;
414
+ else if (options & XML_SAVE_WSNONSIG)
415
+ ret->format = 2;
416
+
417
+ return(ret);
418
+ }
419
+
420
+ /************************************************************************
421
+ * *
422
+ * Dumping XML tree content to a simple buffer *
423
+ * *
424
+ ************************************************************************/
425
+ /**
426
+ * xmlAttrSerializeContent:
427
+ * @buf: the XML buffer output
428
+ * @doc: the document
429
+ * @attr: the attribute pointer
430
+ *
431
+ * Serialize the attribute in the buffer
432
+ */
433
+ static void
434
+ xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr)
435
+ {
436
+ xmlNodePtr children;
437
+
438
+ children = attr->children;
439
+ while (children != NULL) {
440
+ switch (children->type) {
441
+ case XML_TEXT_NODE:
442
+ xmlBufAttrSerializeTxtContent(buf->buffer, attr->doc,
443
+ attr, children->content);
444
+ break;
445
+ case XML_ENTITY_REF_NODE:
446
+ xmlBufAdd(buf->buffer, BAD_CAST "&", 1);
447
+ xmlBufAdd(buf->buffer, children->name,
448
+ xmlStrlen(children->name));
449
+ xmlBufAdd(buf->buffer, BAD_CAST ";", 1);
450
+ break;
451
+ default:
452
+ /* should not happen unless we have a badly built tree */
453
+ break;
454
+ }
455
+ children = children->next;
456
+ }
457
+ }
458
+
459
+ /**
460
+ * xmlBufDumpNotationTable:
461
+ * @buf: an xmlBufPtr output
462
+ * @table: A notation table
463
+ *
464
+ * This will dump the content of the notation table as an XML DTD definition
465
+ */
466
+ void
467
+ xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table) {
468
+ xmlBufferPtr buffer;
469
+
470
+ buffer = xmlBufferCreate();
471
+ if (buffer == NULL) {
472
+ /*
473
+ * TODO set the error in buf
474
+ */
475
+ return;
476
+ }
477
+ xmlDumpNotationTable(buffer, table);
478
+ xmlBufMergeBuffer(buf, buffer);
479
+ }
480
+
481
+ /**
482
+ * xmlBufDumpElementDecl:
483
+ * @buf: an xmlBufPtr output
484
+ * @elem: An element table
485
+ *
486
+ * This will dump the content of the element declaration as an XML
487
+ * DTD definition
488
+ */
489
+ void
490
+ xmlBufDumpElementDecl(xmlBufPtr buf, xmlElementPtr elem) {
491
+ xmlBufferPtr buffer;
492
+
493
+ buffer = xmlBufferCreate();
494
+ if (buffer == NULL) {
495
+ /*
496
+ * TODO set the error in buf
497
+ */
498
+ return;
499
+ }
500
+ xmlDumpElementDecl(buffer, elem);
501
+ xmlBufMergeBuffer(buf, buffer);
502
+ }
503
+
504
+ /**
505
+ * xmlBufDumpAttributeDecl:
506
+ * @buf: an xmlBufPtr output
507
+ * @attr: An attribute declaration
508
+ *
509
+ * This will dump the content of the attribute declaration as an XML
510
+ * DTD definition
511
+ */
512
+ void
513
+ xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr) {
514
+ xmlBufferPtr buffer;
515
+
516
+ buffer = xmlBufferCreate();
517
+ if (buffer == NULL) {
518
+ /*
519
+ * TODO set the error in buf
520
+ */
521
+ return;
522
+ }
523
+ xmlDumpAttributeDecl(buffer, attr);
524
+ xmlBufMergeBuffer(buf, buffer);
525
+ }
526
+
527
+ /**
528
+ * xmlBufDumpEntityDecl:
529
+ * @buf: an xmlBufPtr output
530
+ * @ent: An entity table
531
+ *
532
+ * This will dump the content of the entity table as an XML DTD definition
533
+ */
534
+ void
535
+ xmlBufDumpEntityDecl(xmlBufPtr buf, xmlEntityPtr ent) {
536
+ xmlBufferPtr buffer;
537
+
538
+ buffer = xmlBufferCreate();
539
+ if (buffer == NULL) {
540
+ /*
541
+ * TODO set the error in buf
542
+ */
543
+ return;
544
+ }
545
+ xmlDumpEntityDecl(buffer, ent);
546
+ xmlBufMergeBuffer(buf, buffer);
547
+ }
548
+
549
+ /************************************************************************
550
+ * *
551
+ * Dumping XML tree content to an I/O output buffer *
552
+ * *
553
+ ************************************************************************/
554
+
555
+ static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) {
556
+ xmlOutputBufferPtr buf = ctxt->buf;
557
+
558
+ if ((encoding != NULL) && (buf->encoder == NULL) && (buf->conv == NULL)) {
559
+ buf->encoder = xmlFindCharEncodingHandler((const char *)encoding);
560
+ if (buf->encoder == NULL) {
561
+ xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL,
562
+ (const char *)encoding);
563
+ return(-1);
564
+ }
565
+ buf->conv = xmlBufCreate();
566
+ if (buf->conv == NULL) {
567
+ xmlCharEncCloseFunc(buf->encoder);
568
+ xmlSaveErrMemory("creating encoding buffer");
569
+ return(-1);
570
+ }
571
+ /*
572
+ * initialize the state, e.g. if outputting a BOM
573
+ */
574
+ xmlCharEncOutput(buf, 1);
575
+ }
576
+ return(0);
577
+ }
578
+
579
+ static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) {
580
+ xmlOutputBufferPtr buf = ctxt->buf;
581
+ xmlOutputBufferFlush(buf);
582
+ xmlCharEncCloseFunc(buf->encoder);
583
+ xmlBufFree(buf->conv);
584
+ buf->encoder = NULL;
585
+ buf->conv = NULL;
586
+ return(0);
587
+ }
588
+
589
+ #ifdef LIBXML_HTML_ENABLED
590
+ static void
591
+ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
592
+ #endif
593
+ static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
594
+ void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
595
+ static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur);
596
+
597
+ /**
598
+ * xmlOutputBufferWriteWSNonSig:
599
+ * @ctxt: The save context
600
+ * @extra: Number of extra indents to apply to ctxt->level
601
+ *
602
+ * Write out formatting for non-significant whitespace output.
603
+ */
604
+ static void
605
+ xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra)
606
+ {
607
+ int i;
608
+ if ((ctxt == NULL) || (ctxt->buf == NULL))
609
+ return;
610
+ xmlOutputBufferWrite(ctxt->buf, 1, "\n");
611
+ for (i = 0; i < (ctxt->level + extra); i += ctxt->indent_nr) {
612
+ xmlOutputBufferWrite(ctxt->buf, ctxt->indent_size *
613
+ ((ctxt->level + extra - i) > ctxt->indent_nr ?
614
+ ctxt->indent_nr : (ctxt->level + extra - i)),
615
+ ctxt->indent);
616
+ }
617
+ }
618
+
619
+ /**
620
+ * xmlNsDumpOutput:
621
+ * @buf: the XML buffer output
622
+ * @cur: a namespace
623
+ * @ctxt: the output save context. Optional.
624
+ *
625
+ * Dump a local Namespace definition.
626
+ * Should be called in the context of attributes dumps.
627
+ * If @ctxt is supplied, @buf should be its buffer.
628
+ */
629
+ static void
630
+ xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) {
631
+ if ((cur == NULL) || (buf == NULL)) return;
632
+ if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
633
+ if (xmlStrEqual(cur->prefix, BAD_CAST "xml"))
634
+ return;
635
+
636
+ if (ctxt != NULL && ctxt->format == 2)
637
+ xmlOutputBufferWriteWSNonSig(ctxt, 2);
638
+ else
639
+ xmlOutputBufferWrite(buf, 1, " ");
640
+
641
+ /* Within the context of an element attributes */
642
+ if (cur->prefix != NULL) {
643
+ xmlOutputBufferWrite(buf, 6, "xmlns:");
644
+ xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
645
+ } else
646
+ xmlOutputBufferWrite(buf, 5, "xmlns");
647
+ xmlOutputBufferWrite(buf, 1, "=");
648
+ xmlBufWriteQuotedString(buf->buffer, cur->href);
649
+ }
650
+ }
651
+
652
+ /**
653
+ * xmlNsDumpOutputCtxt
654
+ * @ctxt: the save context
655
+ * @cur: a namespace
656
+ *
657
+ * Dump a local Namespace definition to a save context.
658
+ * Should be called in the context of attribute dumps.
659
+ */
660
+ static void
661
+ xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
662
+ xmlNsDumpOutput(ctxt->buf, cur, ctxt);
663
+ }
664
+
665
+ /**
666
+ * xmlNsListDumpOutputCtxt
667
+ * @ctxt: the save context
668
+ * @cur: the first namespace
669
+ *
670
+ * Dump a list of local namespace definitions to a save context.
671
+ * Should be called in the context of attribute dumps.
672
+ */
673
+ static void
674
+ xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
675
+ while (cur != NULL) {
676
+ xmlNsDumpOutput(ctxt->buf, cur, ctxt);
677
+ cur = cur->next;
678
+ }
679
+ }
680
+
681
+ /**
682
+ * xmlNsListDumpOutput:
683
+ * @buf: the XML buffer output
684
+ * @cur: the first namespace
685
+ *
686
+ * Dump a list of local Namespace definitions.
687
+ * Should be called in the context of attributes dumps.
688
+ */
689
+ void
690
+ xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
691
+ while (cur != NULL) {
692
+ xmlNsDumpOutput(buf, cur, NULL);
693
+ cur = cur->next;
694
+ }
695
+ }
696
+
697
+ /**
698
+ * xmlDtdDumpOutput:
699
+ * @buf: the XML buffer output
700
+ * @dtd: the pointer to the DTD
701
+ *
702
+ * Dump the XML document DTD, if any.
703
+ */
704
+ static void
705
+ xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
706
+ xmlOutputBufferPtr buf;
707
+ xmlNodePtr cur;
708
+ int format, level;
709
+
710
+ if (dtd == NULL) return;
711
+ if ((ctxt == NULL) || (ctxt->buf == NULL))
712
+ return;
713
+ buf = ctxt->buf;
714
+ xmlOutputBufferWrite(buf, 10, "<!DOCTYPE ");
715
+ xmlOutputBufferWriteString(buf, (const char *)dtd->name);
716
+ if (dtd->ExternalID != NULL) {
717
+ xmlOutputBufferWrite(buf, 8, " PUBLIC ");
718
+ xmlBufWriteQuotedString(buf->buffer, dtd->ExternalID);
719
+ xmlOutputBufferWrite(buf, 1, " ");
720
+ xmlBufWriteQuotedString(buf->buffer, dtd->SystemID);
721
+ } else if (dtd->SystemID != NULL) {
722
+ xmlOutputBufferWrite(buf, 8, " SYSTEM ");
723
+ xmlBufWriteQuotedString(buf->buffer, dtd->SystemID);
724
+ }
725
+ if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
726
+ (dtd->attributes == NULL) && (dtd->notations == NULL) &&
727
+ (dtd->pentities == NULL)) {
728
+ xmlOutputBufferWrite(buf, 1, ">");
729
+ return;
730
+ }
731
+ xmlOutputBufferWrite(buf, 3, " [\n");
732
+ /*
733
+ * Dump the notations first they are not in the DTD children list
734
+ * Do this only on a standalone DTD or on the internal subset though.
735
+ */
736
+ if ((dtd->notations != NULL) && ((dtd->doc == NULL) ||
737
+ (dtd->doc->intSubset == dtd))) {
738
+ xmlBufDumpNotationTable(buf->buffer,
739
+ (xmlNotationTablePtr) dtd->notations);
740
+ }
741
+ format = ctxt->format;
742
+ level = ctxt->level;
743
+ ctxt->format = 0;
744
+ ctxt->level = -1;
745
+ for (cur = dtd->children; cur != NULL; cur = cur->next) {
746
+ xmlNodeDumpOutputInternal(ctxt, cur);
747
+ }
748
+ ctxt->format = format;
749
+ ctxt->level = level;
750
+ xmlOutputBufferWrite(buf, 2, "]>");
751
+ }
752
+
753
+ /**
754
+ * xmlAttrDumpOutput:
755
+ * @buf: the XML buffer output
756
+ * @cur: the attribute pointer
757
+ *
758
+ * Dump an XML attribute
759
+ */
760
+ static void
761
+ xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
762
+ xmlOutputBufferPtr buf;
763
+
764
+ if (cur == NULL) return;
765
+ buf = ctxt->buf;
766
+ if (buf == NULL) return;
767
+ if (ctxt->format == 2)
768
+ xmlOutputBufferWriteWSNonSig(ctxt, 2);
769
+ else
770
+ xmlOutputBufferWrite(buf, 1, " ");
771
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
772
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
773
+ xmlOutputBufferWrite(buf, 1, ":");
774
+ }
775
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
776
+ xmlOutputBufferWrite(buf, 2, "=\"");
777
+ xmlAttrSerializeContent(buf, cur);
778
+ xmlOutputBufferWrite(buf, 1, "\"");
779
+ }
780
+
781
+ #ifdef LIBXML_HTML_ENABLED
782
+ /**
783
+ * htmlNodeDumpOutputInternal:
784
+ * @cur: the current node
785
+ *
786
+ * Dump an HTML node, recursive behaviour, children are printed too.
787
+ */
788
+ static int
789
+ htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
790
+ const xmlChar *oldenc = NULL;
791
+ const xmlChar *oldctxtenc = ctxt->encoding;
792
+ const xmlChar *encoding = ctxt->encoding;
793
+ xmlOutputBufferPtr buf = ctxt->buf;
794
+ int switched_encoding = 0;
795
+ xmlDocPtr doc;
796
+
797
+ xmlInitParser();
798
+
799
+ doc = cur->doc;
800
+ if (doc != NULL) {
801
+ oldenc = doc->encoding;
802
+ if (ctxt->encoding != NULL) {
803
+ doc->encoding = BAD_CAST ctxt->encoding;
804
+ } else if (doc->encoding != NULL) {
805
+ encoding = doc->encoding;
806
+ }
807
+ }
808
+
809
+ if ((encoding != NULL) && (doc != NULL))
810
+ htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
811
+ if ((encoding == NULL) && (doc != NULL))
812
+ encoding = htmlGetMetaEncoding(doc);
813
+ if (encoding == NULL)
814
+ encoding = BAD_CAST "HTML";
815
+ if ((encoding != NULL) && (oldctxtenc == NULL) &&
816
+ (buf->encoder == NULL) && (buf->conv == NULL)) {
817
+ if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
818
+ doc->encoding = oldenc;
819
+ return(-1);
820
+ }
821
+ switched_encoding = 1;
822
+ }
823
+ if (ctxt->options & XML_SAVE_FORMAT)
824
+ htmlNodeDumpFormatOutput(buf, doc, cur,
825
+ (const char *)encoding, 1);
826
+ else
827
+ htmlNodeDumpFormatOutput(buf, doc, cur,
828
+ (const char *)encoding, 0);
829
+ /*
830
+ * Restore the state of the saving context at the end of the document
831
+ */
832
+ if ((switched_encoding) && (oldctxtenc == NULL)) {
833
+ xmlSaveClearEncoding(ctxt);
834
+ }
835
+ if (doc != NULL)
836
+ doc->encoding = oldenc;
837
+ return(0);
838
+ }
839
+ #endif
840
+
841
+ /**
842
+ * xmlNodeDumpOutputInternal:
843
+ * @cur: the current node
844
+ *
845
+ * Dump an XML node, recursive behaviour, children are printed too.
846
+ */
847
+ static void
848
+ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
849
+ int format = ctxt->format;
850
+ xmlNodePtr tmp, root, unformattedNode = NULL, parent;
851
+ xmlAttrPtr attr;
852
+ xmlChar *start, *end;
853
+ xmlOutputBufferPtr buf;
854
+
855
+ if (cur == NULL) return;
856
+ buf = ctxt->buf;
857
+
858
+ root = cur;
859
+ parent = cur->parent;
860
+ while (1) {
861
+ switch (cur->type) {
862
+ case XML_DOCUMENT_NODE:
863
+ case XML_HTML_DOCUMENT_NODE:
864
+ xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
865
+ break;
866
+
867
+ case XML_DTD_NODE:
868
+ xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
869
+ break;
870
+
871
+ case XML_DOCUMENT_FRAG_NODE:
872
+ /* Always validate cur->parent when descending. */
873
+ if ((cur->parent == parent) && (cur->children != NULL)) {
874
+ parent = cur;
875
+ cur = cur->children;
876
+ continue;
877
+ }
878
+ break;
879
+
880
+ case XML_ELEMENT_DECL:
881
+ xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
882
+ break;
883
+
884
+ case XML_ATTRIBUTE_DECL:
885
+ xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
886
+ break;
887
+
888
+ case XML_ENTITY_DECL:
889
+ xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
890
+ break;
891
+
892
+ case XML_ELEMENT_NODE:
893
+ if ((cur != root) && (ctxt->format == 1) &&
894
+ (xmlIndentTreeOutput))
895
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
896
+ (ctxt->level > ctxt->indent_nr ?
897
+ ctxt->indent_nr : ctxt->level),
898
+ ctxt->indent);
899
+
900
+ /*
901
+ * Some users like lxml are known to pass nodes with a corrupted
902
+ * tree structure. Fall back to a recursive call to handle this
903
+ * case.
904
+ */
905
+ if ((cur->parent != parent) && (cur->children != NULL)) {
906
+ xmlNodeDumpOutputInternal(ctxt, cur);
907
+ break;
908
+ }
909
+
910
+ xmlOutputBufferWrite(buf, 1, "<");
911
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
912
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
913
+ xmlOutputBufferWrite(buf, 1, ":");
914
+ }
915
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
916
+ if (cur->nsDef)
917
+ xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
918
+ for (attr = cur->properties; attr != NULL; attr = attr->next)
919
+ xmlAttrDumpOutput(ctxt, attr);
920
+
921
+ if (cur->children == NULL) {
922
+ if ((ctxt->options & XML_SAVE_NO_EMPTY) == 0) {
923
+ if (ctxt->format == 2)
924
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
925
+ xmlOutputBufferWrite(buf, 2, "/>");
926
+ } else {
927
+ if (ctxt->format == 2)
928
+ xmlOutputBufferWriteWSNonSig(ctxt, 1);
929
+ xmlOutputBufferWrite(buf, 3, "></");
930
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
931
+ xmlOutputBufferWriteString(buf,
932
+ (const char *)cur->ns->prefix);
933
+ xmlOutputBufferWrite(buf, 1, ":");
934
+ }
935
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
936
+ if (ctxt->format == 2)
937
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
938
+ xmlOutputBufferWrite(buf, 1, ">");
939
+ }
940
+ } else {
941
+ if (ctxt->format == 1) {
942
+ tmp = cur->children;
943
+ while (tmp != NULL) {
944
+ if ((tmp->type == XML_TEXT_NODE) ||
945
+ (tmp->type == XML_CDATA_SECTION_NODE) ||
946
+ (tmp->type == XML_ENTITY_REF_NODE)) {
947
+ ctxt->format = 0;
948
+ unformattedNode = cur;
949
+ break;
950
+ }
951
+ tmp = tmp->next;
952
+ }
953
+ }
954
+ if (ctxt->format == 2)
955
+ xmlOutputBufferWriteWSNonSig(ctxt, 1);
956
+ xmlOutputBufferWrite(buf, 1, ">");
957
+ if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
958
+ if (ctxt->level >= 0) ctxt->level++;
959
+ parent = cur;
960
+ cur = cur->children;
961
+ continue;
962
+ }
963
+
964
+ break;
965
+
966
+ case XML_TEXT_NODE:
967
+ if (cur->content == NULL)
968
+ break;
969
+ if (cur->name != xmlStringTextNoenc) {
970
+ xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
971
+ } else {
972
+ /*
973
+ * Disable escaping, needed for XSLT
974
+ */
975
+ xmlOutputBufferWriteString(buf, (const char *) cur->content);
976
+ }
977
+ break;
978
+
979
+ case XML_PI_NODE:
980
+ if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
981
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
982
+ (ctxt->level > ctxt->indent_nr ?
983
+ ctxt->indent_nr : ctxt->level),
984
+ ctxt->indent);
985
+
986
+ if (cur->content != NULL) {
987
+ xmlOutputBufferWrite(buf, 2, "<?");
988
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
989
+ if (cur->content != NULL) {
990
+ if (ctxt->format == 2)
991
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
992
+ else
993
+ xmlOutputBufferWrite(buf, 1, " ");
994
+ xmlOutputBufferWriteString(buf,
995
+ (const char *)cur->content);
996
+ }
997
+ xmlOutputBufferWrite(buf, 2, "?>");
998
+ } else {
999
+ xmlOutputBufferWrite(buf, 2, "<?");
1000
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
1001
+ if (ctxt->format == 2)
1002
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
1003
+ xmlOutputBufferWrite(buf, 2, "?>");
1004
+ }
1005
+ break;
1006
+
1007
+ case XML_COMMENT_NODE:
1008
+ if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
1009
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
1010
+ (ctxt->level > ctxt->indent_nr ?
1011
+ ctxt->indent_nr : ctxt->level),
1012
+ ctxt->indent);
1013
+
1014
+ if (cur->content != NULL) {
1015
+ xmlOutputBufferWrite(buf, 4, "<!--");
1016
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
1017
+ xmlOutputBufferWrite(buf, 3, "-->");
1018
+ }
1019
+ break;
1020
+
1021
+ case XML_ENTITY_REF_NODE:
1022
+ xmlOutputBufferWrite(buf, 1, "&");
1023
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
1024
+ xmlOutputBufferWrite(buf, 1, ";");
1025
+ break;
1026
+
1027
+ case XML_CDATA_SECTION_NODE:
1028
+ if (cur->content == NULL || *cur->content == '\0') {
1029
+ xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
1030
+ } else {
1031
+ start = end = cur->content;
1032
+ while (*end != '\0') {
1033
+ if ((*end == ']') && (*(end + 1) == ']') &&
1034
+ (*(end + 2) == '>')) {
1035
+ end = end + 2;
1036
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1037
+ xmlOutputBufferWrite(buf, end - start,
1038
+ (const char *)start);
1039
+ xmlOutputBufferWrite(buf, 3, "]]>");
1040
+ start = end;
1041
+ }
1042
+ end++;
1043
+ }
1044
+ if (start != end) {
1045
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1046
+ xmlOutputBufferWriteString(buf, (const char *)start);
1047
+ xmlOutputBufferWrite(buf, 3, "]]>");
1048
+ }
1049
+ }
1050
+ break;
1051
+
1052
+ case XML_ATTRIBUTE_NODE:
1053
+ xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
1054
+ break;
1055
+
1056
+ case XML_NAMESPACE_DECL:
1057
+ xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
1058
+ break;
1059
+
1060
+ default:
1061
+ break;
1062
+ }
1063
+
1064
+ while (1) {
1065
+ if (cur == root)
1066
+ return;
1067
+ if ((ctxt->format == 1) &&
1068
+ (cur->type != XML_XINCLUDE_START) &&
1069
+ (cur->type != XML_XINCLUDE_END))
1070
+ xmlOutputBufferWrite(buf, 1, "\n");
1071
+ if (cur->next != NULL) {
1072
+ cur = cur->next;
1073
+ break;
1074
+ }
1075
+
1076
+ cur = parent;
1077
+ /* cur->parent was validated when descending. */
1078
+ parent = cur->parent;
1079
+
1080
+ if (cur->type == XML_ELEMENT_NODE) {
1081
+ if (ctxt->level > 0) ctxt->level--;
1082
+ if ((xmlIndentTreeOutput) && (ctxt->format == 1))
1083
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
1084
+ (ctxt->level > ctxt->indent_nr ?
1085
+ ctxt->indent_nr : ctxt->level),
1086
+ ctxt->indent);
1087
+
1088
+ xmlOutputBufferWrite(buf, 2, "</");
1089
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1090
+ xmlOutputBufferWriteString(buf,
1091
+ (const char *)cur->ns->prefix);
1092
+ xmlOutputBufferWrite(buf, 1, ":");
1093
+ }
1094
+
1095
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
1096
+ if (ctxt->format == 2)
1097
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
1098
+ xmlOutputBufferWrite(buf, 1, ">");
1099
+
1100
+ if (cur == unformattedNode) {
1101
+ ctxt->format = format;
1102
+ unformattedNode = NULL;
1103
+ }
1104
+ }
1105
+ }
1106
+ }
1107
+ }
1108
+
1109
+ /**
1110
+ * xmlDocContentDumpOutput:
1111
+ * @cur: the document
1112
+ *
1113
+ * Dump an XML document.
1114
+ */
1115
+ static int
1116
+ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
1117
+ #ifdef LIBXML_HTML_ENABLED
1118
+ xmlDtdPtr dtd;
1119
+ int is_xhtml = 0;
1120
+ #endif
1121
+ const xmlChar *oldenc = cur->encoding;
1122
+ const xmlChar *oldctxtenc = ctxt->encoding;
1123
+ const xmlChar *encoding = ctxt->encoding;
1124
+ xmlCharEncodingOutputFunc oldescape = ctxt->escape;
1125
+ xmlCharEncodingOutputFunc oldescapeAttr = ctxt->escapeAttr;
1126
+ xmlOutputBufferPtr buf = ctxt->buf;
1127
+ xmlCharEncoding enc;
1128
+ int switched_encoding = 0;
1129
+
1130
+ xmlInitParser();
1131
+
1132
+ if ((cur->type != XML_HTML_DOCUMENT_NODE) &&
1133
+ (cur->type != XML_DOCUMENT_NODE))
1134
+ return(-1);
1135
+
1136
+ if (ctxt->encoding != NULL) {
1137
+ cur->encoding = BAD_CAST ctxt->encoding;
1138
+ } else if (cur->encoding != NULL) {
1139
+ encoding = cur->encoding;
1140
+ }
1141
+
1142
+ if (((cur->type == XML_HTML_DOCUMENT_NODE) &&
1143
+ ((ctxt->options & XML_SAVE_AS_XML) == 0) &&
1144
+ ((ctxt->options & XML_SAVE_XHTML) == 0)) ||
1145
+ (ctxt->options & XML_SAVE_AS_HTML)) {
1146
+ #ifdef LIBXML_HTML_ENABLED
1147
+ if (encoding != NULL)
1148
+ htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
1149
+ if (encoding == NULL)
1150
+ encoding = htmlGetMetaEncoding(cur);
1151
+ if (encoding == NULL)
1152
+ encoding = BAD_CAST "HTML";
1153
+ if ((encoding != NULL) && (oldctxtenc == NULL) &&
1154
+ (buf->encoder == NULL) && (buf->conv == NULL)) {
1155
+ if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
1156
+ cur->encoding = oldenc;
1157
+ return(-1);
1158
+ }
1159
+ }
1160
+ if (ctxt->options & XML_SAVE_FORMAT)
1161
+ htmlDocContentDumpFormatOutput(buf, cur,
1162
+ (const char *)encoding, 1);
1163
+ else
1164
+ htmlDocContentDumpFormatOutput(buf, cur,
1165
+ (const char *)encoding, 0);
1166
+ if (ctxt->encoding != NULL)
1167
+ cur->encoding = oldenc;
1168
+ return(0);
1169
+ #else
1170
+ return(-1);
1171
+ #endif
1172
+ } else if ((cur->type == XML_DOCUMENT_NODE) ||
1173
+ (ctxt->options & XML_SAVE_AS_XML) ||
1174
+ (ctxt->options & XML_SAVE_XHTML)) {
1175
+ enc = xmlParseCharEncoding((const char*) encoding);
1176
+ if ((encoding != NULL) && (oldctxtenc == NULL) &&
1177
+ (buf->encoder == NULL) && (buf->conv == NULL) &&
1178
+ ((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
1179
+ if ((enc != XML_CHAR_ENCODING_UTF8) &&
1180
+ (enc != XML_CHAR_ENCODING_NONE) &&
1181
+ (enc != XML_CHAR_ENCODING_ASCII)) {
1182
+ /*
1183
+ * we need to switch to this encoding but just for this
1184
+ * document since we output the XMLDecl the conversion
1185
+ * must be done to not generate not well formed documents.
1186
+ */
1187
+ if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
1188
+ cur->encoding = oldenc;
1189
+ return(-1);
1190
+ }
1191
+ switched_encoding = 1;
1192
+ }
1193
+ if (ctxt->escape == xmlEscapeEntities)
1194
+ ctxt->escape = NULL;
1195
+ if (ctxt->escapeAttr == xmlEscapeEntities)
1196
+ ctxt->escapeAttr = NULL;
1197
+ }
1198
+
1199
+
1200
+ /*
1201
+ * Save the XML declaration
1202
+ */
1203
+ if ((ctxt->options & XML_SAVE_NO_DECL) == 0) {
1204
+ xmlOutputBufferWrite(buf, 14, "<?xml version=");
1205
+ if (cur->version != NULL)
1206
+ xmlBufWriteQuotedString(buf->buffer, cur->version);
1207
+ else
1208
+ xmlOutputBufferWrite(buf, 5, "\"1.0\"");
1209
+ if (encoding != NULL) {
1210
+ xmlOutputBufferWrite(buf, 10, " encoding=");
1211
+ xmlBufWriteQuotedString(buf->buffer, (xmlChar *) encoding);
1212
+ }
1213
+ switch (cur->standalone) {
1214
+ case 0:
1215
+ xmlOutputBufferWrite(buf, 16, " standalone=\"no\"");
1216
+ break;
1217
+ case 1:
1218
+ xmlOutputBufferWrite(buf, 17, " standalone=\"yes\"");
1219
+ break;
1220
+ }
1221
+ xmlOutputBufferWrite(buf, 3, "?>\n");
1222
+ }
1223
+
1224
+ #ifdef LIBXML_HTML_ENABLED
1225
+ if (ctxt->options & XML_SAVE_XHTML)
1226
+ is_xhtml = 1;
1227
+ if ((ctxt->options & XML_SAVE_NO_XHTML) == 0) {
1228
+ dtd = xmlGetIntSubset(cur);
1229
+ if (dtd != NULL) {
1230
+ is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
1231
+ if (is_xhtml < 0) is_xhtml = 0;
1232
+ }
1233
+ }
1234
+ #endif
1235
+ if (cur->children != NULL) {
1236
+ xmlNodePtr child = cur->children;
1237
+
1238
+ while (child != NULL) {
1239
+ ctxt->level = 0;
1240
+ #ifdef LIBXML_HTML_ENABLED
1241
+ if (is_xhtml)
1242
+ xhtmlNodeDumpOutput(ctxt, child);
1243
+ else
1244
+ #endif
1245
+ xmlNodeDumpOutputInternal(ctxt, child);
1246
+ if ((child->type != XML_XINCLUDE_START) &&
1247
+ (child->type != XML_XINCLUDE_END))
1248
+ xmlOutputBufferWrite(buf, 1, "\n");
1249
+ child = child->next;
1250
+ }
1251
+ }
1252
+ }
1253
+
1254
+ /*
1255
+ * Restore the state of the saving context at the end of the document
1256
+ */
1257
+ if ((switched_encoding) && (oldctxtenc == NULL)) {
1258
+ xmlSaveClearEncoding(ctxt);
1259
+ ctxt->escape = oldescape;
1260
+ ctxt->escapeAttr = oldescapeAttr;
1261
+ }
1262
+ cur->encoding = oldenc;
1263
+ return(0);
1264
+ }
1265
+
1266
+ #ifdef LIBXML_HTML_ENABLED
1267
+ /************************************************************************
1268
+ * *
1269
+ * Functions specific to XHTML serialization *
1270
+ * *
1271
+ ************************************************************************/
1272
+
1273
+ /**
1274
+ * xhtmlIsEmpty:
1275
+ * @node: the node
1276
+ *
1277
+ * Check if a node is an empty xhtml node
1278
+ *
1279
+ * Returns 1 if the node is an empty node, 0 if not and -1 in case of error
1280
+ */
1281
+ static int
1282
+ xhtmlIsEmpty(xmlNodePtr node) {
1283
+ if (node == NULL)
1284
+ return(-1);
1285
+ if (node->type != XML_ELEMENT_NODE)
1286
+ return(0);
1287
+ if ((node->ns != NULL) && (!xmlStrEqual(node->ns->href, XHTML_NS_NAME)))
1288
+ return(0);
1289
+ if (node->children != NULL)
1290
+ return(0);
1291
+ switch (node->name[0]) {
1292
+ case 'a':
1293
+ if (xmlStrEqual(node->name, BAD_CAST "area"))
1294
+ return(1);
1295
+ return(0);
1296
+ case 'b':
1297
+ if (xmlStrEqual(node->name, BAD_CAST "br"))
1298
+ return(1);
1299
+ if (xmlStrEqual(node->name, BAD_CAST "base"))
1300
+ return(1);
1301
+ if (xmlStrEqual(node->name, BAD_CAST "basefont"))
1302
+ return(1);
1303
+ return(0);
1304
+ case 'c':
1305
+ if (xmlStrEqual(node->name, BAD_CAST "col"))
1306
+ return(1);
1307
+ return(0);
1308
+ case 'f':
1309
+ if (xmlStrEqual(node->name, BAD_CAST "frame"))
1310
+ return(1);
1311
+ return(0);
1312
+ case 'h':
1313
+ if (xmlStrEqual(node->name, BAD_CAST "hr"))
1314
+ return(1);
1315
+ return(0);
1316
+ case 'i':
1317
+ if (xmlStrEqual(node->name, BAD_CAST "img"))
1318
+ return(1);
1319
+ if (xmlStrEqual(node->name, BAD_CAST "input"))
1320
+ return(1);
1321
+ if (xmlStrEqual(node->name, BAD_CAST "isindex"))
1322
+ return(1);
1323
+ return(0);
1324
+ case 'l':
1325
+ if (xmlStrEqual(node->name, BAD_CAST "link"))
1326
+ return(1);
1327
+ return(0);
1328
+ case 'm':
1329
+ if (xmlStrEqual(node->name, BAD_CAST "meta"))
1330
+ return(1);
1331
+ return(0);
1332
+ case 'p':
1333
+ if (xmlStrEqual(node->name, BAD_CAST "param"))
1334
+ return(1);
1335
+ return(0);
1336
+ }
1337
+ return(0);
1338
+ }
1339
+
1340
+ /**
1341
+ * xhtmlAttrListDumpOutput:
1342
+ * @cur: the first attribute pointer
1343
+ *
1344
+ * Dump a list of XML attributes
1345
+ */
1346
+ static void
1347
+ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
1348
+ xmlAttrPtr xml_lang = NULL;
1349
+ xmlAttrPtr lang = NULL;
1350
+ xmlAttrPtr name = NULL;
1351
+ xmlAttrPtr id = NULL;
1352
+ xmlNodePtr parent;
1353
+ xmlOutputBufferPtr buf;
1354
+
1355
+ if (cur == NULL) return;
1356
+ buf = ctxt->buf;
1357
+ parent = cur->parent;
1358
+ while (cur != NULL) {
1359
+ if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "id")))
1360
+ id = cur;
1361
+ else
1362
+ if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "name")))
1363
+ name = cur;
1364
+ else
1365
+ if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")))
1366
+ lang = cur;
1367
+ else
1368
+ if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) &&
1369
+ (xmlStrEqual(cur->ns->prefix, BAD_CAST "xml")))
1370
+ xml_lang = cur;
1371
+ else if ((cur->ns == NULL) &&
1372
+ ((cur->children == NULL) ||
1373
+ (cur->children->content == NULL) ||
1374
+ (cur->children->content[0] == 0)) &&
1375
+ (htmlIsBooleanAttr(cur->name))) {
1376
+ if (cur->children != NULL)
1377
+ xmlFreeNode(cur->children);
1378
+ cur->children = xmlNewText(cur->name);
1379
+ if (cur->children != NULL)
1380
+ cur->children->parent = (xmlNodePtr) cur;
1381
+ }
1382
+ xmlAttrDumpOutput(ctxt, cur);
1383
+ cur = cur->next;
1384
+ }
1385
+ /*
1386
+ * C.8
1387
+ */
1388
+ if ((name != NULL) && (id == NULL)) {
1389
+ if ((parent != NULL) && (parent->name != NULL) &&
1390
+ ((xmlStrEqual(parent->name, BAD_CAST "a")) ||
1391
+ (xmlStrEqual(parent->name, BAD_CAST "p")) ||
1392
+ (xmlStrEqual(parent->name, BAD_CAST "div")) ||
1393
+ (xmlStrEqual(parent->name, BAD_CAST "img")) ||
1394
+ (xmlStrEqual(parent->name, BAD_CAST "map")) ||
1395
+ (xmlStrEqual(parent->name, BAD_CAST "applet")) ||
1396
+ (xmlStrEqual(parent->name, BAD_CAST "form")) ||
1397
+ (xmlStrEqual(parent->name, BAD_CAST "frame")) ||
1398
+ (xmlStrEqual(parent->name, BAD_CAST "iframe")))) {
1399
+ xmlOutputBufferWrite(buf, 5, " id=\"");
1400
+ xmlAttrSerializeContent(buf, name);
1401
+ xmlOutputBufferWrite(buf, 1, "\"");
1402
+ }
1403
+ }
1404
+ /*
1405
+ * C.7.
1406
+ */
1407
+ if ((lang != NULL) && (xml_lang == NULL)) {
1408
+ xmlOutputBufferWrite(buf, 11, " xml:lang=\"");
1409
+ xmlAttrSerializeContent(buf, lang);
1410
+ xmlOutputBufferWrite(buf, 1, "\"");
1411
+ } else
1412
+ if ((xml_lang != NULL) && (lang == NULL)) {
1413
+ xmlOutputBufferWrite(buf, 7, " lang=\"");
1414
+ xmlAttrSerializeContent(buf, xml_lang);
1415
+ xmlOutputBufferWrite(buf, 1, "\"");
1416
+ }
1417
+ }
1418
+
1419
+ /**
1420
+ * xhtmlNodeDumpOutput:
1421
+ * @buf: the XML buffer output
1422
+ * @doc: the XHTML document
1423
+ * @cur: the current node
1424
+ * @level: the imbrication level for indenting
1425
+ * @format: is formatting allowed
1426
+ * @encoding: an optional encoding string
1427
+ *
1428
+ * Dump an XHTML node, recursive behaviour, children are printed too.
1429
+ */
1430
+ static void
1431
+ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
1432
+ int format = ctxt->format, addmeta;
1433
+ xmlNodePtr tmp, root, unformattedNode = NULL;
1434
+ xmlChar *start, *end;
1435
+ xmlOutputBufferPtr buf = ctxt->buf;
1436
+
1437
+ if (cur == NULL) return;
1438
+
1439
+ root = cur;
1440
+ while (1) {
1441
+ switch (cur->type) {
1442
+ case XML_DOCUMENT_NODE:
1443
+ case XML_HTML_DOCUMENT_NODE:
1444
+ xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
1445
+ break;
1446
+
1447
+ case XML_NAMESPACE_DECL:
1448
+ xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
1449
+ break;
1450
+
1451
+ case XML_DTD_NODE:
1452
+ xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
1453
+ break;
1454
+
1455
+ case XML_DOCUMENT_FRAG_NODE:
1456
+ if (cur->children) {
1457
+ cur = cur->children;
1458
+ continue;
1459
+ }
1460
+ break;
1461
+
1462
+ case XML_ELEMENT_DECL:
1463
+ xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
1464
+ break;
1465
+
1466
+ case XML_ATTRIBUTE_DECL:
1467
+ xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
1468
+ break;
1469
+
1470
+ case XML_ENTITY_DECL:
1471
+ xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
1472
+ break;
1473
+
1474
+ case XML_ELEMENT_NODE:
1475
+ addmeta = 0;
1476
+
1477
+ if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
1478
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
1479
+ (ctxt->level > ctxt->indent_nr ?
1480
+ ctxt->indent_nr : ctxt->level),
1481
+ ctxt->indent);
1482
+
1483
+ xmlOutputBufferWrite(buf, 1, "<");
1484
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1485
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
1486
+ xmlOutputBufferWrite(buf, 1, ":");
1487
+ }
1488
+
1489
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
1490
+ if (cur->nsDef)
1491
+ xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
1492
+ if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
1493
+ (cur->ns == NULL) && (cur->nsDef == NULL))) {
1494
+ /*
1495
+ * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
1496
+ */
1497
+ xmlOutputBufferWriteString(buf,
1498
+ " xmlns=\"http://www.w3.org/1999/xhtml\"");
1499
+ }
1500
+ if (cur->properties != NULL)
1501
+ xhtmlAttrListDumpOutput(ctxt, cur->properties);
1502
+
1503
+ if ((cur->parent != NULL) &&
1504
+ (cur->parent->parent == (xmlNodePtr) cur->doc) &&
1505
+ xmlStrEqual(cur->name, BAD_CAST"head") &&
1506
+ xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
1507
+
1508
+ tmp = cur->children;
1509
+ while (tmp != NULL) {
1510
+ if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
1511
+ xmlChar *httpequiv;
1512
+
1513
+ httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
1514
+ if (httpequiv != NULL) {
1515
+ if (xmlStrcasecmp(httpequiv,
1516
+ BAD_CAST"Content-Type") == 0) {
1517
+ xmlFree(httpequiv);
1518
+ break;
1519
+ }
1520
+ xmlFree(httpequiv);
1521
+ }
1522
+ }
1523
+ tmp = tmp->next;
1524
+ }
1525
+ if (tmp == NULL)
1526
+ addmeta = 1;
1527
+ }
1528
+
1529
+ if (cur->children == NULL) {
1530
+ if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
1531
+ ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) {
1532
+ /*
1533
+ * C.2. Empty Elements
1534
+ */
1535
+ xmlOutputBufferWrite(buf, 3, " />");
1536
+ } else {
1537
+ if (addmeta == 1) {
1538
+ xmlOutputBufferWrite(buf, 1, ">");
1539
+ if (ctxt->format == 1) {
1540
+ xmlOutputBufferWrite(buf, 1, "\n");
1541
+ if (xmlIndentTreeOutput)
1542
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
1543
+ (ctxt->level + 1 > ctxt->indent_nr ?
1544
+ ctxt->indent_nr : ctxt->level + 1),
1545
+ ctxt->indent);
1546
+ }
1547
+ xmlOutputBufferWriteString(buf,
1548
+ "<meta http-equiv=\"Content-Type\" "
1549
+ "content=\"text/html; charset=");
1550
+ if (ctxt->encoding) {
1551
+ xmlOutputBufferWriteString(buf,
1552
+ (const char *)ctxt->encoding);
1553
+ } else {
1554
+ xmlOutputBufferWrite(buf, 5, "UTF-8");
1555
+ }
1556
+ xmlOutputBufferWrite(buf, 4, "\" />");
1557
+ if (ctxt->format == 1)
1558
+ xmlOutputBufferWrite(buf, 1, "\n");
1559
+ } else {
1560
+ xmlOutputBufferWrite(buf, 1, ">");
1561
+ }
1562
+ /*
1563
+ * C.3. Element Minimization and Empty Element Content
1564
+ */
1565
+ xmlOutputBufferWrite(buf, 2, "</");
1566
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1567
+ xmlOutputBufferWriteString(buf,
1568
+ (const char *)cur->ns->prefix);
1569
+ xmlOutputBufferWrite(buf, 1, ":");
1570
+ }
1571
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
1572
+ xmlOutputBufferWrite(buf, 1, ">");
1573
+ }
1574
+ } else {
1575
+ xmlOutputBufferWrite(buf, 1, ">");
1576
+ if (addmeta == 1) {
1577
+ if (ctxt->format == 1) {
1578
+ xmlOutputBufferWrite(buf, 1, "\n");
1579
+ if (xmlIndentTreeOutput)
1580
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
1581
+ (ctxt->level + 1 > ctxt->indent_nr ?
1582
+ ctxt->indent_nr : ctxt->level + 1),
1583
+ ctxt->indent);
1584
+ }
1585
+ xmlOutputBufferWriteString(buf,
1586
+ "<meta http-equiv=\"Content-Type\" "
1587
+ "content=\"text/html; charset=");
1588
+ if (ctxt->encoding) {
1589
+ xmlOutputBufferWriteString(buf,
1590
+ (const char *)ctxt->encoding);
1591
+ } else {
1592
+ xmlOutputBufferWrite(buf, 5, "UTF-8");
1593
+ }
1594
+ xmlOutputBufferWrite(buf, 4, "\" />");
1595
+ }
1596
+
1597
+ if (ctxt->format == 1) {
1598
+ tmp = cur->children;
1599
+ while (tmp != NULL) {
1600
+ if ((tmp->type == XML_TEXT_NODE) ||
1601
+ (tmp->type == XML_ENTITY_REF_NODE)) {
1602
+ unformattedNode = cur;
1603
+ ctxt->format = 0;
1604
+ break;
1605
+ }
1606
+ tmp = tmp->next;
1607
+ }
1608
+ }
1609
+
1610
+ if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
1611
+ if (ctxt->level >= 0) ctxt->level++;
1612
+ cur = cur->children;
1613
+ continue;
1614
+ }
1615
+
1616
+ break;
1617
+
1618
+ case XML_TEXT_NODE:
1619
+ if (cur->content == NULL)
1620
+ break;
1621
+ if ((cur->name == xmlStringText) ||
1622
+ (cur->name != xmlStringTextNoenc)) {
1623
+ xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
1624
+ } else {
1625
+ /*
1626
+ * Disable escaping, needed for XSLT
1627
+ */
1628
+ xmlOutputBufferWriteString(buf, (const char *) cur->content);
1629
+ }
1630
+ break;
1631
+
1632
+ case XML_PI_NODE:
1633
+ if (cur->content != NULL) {
1634
+ xmlOutputBufferWrite(buf, 2, "<?");
1635
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
1636
+ if (cur->content != NULL) {
1637
+ xmlOutputBufferWrite(buf, 1, " ");
1638
+ xmlOutputBufferWriteString(buf,
1639
+ (const char *)cur->content);
1640
+ }
1641
+ xmlOutputBufferWrite(buf, 2, "?>");
1642
+ } else {
1643
+ xmlOutputBufferWrite(buf, 2, "<?");
1644
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
1645
+ xmlOutputBufferWrite(buf, 2, "?>");
1646
+ }
1647
+ break;
1648
+
1649
+ case XML_COMMENT_NODE:
1650
+ if (cur->content != NULL) {
1651
+ xmlOutputBufferWrite(buf, 4, "<!--");
1652
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
1653
+ xmlOutputBufferWrite(buf, 3, "-->");
1654
+ }
1655
+ break;
1656
+
1657
+ case XML_ENTITY_REF_NODE:
1658
+ xmlOutputBufferWrite(buf, 1, "&");
1659
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
1660
+ xmlOutputBufferWrite(buf, 1, ";");
1661
+ break;
1662
+
1663
+ case XML_CDATA_SECTION_NODE:
1664
+ if (cur->content == NULL || *cur->content == '\0') {
1665
+ xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
1666
+ } else {
1667
+ start = end = cur->content;
1668
+ while (*end != '\0') {
1669
+ if (*end == ']' && *(end + 1) == ']' &&
1670
+ *(end + 2) == '>') {
1671
+ end = end + 2;
1672
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1673
+ xmlOutputBufferWrite(buf, end - start,
1674
+ (const char *)start);
1675
+ xmlOutputBufferWrite(buf, 3, "]]>");
1676
+ start = end;
1677
+ }
1678
+ end++;
1679
+ }
1680
+ if (start != end) {
1681
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1682
+ xmlOutputBufferWriteString(buf, (const char *)start);
1683
+ xmlOutputBufferWrite(buf, 3, "]]>");
1684
+ }
1685
+ }
1686
+ break;
1687
+
1688
+ case XML_ATTRIBUTE_NODE:
1689
+ xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
1690
+ break;
1691
+
1692
+ default:
1693
+ break;
1694
+ }
1695
+
1696
+ while (1) {
1697
+ if (cur == root)
1698
+ return;
1699
+ if (ctxt->format == 1)
1700
+ xmlOutputBufferWrite(buf, 1, "\n");
1701
+ if (cur->next != NULL) {
1702
+ cur = cur->next;
1703
+ break;
1704
+ }
1705
+
1706
+ /*
1707
+ * The parent should never be NULL here but we want to handle
1708
+ * corrupted documents gracefully.
1709
+ */
1710
+ if (cur->parent == NULL)
1711
+ return;
1712
+ cur = cur->parent;
1713
+
1714
+ if (cur->type == XML_ELEMENT_NODE) {
1715
+ if (ctxt->level > 0) ctxt->level--;
1716
+ if ((xmlIndentTreeOutput) && (ctxt->format == 1))
1717
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
1718
+ (ctxt->level > ctxt->indent_nr ?
1719
+ ctxt->indent_nr : ctxt->level),
1720
+ ctxt->indent);
1721
+
1722
+ xmlOutputBufferWrite(buf, 2, "</");
1723
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1724
+ xmlOutputBufferWriteString(buf,
1725
+ (const char *)cur->ns->prefix);
1726
+ xmlOutputBufferWrite(buf, 1, ":");
1727
+ }
1728
+
1729
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
1730
+ xmlOutputBufferWrite(buf, 1, ">");
1731
+
1732
+ if (cur == unformattedNode) {
1733
+ ctxt->format = format;
1734
+ unformattedNode = NULL;
1735
+ }
1736
+ }
1737
+ }
1738
+ }
1739
+ }
1740
+ #endif
1741
+
1742
+ /************************************************************************
1743
+ * *
1744
+ * Public entry points *
1745
+ * *
1746
+ ************************************************************************/
1747
+
1748
+ /**
1749
+ * xmlSaveToFd:
1750
+ * @fd: a file descriptor number
1751
+ * @encoding: the encoding name to use or NULL
1752
+ * @options: a set of xmlSaveOptions
1753
+ *
1754
+ * Create a document saving context serializing to a file descriptor
1755
+ * with the encoding and the options given.
1756
+ *
1757
+ * Returns a new serialization context or NULL in case of error.
1758
+ */
1759
+ xmlSaveCtxtPtr
1760
+ xmlSaveToFd(int fd, const char *encoding, int options)
1761
+ {
1762
+ xmlSaveCtxtPtr ret;
1763
+
1764
+ ret = xmlNewSaveCtxt(encoding, options);
1765
+ if (ret == NULL) return(NULL);
1766
+ ret->buf = xmlOutputBufferCreateFd(fd, ret->handler);
1767
+ if (ret->buf == NULL) {
1768
+ xmlCharEncCloseFunc(ret->handler);
1769
+ xmlFreeSaveCtxt(ret);
1770
+ return(NULL);
1771
+ }
1772
+ return(ret);
1773
+ }
1774
+
1775
+ /**
1776
+ * xmlSaveToFilename:
1777
+ * @filename: a file name or an URL
1778
+ * @encoding: the encoding name to use or NULL
1779
+ * @options: a set of xmlSaveOptions
1780
+ *
1781
+ * Create a document saving context serializing to a filename or possibly
1782
+ * to an URL (but this is less reliable) with the encoding and the options
1783
+ * given.
1784
+ *
1785
+ * Returns a new serialization context or NULL in case of error.
1786
+ */
1787
+ xmlSaveCtxtPtr
1788
+ xmlSaveToFilename(const char *filename, const char *encoding, int options)
1789
+ {
1790
+ xmlSaveCtxtPtr ret;
1791
+ int compression = 0; /* TODO handle compression option */
1792
+
1793
+ ret = xmlNewSaveCtxt(encoding, options);
1794
+ if (ret == NULL) return(NULL);
1795
+ ret->buf = xmlOutputBufferCreateFilename(filename, ret->handler,
1796
+ compression);
1797
+ if (ret->buf == NULL) {
1798
+ xmlCharEncCloseFunc(ret->handler);
1799
+ xmlFreeSaveCtxt(ret);
1800
+ return(NULL);
1801
+ }
1802
+ return(ret);
1803
+ }
1804
+
1805
+ /**
1806
+ * xmlSaveToBuffer:
1807
+ * @buffer: a buffer
1808
+ * @encoding: the encoding name to use or NULL
1809
+ * @options: a set of xmlSaveOptions
1810
+ *
1811
+ * Create a document saving context serializing to a buffer
1812
+ * with the encoding and the options given
1813
+ *
1814
+ * Returns a new serialization context or NULL in case of error.
1815
+ */
1816
+
1817
+ xmlSaveCtxtPtr
1818
+ xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options)
1819
+ {
1820
+ xmlSaveCtxtPtr ret;
1821
+
1822
+ ret = xmlNewSaveCtxt(encoding, options);
1823
+ if (ret == NULL) return(NULL);
1824
+ ret->buf = xmlOutputBufferCreateBuffer(buffer, ret->handler);
1825
+ if (ret->buf == NULL) {
1826
+ xmlCharEncCloseFunc(ret->handler);
1827
+ xmlFreeSaveCtxt(ret);
1828
+ return(NULL);
1829
+ }
1830
+ return(ret);
1831
+ }
1832
+
1833
+ /**
1834
+ * xmlSaveToIO:
1835
+ * @iowrite: an I/O write function
1836
+ * @ioclose: an I/O close function
1837
+ * @ioctx: an I/O handler
1838
+ * @encoding: the encoding name to use or NULL
1839
+ * @options: a set of xmlSaveOptions
1840
+ *
1841
+ * Create a document saving context serializing to a file descriptor
1842
+ * with the encoding and the options given
1843
+ *
1844
+ * Returns a new serialization context or NULL in case of error.
1845
+ */
1846
+ xmlSaveCtxtPtr
1847
+ xmlSaveToIO(xmlOutputWriteCallback iowrite,
1848
+ xmlOutputCloseCallback ioclose,
1849
+ void *ioctx, const char *encoding, int options)
1850
+ {
1851
+ xmlSaveCtxtPtr ret;
1852
+
1853
+ ret = xmlNewSaveCtxt(encoding, options);
1854
+ if (ret == NULL) return(NULL);
1855
+ ret->buf = xmlOutputBufferCreateIO(iowrite, ioclose, ioctx, ret->handler);
1856
+ if (ret->buf == NULL) {
1857
+ xmlCharEncCloseFunc(ret->handler);
1858
+ xmlFreeSaveCtxt(ret);
1859
+ return(NULL);
1860
+ }
1861
+ return(ret);
1862
+ }
1863
+
1864
+ /**
1865
+ * xmlSaveDoc:
1866
+ * @ctxt: a document saving context
1867
+ * @doc: a document
1868
+ *
1869
+ * Save a full document to a saving context
1870
+ * TODO: The function is not fully implemented yet as it does not return the
1871
+ * byte count but 0 instead
1872
+ *
1873
+ * Returns the number of byte written or -1 in case of error
1874
+ */
1875
+ long
1876
+ xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc)
1877
+ {
1878
+ long ret = 0;
1879
+
1880
+ if ((ctxt == NULL) || (doc == NULL)) return(-1);
1881
+ if (xmlDocContentDumpOutput(ctxt, doc) < 0)
1882
+ return(-1);
1883
+ return(ret);
1884
+ }
1885
+
1886
+ /**
1887
+ * xmlSaveTree:
1888
+ * @ctxt: a document saving context
1889
+ * @node: the top node of the subtree to save
1890
+ *
1891
+ * Save a subtree starting at the node parameter to a saving context
1892
+ * TODO: The function is not fully implemented yet as it does not return the
1893
+ * byte count but 0 instead
1894
+ *
1895
+ * Returns the number of byte written or -1 in case of error
1896
+ */
1897
+ long
1898
+ xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr cur)
1899
+ {
1900
+ long ret = 0;
1901
+
1902
+ if ((ctxt == NULL) || (cur == NULL)) return(-1);
1903
+ #ifdef LIBXML_HTML_ENABLED
1904
+ if (ctxt->options & XML_SAVE_XHTML) {
1905
+ xhtmlNodeDumpOutput(ctxt, cur);
1906
+ return(ret);
1907
+ }
1908
+ if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
1909
+ (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
1910
+ ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
1911
+ (ctxt->options & XML_SAVE_AS_HTML)) {
1912
+ htmlNodeDumpOutputInternal(ctxt, cur);
1913
+ return(ret);
1914
+ }
1915
+ #endif
1916
+ xmlNodeDumpOutputInternal(ctxt, cur);
1917
+ return(ret);
1918
+ }
1919
+
1920
+ /**
1921
+ * xmlSaveFlush:
1922
+ * @ctxt: a document saving context
1923
+ *
1924
+ * Flush a document saving context, i.e. make sure that all bytes have
1925
+ * been output.
1926
+ *
1927
+ * Returns the number of byte written or -1 in case of error.
1928
+ */
1929
+ int
1930
+ xmlSaveFlush(xmlSaveCtxtPtr ctxt)
1931
+ {
1932
+ if (ctxt == NULL) return(-1);
1933
+ if (ctxt->buf == NULL) return(-1);
1934
+ return(xmlOutputBufferFlush(ctxt->buf));
1935
+ }
1936
+
1937
+ /**
1938
+ * xmlSaveClose:
1939
+ * @ctxt: a document saving context
1940
+ *
1941
+ * Close a document saving context, i.e. make sure that all bytes have
1942
+ * been output and free the associated data.
1943
+ *
1944
+ * Returns the number of byte written or -1 in case of error.
1945
+ */
1946
+ int
1947
+ xmlSaveClose(xmlSaveCtxtPtr ctxt)
1948
+ {
1949
+ int ret;
1950
+
1951
+ if (ctxt == NULL) return(-1);
1952
+ ret = xmlSaveFlush(ctxt);
1953
+ xmlFreeSaveCtxt(ctxt);
1954
+ return(ret);
1955
+ }
1956
+
1957
+ /**
1958
+ * xmlSaveSetEscape:
1959
+ * @ctxt: a document saving context
1960
+ * @escape: the escaping function
1961
+ *
1962
+ * Set a custom escaping function to be used for text in element content
1963
+ *
1964
+ * Returns 0 if successful or -1 in case of error.
1965
+ */
1966
+ int
1967
+ xmlSaveSetEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
1968
+ {
1969
+ if (ctxt == NULL) return(-1);
1970
+ ctxt->escape = escape;
1971
+ return(0);
1972
+ }
1973
+
1974
+ /**
1975
+ * xmlSaveSetAttrEscape:
1976
+ * @ctxt: a document saving context
1977
+ * @escape: the escaping function
1978
+ *
1979
+ * Set a custom escaping function to be used for text in attribute content
1980
+ *
1981
+ * Returns 0 if successful or -1 in case of error.
1982
+ */
1983
+ int
1984
+ xmlSaveSetAttrEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
1985
+ {
1986
+ if (ctxt == NULL) return(-1);
1987
+ ctxt->escapeAttr = escape;
1988
+ return(0);
1989
+ }
1990
+
1991
+ /************************************************************************
1992
+ * *
1993
+ * Public entry points based on buffers *
1994
+ * *
1995
+ ************************************************************************/
1996
+
1997
+ /**
1998
+ * xmlBufAttrSerializeTxtContent:
1999
+ * @buf: and xmlBufPtr output
2000
+ * @doc: the document
2001
+ * @attr: the attribute node
2002
+ * @string: the text content
2003
+ *
2004
+ * Serialize text attribute values to an xmlBufPtr
2005
+ */
2006
+ void
2007
+ xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc,
2008
+ xmlAttrPtr attr, const xmlChar * string)
2009
+ {
2010
+ xmlChar *base, *cur;
2011
+
2012
+ if (string == NULL)
2013
+ return;
2014
+ base = cur = (xmlChar *) string;
2015
+ while (*cur != 0) {
2016
+ if (*cur == '\n') {
2017
+ if (base != cur)
2018
+ xmlBufAdd(buf, base, cur - base);
2019
+ xmlBufAdd(buf, BAD_CAST "&#10;", 5);
2020
+ cur++;
2021
+ base = cur;
2022
+ } else if (*cur == '\r') {
2023
+ if (base != cur)
2024
+ xmlBufAdd(buf, base, cur - base);
2025
+ xmlBufAdd(buf, BAD_CAST "&#13;", 5);
2026
+ cur++;
2027
+ base = cur;
2028
+ } else if (*cur == '\t') {
2029
+ if (base != cur)
2030
+ xmlBufAdd(buf, base, cur - base);
2031
+ xmlBufAdd(buf, BAD_CAST "&#9;", 4);
2032
+ cur++;
2033
+ base = cur;
2034
+ } else if (*cur == '"') {
2035
+ if (base != cur)
2036
+ xmlBufAdd(buf, base, cur - base);
2037
+ xmlBufAdd(buf, BAD_CAST "&quot;", 6);
2038
+ cur++;
2039
+ base = cur;
2040
+ } else if (*cur == '<') {
2041
+ if (base != cur)
2042
+ xmlBufAdd(buf, base, cur - base);
2043
+ xmlBufAdd(buf, BAD_CAST "&lt;", 4);
2044
+ cur++;
2045
+ base = cur;
2046
+ } else if (*cur == '>') {
2047
+ if (base != cur)
2048
+ xmlBufAdd(buf, base, cur - base);
2049
+ xmlBufAdd(buf, BAD_CAST "&gt;", 4);
2050
+ cur++;
2051
+ base = cur;
2052
+ } else if (*cur == '&') {
2053
+ if (base != cur)
2054
+ xmlBufAdd(buf, base, cur - base);
2055
+ xmlBufAdd(buf, BAD_CAST "&amp;", 5);
2056
+ cur++;
2057
+ base = cur;
2058
+ } else if ((*cur >= 0x80) && (cur[1] != 0) &&
2059
+ ((doc == NULL) || (doc->encoding == NULL))) {
2060
+ /*
2061
+ * We assume we have UTF-8 content.
2062
+ */
2063
+ unsigned char tmp[12];
2064
+ int val = 0, l = 1;
2065
+
2066
+ if (base != cur)
2067
+ xmlBufAdd(buf, base, cur - base);
2068
+ if (*cur < 0xC0) {
2069
+ xmlSaveErr(XML_SAVE_NOT_UTF8, (xmlNodePtr) attr, NULL);
2070
+ xmlSerializeHexCharRef(tmp, *cur);
2071
+ xmlBufAdd(buf, (xmlChar *) tmp, -1);
2072
+ cur++;
2073
+ base = cur;
2074
+ continue;
2075
+ } else if (*cur < 0xE0) {
2076
+ val = (cur[0]) & 0x1F;
2077
+ val <<= 6;
2078
+ val |= (cur[1]) & 0x3F;
2079
+ l = 2;
2080
+ } else if ((*cur < 0xF0) && (cur [2] != 0)) {
2081
+ val = (cur[0]) & 0x0F;
2082
+ val <<= 6;
2083
+ val |= (cur[1]) & 0x3F;
2084
+ val <<= 6;
2085
+ val |= (cur[2]) & 0x3F;
2086
+ l = 3;
2087
+ } else if ((*cur < 0xF8) && (cur [2] != 0) && (cur[3] != 0)) {
2088
+ val = (cur[0]) & 0x07;
2089
+ val <<= 6;
2090
+ val |= (cur[1]) & 0x3F;
2091
+ val <<= 6;
2092
+ val |= (cur[2]) & 0x3F;
2093
+ val <<= 6;
2094
+ val |= (cur[3]) & 0x3F;
2095
+ l = 4;
2096
+ }
2097
+ if ((l == 1) || (!IS_CHAR(val))) {
2098
+ xmlSaveErr(XML_SAVE_CHAR_INVALID, (xmlNodePtr) attr, NULL);
2099
+ xmlSerializeHexCharRef(tmp, *cur);
2100
+ xmlBufAdd(buf, (xmlChar *) tmp, -1);
2101
+ cur++;
2102
+ base = cur;
2103
+ continue;
2104
+ }
2105
+ /*
2106
+ * We could do multiple things here. Just save
2107
+ * as a char ref
2108
+ */
2109
+ xmlSerializeHexCharRef(tmp, val);
2110
+ xmlBufAdd(buf, (xmlChar *) tmp, -1);
2111
+ cur += l;
2112
+ base = cur;
2113
+ } else {
2114
+ cur++;
2115
+ }
2116
+ }
2117
+ if (base != cur)
2118
+ xmlBufAdd(buf, base, cur - base);
2119
+ }
2120
+
2121
+ /**
2122
+ * xmlAttrSerializeTxtContent:
2123
+ * @buf: the XML buffer output
2124
+ * @doc: the document
2125
+ * @attr: the attribute node
2126
+ * @string: the text content
2127
+ *
2128
+ * Serialize text attribute values to an xml simple buffer
2129
+ */
2130
+ void
2131
+ xmlAttrSerializeTxtContent(xmlBufferPtr buf, xmlDocPtr doc,
2132
+ xmlAttrPtr attr, const xmlChar * string)
2133
+ {
2134
+ xmlBufPtr buffer;
2135
+
2136
+ if ((buf == NULL) || (string == NULL))
2137
+ return;
2138
+ buffer = xmlBufFromBuffer(buf);
2139
+ if (buffer == NULL)
2140
+ return;
2141
+ xmlBufAttrSerializeTxtContent(buffer, doc, attr, string);
2142
+ xmlBufBackToBuffer(buffer);
2143
+ }
2144
+
2145
+ /**
2146
+ * xmlNodeDump:
2147
+ * @buf: the XML buffer output
2148
+ * @doc: the document
2149
+ * @cur: the current node
2150
+ * @level: the imbrication level for indenting
2151
+ * @format: is formatting allowed
2152
+ *
2153
+ * Dump an XML node, recursive behaviour,children are printed too.
2154
+ * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2155
+ * or xmlKeepBlanksDefault(0) was called.
2156
+ * Since this is using xmlBuffer structures it is limited to 2GB and somehow
2157
+ * deprecated, use xmlNodeDumpOutput() instead.
2158
+ *
2159
+ * Returns the number of bytes written to the buffer or -1 in case of error
2160
+ */
2161
+ int
2162
+ xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2163
+ int format)
2164
+ {
2165
+ xmlBufPtr buffer;
2166
+ size_t ret;
2167
+
2168
+ if ((buf == NULL) || (cur == NULL))
2169
+ return(-1);
2170
+ buffer = xmlBufFromBuffer(buf);
2171
+ if (buffer == NULL)
2172
+ return(-1);
2173
+ ret = xmlBufNodeDump(buffer, doc, cur, level, format);
2174
+ xmlBufBackToBuffer(buffer);
2175
+ if (ret > INT_MAX)
2176
+ return(-1);
2177
+ return((int) ret);
2178
+ }
2179
+
2180
+ /**
2181
+ * xmlBufNodeDump:
2182
+ * @buf: the XML buffer output
2183
+ * @doc: the document
2184
+ * @cur: the current node
2185
+ * @level: the imbrication level for indenting
2186
+ * @format: is formatting allowed
2187
+ *
2188
+ * Dump an XML node, recursive behaviour,children are printed too.
2189
+ * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2190
+ * or xmlKeepBlanksDefault(0) was called
2191
+ *
2192
+ * Returns the number of bytes written to the buffer, in case of error 0
2193
+ * is returned or @buf stores the error
2194
+ */
2195
+
2196
+ size_t
2197
+ xmlBufNodeDump(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2198
+ int format)
2199
+ {
2200
+ size_t use;
2201
+ int ret;
2202
+ xmlOutputBufferPtr outbuf;
2203
+ int oldalloc;
2204
+
2205
+ xmlInitParser();
2206
+
2207
+ if (cur == NULL) {
2208
+ #ifdef DEBUG_TREE
2209
+ xmlGenericError(xmlGenericErrorContext,
2210
+ "xmlNodeDump : node == NULL\n");
2211
+ #endif
2212
+ return (-1);
2213
+ }
2214
+ if (buf == NULL) {
2215
+ #ifdef DEBUG_TREE
2216
+ xmlGenericError(xmlGenericErrorContext,
2217
+ "xmlNodeDump : buf == NULL\n");
2218
+ #endif
2219
+ return (-1);
2220
+ }
2221
+ outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2222
+ if (outbuf == NULL) {
2223
+ xmlSaveErrMemory("creating buffer");
2224
+ return (-1);
2225
+ }
2226
+ memset(outbuf, 0, (size_t) sizeof(xmlOutputBuffer));
2227
+ outbuf->buffer = buf;
2228
+ outbuf->encoder = NULL;
2229
+ outbuf->writecallback = NULL;
2230
+ outbuf->closecallback = NULL;
2231
+ outbuf->context = NULL;
2232
+ outbuf->written = 0;
2233
+
2234
+ use = xmlBufUse(buf);
2235
+ oldalloc = xmlBufGetAllocationScheme(buf);
2236
+ xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
2237
+ xmlNodeDumpOutput(outbuf, doc, cur, level, format, NULL);
2238
+ xmlBufSetAllocationScheme(buf, oldalloc);
2239
+ xmlFree(outbuf);
2240
+ ret = xmlBufUse(buf) - use;
2241
+ return (ret);
2242
+ }
2243
+
2244
+ /**
2245
+ * xmlElemDump:
2246
+ * @f: the FILE * for the output
2247
+ * @doc: the document
2248
+ * @cur: the current node
2249
+ *
2250
+ * Dump an XML/HTML node, recursive behaviour, children are printed too.
2251
+ */
2252
+ void
2253
+ xmlElemDump(FILE * f, xmlDocPtr doc, xmlNodePtr cur)
2254
+ {
2255
+ xmlOutputBufferPtr outbuf;
2256
+
2257
+ xmlInitParser();
2258
+
2259
+ if (cur == NULL) {
2260
+ #ifdef DEBUG_TREE
2261
+ xmlGenericError(xmlGenericErrorContext,
2262
+ "xmlElemDump : cur == NULL\n");
2263
+ #endif
2264
+ return;
2265
+ }
2266
+ #ifdef DEBUG_TREE
2267
+ if (doc == NULL) {
2268
+ xmlGenericError(xmlGenericErrorContext,
2269
+ "xmlElemDump : doc == NULL\n");
2270
+ }
2271
+ #endif
2272
+
2273
+ outbuf = xmlOutputBufferCreateFile(f, NULL);
2274
+ if (outbuf == NULL)
2275
+ return;
2276
+ if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2277
+ #ifdef LIBXML_HTML_ENABLED
2278
+ htmlNodeDumpOutput(outbuf, doc, cur, NULL);
2279
+ #else
2280
+ xmlSaveErr(XML_ERR_INTERNAL_ERROR, cur, "HTML support not compiled in\n");
2281
+ #endif /* LIBXML_HTML_ENABLED */
2282
+ } else
2283
+ xmlNodeDumpOutput(outbuf, doc, cur, 0, 1, NULL);
2284
+ xmlOutputBufferClose(outbuf);
2285
+ }
2286
+
2287
+ /************************************************************************
2288
+ * *
2289
+ * Saving functions front-ends *
2290
+ * *
2291
+ ************************************************************************/
2292
+
2293
+ /**
2294
+ * xmlNodeDumpOutput:
2295
+ * @buf: the XML buffer output
2296
+ * @doc: the document
2297
+ * @cur: the current node
2298
+ * @level: the imbrication level for indenting
2299
+ * @format: is formatting allowed
2300
+ * @encoding: an optional encoding string
2301
+ *
2302
+ * Dump an XML node, recursive behaviour, children are printed too.
2303
+ * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2304
+ * or xmlKeepBlanksDefault(0) was called
2305
+ */
2306
+ void
2307
+ xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
2308
+ int level, int format, const char *encoding)
2309
+ {
2310
+ xmlSaveCtxt ctxt;
2311
+ #ifdef LIBXML_HTML_ENABLED
2312
+ xmlDtdPtr dtd;
2313
+ int is_xhtml = 0;
2314
+ #endif
2315
+
2316
+ xmlInitParser();
2317
+
2318
+ if ((buf == NULL) || (cur == NULL)) return;
2319
+
2320
+ if (encoding == NULL)
2321
+ encoding = "UTF-8";
2322
+
2323
+ memset(&ctxt, 0, sizeof(ctxt));
2324
+ ctxt.buf = buf;
2325
+ ctxt.level = level;
2326
+ ctxt.format = format ? 1 : 0;
2327
+ ctxt.encoding = (const xmlChar *) encoding;
2328
+ xmlSaveCtxtInit(&ctxt);
2329
+ ctxt.options |= XML_SAVE_AS_XML;
2330
+
2331
+ #ifdef LIBXML_HTML_ENABLED
2332
+ dtd = xmlGetIntSubset(doc);
2333
+ if (dtd != NULL) {
2334
+ is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
2335
+ if (is_xhtml < 0)
2336
+ is_xhtml = 0;
2337
+ }
2338
+
2339
+ if (is_xhtml)
2340
+ xhtmlNodeDumpOutput(&ctxt, cur);
2341
+ else
2342
+ #endif
2343
+ xmlNodeDumpOutputInternal(&ctxt, cur);
2344
+ }
2345
+
2346
+ /**
2347
+ * xmlDocDumpFormatMemoryEnc:
2348
+ * @out_doc: Document to generate XML text from
2349
+ * @doc_txt_ptr: Memory pointer for allocated XML text
2350
+ * @doc_txt_len: Length of the generated XML text
2351
+ * @txt_encoding: Character encoding to use when generating XML text
2352
+ * @format: should formatting spaces been added
2353
+ *
2354
+ * Dump the current DOM tree into memory using the character encoding specified
2355
+ * by the caller. Note it is up to the caller of this function to free the
2356
+ * allocated memory with xmlFree().
2357
+ * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2358
+ * or xmlKeepBlanksDefault(0) was called
2359
+ */
2360
+
2361
+ void
2362
+ xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
2363
+ int * doc_txt_len, const char * txt_encoding,
2364
+ int format) {
2365
+ xmlSaveCtxt ctxt;
2366
+ int dummy = 0;
2367
+ xmlOutputBufferPtr out_buff = NULL;
2368
+ xmlCharEncodingHandlerPtr conv_hdlr = NULL;
2369
+
2370
+ if (doc_txt_len == NULL) {
2371
+ doc_txt_len = &dummy; /* Continue, caller just won't get length */
2372
+ }
2373
+
2374
+ if (doc_txt_ptr == NULL) {
2375
+ *doc_txt_len = 0;
2376
+ return;
2377
+ }
2378
+
2379
+ *doc_txt_ptr = NULL;
2380
+ *doc_txt_len = 0;
2381
+
2382
+ if (out_doc == NULL) {
2383
+ /* No document, no output */
2384
+ return;
2385
+ }
2386
+
2387
+ /*
2388
+ * Validate the encoding value, if provided.
2389
+ * This logic is copied from xmlSaveFileEnc.
2390
+ */
2391
+
2392
+ if (txt_encoding == NULL)
2393
+ txt_encoding = (const char *) out_doc->encoding;
2394
+ if (txt_encoding != NULL) {
2395
+ conv_hdlr = xmlFindCharEncodingHandler(txt_encoding);
2396
+ if ( conv_hdlr == NULL ) {
2397
+ xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, (xmlNodePtr) out_doc,
2398
+ txt_encoding);
2399
+ return;
2400
+ }
2401
+ }
2402
+
2403
+ if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) {
2404
+ xmlSaveErrMemory("creating buffer");
2405
+ return;
2406
+ }
2407
+
2408
+ memset(&ctxt, 0, sizeof(ctxt));
2409
+ ctxt.buf = out_buff;
2410
+ ctxt.level = 0;
2411
+ ctxt.format = format ? 1 : 0;
2412
+ ctxt.encoding = (const xmlChar *) txt_encoding;
2413
+ xmlSaveCtxtInit(&ctxt);
2414
+ ctxt.options |= XML_SAVE_AS_XML;
2415
+ xmlDocContentDumpOutput(&ctxt, out_doc);
2416
+ xmlOutputBufferFlush(out_buff);
2417
+ if (out_buff->conv != NULL) {
2418
+ *doc_txt_len = xmlBufUse(out_buff->conv);
2419
+ *doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->conv), *doc_txt_len);
2420
+ } else {
2421
+ *doc_txt_len = xmlBufUse(out_buff->buffer);
2422
+ *doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->buffer),*doc_txt_len);
2423
+ }
2424
+ (void)xmlOutputBufferClose(out_buff);
2425
+
2426
+ if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) {
2427
+ *doc_txt_len = 0;
2428
+ xmlSaveErrMemory("creating output");
2429
+ }
2430
+
2431
+ return;
2432
+ }
2433
+
2434
+ /**
2435
+ * xmlDocDumpMemory:
2436
+ * @cur: the document
2437
+ * @mem: OUT: the memory pointer
2438
+ * @size: OUT: the memory length
2439
+ *
2440
+ * Dump an XML document in memory and return the #xmlChar * and it's size
2441
+ * in bytes. It's up to the caller to free the memory with xmlFree().
2442
+ * The resulting byte array is zero terminated, though the last 0 is not
2443
+ * included in the returned size.
2444
+ */
2445
+ void
2446
+ xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
2447
+ xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, 0);
2448
+ }
2449
+
2450
+ /**
2451
+ * xmlDocDumpFormatMemory:
2452
+ * @cur: the document
2453
+ * @mem: OUT: the memory pointer
2454
+ * @size: OUT: the memory length
2455
+ * @format: should formatting spaces been added
2456
+ *
2457
+ *
2458
+ * Dump an XML document in memory and return the #xmlChar * and it's size.
2459
+ * It's up to the caller to free the memory with xmlFree().
2460
+ * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2461
+ * or xmlKeepBlanksDefault(0) was called
2462
+ */
2463
+ void
2464
+ xmlDocDumpFormatMemory(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
2465
+ xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, format);
2466
+ }
2467
+
2468
+ /**
2469
+ * xmlDocDumpMemoryEnc:
2470
+ * @out_doc: Document to generate XML text from
2471
+ * @doc_txt_ptr: Memory pointer for allocated XML text
2472
+ * @doc_txt_len: Length of the generated XML text
2473
+ * @txt_encoding: Character encoding to use when generating XML text
2474
+ *
2475
+ * Dump the current DOM tree into memory using the character encoding specified
2476
+ * by the caller. Note it is up to the caller of this function to free the
2477
+ * allocated memory with xmlFree().
2478
+ */
2479
+
2480
+ void
2481
+ xmlDocDumpMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
2482
+ int * doc_txt_len, const char * txt_encoding) {
2483
+ xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len,
2484
+ txt_encoding, 0);
2485
+ }
2486
+
2487
+ /**
2488
+ * xmlDocFormatDump:
2489
+ * @f: the FILE*
2490
+ * @cur: the document
2491
+ * @format: should formatting spaces been added
2492
+ *
2493
+ * Dump an XML document to an open FILE.
2494
+ *
2495
+ * returns: the number of bytes written or -1 in case of failure.
2496
+ * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2497
+ * or xmlKeepBlanksDefault(0) was called
2498
+ */
2499
+ int
2500
+ xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) {
2501
+ xmlSaveCtxt ctxt;
2502
+ xmlOutputBufferPtr buf;
2503
+ const char * encoding;
2504
+ xmlCharEncodingHandlerPtr handler = NULL;
2505
+ int ret;
2506
+
2507
+ if (cur == NULL) {
2508
+ #ifdef DEBUG_TREE
2509
+ xmlGenericError(xmlGenericErrorContext,
2510
+ "xmlDocDump : document == NULL\n");
2511
+ #endif
2512
+ return(-1);
2513
+ }
2514
+ encoding = (const char *) cur->encoding;
2515
+
2516
+ if (encoding != NULL) {
2517
+ handler = xmlFindCharEncodingHandler(encoding);
2518
+ if (handler == NULL) {
2519
+ xmlFree((char *) cur->encoding);
2520
+ cur->encoding = NULL;
2521
+ encoding = NULL;
2522
+ }
2523
+ }
2524
+ buf = xmlOutputBufferCreateFile(f, handler);
2525
+ if (buf == NULL) return(-1);
2526
+ memset(&ctxt, 0, sizeof(ctxt));
2527
+ ctxt.buf = buf;
2528
+ ctxt.level = 0;
2529
+ ctxt.format = format ? 1 : 0;
2530
+ ctxt.encoding = (const xmlChar *) encoding;
2531
+ xmlSaveCtxtInit(&ctxt);
2532
+ ctxt.options |= XML_SAVE_AS_XML;
2533
+ xmlDocContentDumpOutput(&ctxt, cur);
2534
+
2535
+ ret = xmlOutputBufferClose(buf);
2536
+ return(ret);
2537
+ }
2538
+
2539
+ /**
2540
+ * xmlDocDump:
2541
+ * @f: the FILE*
2542
+ * @cur: the document
2543
+ *
2544
+ * Dump an XML document to an open FILE.
2545
+ *
2546
+ * returns: the number of bytes written or -1 in case of failure.
2547
+ */
2548
+ int
2549
+ xmlDocDump(FILE *f, xmlDocPtr cur) {
2550
+ return(xmlDocFormatDump (f, cur, 0));
2551
+ }
2552
+
2553
+ /**
2554
+ * xmlSaveFileTo:
2555
+ * @buf: an output I/O buffer
2556
+ * @cur: the document
2557
+ * @encoding: the encoding if any assuming the I/O layer handles the transcoding
2558
+ *
2559
+ * Dump an XML document to an I/O buffer.
2560
+ * Warning ! This call xmlOutputBufferClose() on buf which is not available
2561
+ * after this call.
2562
+ *
2563
+ * returns: the number of bytes written or -1 in case of failure.
2564
+ */
2565
+ int
2566
+ xmlSaveFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding) {
2567
+ xmlSaveCtxt ctxt;
2568
+ int ret;
2569
+
2570
+ if (buf == NULL) return(-1);
2571
+ if (cur == NULL) {
2572
+ xmlOutputBufferClose(buf);
2573
+ return(-1);
2574
+ }
2575
+ memset(&ctxt, 0, sizeof(ctxt));
2576
+ ctxt.buf = buf;
2577
+ ctxt.level = 0;
2578
+ ctxt.format = 0;
2579
+ ctxt.encoding = (const xmlChar *) encoding;
2580
+ xmlSaveCtxtInit(&ctxt);
2581
+ ctxt.options |= XML_SAVE_AS_XML;
2582
+ xmlDocContentDumpOutput(&ctxt, cur);
2583
+ ret = xmlOutputBufferClose(buf);
2584
+ return(ret);
2585
+ }
2586
+
2587
+ /**
2588
+ * xmlSaveFormatFileTo:
2589
+ * @buf: an output I/O buffer
2590
+ * @cur: the document
2591
+ * @encoding: the encoding if any assuming the I/O layer handles the transcoding
2592
+ * @format: should formatting spaces been added
2593
+ *
2594
+ * Dump an XML document to an I/O buffer.
2595
+ * Warning ! This call xmlOutputBufferClose() on buf which is not available
2596
+ * after this call.
2597
+ *
2598
+ * returns: the number of bytes written or -1 in case of failure.
2599
+ */
2600
+ int
2601
+ xmlSaveFormatFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur,
2602
+ const char *encoding, int format)
2603
+ {
2604
+ xmlSaveCtxt ctxt;
2605
+ int ret;
2606
+
2607
+ if (buf == NULL) return(-1);
2608
+ if ((cur == NULL) ||
2609
+ ((cur->type != XML_DOCUMENT_NODE) &&
2610
+ (cur->type != XML_HTML_DOCUMENT_NODE))) {
2611
+ xmlOutputBufferClose(buf);
2612
+ return(-1);
2613
+ }
2614
+ memset(&ctxt, 0, sizeof(ctxt));
2615
+ ctxt.buf = buf;
2616
+ ctxt.level = 0;
2617
+ ctxt.format = format ? 1 : 0;
2618
+ ctxt.encoding = (const xmlChar *) encoding;
2619
+ xmlSaveCtxtInit(&ctxt);
2620
+ ctxt.options |= XML_SAVE_AS_XML;
2621
+ xmlDocContentDumpOutput(&ctxt, cur);
2622
+ ret = xmlOutputBufferClose(buf);
2623
+ return (ret);
2624
+ }
2625
+
2626
+ /**
2627
+ * xmlSaveFormatFileEnc:
2628
+ * @filename: the filename or URL to output
2629
+ * @cur: the document being saved
2630
+ * @encoding: the name of the encoding to use or NULL.
2631
+ * @format: should formatting spaces be added.
2632
+ *
2633
+ * Dump an XML document to a file or an URL.
2634
+ *
2635
+ * Returns the number of bytes written or -1 in case of error.
2636
+ * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2637
+ * or xmlKeepBlanksDefault(0) was called
2638
+ */
2639
+ int
2640
+ xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur,
2641
+ const char * encoding, int format ) {
2642
+ xmlSaveCtxt ctxt;
2643
+ xmlOutputBufferPtr buf;
2644
+ xmlCharEncodingHandlerPtr handler = NULL;
2645
+ int ret;
2646
+
2647
+ if (cur == NULL)
2648
+ return(-1);
2649
+
2650
+ if (encoding == NULL)
2651
+ encoding = (const char *) cur->encoding;
2652
+
2653
+ if (encoding != NULL) {
2654
+
2655
+ handler = xmlFindCharEncodingHandler(encoding);
2656
+ if (handler == NULL)
2657
+ return(-1);
2658
+ }
2659
+
2660
+ #ifdef LIBXML_ZLIB_ENABLED
2661
+ if (cur->compression < 0) cur->compression = xmlGetCompressMode();
2662
+ #endif
2663
+ /*
2664
+ * save the content to a temp buffer.
2665
+ */
2666
+ buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
2667
+ if (buf == NULL) return(-1);
2668
+ memset(&ctxt, 0, sizeof(ctxt));
2669
+ ctxt.buf = buf;
2670
+ ctxt.level = 0;
2671
+ ctxt.format = format ? 1 : 0;
2672
+ ctxt.encoding = (const xmlChar *) encoding;
2673
+ xmlSaveCtxtInit(&ctxt);
2674
+ ctxt.options |= XML_SAVE_AS_XML;
2675
+
2676
+ xmlDocContentDumpOutput(&ctxt, cur);
2677
+
2678
+ ret = xmlOutputBufferClose(buf);
2679
+ return(ret);
2680
+ }
2681
+
2682
+
2683
+ /**
2684
+ * xmlSaveFileEnc:
2685
+ * @filename: the filename (or URL)
2686
+ * @cur: the document
2687
+ * @encoding: the name of an encoding (or NULL)
2688
+ *
2689
+ * Dump an XML document, converting it to the given encoding
2690
+ *
2691
+ * returns: the number of bytes written or -1 in case of failure.
2692
+ */
2693
+ int
2694
+ xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
2695
+ return ( xmlSaveFormatFileEnc( filename, cur, encoding, 0 ) );
2696
+ }
2697
+
2698
+ /**
2699
+ * xmlSaveFormatFile:
2700
+ * @filename: the filename (or URL)
2701
+ * @cur: the document
2702
+ * @format: should formatting spaces been added
2703
+ *
2704
+ * Dump an XML document to a file. Will use compression if
2705
+ * compiled in and enabled. If @filename is "-" the stdout file is
2706
+ * used. If @format is set then the document will be indented on output.
2707
+ * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2708
+ * or xmlKeepBlanksDefault(0) was called
2709
+ *
2710
+ * returns: the number of bytes written or -1 in case of failure.
2711
+ */
2712
+ int
2713
+ xmlSaveFormatFile(const char *filename, xmlDocPtr cur, int format) {
2714
+ return ( xmlSaveFormatFileEnc( filename, cur, NULL, format ) );
2715
+ }
2716
+
2717
+ /**
2718
+ * xmlSaveFile:
2719
+ * @filename: the filename (or URL)
2720
+ * @cur: the document
2721
+ *
2722
+ * Dump an XML document to a file. Will use compression if
2723
+ * compiled in and enabled. If @filename is "-" the stdout file is
2724
+ * used.
2725
+ * returns: the number of bytes written or -1 in case of failure.
2726
+ */
2727
+ int
2728
+ xmlSaveFile(const char *filename, xmlDocPtr cur) {
2729
+ return(xmlSaveFormatFileEnc(filename, cur, NULL, 0));
2730
+ }
2731
+
2732
+ #endif /* LIBXML_OUTPUT_ENABLED */
2733
+
2734
+ #define bottom_xmlsave
2735
+ #include "elfgcchack.h"