@helm2/poc_jenki_rce 0.0.1

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

Potentially problematic release.


This version of @helm2/poc_jenki_rce 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 +118 -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"