ReactOS  0.4.15-dev-2144-g2282205
xmlsave.c
Go to the documentation of this file.
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 
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;
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  ************************************************************************/
107 static void
108 xmlSaveErrMemory(const char *extra)
109 {
110  __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra);
111 }
112 
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;
131  msg = "invalid character value\n";
132  break;
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 
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 {
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  ************************************************************************/
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;
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 
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 
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) {
392  if (ret->handler == NULL) {
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  ************************************************************************/
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 
466 void
467 xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table) {
469 
471  if (buffer == NULL) {
472  /*
473  * TODO set the error in buf
474  */
475  return;
476  }
477  xmlDumpNotationTable(buffer, table);
479 }
480 
489 void
490 xmlBufDumpElementDecl(xmlBufPtr buf, xmlElementPtr elem) {
492 
494  if (buffer == NULL) {
495  /*
496  * TODO set the error in buf
497  */
498  return;
499  }
500  xmlDumpElementDecl(buffer, elem);
502 }
503 
512 void
513 xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr) {
515 
517  if (buffer == NULL) {
518  /*
519  * TODO set the error in buf
520  */
521  return;
522  }
523  xmlDumpAttributeDecl(buffer, attr);
525 }
526 
534 void
535 xmlBufDumpEntityDecl(xmlBufPtr buf, xmlEntityPtr ent) {
537 
539  if (buffer == NULL) {
540  /*
541  * TODO set the error in buf
542  */
543  return;
544  }
545  xmlDumpEntityDecl(buffer, ent);
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 xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
594 static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
595 void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
596 static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur);
597 
605 static void
606 xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra)
607 {
608  int i;
609  if ((ctxt == NULL) || (ctxt->buf == NULL))
610  return;
611  xmlOutputBufferWrite(ctxt->buf, 1, "\n");
612  for (i = 0; i < (ctxt->level + extra); i += ctxt->indent_nr) {
613  xmlOutputBufferWrite(ctxt->buf, ctxt->indent_size *
614  ((ctxt->level + extra - i) > ctxt->indent_nr ?
615  ctxt->indent_nr : (ctxt->level + extra - i)),
616  ctxt->indent);
617  }
618 }
619 
630 static void
631 xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) {
632  if ((cur == NULL) || (buf == NULL)) return;
633  if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
634  if (xmlStrEqual(cur->prefix, BAD_CAST "xml"))
635  return;
636 
637  if (ctxt != NULL && ctxt->format == 2)
638  xmlOutputBufferWriteWSNonSig(ctxt, 2);
639  else
640  xmlOutputBufferWrite(buf, 1, " ");
641 
642  /* Within the context of an element attributes */
643  if (cur->prefix != NULL) {
644  xmlOutputBufferWrite(buf, 6, "xmlns:");
645  xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
646  } else
647  xmlOutputBufferWrite(buf, 5, "xmlns");
648  xmlOutputBufferWrite(buf, 1, "=");
649  xmlBufWriteQuotedString(buf->buffer, cur->href);
650  }
651 }
652 
661 static void
662 xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
663  xmlNsDumpOutput(ctxt->buf, cur, ctxt);
664 }
665 
674 static void
675 xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
676  while (cur != NULL) {
677  xmlNsDumpOutput(ctxt->buf, cur, ctxt);
678  cur = cur->next;
679  }
680 }
681 
690 void
691 xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
692  while (cur != NULL) {
693  xmlNsDumpOutput(buf, cur, NULL);
694  cur = cur->next;
695  }
696 }
697 
705 static void
706 xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
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,
740  }
741  format = ctxt->format;
742  level = ctxt->level;
743  ctxt->format = 0;
744  ctxt->level = -1;
745  xmlNodeListDumpOutput(ctxt, dtd->children);
746  ctxt->format = format;
747  ctxt->level = level;
748  xmlOutputBufferWrite(buf, 2, "]>");
749 }
750 
758 static void
759 xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
761 
762  if (cur == NULL) return;
763  buf = ctxt->buf;
764  if (buf == NULL) return;
765  if (ctxt->format == 2)
766  xmlOutputBufferWriteWSNonSig(ctxt, 2);
767  else
768  xmlOutputBufferWrite(buf, 1, " ");
769  if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
770  xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
771  xmlOutputBufferWrite(buf, 1, ":");
772  }
773  xmlOutputBufferWriteString(buf, (const char *)cur->name);
774  xmlOutputBufferWrite(buf, 2, "=\"");
775  xmlAttrSerializeContent(buf, cur);
776  xmlOutputBufferWrite(buf, 1, "\"");
777 }
778 
788 static void
789 xmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
790  if (cur == NULL) return;
791  while (cur != NULL) {
792  xmlAttrDumpOutput(ctxt, cur);
793  cur = cur->next;
794  }
795 }
796 
797 
798 
805 static void
806 xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
808 
809  if (cur == NULL) return;
810  buf = ctxt->buf;
811  while (cur != NULL) {
812  if ((ctxt->format == 1) && (xmlIndentTreeOutput) &&
813  ((cur->type == XML_ELEMENT_NODE) ||
814  (cur->type == XML_COMMENT_NODE) ||
815  (cur->type == XML_PI_NODE)))
816  xmlOutputBufferWrite(buf, ctxt->indent_size *
817  (ctxt->level > ctxt->indent_nr ?
818  ctxt->indent_nr : ctxt->level),
819  ctxt->indent);
820  xmlNodeDumpOutputInternal(ctxt, cur);
821  if (ctxt->format == 1) {
822  xmlOutputBufferWrite(buf, 1, "\n");
823  }
824  cur = cur->next;
825  }
826 }
827 
828 #ifdef LIBXML_HTML_ENABLED
829 
835 static int
836 htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
837  const xmlChar *oldenc = NULL;
838  const xmlChar *oldctxtenc = ctxt->encoding;
839  const xmlChar *encoding = ctxt->encoding;
840  xmlOutputBufferPtr buf = ctxt->buf;
841  int switched_encoding = 0;
842  xmlDocPtr doc;
843 
844  xmlInitParser();
845 
846  doc = cur->doc;
847  if (doc != NULL) {
848  oldenc = doc->encoding;
849  if (ctxt->encoding != NULL) {
850  doc->encoding = BAD_CAST ctxt->encoding;
851  } else if (doc->encoding != NULL) {
852  encoding = doc->encoding;
853  }
854  }
855 
856  if ((encoding != NULL) && (doc != NULL))
857  htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
858  if ((encoding == NULL) && (doc != NULL))
859  encoding = htmlGetMetaEncoding(doc);
860  if (encoding == NULL)
861  encoding = BAD_CAST "HTML";
862  if ((encoding != NULL) && (oldctxtenc == NULL) &&
863  (buf->encoder == NULL) && (buf->conv == NULL)) {
864  if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
865  doc->encoding = oldenc;
866  return(-1);
867  }
868  switched_encoding = 1;
869  }
870  if (ctxt->options & XML_SAVE_FORMAT)
871  htmlNodeDumpFormatOutput(buf, doc, cur,
872  (const char *)encoding, 1);
873  else
874  htmlNodeDumpFormatOutput(buf, doc, cur,
875  (const char *)encoding, 0);
876  /*
877  * Restore the state of the saving context at the end of the document
878  */
879  if ((switched_encoding) && (oldctxtenc == NULL)) {
880  xmlSaveClearEncoding(ctxt);
881  }
882  if (doc != NULL)
883  doc->encoding = oldenc;
884  return(0);
885 }
886 #endif
887 
894 static void
895 xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
896  int format;
897  xmlNodePtr tmp;
898  xmlChar *start, *end;
900 
901  if (cur == NULL) return;
902  buf = ctxt->buf;
903  if (cur->type == XML_XINCLUDE_START)
904  return;
905  if (cur->type == XML_XINCLUDE_END)
906  return;
907  if ((cur->type == XML_DOCUMENT_NODE) ||
908  (cur->type == XML_HTML_DOCUMENT_NODE)) {
909  xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
910  return;
911  }
912 #ifdef LIBXML_HTML_ENABLED
913  if (ctxt->options & XML_SAVE_XHTML) {
914  xhtmlNodeDumpOutput(ctxt, cur);
915  return;
916  }
917  if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
918  (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
919  ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
920  (ctxt->options & XML_SAVE_AS_HTML)) {
921  htmlNodeDumpOutputInternal(ctxt, cur);
922  return;
923  }
924 #endif
925  if (cur->type == XML_DTD_NODE) {
926  xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
927  return;
928  }
929  if (cur->type == XML_DOCUMENT_FRAG_NODE) {
930  xmlNodeListDumpOutput(ctxt, cur->children);
931  return;
932  }
933  if (cur->type == XML_ELEMENT_DECL) {
934  xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
935  return;
936  }
937  if (cur->type == XML_ATTRIBUTE_DECL) {
938  xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
939  return;
940  }
941  if (cur->type == XML_ENTITY_DECL) {
942  xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
943  return;
944  }
945  if (cur->type == XML_TEXT_NODE) {
946  if (cur->content != NULL) {
947  if (cur->name != xmlStringTextNoenc) {
948  xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
949  } else {
950  /*
951  * Disable escaping, needed for XSLT
952  */
953  xmlOutputBufferWriteString(buf, (const char *) cur->content);
954  }
955  }
956 
957  return;
958  }
959  if (cur->type == XML_PI_NODE) {
960  if (cur->content != NULL) {
961  xmlOutputBufferWrite(buf, 2, "<?");
962  xmlOutputBufferWriteString(buf, (const char *)cur->name);
963  if (cur->content != NULL) {
964  if (ctxt->format == 2)
965  xmlOutputBufferWriteWSNonSig(ctxt, 0);
966  else
967  xmlOutputBufferWrite(buf, 1, " ");
968  xmlOutputBufferWriteString(buf, (const char *)cur->content);
969  }
970  xmlOutputBufferWrite(buf, 2, "?>");
971  } else {
972  xmlOutputBufferWrite(buf, 2, "<?");
973  xmlOutputBufferWriteString(buf, (const char *)cur->name);
974  if (ctxt->format == 2)
975  xmlOutputBufferWriteWSNonSig(ctxt, 0);
976  xmlOutputBufferWrite(buf, 2, "?>");
977  }
978  return;
979  }
980  if (cur->type == XML_COMMENT_NODE) {
981  if (cur->content != NULL) {
982  xmlOutputBufferWrite(buf, 4, "<!--");
983  xmlOutputBufferWriteString(buf, (const char *)cur->content);
984  xmlOutputBufferWrite(buf, 3, "-->");
985  }
986  return;
987  }
988  if (cur->type == XML_ENTITY_REF_NODE) {
989  xmlOutputBufferWrite(buf, 1, "&");
990  xmlOutputBufferWriteString(buf, (const char *)cur->name);
991  xmlOutputBufferWrite(buf, 1, ";");
992  return;
993  }
994  if (cur->type == XML_CDATA_SECTION_NODE) {
995  if (cur->content == NULL || *cur->content == '\0') {
996  xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
997  } else {
998  start = end = cur->content;
999  while (*end != '\0') {
1000  if ((*end == ']') && (*(end + 1) == ']') &&
1001  (*(end + 2) == '>')) {
1002  end = end + 2;
1003  xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1004  xmlOutputBufferWrite(buf, end - start, (const char *)start);
1005  xmlOutputBufferWrite(buf, 3, "]]>");
1006  start = end;
1007  }
1008  end++;
1009  }
1010  if (start != end) {
1011  xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1012  xmlOutputBufferWriteString(buf, (const char *)start);
1013  xmlOutputBufferWrite(buf, 3, "]]>");
1014  }
1015  }
1016  return;
1017  }
1018  if (cur->type == XML_ATTRIBUTE_NODE) {
1019  xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
1020  return;
1021  }
1022  if (cur->type == XML_NAMESPACE_DECL) {
1023  xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
1024  return;
1025  }
1026 
1027  format = ctxt->format;
1028  if (format == 1) {
1029  tmp = cur->children;
1030  while (tmp != NULL) {
1031  if ((tmp->type == XML_TEXT_NODE) ||
1032  (tmp->type == XML_CDATA_SECTION_NODE) ||
1033  (tmp->type == XML_ENTITY_REF_NODE)) {
1034  ctxt->format = 0;
1035  break;
1036  }
1037  tmp = tmp->next;
1038  }
1039  }
1040  xmlOutputBufferWrite(buf, 1, "<");
1041  if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1042  xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
1043  xmlOutputBufferWrite(buf, 1, ":");
1044  }
1045 
1046  xmlOutputBufferWriteString(buf, (const char *)cur->name);
1047  if (cur->nsDef)
1048  xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
1049  if (cur->properties != NULL)
1050  xmlAttrListDumpOutput(ctxt, cur->properties);
1051 
1052  if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) &&
1053  (cur->children == NULL) && ((ctxt->options & XML_SAVE_NO_EMPTY) == 0)) {
1054  if (ctxt->format == 2)
1055  xmlOutputBufferWriteWSNonSig(ctxt, 0);
1056  xmlOutputBufferWrite(buf, 2, "/>");
1057  ctxt->format = format;
1058  return;
1059  }
1060  if (ctxt->format == 2)
1061  xmlOutputBufferWriteWSNonSig(ctxt, 1);
1062  xmlOutputBufferWrite(buf, 1, ">");
1063  if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
1064  xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
1065  }
1066  if (cur->children != NULL) {
1067  if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
1068  if (ctxt->level >= 0) ctxt->level++;
1069  xmlNodeListDumpOutput(ctxt, cur->children);
1070  if (ctxt->level > 0) ctxt->level--;
1071  if ((xmlIndentTreeOutput) && (ctxt->format == 1))
1072  xmlOutputBufferWrite(buf, ctxt->indent_size *
1073  (ctxt->level > ctxt->indent_nr ?
1074  ctxt->indent_nr : ctxt->level),
1075  ctxt->indent);
1076  }
1077  xmlOutputBufferWrite(buf, 2, "</");
1078  if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1079  xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
1080  xmlOutputBufferWrite(buf, 1, ":");
1081  }
1082 
1083  xmlOutputBufferWriteString(buf, (const char *)cur->name);
1084  if (ctxt->format == 2)
1085  xmlOutputBufferWriteWSNonSig(ctxt, 0);
1086  xmlOutputBufferWrite(buf, 1, ">");
1087  ctxt->format = format;
1088 }
1089 
1096 static int
1097 xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
1098 #ifdef LIBXML_HTML_ENABLED
1099  xmlDtdPtr dtd;
1100  int is_xhtml = 0;
1101 #endif
1102  const xmlChar *oldenc = cur->encoding;
1103  const xmlChar *oldctxtenc = ctxt->encoding;
1104  const xmlChar *encoding = ctxt->encoding;
1105  xmlCharEncodingOutputFunc oldescape = ctxt->escape;
1106  xmlCharEncodingOutputFunc oldescapeAttr = ctxt->escapeAttr;
1107  xmlOutputBufferPtr buf = ctxt->buf;
1108  xmlCharEncoding enc;
1109  int switched_encoding = 0;
1110 
1111  xmlInitParser();
1112 
1113  if ((cur->type != XML_HTML_DOCUMENT_NODE) &&
1114  (cur->type != XML_DOCUMENT_NODE))
1115  return(-1);
1116 
1117  if (ctxt->encoding != NULL) {
1118  cur->encoding = BAD_CAST ctxt->encoding;
1119  } else if (cur->encoding != NULL) {
1120  encoding = cur->encoding;
1121  }
1122 
1123  if (((cur->type == XML_HTML_DOCUMENT_NODE) &&
1124  ((ctxt->options & XML_SAVE_AS_XML) == 0) &&
1125  ((ctxt->options & XML_SAVE_XHTML) == 0)) ||
1126  (ctxt->options & XML_SAVE_AS_HTML)) {
1127 #ifdef LIBXML_HTML_ENABLED
1128  if (encoding != NULL)
1129  htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
1130  if (encoding == NULL)
1131  encoding = htmlGetMetaEncoding(cur);
1132  if (encoding == NULL)
1133  encoding = BAD_CAST "HTML";
1134  if ((encoding != NULL) && (oldctxtenc == NULL) &&
1135  (buf->encoder == NULL) && (buf->conv == NULL)) {
1136  if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
1137  cur->encoding = oldenc;
1138  return(-1);
1139  }
1140  }
1141  if (ctxt->options & XML_SAVE_FORMAT)
1142  htmlDocContentDumpFormatOutput(buf, cur,
1143  (const char *)encoding, 1);
1144  else
1145  htmlDocContentDumpFormatOutput(buf, cur,
1146  (const char *)encoding, 0);
1147  if (ctxt->encoding != NULL)
1148  cur->encoding = oldenc;
1149  return(0);
1150 #else
1151  return(-1);
1152 #endif
1153  } else if ((cur->type == XML_DOCUMENT_NODE) ||
1154  (ctxt->options & XML_SAVE_AS_XML) ||
1155  (ctxt->options & XML_SAVE_XHTML)) {
1156  enc = xmlParseCharEncoding((const char*) encoding);
1157  if ((encoding != NULL) && (oldctxtenc == NULL) &&
1158  (buf->encoder == NULL) && (buf->conv == NULL) &&
1159  ((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
1160  if ((enc != XML_CHAR_ENCODING_UTF8) &&
1161  (enc != XML_CHAR_ENCODING_NONE) &&
1162  (enc != XML_CHAR_ENCODING_ASCII)) {
1163  /*
1164  * we need to switch to this encoding but just for this
1165  * document since we output the XMLDecl the conversion
1166  * must be done to not generate not well formed documents.
1167  */
1168  if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
1169  cur->encoding = oldenc;
1170  return(-1);
1171  }
1172  switched_encoding = 1;
1173  }
1174  if (ctxt->escape == xmlEscapeEntities)
1175  ctxt->escape = NULL;
1176  if (ctxt->escapeAttr == xmlEscapeEntities)
1177  ctxt->escapeAttr = NULL;
1178  }
1179 
1180 
1181  /*
1182  * Save the XML declaration
1183  */
1184  if ((ctxt->options & XML_SAVE_NO_DECL) == 0) {
1185  xmlOutputBufferWrite(buf, 14, "<?xml version=");
1186  if (cur->version != NULL)
1187  xmlBufWriteQuotedString(buf->buffer, cur->version);
1188  else
1189  xmlOutputBufferWrite(buf, 5, "\"1.0\"");
1190  if (encoding != NULL) {
1191  xmlOutputBufferWrite(buf, 10, " encoding=");
1193  }
1194  switch (cur->standalone) {
1195  case 0:
1196  xmlOutputBufferWrite(buf, 16, " standalone=\"no\"");
1197  break;
1198  case 1:
1199  xmlOutputBufferWrite(buf, 17, " standalone=\"yes\"");
1200  break;
1201  }
1202  xmlOutputBufferWrite(buf, 3, "?>\n");
1203  }
1204 
1205 #ifdef LIBXML_HTML_ENABLED
1206  if (ctxt->options & XML_SAVE_XHTML)
1207  is_xhtml = 1;
1208  if ((ctxt->options & XML_SAVE_NO_XHTML) == 0) {
1209  dtd = xmlGetIntSubset(cur);
1210  if (dtd != NULL) {
1211  is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
1212  if (is_xhtml < 0) is_xhtml = 0;
1213  }
1214  }
1215 #endif
1216  if (cur->children != NULL) {
1217  xmlNodePtr child = cur->children;
1218 
1219  while (child != NULL) {
1220  ctxt->level = 0;
1221 #ifdef LIBXML_HTML_ENABLED
1222  if (is_xhtml)
1223  xhtmlNodeDumpOutput(ctxt, child);
1224  else
1225 #endif
1226  xmlNodeDumpOutputInternal(ctxt, child);
1227  xmlOutputBufferWrite(buf, 1, "\n");
1228  child = child->next;
1229  }
1230  }
1231  }
1232 
1233  /*
1234  * Restore the state of the saving context at the end of the document
1235  */
1236  if ((switched_encoding) && (oldctxtenc == NULL)) {
1237  xmlSaveClearEncoding(ctxt);
1238  ctxt->escape = oldescape;
1239  ctxt->escapeAttr = oldescapeAttr;
1240  }
1241  cur->encoding = oldenc;
1242  return(0);
1243 }
1244 
1245 #ifdef LIBXML_HTML_ENABLED
1246 /************************************************************************
1247  * *
1248  * Functions specific to XHTML serialization *
1249  * *
1250  ************************************************************************/
1251 
1260 static int
1261 xhtmlIsEmpty(xmlNodePtr node) {
1262  if (node == NULL)
1263  return(-1);
1264  if (node->type != XML_ELEMENT_NODE)
1265  return(0);
1266  if ((node->ns != NULL) && (!xmlStrEqual(node->ns->href, XHTML_NS_NAME)))
1267  return(0);
1268  if (node->children != NULL)
1269  return(0);
1270  switch (node->name[0]) {
1271  case 'a':
1272  if (xmlStrEqual(node->name, BAD_CAST "area"))
1273  return(1);
1274  return(0);
1275  case 'b':
1276  if (xmlStrEqual(node->name, BAD_CAST "br"))
1277  return(1);
1278  if (xmlStrEqual(node->name, BAD_CAST "base"))
1279  return(1);
1280  if (xmlStrEqual(node->name, BAD_CAST "basefont"))
1281  return(1);
1282  return(0);
1283  case 'c':
1284  if (xmlStrEqual(node->name, BAD_CAST "col"))
1285  return(1);
1286  return(0);
1287  case 'f':
1288  if (xmlStrEqual(node->name, BAD_CAST "frame"))
1289  return(1);
1290  return(0);
1291  case 'h':
1292  if (xmlStrEqual(node->name, BAD_CAST "hr"))
1293  return(1);
1294  return(0);
1295  case 'i':
1296  if (xmlStrEqual(node->name, BAD_CAST "img"))
1297  return(1);
1298  if (xmlStrEqual(node->name, BAD_CAST "input"))
1299  return(1);
1300  if (xmlStrEqual(node->name, BAD_CAST "isindex"))
1301  return(1);
1302  return(0);
1303  case 'l':
1304  if (xmlStrEqual(node->name, BAD_CAST "link"))
1305  return(1);
1306  return(0);
1307  case 'm':
1308  if (xmlStrEqual(node->name, BAD_CAST "meta"))
1309  return(1);
1310  return(0);
1311  case 'p':
1312  if (xmlStrEqual(node->name, BAD_CAST "param"))
1313  return(1);
1314  return(0);
1315  }
1316  return(0);
1317 }
1318 
1325 static void
1326 xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
1327  xmlAttrPtr xml_lang = NULL;
1328  xmlAttrPtr lang = NULL;
1329  xmlAttrPtr name = NULL;
1330  xmlAttrPtr id = NULL;
1333 
1334  if (cur == NULL) return;
1335  buf = ctxt->buf;
1336  parent = cur->parent;
1337  while (cur != NULL) {
1338  if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "id")))
1339  id = cur;
1340  else
1341  if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "name")))
1342  name = cur;
1343  else
1344  if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")))
1345  lang = cur;
1346  else
1347  if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) &&
1348  (xmlStrEqual(cur->ns->prefix, BAD_CAST "xml")))
1349  xml_lang = cur;
1350  else if ((cur->ns == NULL) &&
1351  ((cur->children == NULL) ||
1352  (cur->children->content == NULL) ||
1353  (cur->children->content[0] == 0)) &&
1354  (htmlIsBooleanAttr(cur->name))) {
1355  if (cur->children != NULL)
1356  xmlFreeNode(cur->children);
1357  cur->children = xmlNewText(cur->name);
1358  if (cur->children != NULL)
1359  cur->children->parent = (xmlNodePtr) cur;
1360  }
1361  xmlAttrDumpOutput(ctxt, cur);
1362  cur = cur->next;
1363  }
1364  /*
1365  * C.8
1366  */
1367  if ((name != NULL) && (id == NULL)) {
1368  if ((parent != NULL) && (parent->name != NULL) &&
1369  ((xmlStrEqual(parent->name, BAD_CAST "a")) ||
1370  (xmlStrEqual(parent->name, BAD_CAST "p")) ||
1371  (xmlStrEqual(parent->name, BAD_CAST "div")) ||
1372  (xmlStrEqual(parent->name, BAD_CAST "img")) ||
1373  (xmlStrEqual(parent->name, BAD_CAST "map")) ||
1374  (xmlStrEqual(parent->name, BAD_CAST "applet")) ||
1375  (xmlStrEqual(parent->name, BAD_CAST "form")) ||
1376  (xmlStrEqual(parent->name, BAD_CAST "frame")) ||
1377  (xmlStrEqual(parent->name, BAD_CAST "iframe")))) {
1378  xmlOutputBufferWrite(buf, 5, " id=\"");
1379  xmlAttrSerializeContent(buf, name);
1380  xmlOutputBufferWrite(buf, 1, "\"");
1381  }
1382  }
1383  /*
1384  * C.7.
1385  */
1386  if ((lang != NULL) && (xml_lang == NULL)) {
1387  xmlOutputBufferWrite(buf, 11, " xml:lang=\"");
1388  xmlAttrSerializeContent(buf, lang);
1389  xmlOutputBufferWrite(buf, 1, "\"");
1390  } else
1391  if ((xml_lang != NULL) && (lang == NULL)) {
1392  xmlOutputBufferWrite(buf, 7, " lang=\"");
1393  xmlAttrSerializeContent(buf, xml_lang);
1394  xmlOutputBufferWrite(buf, 1, "\"");
1395  }
1396 }
1397 
1411 static void
1412 xhtmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
1414 
1415  if (cur == NULL) return;
1416  buf = ctxt->buf;
1417  while (cur != NULL) {
1418  if ((ctxt->format == 1) && (xmlIndentTreeOutput) &&
1419  (cur->type == XML_ELEMENT_NODE))
1420  xmlOutputBufferWrite(buf, ctxt->indent_size *
1421  (ctxt->level > ctxt->indent_nr ?
1422  ctxt->indent_nr : ctxt->level),
1423  ctxt->indent);
1424  xhtmlNodeDumpOutput(ctxt, cur);
1425  if (ctxt->format == 1) {
1426  xmlOutputBufferWrite(buf, 1, "\n");
1427  }
1428  cur = cur->next;
1429  }
1430 }
1431 
1443 static void
1444 xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
1445  int format, addmeta = 0;
1446  xmlNodePtr tmp;
1447  xmlChar *start, *end;
1449 
1450  if (cur == NULL) return;
1451  if ((cur->type == XML_DOCUMENT_NODE) ||
1452  (cur->type == XML_HTML_DOCUMENT_NODE)) {
1453  xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
1454  return;
1455  }
1456  if (cur->type == XML_XINCLUDE_START)
1457  return;
1458  if (cur->type == XML_XINCLUDE_END)
1459  return;
1460  if (cur->type == XML_NAMESPACE_DECL) {
1461  xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
1462  return;
1463  }
1464  if (cur->type == XML_DTD_NODE) {
1465  xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
1466  return;
1467  }
1468  if (cur->type == XML_DOCUMENT_FRAG_NODE) {
1469  xhtmlNodeListDumpOutput(ctxt, cur->children);
1470  return;
1471  }
1472  buf = ctxt->buf;
1473  if (cur->type == XML_ELEMENT_DECL) {
1474  xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
1475  return;
1476  }
1477  if (cur->type == XML_ATTRIBUTE_DECL) {
1478  xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
1479  return;
1480  }
1481  if (cur->type == XML_ENTITY_DECL) {
1482  xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
1483  return;
1484  }
1485  if (cur->type == XML_TEXT_NODE) {
1486  if (cur->content != NULL) {
1487  if ((cur->name == xmlStringText) ||
1488  (cur->name != xmlStringTextNoenc)) {
1489  xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
1490  } else {
1491  /*
1492  * Disable escaping, needed for XSLT
1493  */
1494  xmlOutputBufferWriteString(buf, (const char *) cur->content);
1495  }
1496  }
1497 
1498  return;
1499  }
1500  if (cur->type == XML_PI_NODE) {
1501  if (cur->content != NULL) {
1502  xmlOutputBufferWrite(buf, 2, "<?");
1503  xmlOutputBufferWriteString(buf, (const char *)cur->name);
1504  if (cur->content != NULL) {
1505  xmlOutputBufferWrite(buf, 1, " ");
1506  xmlOutputBufferWriteString(buf, (const char *)cur->content);
1507  }
1508  xmlOutputBufferWrite(buf, 2, "?>");
1509  } else {
1510  xmlOutputBufferWrite(buf, 2, "<?");
1511  xmlOutputBufferWriteString(buf, (const char *)cur->name);
1512  xmlOutputBufferWrite(buf, 2, "?>");
1513  }
1514  return;
1515  }
1516  if (cur->type == XML_COMMENT_NODE) {
1517  if (cur->content != NULL) {
1518  xmlOutputBufferWrite(buf, 4, "<!--");
1519  xmlOutputBufferWriteString(buf, (const char *)cur->content);
1520  xmlOutputBufferWrite(buf, 3, "-->");
1521  }
1522  return;
1523  }
1524  if (cur->type == XML_ENTITY_REF_NODE) {
1525  xmlOutputBufferWrite(buf, 1, "&");
1526  xmlOutputBufferWriteString(buf, (const char *)cur->name);
1527  xmlOutputBufferWrite(buf, 1, ";");
1528  return;
1529  }
1530  if (cur->type == XML_CDATA_SECTION_NODE) {
1531  if (cur->content == NULL || *cur->content == '\0') {
1532  xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
1533  } else {
1534  start = end = cur->content;
1535  while (*end != '\0') {
1536  if (*end == ']' && *(end + 1) == ']' && *(end + 2) == '>') {
1537  end = end + 2;
1538  xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1539  xmlOutputBufferWrite(buf, end - start, (const char *)start);
1540  xmlOutputBufferWrite(buf, 3, "]]>");
1541  start = end;
1542  }
1543  end++;
1544  }
1545  if (start != end) {
1546  xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1547  xmlOutputBufferWriteString(buf, (const char *)start);
1548  xmlOutputBufferWrite(buf, 3, "]]>");
1549  }
1550  }
1551  return;
1552  }
1553  if (cur->type == XML_ATTRIBUTE_NODE) {
1554  xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
1555  return;
1556  }
1557 
1558  format = ctxt->format;
1559  if (format == 1) {
1560  tmp = cur->children;
1561  while (tmp != NULL) {
1562  if ((tmp->type == XML_TEXT_NODE) ||
1563  (tmp->type == XML_ENTITY_REF_NODE)) {
1564  format = 0;
1565  break;
1566  }
1567  tmp = tmp->next;
1568  }
1569  }
1570  xmlOutputBufferWrite(buf, 1, "<");
1571  if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1572  xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
1573  xmlOutputBufferWrite(buf, 1, ":");
1574  }
1575 
1576  xmlOutputBufferWriteString(buf, (const char *)cur->name);
1577  if (cur->nsDef)
1578  xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
1579  if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
1580  (cur->ns == NULL) && (cur->nsDef == NULL))) {
1581  /*
1582  * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
1583  */
1584  xmlOutputBufferWriteString(buf,
1585  " xmlns=\"http://www.w3.org/1999/xhtml\"");
1586  }
1587  if (cur->properties != NULL)
1588  xhtmlAttrListDumpOutput(ctxt, cur->properties);
1589 
1590  if ((cur->type == XML_ELEMENT_NODE) &&
1591  (cur->parent != NULL) &&
1592  (cur->parent->parent == (xmlNodePtr) cur->doc) &&
1593  xmlStrEqual(cur->name, BAD_CAST"head") &&
1594  xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
1595 
1596  tmp = cur->children;
1597  while (tmp != NULL) {
1598  if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
1599  xmlChar *httpequiv;
1600 
1601  httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
1602  if (httpequiv != NULL) {
1603  if (xmlStrcasecmp(httpequiv, BAD_CAST"Content-Type") == 0) {
1604  xmlFree(httpequiv);
1605  break;
1606  }
1607  xmlFree(httpequiv);
1608  }
1609  }
1610  tmp = tmp->next;
1611  }
1612  if (tmp == NULL)
1613  addmeta = 1;
1614  }
1615 
1616  if ((cur->type == XML_ELEMENT_NODE) && (cur->children == NULL)) {
1617  if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
1618  ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) {
1619  /*
1620  * C.2. Empty Elements
1621  */
1622  xmlOutputBufferWrite(buf, 3, " />");
1623  } else {
1624  if (addmeta == 1) {
1625  xmlOutputBufferWrite(buf, 1, ">");
1626  if (ctxt->format == 1) {
1627  xmlOutputBufferWrite(buf, 1, "\n");
1628  if (xmlIndentTreeOutput)
1629  xmlOutputBufferWrite(buf, ctxt->indent_size *
1630  (ctxt->level + 1 > ctxt->indent_nr ?
1631  ctxt->indent_nr : ctxt->level + 1), ctxt->indent);
1632  }
1633  xmlOutputBufferWriteString(buf,
1634  "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
1635  if (ctxt->encoding) {
1636  xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding);
1637  } else {
1638  xmlOutputBufferWrite(buf, 5, "UTF-8");
1639  }
1640  xmlOutputBufferWrite(buf, 4, "\" />");
1641  if (ctxt->format == 1)
1642  xmlOutputBufferWrite(buf, 1, "\n");
1643  } else {
1644  xmlOutputBufferWrite(buf, 1, ">");
1645  }
1646  /*
1647  * C.3. Element Minimization and Empty Element Content
1648  */
1649  xmlOutputBufferWrite(buf, 2, "</");
1650  if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1651  xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
1652  xmlOutputBufferWrite(buf, 1, ":");
1653  }
1654  xmlOutputBufferWriteString(buf, (const char *)cur->name);
1655  xmlOutputBufferWrite(buf, 1, ">");
1656  }
1657  return;
1658  }
1659  xmlOutputBufferWrite(buf, 1, ">");
1660  if (addmeta == 1) {
1661  if (ctxt->format == 1) {
1662  xmlOutputBufferWrite(buf, 1, "\n");
1663  if (xmlIndentTreeOutput)
1664  xmlOutputBufferWrite(buf, ctxt->indent_size *
1665  (ctxt->level + 1 > ctxt->indent_nr ?
1666  ctxt->indent_nr : ctxt->level + 1), ctxt->indent);
1667  }
1668  xmlOutputBufferWriteString(buf,
1669  "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
1670  if (ctxt->encoding) {
1671  xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding);
1672  } else {
1673  xmlOutputBufferWrite(buf, 5, "UTF-8");
1674  }
1675  xmlOutputBufferWrite(buf, 4, "\" />");
1676  }
1677  if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
1678  xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
1679  }
1680 
1681 #if 0
1682  /*
1683  * This was removed due to problems with HTML processors.
1684  * See bug #345147.
1685  */
1686  /*
1687  * 4.8. Script and Style elements
1688  */
1689  if ((cur->type == XML_ELEMENT_NODE) &&
1690  ((xmlStrEqual(cur->name, BAD_CAST "script")) ||
1691  (xmlStrEqual(cur->name, BAD_CAST "style"))) &&
1692  ((cur->ns == NULL) ||
1693  (xmlStrEqual(cur->ns->href, XHTML_NS_NAME)))) {
1694  xmlNodePtr child = cur->children;
1695 
1696  while (child != NULL) {
1697  if (child->type == XML_TEXT_NODE) {
1698  if ((xmlStrchr(child->content, '<') == NULL) &&
1699  (xmlStrchr(child->content, '&') == NULL) &&
1700  (xmlStrstr(child->content, BAD_CAST "]]>") == NULL)) {
1701  /* Nothing to escape, so just output as is... */
1702  /* FIXME: Should we do something about "--" also? */
1703  int level = ctxt->level;
1704  int indent = ctxt->format;
1705 
1706  ctxt->level = 0;
1707  ctxt->format = 0;
1708  xmlOutputBufferWriteString(buf, (const char *) child->content);
1709  /* (We cannot use xhtmlNodeDumpOutput() here because
1710  * we wish to leave '>' unescaped!) */
1711  ctxt->level = level;
1712  ctxt->format = indent;
1713  } else {
1714  /* We must use a CDATA section. Unfortunately,
1715  * this will break CSS and JavaScript when read by
1716  * a browser in HTML4-compliant mode. :-( */
1717  start = end = child->content;
1718  while (*end != '\0') {
1719  if (*end == ']' &&
1720  *(end + 1) == ']' &&
1721  *(end + 2) == '>') {
1722  end = end + 2;
1723  xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1724  xmlOutputBufferWrite(buf, end - start,
1725  (const char *)start);
1726  xmlOutputBufferWrite(buf, 3, "]]>");
1727  start = end;
1728  }
1729  end++;
1730  }
1731  if (start != end) {
1732  xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1733  xmlOutputBufferWrite(buf, end - start,
1734  (const char *)start);
1735  xmlOutputBufferWrite(buf, 3, "]]>");
1736  }
1737  }
1738  } else {
1739  int level = ctxt->level;
1740  int indent = ctxt->format;
1741 
1742  ctxt->level = 0;
1743  ctxt->format = 0;
1744  xhtmlNodeDumpOutput(ctxt, child);
1745  ctxt->level = level;
1746  ctxt->format = indent;
1747  }
1748  child = child->next;
1749  }
1750  }
1751 #endif
1752 
1753  if (cur->children != NULL) {
1754  int indent = ctxt->format;
1755 
1756  if (format == 1) xmlOutputBufferWrite(buf, 1, "\n");
1757  if (ctxt->level >= 0) ctxt->level++;
1758  ctxt->format = format;
1759  xhtmlNodeListDumpOutput(ctxt, cur->children);
1760  if (ctxt->level > 0) ctxt->level--;
1761  ctxt->format = indent;
1762  if ((xmlIndentTreeOutput) && (format == 1))
1763  xmlOutputBufferWrite(buf, ctxt->indent_size *
1764  (ctxt->level > ctxt->indent_nr ?
1765  ctxt->indent_nr : ctxt->level),
1766  ctxt->indent);
1767  }
1768  xmlOutputBufferWrite(buf, 2, "</");
1769  if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1770  xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
1771  xmlOutputBufferWrite(buf, 1, ":");
1772  }
1773 
1774  xmlOutputBufferWriteString(buf, (const char *)cur->name);
1775  xmlOutputBufferWrite(buf, 1, ">");
1776 }
1777 #endif
1778 
1779 /************************************************************************
1780  * *
1781  * Public entry points *
1782  * *
1783  ************************************************************************/
1784 
1796 xmlSaveCtxtPtr
1797 xmlSaveToFd(int fd, const char *encoding, int options)
1798 {
1799  xmlSaveCtxtPtr ret;
1800 
1801  ret = xmlNewSaveCtxt(encoding, options);
1802  if (ret == NULL) return(NULL);
1803  ret->buf = xmlOutputBufferCreateFd(fd, ret->handler);
1804  if (ret->buf == NULL) {
1805  xmlFreeSaveCtxt(ret);
1806  return(NULL);
1807  }
1808  return(ret);
1809 }
1810 
1823 xmlSaveCtxtPtr
1824 xmlSaveToFilename(const char *filename, const char *encoding, int options)
1825 {
1826  xmlSaveCtxtPtr ret;
1827  int compression = 0; /* TODO handle compression option */
1828 
1829  ret = xmlNewSaveCtxt(encoding, options);
1830  if (ret == NULL) return(NULL);
1831  ret->buf = xmlOutputBufferCreateFilename(filename, ret->handler,
1832  compression);
1833  if (ret->buf == NULL) {
1834  xmlFreeSaveCtxt(ret);
1835  return(NULL);
1836  }
1837  return(ret);
1838 }
1839 
1852 xmlSaveCtxtPtr
1853 xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options)
1854 {
1855  xmlSaveCtxtPtr ret;
1856  xmlOutputBufferPtr out_buff;
1858 
1859  ret = xmlNewSaveCtxt(encoding, options);
1860  if (ret == NULL) return(NULL);
1861 
1862  if (encoding != NULL) {
1864  if (handler == NULL) {
1865  xmlFree(ret);
1866  return(NULL);
1867  }
1868  } else
1869  handler = NULL;
1870  out_buff = xmlOutputBufferCreateBuffer(buffer, handler);
1871  if (out_buff == NULL) {
1872  xmlFree(ret);
1874  return(NULL);
1875  }
1876 
1877  ret->buf = out_buff;
1878  return(ret);
1879 }
1880 
1894 xmlSaveCtxtPtr
1895 xmlSaveToIO(xmlOutputWriteCallback iowrite,
1896  xmlOutputCloseCallback ioclose,
1897  void *ioctx, const char *encoding, int options)
1898 {
1899  xmlSaveCtxtPtr ret;
1900 
1901  ret = xmlNewSaveCtxt(encoding, options);
1902  if (ret == NULL) return(NULL);
1903  ret->buf = xmlOutputBufferCreateIO(iowrite, ioclose, ioctx, ret->handler);
1904  if (ret->buf == NULL) {
1905  xmlFreeSaveCtxt(ret);
1906  return(NULL);
1907  }
1908  return(ret);
1909 }
1910 
1922 long
1923 xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc)
1924 {
1925  long ret = 0;
1926 
1927  if ((ctxt == NULL) || (doc == NULL)) return(-1);
1928  if (xmlDocContentDumpOutput(ctxt, doc) < 0)
1929  return(-1);
1930  return(ret);
1931 }
1932 
1944 long
1945 xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr node)
1946 {
1947  long ret = 0;
1948 
1949  if ((ctxt == NULL) || (node == NULL)) return(-1);
1950  xmlNodeDumpOutputInternal(ctxt, node);
1951  return(ret);
1952 }
1953 
1963 int
1964 xmlSaveFlush(xmlSaveCtxtPtr ctxt)
1965 {
1966  if (ctxt == NULL) return(-1);
1967  if (ctxt->buf == NULL) return(-1);
1968  return(xmlOutputBufferFlush(ctxt->buf));
1969 }
1970 
1980 int
1981 xmlSaveClose(xmlSaveCtxtPtr ctxt)
1982 {
1983  int ret;
1984 
1985  if (ctxt == NULL) return(-1);
1986  ret = xmlSaveFlush(ctxt);
1987  xmlFreeSaveCtxt(ctxt);
1988  return(ret);
1989 }
1990 
2000 int
2001 xmlSaveSetEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
2002 {
2003  if (ctxt == NULL) return(-1);
2004  ctxt->escape = escape;
2005  return(0);
2006 }
2007 
2017 int
2018 xmlSaveSetAttrEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
2019 {
2020  if (ctxt == NULL) return(-1);
2021  ctxt->escapeAttr = escape;
2022  return(0);
2023 }
2024 
2025 /************************************************************************
2026  * *
2027  * Public entry points based on buffers *
2028  * *
2029  ************************************************************************/
2030 
2040 void
2041 xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc,
2042  xmlAttrPtr attr, const xmlChar * string)
2043 {
2044  xmlChar *base, *cur;
2045 
2046  if (string == NULL)
2047  return;
2048  base = cur = (xmlChar *) string;
2049  while (*cur != 0) {
2050  if (*cur == '\n') {
2051  if (base != cur)
2052  xmlBufAdd(buf, base, cur - base);
2053  xmlBufAdd(buf, BAD_CAST "&#10;", 5);
2054  cur++;
2055  base = cur;
2056  } else if (*cur == '\r') {
2057  if (base != cur)
2058  xmlBufAdd(buf, base, cur - base);
2059  xmlBufAdd(buf, BAD_CAST "&#13;", 5);
2060  cur++;
2061  base = cur;
2062  } else if (*cur == '\t') {
2063  if (base != cur)
2064  xmlBufAdd(buf, base, cur - base);
2065  xmlBufAdd(buf, BAD_CAST "&#9;", 4);
2066  cur++;
2067  base = cur;
2068  } else if (*cur == '"') {
2069  if (base != cur)
2070  xmlBufAdd(buf, base, cur - base);
2071  xmlBufAdd(buf, BAD_CAST "&quot;", 6);
2072  cur++;
2073  base = cur;
2074  } else if (*cur == '<') {
2075  if (base != cur)
2076  xmlBufAdd(buf, base, cur - base);
2077  xmlBufAdd(buf, BAD_CAST "&lt;", 4);
2078  cur++;
2079  base = cur;
2080  } else if (*cur == '>') {
2081  if (base != cur)
2082  xmlBufAdd(buf, base, cur - base);
2083  xmlBufAdd(buf, BAD_CAST "&gt;", 4);
2084  cur++;
2085  base = cur;
2086  } else if (*cur == '&') {
2087  if (base != cur)
2088  xmlBufAdd(buf, base, cur - base);
2089  xmlBufAdd(buf, BAD_CAST "&amp;", 5);
2090  cur++;
2091  base = cur;
2092  } else if ((*cur >= 0x80) && (cur[1] != 0) &&
2093  ((doc == NULL) || (doc->encoding == NULL))) {
2094  /*
2095  * We assume we have UTF-8 content.
2096  */
2097  unsigned char tmp[12];
2098  int val = 0, l = 1;
2099 
2100  if (base != cur)
2101  xmlBufAdd(buf, base, cur - base);
2102  if (*cur < 0xC0) {
2103  xmlSaveErr(XML_SAVE_NOT_UTF8, (xmlNodePtr) attr, NULL);
2104  xmlSerializeHexCharRef(tmp, *cur);
2105  xmlBufAdd(buf, (xmlChar *) tmp, -1);
2106  cur++;
2107  base = cur;
2108  continue;
2109  } else if (*cur < 0xE0) {
2110  val = (cur[0]) & 0x1F;
2111  val <<= 6;
2112  val |= (cur[1]) & 0x3F;
2113  l = 2;
2114  } else if ((*cur < 0xF0) && (cur [2] != 0)) {
2115  val = (cur[0]) & 0x0F;
2116  val <<= 6;
2117  val |= (cur[1]) & 0x3F;
2118  val <<= 6;
2119  val |= (cur[2]) & 0x3F;
2120  l = 3;
2121  } else if ((*cur < 0xF8) && (cur [2] != 0) && (cur[3] != 0)) {
2122  val = (cur[0]) & 0x07;
2123  val <<= 6;
2124  val |= (cur[1]) & 0x3F;
2125  val <<= 6;
2126  val |= (cur[2]) & 0x3F;
2127  val <<= 6;
2128  val |= (cur[3]) & 0x3F;
2129  l = 4;
2130  }
2131  if ((l == 1) || (!IS_CHAR(val))) {
2132  xmlSaveErr(XML_SAVE_CHAR_INVALID, (xmlNodePtr) attr, NULL);
2133  xmlSerializeHexCharRef(tmp, *cur);
2134  xmlBufAdd(buf, (xmlChar *) tmp, -1);
2135  cur++;
2136  base = cur;
2137  continue;
2138  }
2139  /*
2140  * We could do multiple things here. Just save
2141  * as a char ref
2142  */
2143  xmlSerializeHexCharRef(tmp, val);
2144  xmlBufAdd(buf, (xmlChar *) tmp, -1);
2145  cur += l;
2146  base = cur;
2147  } else {
2148  cur++;
2149  }
2150  }
2151  if (base != cur)
2152  xmlBufAdd(buf, base, cur - base);
2153 }
2154 
2164 void
2165 xmlAttrSerializeTxtContent(xmlBufferPtr buf, xmlDocPtr doc,
2166  xmlAttrPtr attr, const xmlChar * string)
2167 {
2168  xmlBufPtr buffer;
2169 
2170  if ((buf == NULL) || (string == NULL))
2171  return;
2173  if (buffer == NULL)
2174  return;
2175  xmlBufAttrSerializeTxtContent(buffer, doc, attr, string);
2177 }
2178 
2195 int
2196 xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2197  int format)
2198 {
2199  xmlBufPtr buffer;
2200  int ret;
2201 
2202  if ((buf == NULL) || (cur == NULL))
2203  return(-1);
2205  if (buffer == NULL)
2206  return(-1);
2207  ret = xmlBufNodeDump(buffer, doc, cur, level, format);
2209  if (ret > INT_MAX)
2210  return(-1);
2211  return((int) ret);
2212 }
2213 
2230 size_t
2231 xmlBufNodeDump(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2232  int format)
2233 {
2234  size_t use;
2235  int ret;
2236  xmlOutputBufferPtr outbuf;
2237  int oldalloc;
2238 
2239  xmlInitParser();
2240 
2241  if (cur == NULL) {
2242 #ifdef DEBUG_TREE
2244  "xmlNodeDump : node == NULL\n");
2245 #endif
2246  return (-1);
2247  }
2248  if (buf == NULL) {
2249 #ifdef DEBUG_TREE
2251  "xmlNodeDump : buf == NULL\n");
2252 #endif
2253  return (-1);
2254  }
2255  outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2256  if (outbuf == NULL) {
2257  xmlSaveErrMemory("creating buffer");
2258  return (-1);
2259  }
2260  memset(outbuf, 0, (size_t) sizeof(xmlOutputBuffer));
2261  outbuf->buffer = buf;
2262  outbuf->encoder = NULL;
2263  outbuf->writecallback = NULL;
2264  outbuf->closecallback = NULL;
2265  outbuf->context = NULL;
2266  outbuf->written = 0;
2267 
2268  use = xmlBufUse(buf);
2269  oldalloc = xmlBufGetAllocationScheme(buf);
2271  xmlNodeDumpOutput(outbuf, doc, cur, level, format, NULL);
2272  xmlBufSetAllocationScheme(buf, oldalloc);
2273  xmlFree(outbuf);
2274  ret = xmlBufUse(buf) - use;
2275  return (ret);
2276 }
2277 
2286 void
2287 xmlElemDump(FILE * f, xmlDocPtr doc, xmlNodePtr cur)
2288 {
2289  xmlOutputBufferPtr outbuf;
2290 
2291  xmlInitParser();
2292 
2293  if (cur == NULL) {
2294 #ifdef DEBUG_TREE
2296  "xmlElemDump : cur == NULL\n");
2297 #endif
2298  return;
2299  }
2300 #ifdef DEBUG_TREE
2301  if (doc == NULL) {
2303  "xmlElemDump : doc == NULL\n");
2304  }
2305 #endif
2306 
2307  outbuf = xmlOutputBufferCreateFile(f, NULL);
2308  if (outbuf == NULL)
2309  return;
2310  if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2311 #ifdef LIBXML_HTML_ENABLED
2312  htmlNodeDumpOutput(outbuf, doc, cur, NULL);
2313 #else
2314  xmlSaveErr(XML_ERR_INTERNAL_ERROR, cur, "HTML support not compiled in\n");
2315 #endif /* LIBXML_HTML_ENABLED */
2316  } else
2317  xmlNodeDumpOutput(outbuf, doc, cur, 0, 1, NULL);
2318  xmlOutputBufferClose(outbuf);
2319 }
2320 
2321 /************************************************************************
2322  * *
2323  * Saving functions front-ends *
2324  * *
2325  ************************************************************************/
2326 
2340 void
2341 xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
2342  int level, int format, const char *encoding)
2343 {
2344  xmlSaveCtxt ctxt;
2345 #ifdef LIBXML_HTML_ENABLED
2346  xmlDtdPtr dtd;
2347  int is_xhtml = 0;
2348 #endif
2349 
2350  xmlInitParser();
2351 
2352  if ((buf == NULL) || (cur == NULL)) return;
2353 
2354  if (encoding == NULL)
2355  encoding = "UTF-8";
2356 
2357  memset(&ctxt, 0, sizeof(ctxt));
2358  ctxt.buf = buf;
2359  ctxt.level = level;
2360  ctxt.format = format ? 1 : 0;
2361  ctxt.encoding = (const xmlChar *) encoding;
2362  xmlSaveCtxtInit(&ctxt);
2363  ctxt.options |= XML_SAVE_AS_XML;
2364 
2365 #ifdef LIBXML_HTML_ENABLED
2366  dtd = xmlGetIntSubset(doc);
2367  if (dtd != NULL) {
2368  is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
2369  if (is_xhtml < 0)
2370  is_xhtml = 0;
2371  }
2372 
2373  if (is_xhtml)
2374  xhtmlNodeDumpOutput(&ctxt, cur);
2375  else
2376 #endif
2377  xmlNodeDumpOutputInternal(&ctxt, cur);
2378 }
2379 
2395 void
2396 xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
2397  int * doc_txt_len, const char * txt_encoding,
2398  int format) {
2399  xmlSaveCtxt ctxt;
2400  int dummy = 0;
2401  xmlOutputBufferPtr out_buff = NULL;
2402  xmlCharEncodingHandlerPtr conv_hdlr = NULL;
2403 
2404  if (doc_txt_len == NULL) {
2405  doc_txt_len = &dummy; /* Continue, caller just won't get length */
2406  }
2407 
2408  if (doc_txt_ptr == NULL) {
2409  *doc_txt_len = 0;
2410  return;
2411  }
2412 
2413  *doc_txt_ptr = NULL;
2414  *doc_txt_len = 0;
2415 
2416  if (out_doc == NULL) {
2417  /* No document, no output */
2418  return;
2419  }
2420 
2421  /*
2422  * Validate the encoding value, if provided.
2423  * This logic is copied from xmlSaveFileEnc.
2424  */
2425 
2426  if (txt_encoding == NULL)
2427  txt_encoding = (const char *) out_doc->encoding;
2428  if (txt_encoding != NULL) {
2429  conv_hdlr = xmlFindCharEncodingHandler(txt_encoding);
2430  if ( conv_hdlr == NULL ) {
2431  xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, (xmlNodePtr) out_doc,
2432  txt_encoding);
2433  return;
2434  }
2435  }
2436 
2437  if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) {
2438  xmlSaveErrMemory("creating buffer");
2439  return;
2440  }
2441 
2442  memset(&ctxt, 0, sizeof(ctxt));
2443  ctxt.buf = out_buff;
2444  ctxt.level = 0;
2445  ctxt.format = format ? 1 : 0;
2446  ctxt.encoding = (const xmlChar *) txt_encoding;
2447  xmlSaveCtxtInit(&ctxt);
2448  ctxt.options |= XML_SAVE_AS_XML;
2449  xmlDocContentDumpOutput(&ctxt, out_doc);
2450  xmlOutputBufferFlush(out_buff);
2451  if (out_buff->conv != NULL) {
2452  *doc_txt_len = xmlBufUse(out_buff->conv);
2453  *doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->conv), *doc_txt_len);
2454  } else {
2455  *doc_txt_len = xmlBufUse(out_buff->buffer);
2456  *doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->buffer),*doc_txt_len);
2457  }
2458  (void)xmlOutputBufferClose(out_buff);
2459 
2460  if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) {
2461  *doc_txt_len = 0;
2462  xmlSaveErrMemory("creating output");
2463  }
2464 
2465  return;
2466 }
2467 
2479 void
2480 xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
2481  xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, 0);
2482 }
2483 
2497 void
2498 xmlDocDumpFormatMemory(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
2499  xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, format);
2500 }
2501 
2514 void
2515 xmlDocDumpMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
2516  int * doc_txt_len, const char * txt_encoding) {
2517  xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len,
2518  txt_encoding, 0);
2519 }
2520 
2533 int
2534 xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) {
2535  xmlSaveCtxt ctxt;
2537  const char * encoding;
2539  int ret;
2540 
2541  if (cur == NULL) {
2542 #ifdef DEBUG_TREE
2544  "xmlDocDump : document == NULL\n");
2545 #endif
2546  return(-1);
2547  }
2548  encoding = (const char *) cur->encoding;
2549 
2550  if (encoding != NULL) {
2552  if (handler == NULL) {
2553  xmlFree((char *) cur->encoding);
2554  cur->encoding = NULL;
2555  encoding = NULL;
2556  }
2557  }
2558  buf = xmlOutputBufferCreateFile(f, handler);
2559  if (buf == NULL) return(-1);
2560  memset(&ctxt, 0, sizeof(ctxt));
2561  ctxt.buf = buf;
2562  ctxt.level = 0;
2563  ctxt.format = format ? 1 : 0;
2564  ctxt.encoding = (const xmlChar *) encoding;
2565  xmlSaveCtxtInit(&ctxt);
2566  ctxt.options |= XML_SAVE_AS_XML;
2567  xmlDocContentDumpOutput(&ctxt, cur);
2568 
2569  ret = xmlOutputBufferClose(buf);
2570  return(ret);
2571 }
2572 
2582 int
2583 xmlDocDump(FILE *f, xmlDocPtr cur) {
2584  return(xmlDocFormatDump (f, cur, 0));
2585 }
2586 
2599 int
2600 xmlSaveFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding) {
2601  xmlSaveCtxt ctxt;
2602  int ret;
2603 
2604  if (buf == NULL) return(-1);
2605  if (cur == NULL) {
2606  xmlOutputBufferClose(buf);
2607  return(-1);
2608  }
2609  memset(&ctxt, 0, sizeof(ctxt));
2610  ctxt.buf = buf;
2611  ctxt.level = 0;
2612  ctxt.format = 0;
2613  ctxt.encoding = (const xmlChar *) encoding;
2614  xmlSaveCtxtInit(&ctxt);
2615  ctxt.options |= XML_SAVE_AS_XML;
2616  xmlDocContentDumpOutput(&ctxt, cur);
2617  ret = xmlOutputBufferClose(buf);
2618  return(ret);
2619 }
2620 
2634 int
2635 xmlSaveFormatFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur,
2636  const char *encoding, int format)
2637 {
2638  xmlSaveCtxt ctxt;
2639  int ret;
2640 
2641  if (buf == NULL) return(-1);
2642  if ((cur == NULL) ||
2643  ((cur->type != XML_DOCUMENT_NODE) &&
2644  (cur->type != XML_HTML_DOCUMENT_NODE))) {
2645  xmlOutputBufferClose(buf);
2646  return(-1);
2647  }
2648  memset(&ctxt, 0, sizeof(ctxt));
2649  ctxt.buf = buf;
2650  ctxt.level = 0;
2651  ctxt.format = format ? 1 : 0;
2652  ctxt.encoding = (const xmlChar *) encoding;
2653  xmlSaveCtxtInit(&ctxt);
2654  ctxt.options |= XML_SAVE_AS_XML;
2655  xmlDocContentDumpOutput(&ctxt, cur);
2656  ret = xmlOutputBufferClose(buf);
2657  return (ret);
2658 }
2659 
2673 int
2674 xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur,
2675  const char * encoding, int format ) {
2676  xmlSaveCtxt ctxt;
2679  int ret;
2680 
2681  if (cur == NULL)
2682  return(-1);
2683 
2684  if (encoding == NULL)
2685  encoding = (const char *) cur->encoding;
2686 
2687  if (encoding != NULL) {
2688 
2690  if (handler == NULL)
2691  return(-1);
2692  }
2693 
2694 #ifdef LIBXML_ZLIB_ENABLED
2695  if (cur->compression < 0) cur->compression = xmlGetCompressMode();
2696 #endif
2697  /*
2698  * save the content to a temp buffer.
2699  */
2700  buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
2701  if (buf == NULL) return(-1);
2702  memset(&ctxt, 0, sizeof(ctxt));
2703  ctxt.buf = buf;
2704  ctxt.level = 0;
2705  ctxt.format = format ? 1 : 0;
2706  ctxt.encoding = (const xmlChar *) encoding;
2707  xmlSaveCtxtInit(&ctxt);
2708  ctxt.options |= XML_SAVE_AS_XML;
2709 
2710  xmlDocContentDumpOutput(&ctxt, cur);
2711 
2712  ret = xmlOutputBufferClose(buf);
2713  return(ret);
2714 }
2715 
2716 
2727 int
2728 xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
2729  return ( xmlSaveFormatFileEnc( filename, cur, encoding, 0 ) );
2730 }
2731 
2746 int
2747 xmlSaveFormatFile(const char *filename, xmlDocPtr cur, int format) {
2748  return ( xmlSaveFormatFileEnc( filename, cur, NULL, format ) );
2749 }
2750 
2761 int
2762 xmlSaveFile(const char *filename, xmlDocPtr cur) {
2763  return(xmlSaveFormatFileEnc(filename, cur, NULL, 0));
2764 }
2765 
2766 #endif /* LIBXML_OUTPUT_ENABLED */
2767 
2768 #define bottom_xmlsave
2769 #include "elfgcchack.h"
GLint level
Definition: gl.h:1546
xmlElementType type
Definition: tree.h:553
XMLPUBFUN const xmlChar *XMLCALL xmlStrstr(const xmlChar *str, const xmlChar *val)
Definition: xmlstring.c:341
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
XMLPUBFUN xmlCharEncoding XMLCALL xmlParseCharEncoding(const char *name)
Definition: encoding.c:1150
static const WCHAR indent[]
Definition: object.c:1156
XMLPUBFUN xmlChar *XMLCALL xmlBufContent(const xmlBuf *buf)
Definition: buf.c:582
#define INT_MAX
Definition: limits.h:40
#define error(str)
Definition: mkdosfs.c:1605
const xmlChar * name
Definition: tree.h:492
#define XHTML_TRANS_SYSTEM_ID
Definition: xmlsave.c:41
struct _xmlDoc * doc
Definition: tree.h:415
void * notations
Definition: tree.h:418
Definition: tree.h:389
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:41
XMLPUBFUN void XMLCALL xmlInitParser(void)
Definition: parser.c:14740
int xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID)
Definition: xmlsave.c:55
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:422
XMLPUBFUN xmlChar *XMLCALL xmlGetProp(const xmlNode *node, const xmlChar *name)
#define MAX_INDENT
Definition: xmlsave.c:18
#define XHTML_TRANS_PUBLIC_ID
Definition: xmlsave.c:39
xmlBufPtr xmlBufFromBuffer(xmlBufferPtr buffer)
Definition: buf.c:1167
GLuint buffer
Definition: glext.h:5915
static int fd
Definition: io.c:51
xmlCharEncoding
Definition: encoding.h:58
XMLPUBVAR int xmlIndentTreeOutput
Definition: globals.h:387
const char * filename
Definition: ioapi.h:135
XMLPUBFUN const xmlChar *XMLCALL xmlStrchr(const xmlChar *str, xmlChar val)
Definition: xmlstring.c:321
void * attributes
Definition: tree.h:420
static HWND child
Definition: cursoricon.c:298
XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreate(void)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
Definition: tree.h:406
struct _xmlOutputBuffer xmlOutputBuffer
Definition: tree.h:31
Definition: buf.c:43
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint base
Definition: 3dtext.c:35
const xmlChar * name
Definition: tree.h:409
xmlOutputBuffer * xmlOutputBufferPtr
Definition: tree.h:32
XMLPUBFUN int XMLCALL xmlGetCompressMode(void)
int(* xmlCharEncodingOutputFunc)(unsigned char *out, int *outlen, const unsigned char *in, int *inlen)
Definition: encoding.h:123
static size_t elem
Definition: string.c:68
#define IS_CHAR(c)
#define XHTML_STRICT_SYSTEM_ID
Definition: xmlsave.c:33
static PVOID ptr
Definition: dispmode.c:27
XMLPUBVAR const xmlChar xmlStringText[]
XMLPUBVAR xmlGenericErrorFunc xmlGenericError
Definition: globals.h:346
#define XML_LOCAL_NAMESPACE
Definition: tree.h:374
void xmlBufFree(xmlBufPtr buf)
Definition: buf.c:329
xmlNode * xmlNodePtr
Definition: tree.h:488
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBVAR const char * xmlTreeIndentString
Definition: globals.h:396
int options
Definition: main.c:106
#define XHTML_FRAME_PUBLIC_ID
Definition: xmlsave.c:35
GLuint GLfloat * val
Definition: glext.h:7180
const xmlChar * ExternalID
Definition: tree.h:422
r l[0]
Definition: byte_order.h:167
static const WCHAR lang[]
Definition: wbemdisp.c:287
GLfloat f
Definition: glext.h:7540
GLsizeiptr size
Definition: glext.h:5919
Definition: id3.c:95
r parent
Definition: btrfs.c:2944
if(!(yy_init))
Definition: macro.lex.yy.c:714
void * elements
Definition: tree.h:419
#define IS_BYTE_CHAR(c)
static FILE * out
Definition: regtests2xml.c:44
int xmlCharEncOutput(xmlOutputBufferPtr output, int init)
XMLPUBFUN int XMLCALL xmlCharEncCloseFunc(xmlCharEncodingHandler *handler)
Definition: encoding.c:2720
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:250
int xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len)
Definition: buf.c:868
Definition: cookie.c:201
xmlChar * content
Definition: tree.h:502
const xmlChar * SystemID
Definition: tree.h:423
void * entities
Definition: tree.h:421
GLuint GLuint end
Definition: gl.h:1545
Definition: tree.h:489
int ret
xmlBufferPtr xmlBufBackToBuffer(xmlBufPtr buf)
Definition: buf.c:1204
XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL xmlFindCharEncodingHandler(const char *name)
Definition: encoding.c:1641
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t compression
Definition: btrfs_drv.h:1357
unsigned char xmlChar
Definition: xmlstring.h:28
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
xmlBufPtr xmlBufCreate(void)
Definition: buf.c:122
Definition: inflate.c:139
const xmlChar * encoding
Definition: tree.h:574
xmlElementType type
Definition: tree.h:491
ed encoding
Definition: write.c:2825
FxCollectionEntry * cur
#define XHTML_STRICT_PUBLIC_ID
Definition: xmlsave.c:31
int xmlBufGetAllocationScheme(xmlBufPtr buf)
Definition: buf.c:267
struct _xmlNode * children
Definition: tree.h:410
#define XHTML_NS_NAME
Definition: xmlsave.c:44
XMLPUBVAR int xmlSaveNoEmptyTags
Definition: globals.h:458
int xmlBufSetAllocationScheme(xmlBufPtr buf, xmlBufferAllocationScheme scheme)
Definition: buf.c:288
XMLPUBFUN xmlNodePtr XMLCALL xmlNewText(const xmlChar *content)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLuint in
Definition: glext.h:9616
struct _xmlNode * next
Definition: tree.h:496
GLuint start
Definition: gl.h:1545
unsigned char dummy
Definition: maze.c:118
XMLPUBVAR const xmlChar xmlStringTextNoenc[]
#define NULL
Definition: types.h:112
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:247
Definition: tree.h:551
XMLPUBFUN xmlDtdPtr XMLCALL xmlGetIntSubset(const xmlDoc *doc)
XMLPUBFUN void XMLCALL xmlFreeNode(xmlNodePtr cur)
int xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer)
Definition: buf.c:1257
static WCHAR escape[]
Definition: url.c:36
#define msg(x)
Definition: auth_time.c:54
Definition: mem.c:156
Definition: tree.h:434
Definition: name.c:38
#define XHTML_FRAME_SYSTEM_ID
Definition: xmlsave.c:37
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7786
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:157
#define memset(x, y, z)
Definition: compat.h:39
int xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string)
Definition: buf.c:1111
void * pentities
Definition: tree.h:424
XMLPUBFUN int XMLCALL xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:271
XMLPUBFUN size_t XMLCALL xmlBufUse(const xmlBufPtr buf)
Definition: buf.c:687
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:66
Definition: dlist.c:348
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:362