ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

xmlsave.c
Go to the documentation of this file.
00001 /*
00002  * xmlsave.c: Implemetation of the document serializer
00003  *
00004  * See Copyright for the status of this software.
00005  *
00006  * daniel@veillard.com
00007  */
00008 
00009 #define IN_LIBXML
00010 #include "libxml.h"
00011 
00012 #include <string.h>
00013 #include <libxml/xmlmemory.h>
00014 #include <libxml/parserInternals.h>
00015 #include <libxml/tree.h>
00016 #include <libxml/xmlsave.h>
00017 
00018 #define MAX_INDENT 60
00019 
00020 #include <libxml/HTMLtree.h>
00021 
00022 /************************************************************************
00023  *                                  *
00024  *          XHTML detection                 *
00025  *                                  *
00026  ************************************************************************/
00027 #define XHTML_STRICT_PUBLIC_ID BAD_CAST \
00028    "-//W3C//DTD XHTML 1.0 Strict//EN"
00029 #define XHTML_STRICT_SYSTEM_ID BAD_CAST \
00030    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
00031 #define XHTML_FRAME_PUBLIC_ID BAD_CAST \
00032    "-//W3C//DTD XHTML 1.0 Frameset//EN"
00033 #define XHTML_FRAME_SYSTEM_ID BAD_CAST \
00034    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
00035 #define XHTML_TRANS_PUBLIC_ID BAD_CAST \
00036    "-//W3C//DTD XHTML 1.0 Transitional//EN"
00037 #define XHTML_TRANS_SYSTEM_ID BAD_CAST \
00038    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
00039 
00040 #define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml"
00041 
00050 int
00051 xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) {
00052     if ((systemID == NULL) && (publicID == NULL))
00053     return(-1);
00054     if (publicID != NULL) {
00055     if (xmlStrEqual(publicID, XHTML_STRICT_PUBLIC_ID)) return(1);
00056     if (xmlStrEqual(publicID, XHTML_FRAME_PUBLIC_ID)) return(1);
00057     if (xmlStrEqual(publicID, XHTML_TRANS_PUBLIC_ID)) return(1);
00058     }
00059     if (systemID != NULL) {
00060     if (xmlStrEqual(systemID, XHTML_STRICT_SYSTEM_ID)) return(1);
00061     if (xmlStrEqual(systemID, XHTML_FRAME_SYSTEM_ID)) return(1);
00062     if (xmlStrEqual(systemID, XHTML_TRANS_SYSTEM_ID)) return(1);
00063     }
00064     return(0);
00065 }
00066 
00067 #ifdef LIBXML_OUTPUT_ENABLED
00068 
00069 #define TODO                                \
00070     xmlGenericError(xmlGenericErrorContext,             \
00071         "Unimplemented block at %s:%d\n",               \
00072             __FILE__, __LINE__);
00073 
00074 struct _xmlSaveCtxt {
00075     void *_private;
00076     int type;
00077     int fd;
00078     const xmlChar *filename;
00079     const xmlChar *encoding;
00080     xmlCharEncodingHandlerPtr handler;
00081     xmlOutputBufferPtr buf;
00082     xmlDocPtr doc;
00083     int options;
00084     int level;
00085     int format;
00086     char indent[MAX_INDENT + 1];    /* array for indenting output */
00087     int indent_nr;
00088     int indent_size;
00089     xmlCharEncodingOutputFunc escape;   /* used for element content */
00090     xmlCharEncodingOutputFunc escapeAttr;/* used for attribute content */
00091 };
00092 
00093 /************************************************************************
00094  *                                  *
00095  *          Output error handlers               *
00096  *                                  *
00097  ************************************************************************/
00104 static void
00105 xmlSaveErrMemory(const char *extra)
00106 {
00107     __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra);
00108 }
00109 
00118 static void
00119 xmlSaveErr(int code, xmlNodePtr node, const char *extra)
00120 {
00121     const char *msg = NULL;
00122 
00123     switch(code) {
00124         case XML_SAVE_NOT_UTF8:
00125         msg = "string is not in UTF-8\n";
00126         break;
00127     case XML_SAVE_CHAR_INVALID:
00128         msg = "invalid character value\n";
00129         break;
00130     case XML_SAVE_UNKNOWN_ENCODING:
00131         msg = "unknown encoding %s\n";
00132         break;
00133     case XML_SAVE_NO_DOCTYPE:
00134         msg = "document has no DOCTYPE\n";
00135         break;
00136     default:
00137         msg = "unexpected error number\n";
00138     }
00139     __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra);
00140 }
00141 
00142 /************************************************************************
00143  *                                  *
00144  *          Special escaping routines           *
00145  *                                  *
00146  ************************************************************************/
00147 static unsigned char *
00148 xmlSerializeHexCharRef(unsigned char *out, int val) {
00149     unsigned char *ptr;
00150 
00151     *out++ = '&';
00152     *out++ = '#';
00153     *out++ = 'x';
00154     if (val < 0x10) ptr = out;
00155     else if (val < 0x100) ptr = out + 1;
00156     else if (val < 0x1000) ptr = out + 2;
00157     else if (val < 0x10000) ptr = out + 3;
00158     else if (val < 0x100000) ptr = out + 4;
00159     else ptr = out + 5;
00160     out = ptr + 1;
00161     while (val > 0) {
00162     switch (val & 0xF) {
00163         case 0: *ptr-- = '0'; break;
00164         case 1: *ptr-- = '1'; break;
00165         case 2: *ptr-- = '2'; break;
00166         case 3: *ptr-- = '3'; break;
00167         case 4: *ptr-- = '4'; break;
00168         case 5: *ptr-- = '5'; break;
00169         case 6: *ptr-- = '6'; break;
00170         case 7: *ptr-- = '7'; break;
00171         case 8: *ptr-- = '8'; break;
00172         case 9: *ptr-- = '9'; break;
00173         case 0xA: *ptr-- = 'A'; break;
00174         case 0xB: *ptr-- = 'B'; break;
00175         case 0xC: *ptr-- = 'C'; break;
00176         case 0xD: *ptr-- = 'D'; break;
00177         case 0xE: *ptr-- = 'E'; break;
00178         case 0xF: *ptr-- = 'F'; break;
00179         default: *ptr-- = '0'; break;
00180     }
00181     val >>= 4;
00182     }
00183     *out++ = ';';
00184     *out = 0;
00185     return(out);
00186 }
00187 
00203 static int
00204 xmlEscapeEntities(unsigned char* out, int *outlen,
00205                  const xmlChar* in, int *inlen) {
00206     unsigned char* outstart = out;
00207     const unsigned char* base = in;
00208     unsigned char* outend = out + *outlen;
00209     const unsigned char* inend;
00210     int val;
00211 
00212     inend = in + (*inlen);
00213     
00214     while ((in < inend) && (out < outend)) {
00215         if (*in == '<') {
00216         if (outend - out < 4) break;
00217         *out++ = '&';
00218         *out++ = 'l';
00219         *out++ = 't';
00220         *out++ = ';';
00221         in++;
00222         continue;
00223     } else if (*in == '>') {
00224         if (outend - out < 4) break;
00225         *out++ = '&';
00226         *out++ = 'g';
00227         *out++ = 't';
00228         *out++ = ';';
00229         in++;
00230         continue;
00231     } else if (*in == '&') {
00232         if (outend - out < 5) break;
00233         *out++ = '&';
00234         *out++ = 'a';
00235         *out++ = 'm';
00236         *out++ = 'p';
00237         *out++ = ';';
00238         in++;
00239         continue;
00240     } else if (((*in >= 0x20) && (*in < 0x80)) ||
00241                (*in == '\n') || (*in == '\t')) {
00242         /*
00243          * default case, just copy !
00244          */
00245         *out++ = *in++;
00246         continue;
00247     } else if (*in >= 0x80) {
00248         /*
00249          * We assume we have UTF-8 input.
00250          */
00251         if (outend - out < 10) break;
00252 
00253         if (*in < 0xC0) {
00254         xmlSaveErr(XML_SAVE_NOT_UTF8, NULL, NULL);
00255         in++;
00256         goto error;
00257         } else if (*in < 0xE0) {
00258         if (inend - in < 2) break;
00259         val = (in[0]) & 0x1F;
00260         val <<= 6;
00261         val |= (in[1]) & 0x3F;
00262         in += 2;
00263         } else if (*in < 0xF0) {
00264         if (inend - in < 3) break;
00265         val = (in[0]) & 0x0F;
00266         val <<= 6;
00267         val |= (in[1]) & 0x3F;
00268         val <<= 6;
00269         val |= (in[2]) & 0x3F;
00270         in += 3;
00271         } else if (*in < 0xF8) {
00272         if (inend - in < 4) break;
00273         val = (in[0]) & 0x07;
00274         val <<= 6;
00275         val |= (in[1]) & 0x3F;
00276         val <<= 6;
00277         val |= (in[2]) & 0x3F;
00278         val <<= 6;
00279         val |= (in[3]) & 0x3F;
00280         in += 4;
00281         } else {
00282         xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);
00283         in++;
00284         goto error;
00285         }
00286         if (!IS_CHAR(val)) {
00287         xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);
00288         in++;
00289         goto error;
00290         }
00291 
00292         /*
00293          * We could do multiple things here. Just save as a char ref
00294          */
00295         out = xmlSerializeHexCharRef(out, val);
00296     } else if (IS_BYTE_CHAR(*in)) {
00297         if (outend - out < 6) break;
00298         out = xmlSerializeHexCharRef(out, *in++);
00299     } else {
00300         xmlGenericError(xmlGenericErrorContext,
00301         "xmlEscapeEntities : char out of range\n");
00302         in++;
00303         goto error;
00304     }
00305     }
00306     *outlen = out - outstart;
00307     *inlen = in - base;
00308     return(0);
00309 error:
00310     *outlen = out - outstart;
00311     *inlen = in - base;
00312     return(-1);
00313 }
00314 
00315 /************************************************************************
00316  *                                  *
00317  *          Allocation and deallocation         *
00318  *                                  *
00319  ************************************************************************/
00326 static void
00327 xmlSaveCtxtInit(xmlSaveCtxtPtr ctxt)
00328 {
00329     int i;
00330     int len;
00331 
00332     if (ctxt == NULL) return;
00333     if ((ctxt->encoding == NULL) && (ctxt->escape == NULL))
00334         ctxt->escape = xmlEscapeEntities;
00335     len = xmlStrlen((xmlChar *)xmlTreeIndentString);
00336     if ((xmlTreeIndentString == NULL) || (len == 0)) {
00337         memset(&ctxt->indent[0], 0, MAX_INDENT + 1);
00338     } else {
00339     ctxt->indent_size = len;
00340     ctxt->indent_nr = MAX_INDENT / ctxt->indent_size;
00341     for (i = 0;i < ctxt->indent_nr;i++)
00342         memcpy(&ctxt->indent[i * ctxt->indent_size], xmlTreeIndentString,
00343            ctxt->indent_size);
00344         ctxt->indent[ctxt->indent_nr * ctxt->indent_size] = 0;
00345     }
00346 
00347     if (xmlSaveNoEmptyTags) {
00348     ctxt->options |= XML_SAVE_NO_EMPTY;
00349     }
00350 }
00351 
00357 static void
00358 xmlFreeSaveCtxt(xmlSaveCtxtPtr ctxt)
00359 {
00360     if (ctxt == NULL) return;
00361     if (ctxt->encoding != NULL)
00362         xmlFree((char *) ctxt->encoding);
00363     if (ctxt->buf != NULL)
00364         xmlOutputBufferClose(ctxt->buf);
00365     xmlFree(ctxt);
00366 }
00367 
00375 static xmlSaveCtxtPtr
00376 xmlNewSaveCtxt(const char *encoding, int options)
00377 {
00378     xmlSaveCtxtPtr ret;
00379 
00380     ret = (xmlSaveCtxtPtr) xmlMalloc(sizeof(xmlSaveCtxt));
00381     if (ret == NULL) {
00382     xmlSaveErrMemory("creating saving context");
00383     return ( NULL );
00384     }
00385     memset(ret, 0, sizeof(xmlSaveCtxt));
00386 
00387     if (encoding != NULL) {
00388         ret->handler = xmlFindCharEncodingHandler(encoding);
00389     if (ret->handler == NULL) {
00390         xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
00391             xmlFreeSaveCtxt(ret);
00392         return(NULL);
00393     }
00394         ret->encoding = xmlStrdup((const xmlChar *)encoding);
00395     ret->escape = NULL;
00396     }
00397     xmlSaveCtxtInit(ret);
00398 
00399     /*
00400      * Use the options
00401      */
00402 
00403     /* Re-check this option as it may already have been set */
00404     if ((ret->options & XML_SAVE_NO_EMPTY) && ! (options & XML_SAVE_NO_EMPTY)) {
00405     options |= XML_SAVE_NO_EMPTY;
00406     }
00407 
00408     ret->options = options;
00409     if (options & XML_SAVE_FORMAT)
00410         ret->format = 1;
00411     else if (options & XML_SAVE_WSNONSIG)
00412         ret->format = 2;
00413 
00414     return(ret);
00415 }
00416 
00417 /************************************************************************
00418  *                                  *
00419  *          Dumping XML tree content to a simple buffer     *
00420  *                                  *
00421  ************************************************************************/
00430 static void
00431 xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr)
00432 {
00433     xmlNodePtr children;
00434 
00435     children = attr->children;
00436     while (children != NULL) {
00437         switch (children->type) {
00438             case XML_TEXT_NODE:
00439             xmlAttrSerializeTxtContent(buf->buffer, attr->doc,
00440                                    attr, children->content);
00441         break;
00442             case XML_ENTITY_REF_NODE:
00443                 xmlBufferAdd(buf->buffer, BAD_CAST "&", 1);
00444                 xmlBufferAdd(buf->buffer, children->name,
00445                              xmlStrlen(children->name));
00446                 xmlBufferAdd(buf->buffer, BAD_CAST ";", 1);
00447                 break;
00448             default:
00449                 /* should not happen unless we have a badly built tree */
00450                 break;
00451         }
00452         children = children->next;
00453     }
00454 }
00455 
00456 /************************************************************************
00457  *                                  *
00458  *          Dumping XML tree content to an I/O output buffer    *
00459  *                                  *
00460  ************************************************************************/
00461 
00462 static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) {
00463     xmlOutputBufferPtr buf = ctxt->buf;
00464 
00465     if ((encoding != NULL) && (buf->encoder == NULL) && (buf->conv == NULL)) {
00466     buf->encoder = xmlFindCharEncodingHandler((const char *)encoding);
00467     if (buf->encoder == NULL) {
00468         xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL,
00469                (const char *)encoding);
00470         return(-1);
00471     }
00472     buf->conv = xmlBufferCreate();
00473     if (buf->conv == NULL) {
00474         xmlCharEncCloseFunc(buf->encoder);
00475         xmlSaveErrMemory("creating encoding buffer");
00476         return(-1);
00477     }
00478     /*
00479      * initialize the state, e.g. if outputting a BOM
00480      */
00481     xmlCharEncOutFunc(buf->encoder, buf->conv, NULL);
00482     }
00483     return(0);
00484 }
00485 
00486 static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) {
00487     xmlOutputBufferPtr buf = ctxt->buf;
00488     xmlOutputBufferFlush(buf);
00489     xmlCharEncCloseFunc(buf->encoder);
00490     xmlBufferFree(buf->conv);
00491     buf->encoder = NULL;
00492     buf->conv = NULL;
00493     return(0);
00494 }
00495 
00496 #ifdef LIBXML_HTML_ENABLED
00497 static void
00498 xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
00499 #endif
00500 static void xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
00501 static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
00502 void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
00503 static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur);
00504 
00512 static void
00513 xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra)
00514 {
00515     int i;
00516     if ((ctxt == NULL) || (ctxt->buf == NULL))
00517         return;
00518     xmlOutputBufferWrite(ctxt->buf, 1, "\n");
00519     for (i = 0; i < (ctxt->level + extra); i += ctxt->indent_nr) {
00520         xmlOutputBufferWrite(ctxt->buf, ctxt->indent_size *
00521                 ((ctxt->level + extra - i) > ctxt->indent_nr ?
00522                  ctxt->indent_nr : (ctxt->level + extra - i)),
00523                 ctxt->indent);
00524     }
00525 }
00526 
00537 static void
00538 xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) {
00539     if ((cur == NULL) || (buf == NULL)) return;
00540     if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
00541     if (xmlStrEqual(cur->prefix, BAD_CAST "xml"))
00542         return;
00543 
00544     if (ctxt != NULL && ctxt->format == 2)
00545         xmlOutputBufferWriteWSNonSig(ctxt, 2);
00546     else
00547         xmlOutputBufferWrite(buf, 1, " ");
00548 
00549         /* Within the context of an element attributes */
00550     if (cur->prefix != NULL) {
00551         xmlOutputBufferWrite(buf, 6, "xmlns:");
00552         xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
00553     } else
00554         xmlOutputBufferWrite(buf, 5, "xmlns");
00555     xmlOutputBufferWrite(buf, 1, "=");
00556     xmlBufferWriteQuotedString(buf->buffer, cur->href);
00557     }
00558 }
00559 
00568 static void
00569 xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
00570     xmlNsDumpOutput(ctxt->buf, cur, ctxt);
00571 }
00572 
00581 static void
00582 xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
00583     while (cur != NULL) {
00584         xmlNsDumpOutput(ctxt->buf, cur, ctxt);
00585     cur = cur->next;
00586     }
00587 }
00588 
00597 void
00598 xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
00599     while (cur != NULL) {
00600         xmlNsDumpOutput(buf, cur, NULL);
00601     cur = cur->next;
00602     }
00603 }
00604 
00612 static void
00613 xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
00614     xmlOutputBufferPtr buf;
00615     int format, level;
00616     xmlDocPtr doc;
00617 
00618     if (dtd == NULL) return;
00619     if ((ctxt == NULL) || (ctxt->buf == NULL))
00620         return;
00621     buf = ctxt->buf;
00622     xmlOutputBufferWrite(buf, 10, "<!DOCTYPE ");
00623     xmlOutputBufferWriteString(buf, (const char *)dtd->name);
00624     if (dtd->ExternalID != NULL) {
00625     xmlOutputBufferWrite(buf, 8, " PUBLIC ");
00626     xmlBufferWriteQuotedString(buf->buffer, dtd->ExternalID);
00627     xmlOutputBufferWrite(buf, 1, " ");
00628     xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
00629     }  else if (dtd->SystemID != NULL) {
00630     xmlOutputBufferWrite(buf, 8, " SYSTEM ");
00631     xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
00632     }
00633     if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
00634         (dtd->attributes == NULL) && (dtd->notations == NULL) &&
00635     (dtd->pentities == NULL)) {
00636     xmlOutputBufferWrite(buf, 1, ">");
00637     return;
00638     }
00639     xmlOutputBufferWrite(buf, 3, " [\n");
00640     /*
00641      * Dump the notations first they are not in the DTD children list
00642      * Do this only on a standalone DTD or on the internal subset though.
00643      */
00644     if ((dtd->notations != NULL) && ((dtd->doc == NULL) ||
00645         (dtd->doc->intSubset == dtd))) {
00646         xmlDumpNotationTable(buf->buffer, (xmlNotationTablePtr) dtd->notations);
00647     }
00648     format = ctxt->format;
00649     level = ctxt->level;
00650     doc = ctxt->doc;
00651     ctxt->format = 0;
00652     ctxt->level = -1;
00653     ctxt->doc = dtd->doc;
00654     xmlNodeListDumpOutput(ctxt, dtd->children);
00655     ctxt->format = format;
00656     ctxt->level = level;
00657     ctxt->doc = doc;
00658     xmlOutputBufferWrite(buf, 2, "]>");
00659 }
00660 
00668 static void
00669 xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
00670     xmlOutputBufferPtr buf;
00671 
00672     if (cur == NULL) return;
00673     buf = ctxt->buf;
00674     if (buf == NULL) return;
00675     if (ctxt->format == 2)
00676         xmlOutputBufferWriteWSNonSig(ctxt, 2);
00677     else
00678         xmlOutputBufferWrite(buf, 1, " ");
00679     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
00680         xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
00681     xmlOutputBufferWrite(buf, 1, ":");
00682     }
00683     xmlOutputBufferWriteString(buf, (const char *)cur->name);
00684     xmlOutputBufferWrite(buf, 2, "=\"");
00685     xmlAttrSerializeContent(buf, cur);
00686     xmlOutputBufferWrite(buf, 1, "\"");
00687 }
00688 
00698 static void
00699 xmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
00700     if (cur == NULL) return;
00701     while (cur != NULL) {
00702         xmlAttrDumpOutput(ctxt, cur);
00703     cur = cur->next;
00704     }
00705 }
00706 
00707 
00708 
00715 static void
00716 xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
00717     xmlOutputBufferPtr buf;
00718 
00719     if (cur == NULL) return;
00720     buf = ctxt->buf;
00721     while (cur != NULL) {
00722     if ((ctxt->format == 1) && (xmlIndentTreeOutput) &&
00723         ((cur->type == XML_ELEMENT_NODE) ||
00724          (cur->type == XML_COMMENT_NODE) ||
00725          (cur->type == XML_PI_NODE)))
00726         xmlOutputBufferWrite(buf, ctxt->indent_size *
00727                              (ctxt->level > ctxt->indent_nr ? 
00728                   ctxt->indent_nr : ctxt->level),
00729                  ctxt->indent);
00730         xmlNodeDumpOutputInternal(ctxt, cur);
00731     if (ctxt->format == 1) {
00732         xmlOutputBufferWrite(buf, 1, "\n");
00733     }
00734     cur = cur->next;
00735     }
00736 }
00737 
00738 #ifdef LIBXML_HTML_ENABLED
00739 
00745 static int
00746 htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
00747     const xmlChar *oldenc = NULL;
00748     const xmlChar *oldctxtenc = ctxt->encoding;
00749     const xmlChar *encoding = ctxt->encoding;
00750     xmlOutputBufferPtr buf = ctxt->buf;
00751     int switched_encoding = 0;
00752     xmlDocPtr doc;
00753 
00754     xmlInitParser();
00755 
00756     doc = cur->doc;
00757     if (doc != NULL) {
00758         oldenc = doc->encoding;
00759     if (ctxt->encoding != NULL) {
00760         doc->encoding = BAD_CAST ctxt->encoding;
00761     } else if (doc->encoding != NULL) {
00762         encoding = doc->encoding;
00763     }
00764     }
00765 
00766     if ((encoding != NULL) && (doc != NULL))
00767     htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
00768     if ((encoding == NULL) && (doc != NULL))
00769     encoding = htmlGetMetaEncoding(doc);
00770     if (encoding == NULL)
00771     encoding = BAD_CAST "HTML";
00772     if ((encoding != NULL) && (oldctxtenc == NULL) &&
00773     (buf->encoder == NULL) && (buf->conv == NULL)) {
00774     if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
00775         doc->encoding = oldenc;
00776         return(-1);
00777     }
00778     switched_encoding = 1;
00779     }
00780     if (ctxt->options & XML_SAVE_FORMAT)
00781     htmlNodeDumpFormatOutput(buf, doc, cur,
00782                        (const char *)encoding, 1);
00783     else
00784     htmlNodeDumpFormatOutput(buf, doc, cur,
00785                        (const char *)encoding, 0);
00786     /*
00787      * Restore the state of the saving context at the end of the document
00788      */
00789     if ((switched_encoding) && (oldctxtenc == NULL)) {
00790     xmlSaveClearEncoding(ctxt);
00791     }
00792     if (doc != NULL)
00793     doc->encoding = oldenc;
00794     return(0);
00795 }
00796 #endif
00797 
00804 static void
00805 xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
00806     int format;
00807     xmlNodePtr tmp;
00808     xmlChar *start, *end;
00809     xmlOutputBufferPtr buf;
00810 
00811     if (cur == NULL) return;
00812     buf = ctxt->buf;
00813     if (cur->type == XML_XINCLUDE_START)
00814     return;
00815     if (cur->type == XML_XINCLUDE_END)
00816     return;
00817     if ((cur->type == XML_DOCUMENT_NODE) ||
00818         (cur->type == XML_HTML_DOCUMENT_NODE)) {
00819     xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
00820     return;
00821     }
00822 #ifdef LIBXML_HTML_ENABLED
00823     if (ctxt->options & XML_SAVE_XHTML) {
00824         xhtmlNodeDumpOutput(ctxt, cur);
00825         return;
00826     }
00827     if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
00828          (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
00829          ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
00830         (ctxt->options & XML_SAVE_AS_HTML)) {
00831     htmlNodeDumpOutputInternal(ctxt, cur);
00832     return;
00833     }
00834 #endif
00835     if (cur->type == XML_DTD_NODE) {
00836         xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
00837     return;
00838     }
00839     if (cur->type == XML_DOCUMENT_FRAG_NODE) {
00840         xmlNodeListDumpOutput(ctxt, cur->children);
00841     return;
00842     }
00843     if (cur->type == XML_ELEMENT_DECL) {
00844         xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
00845     return;
00846     }
00847     if (cur->type == XML_ATTRIBUTE_DECL) {
00848         xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
00849     return;
00850     }
00851     if (cur->type == XML_ENTITY_DECL) {
00852         xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
00853     return;
00854     }
00855     if (cur->type == XML_TEXT_NODE) {
00856     if (cur->content != NULL) {
00857         if (cur->name != xmlStringTextNoenc) {
00858                 xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
00859         } else {
00860         /*
00861          * Disable escaping, needed for XSLT
00862          */
00863         xmlOutputBufferWriteString(buf, (const char *) cur->content);
00864         }
00865     }
00866 
00867     return;
00868     }
00869     if (cur->type == XML_PI_NODE) {
00870     if (cur->content != NULL) {
00871         xmlOutputBufferWrite(buf, 2, "<?");
00872         xmlOutputBufferWriteString(buf, (const char *)cur->name);
00873         if (cur->content != NULL) {
00874             if (ctxt->format == 2)
00875                 xmlOutputBufferWriteWSNonSig(ctxt, 0);
00876             else
00877                 xmlOutputBufferWrite(buf, 1, " ");
00878         xmlOutputBufferWriteString(buf, (const char *)cur->content);
00879         }
00880         xmlOutputBufferWrite(buf, 2, "?>");
00881     } else {
00882         xmlOutputBufferWrite(buf, 2, "<?");
00883         xmlOutputBufferWriteString(buf, (const char *)cur->name);
00884         if (ctxt->format == 2)
00885             xmlOutputBufferWriteWSNonSig(ctxt, 0);
00886         xmlOutputBufferWrite(buf, 2, "?>");
00887     }
00888     return;
00889     }
00890     if (cur->type == XML_COMMENT_NODE) {
00891     if (cur->content != NULL) {
00892         xmlOutputBufferWrite(buf, 4, "<!--");
00893         xmlOutputBufferWriteString(buf, (const char *)cur->content);
00894         xmlOutputBufferWrite(buf, 3, "-->");
00895     }
00896     return;
00897     }
00898     if (cur->type == XML_ENTITY_REF_NODE) {
00899         xmlOutputBufferWrite(buf, 1, "&");
00900     xmlOutputBufferWriteString(buf, (const char *)cur->name);
00901         xmlOutputBufferWrite(buf, 1, ";");
00902     return;
00903     }
00904     if (cur->type == XML_CDATA_SECTION_NODE) {
00905     if (cur->content == NULL || *cur->content == '\0') {
00906         xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
00907     } else {
00908         start = end = cur->content;
00909         while (*end != '\0') {
00910         if ((*end == ']') && (*(end + 1) == ']') &&
00911             (*(end + 2) == '>')) {
00912             end = end + 2;
00913             xmlOutputBufferWrite(buf, 9, "<![CDATA[");
00914             xmlOutputBufferWrite(buf, end - start, (const char *)start);
00915             xmlOutputBufferWrite(buf, 3, "]]>");
00916             start = end;
00917         }
00918         end++;
00919         }
00920         if (start != end) {
00921         xmlOutputBufferWrite(buf, 9, "<![CDATA[");
00922         xmlOutputBufferWriteString(buf, (const char *)start);
00923         xmlOutputBufferWrite(buf, 3, "]]>");
00924         }
00925     }
00926     return;
00927     }
00928     if (cur->type == XML_ATTRIBUTE_NODE) {
00929     xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
00930     return;
00931     }
00932     if (cur->type == XML_NAMESPACE_DECL) {
00933     xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
00934     return;
00935     }
00936 
00937     format = ctxt->format;
00938     if (format == 1) {
00939     tmp = cur->children;
00940     while (tmp != NULL) {
00941         if ((tmp->type == XML_TEXT_NODE) ||
00942         (tmp->type == XML_CDATA_SECTION_NODE) ||
00943         (tmp->type == XML_ENTITY_REF_NODE)) {
00944         ctxt->format = 0;
00945         break;
00946         }
00947         tmp = tmp->next;
00948     }
00949     }
00950     xmlOutputBufferWrite(buf, 1, "<");
00951     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
00952         xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
00953     xmlOutputBufferWrite(buf, 1, ":");
00954     }
00955 
00956     xmlOutputBufferWriteString(buf, (const char *)cur->name);
00957     if (cur->nsDef)
00958         xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
00959     if (cur->properties != NULL)
00960         xmlAttrListDumpOutput(ctxt, cur->properties);
00961 
00962     if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) &&
00963     (cur->children == NULL) && ((ctxt->options & XML_SAVE_NO_EMPTY) == 0)) {
00964         if (ctxt->format == 2)
00965             xmlOutputBufferWriteWSNonSig(ctxt, 0);
00966         xmlOutputBufferWrite(buf, 2, "/>");
00967     ctxt->format = format;
00968     return;
00969     }
00970     if (ctxt->format == 2)
00971         xmlOutputBufferWriteWSNonSig(ctxt, 1);
00972     xmlOutputBufferWrite(buf, 1, ">");
00973     if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
00974     xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
00975     }
00976     if (cur->children != NULL) {
00977     if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
00978     if (ctxt->level >= 0) ctxt->level++;
00979     xmlNodeListDumpOutput(ctxt, cur->children);
00980     if (ctxt->level > 0) ctxt->level--;
00981     if ((xmlIndentTreeOutput) && (ctxt->format == 1))
00982         xmlOutputBufferWrite(buf, ctxt->indent_size *
00983                              (ctxt->level > ctxt->indent_nr ? 
00984                   ctxt->indent_nr : ctxt->level),
00985                  ctxt->indent);
00986     }
00987     xmlOutputBufferWrite(buf, 2, "</");
00988     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
00989         xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
00990     xmlOutputBufferWrite(buf, 1, ":");
00991     }
00992 
00993     xmlOutputBufferWriteString(buf, (const char *)cur->name);
00994     if (ctxt->format == 2)
00995         xmlOutputBufferWriteWSNonSig(ctxt, 0);
00996     xmlOutputBufferWrite(buf, 1, ">");
00997     ctxt->format = format;
00998 }
00999 
01006 static int
01007 xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
01008 #ifdef LIBXML_HTML_ENABLED
01009     xmlDtdPtr dtd;
01010     int is_xhtml = 0;
01011 #endif
01012     const xmlChar *oldenc = cur->encoding;
01013     const xmlChar *oldctxtenc = ctxt->encoding;
01014     const xmlChar *encoding = ctxt->encoding;
01015     xmlCharEncodingOutputFunc oldescape = ctxt->escape;
01016     xmlCharEncodingOutputFunc oldescapeAttr = ctxt->escapeAttr;
01017     xmlOutputBufferPtr buf = ctxt->buf;
01018     xmlCharEncoding enc;
01019     int switched_encoding = 0;
01020 
01021     xmlInitParser();
01022 
01023     if ((cur->type != XML_HTML_DOCUMENT_NODE) &&
01024         (cur->type != XML_DOCUMENT_NODE))
01025      return(-1);
01026 
01027     if (ctxt->encoding != NULL) {
01028         cur->encoding = BAD_CAST ctxt->encoding;
01029     } else if (cur->encoding != NULL) {
01030     encoding = cur->encoding;
01031     } else if (cur->charset != XML_CHAR_ENCODING_UTF8) {
01032     encoding = (const xmlChar *)
01033              xmlGetCharEncodingName((xmlCharEncoding) cur->charset);
01034     }
01035 
01036     if (((cur->type == XML_HTML_DOCUMENT_NODE) &&
01037          ((ctxt->options & XML_SAVE_AS_XML) == 0) &&
01038          ((ctxt->options & XML_SAVE_XHTML) == 0)) ||
01039         (ctxt->options & XML_SAVE_AS_HTML)) {
01040 #ifdef LIBXML_HTML_ENABLED
01041         if (encoding != NULL)
01042         htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
01043         if (encoding == NULL)
01044         encoding = htmlGetMetaEncoding(cur);
01045         if (encoding == NULL)
01046         encoding = BAD_CAST "HTML";
01047     if ((encoding != NULL) && (oldctxtenc == NULL) &&
01048         (buf->encoder == NULL) && (buf->conv == NULL)) {
01049         if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
01050         cur->encoding = oldenc;
01051         return(-1);
01052         }
01053     }
01054         if (ctxt->options & XML_SAVE_FORMAT)
01055         htmlDocContentDumpFormatOutput(buf, cur,
01056                                        (const char *)encoding, 1);
01057     else
01058         htmlDocContentDumpFormatOutput(buf, cur,
01059                                        (const char *)encoding, 0);
01060     if (ctxt->encoding != NULL)
01061         cur->encoding = oldenc;
01062     return(0);
01063 #else
01064         return(-1);
01065 #endif
01066     } else if ((cur->type == XML_DOCUMENT_NODE) ||
01067                (ctxt->options & XML_SAVE_AS_XML) ||
01068                (ctxt->options & XML_SAVE_XHTML)) {
01069     enc = xmlParseCharEncoding((const char*) encoding);
01070     if ((encoding != NULL) && (oldctxtenc == NULL) &&
01071         (buf->encoder == NULL) && (buf->conv == NULL) &&
01072         ((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
01073         if ((enc != XML_CHAR_ENCODING_UTF8) &&
01074         (enc != XML_CHAR_ENCODING_NONE) &&
01075         (enc != XML_CHAR_ENCODING_ASCII)) {
01076         /*
01077          * we need to switch to this encoding but just for this
01078          * document since we output the XMLDecl the conversion
01079          * must be done to not generate not well formed documents.
01080          */
01081         if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
01082             cur->encoding = oldenc;
01083             return(-1);
01084         }
01085         switched_encoding = 1;
01086         }
01087         if (ctxt->escape == xmlEscapeEntities)
01088         ctxt->escape = NULL;
01089         if (ctxt->escapeAttr == xmlEscapeEntities)
01090         ctxt->escapeAttr = NULL;
01091     }
01092 
01093 
01094     /*
01095      * Save the XML declaration
01096      */
01097     if ((ctxt->options & XML_SAVE_NO_DECL) == 0) {
01098         xmlOutputBufferWrite(buf, 14, "<?xml version=");
01099         if (cur->version != NULL) 
01100         xmlBufferWriteQuotedString(buf->buffer, cur->version);
01101         else
01102         xmlOutputBufferWrite(buf, 5, "\"1.0\"");
01103         if (encoding != NULL) {
01104         xmlOutputBufferWrite(buf, 10, " encoding=");
01105         xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
01106         }
01107         switch (cur->standalone) {
01108         case 0:
01109             xmlOutputBufferWrite(buf, 16, " standalone=\"no\"");
01110             break;
01111         case 1:
01112             xmlOutputBufferWrite(buf, 17, " standalone=\"yes\"");
01113             break;
01114         }
01115         xmlOutputBufferWrite(buf, 3, "?>\n");
01116     }
01117 
01118 #ifdef LIBXML_HTML_ENABLED
01119         if (ctxt->options & XML_SAVE_XHTML)
01120             is_xhtml = 1;
01121     if ((ctxt->options & XML_SAVE_NO_XHTML) == 0) {
01122         dtd = xmlGetIntSubset(cur);
01123         if (dtd != NULL) {
01124         is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
01125         if (is_xhtml < 0) is_xhtml = 0;
01126         }
01127     }
01128 #endif
01129     if (cur->children != NULL) {
01130         xmlNodePtr child = cur->children;
01131 
01132         while (child != NULL) {
01133         ctxt->level = 0;
01134 #ifdef LIBXML_HTML_ENABLED
01135         if (is_xhtml)
01136             xhtmlNodeDumpOutput(ctxt, child);
01137         else
01138 #endif
01139             xmlNodeDumpOutputInternal(ctxt, child);
01140         xmlOutputBufferWrite(buf, 1, "\n");
01141         child = child->next;
01142         }
01143     }
01144     }
01145 
01146     /*
01147      * Restore the state of the saving context at the end of the document
01148      */
01149     if ((switched_encoding) && (oldctxtenc == NULL)) {
01150     xmlSaveClearEncoding(ctxt);
01151     ctxt->escape = oldescape;
01152     ctxt->escapeAttr = oldescapeAttr;
01153     }
01154     cur->encoding = oldenc;
01155     return(0);
01156 }
01157 
01158 #ifdef LIBXML_HTML_ENABLED
01159 /************************************************************************
01160  *                                  *
01161  *      Functions specific to XHTML serialization       *
01162  *                                  *
01163  ************************************************************************/
01164 
01173 static int
01174 xhtmlIsEmpty(xmlNodePtr node) {
01175     if (node == NULL)
01176     return(-1);
01177     if (node->type != XML_ELEMENT_NODE)
01178     return(0);
01179     if ((node->ns != NULL) && (!xmlStrEqual(node->ns->href, XHTML_NS_NAME)))
01180     return(0);
01181     if (node->children != NULL)
01182     return(0);
01183     switch (node->name[0]) {
01184     case 'a':
01185         if (xmlStrEqual(node->name, BAD_CAST "area"))
01186         return(1);
01187         return(0);
01188     case 'b':
01189         if (xmlStrEqual(node->name, BAD_CAST "br"))
01190         return(1);
01191         if (xmlStrEqual(node->name, BAD_CAST "base"))
01192         return(1);
01193         if (xmlStrEqual(node->name, BAD_CAST "basefont"))
01194         return(1);
01195         return(0);
01196     case 'c':
01197         if (xmlStrEqual(node->name, BAD_CAST "col"))
01198         return(1);
01199         return(0);
01200     case 'f':
01201         if (xmlStrEqual(node->name, BAD_CAST "frame"))
01202         return(1);
01203         return(0);
01204     case 'h':
01205         if (xmlStrEqual(node->name, BAD_CAST "hr"))
01206         return(1);
01207         return(0);
01208     case 'i':
01209         if (xmlStrEqual(node->name, BAD_CAST "img"))
01210         return(1);
01211         if (xmlStrEqual(node->name, BAD_CAST "input"))
01212         return(1);
01213         if (xmlStrEqual(node->name, BAD_CAST "isindex"))
01214         return(1);
01215         return(0);
01216     case 'l':
01217         if (xmlStrEqual(node->name, BAD_CAST "link"))
01218         return(1);
01219         return(0);
01220     case 'm':
01221         if (xmlStrEqual(node->name, BAD_CAST "meta"))
01222         return(1);
01223         return(0);
01224     case 'p':
01225         if (xmlStrEqual(node->name, BAD_CAST "param"))
01226         return(1);
01227         return(0);
01228     }
01229     return(0);
01230 }
01231 
01238 static void
01239 xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
01240     xmlAttrPtr xml_lang = NULL;
01241     xmlAttrPtr lang = NULL;
01242     xmlAttrPtr name = NULL;
01243     xmlAttrPtr id = NULL;
01244     xmlNodePtr parent;
01245     xmlOutputBufferPtr buf;
01246 
01247     if (cur == NULL) return;
01248     buf = ctxt->buf;
01249     parent = cur->parent;
01250     while (cur != NULL) {
01251     if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "id")))
01252         id = cur;
01253     else
01254     if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "name")))
01255         name = cur;
01256     else
01257     if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")))
01258         lang = cur;
01259     else
01260     if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) &&
01261         (xmlStrEqual(cur->ns->prefix, BAD_CAST "xml")))
01262         xml_lang = cur;
01263     else if ((cur->ns == NULL) && 
01264          ((cur->children == NULL) ||
01265           (cur->children->content == NULL) ||
01266           (cur->children->content[0] == 0)) &&
01267          (htmlIsBooleanAttr(cur->name))) {
01268         if (cur->children != NULL)
01269         xmlFreeNode(cur->children);
01270         cur->children = xmlNewText(cur->name);
01271         if (cur->children != NULL)
01272         cur->children->parent = (xmlNodePtr) cur;
01273     }
01274         xmlAttrDumpOutput(ctxt, cur);
01275     cur = cur->next;
01276     }
01277     /*
01278      * C.8
01279      */
01280     if ((name != NULL) && (id == NULL)) {
01281     if ((parent != NULL) && (parent->name != NULL) &&
01282         ((xmlStrEqual(parent->name, BAD_CAST "a")) ||
01283          (xmlStrEqual(parent->name, BAD_CAST "p")) ||
01284          (xmlStrEqual(parent->name, BAD_CAST "div")) ||
01285          (xmlStrEqual(parent->name, BAD_CAST "img")) ||
01286          (xmlStrEqual(parent->name, BAD_CAST "map")) ||
01287          (xmlStrEqual(parent->name, BAD_CAST "applet")) ||
01288          (xmlStrEqual(parent->name, BAD_CAST "form")) ||
01289          (xmlStrEqual(parent->name, BAD_CAST "frame")) ||
01290          (xmlStrEqual(parent->name, BAD_CAST "iframe")))) {
01291         xmlOutputBufferWrite(buf, 5, " id=\"");
01292         xmlAttrSerializeContent(buf, name);
01293         xmlOutputBufferWrite(buf, 1, "\"");
01294     }
01295     }
01296     /*
01297      * C.7.
01298      */
01299     if ((lang != NULL) && (xml_lang == NULL)) {
01300     xmlOutputBufferWrite(buf, 11, " xml:lang=\"");
01301     xmlAttrSerializeContent(buf, lang);
01302     xmlOutputBufferWrite(buf, 1, "\"");
01303     } else 
01304     if ((xml_lang != NULL) && (lang == NULL)) {
01305     xmlOutputBufferWrite(buf, 7, " lang=\"");
01306     xmlAttrSerializeContent(buf, xml_lang);
01307     xmlOutputBufferWrite(buf, 1, "\"");
01308     }
01309 }
01310 
01324 static void
01325 xhtmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
01326     xmlOutputBufferPtr buf;
01327 
01328     if (cur == NULL) return;
01329     buf = ctxt->buf;
01330     while (cur != NULL) {
01331     if ((ctxt->format == 1) && (xmlIndentTreeOutput) &&
01332         (cur->type == XML_ELEMENT_NODE))
01333         xmlOutputBufferWrite(buf, ctxt->indent_size *
01334                              (ctxt->level > ctxt->indent_nr ? 
01335                   ctxt->indent_nr : ctxt->level),
01336                  ctxt->indent);
01337         xhtmlNodeDumpOutput(ctxt, cur);
01338     if (ctxt->format == 1) {
01339         xmlOutputBufferWrite(buf, 1, "\n");
01340     }
01341     cur = cur->next;
01342     }
01343 }
01344 
01356 static void
01357 xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
01358     int format, addmeta = 0;
01359     xmlNodePtr tmp;
01360     xmlChar *start, *end;
01361     xmlOutputBufferPtr buf;
01362 
01363     if (cur == NULL) return;
01364     if ((cur->type == XML_DOCUMENT_NODE) ||
01365         (cur->type == XML_HTML_DOCUMENT_NODE)) {
01366         xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
01367     return;
01368     }
01369     if (cur->type == XML_XINCLUDE_START)
01370     return;
01371     if (cur->type == XML_XINCLUDE_END)
01372     return;
01373     if (cur->type == XML_DTD_NODE) {
01374         xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
01375     return;
01376     }
01377     if (cur->type == XML_DOCUMENT_FRAG_NODE) {
01378         xhtmlNodeListDumpOutput(ctxt, cur->children);
01379     return;
01380     }
01381     buf = ctxt->buf;
01382     if (cur->type == XML_ELEMENT_DECL) {
01383         xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
01384     return;
01385     }
01386     if (cur->type == XML_ATTRIBUTE_DECL) {
01387         xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
01388     return;
01389     }
01390     if (cur->type == XML_ENTITY_DECL) {
01391         xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
01392     return;
01393     }
01394     if (cur->type == XML_TEXT_NODE) {
01395     if (cur->content != NULL) {
01396         if ((cur->name == xmlStringText) ||
01397         (cur->name != xmlStringTextNoenc)) {
01398                 xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
01399         } else {
01400         /*
01401          * Disable escaping, needed for XSLT
01402          */
01403         xmlOutputBufferWriteString(buf, (const char *) cur->content);
01404         }
01405     }
01406 
01407     return;
01408     }
01409     if (cur->type == XML_PI_NODE) {
01410     if (cur->content != NULL) {
01411         xmlOutputBufferWrite(buf, 2, "<?");
01412         xmlOutputBufferWriteString(buf, (const char *)cur->name);
01413         if (cur->content != NULL) {
01414         xmlOutputBufferWrite(buf, 1, " ");
01415         xmlOutputBufferWriteString(buf, (const char *)cur->content);
01416         }
01417         xmlOutputBufferWrite(buf, 2, "?>");
01418     } else {
01419         xmlOutputBufferWrite(buf, 2, "<?");
01420         xmlOutputBufferWriteString(buf, (const char *)cur->name);
01421         xmlOutputBufferWrite(buf, 2, "?>");
01422     }
01423     return;
01424     }
01425     if (cur->type == XML_COMMENT_NODE) {
01426     if (cur->content != NULL) {
01427         xmlOutputBufferWrite(buf, 4, "<!--");
01428         xmlOutputBufferWriteString(buf, (const char *)cur->content);
01429         xmlOutputBufferWrite(buf, 3, "-->");
01430     }
01431     return;
01432     }
01433     if (cur->type == XML_ENTITY_REF_NODE) {
01434         xmlOutputBufferWrite(buf, 1, "&");
01435     xmlOutputBufferWriteString(buf, (const char *)cur->name);
01436         xmlOutputBufferWrite(buf, 1, ";");
01437     return;
01438     }
01439     if (cur->type == XML_CDATA_SECTION_NODE) {
01440     if (cur->content == NULL || *cur->content == '\0') {
01441         xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
01442     } else {
01443         start = end = cur->content;
01444         while (*end != '\0') {
01445         if (*end == ']' && *(end + 1) == ']' && *(end + 2) == '>') {
01446             end = end + 2;
01447             xmlOutputBufferWrite(buf, 9, "<![CDATA[");
01448             xmlOutputBufferWrite(buf, end - start, (const char *)start);
01449             xmlOutputBufferWrite(buf, 3, "]]>");
01450             start = end;
01451         }
01452         end++;
01453         }
01454         if (start != end) {
01455         xmlOutputBufferWrite(buf, 9, "<![CDATA[");
01456         xmlOutputBufferWriteString(buf, (const char *)start);
01457         xmlOutputBufferWrite(buf, 3, "]]>");
01458         }
01459     }
01460     return;
01461     }
01462     if (cur->type == XML_ATTRIBUTE_NODE) {
01463         xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
01464     return;
01465     }
01466 
01467     format = ctxt->format;
01468     if (format == 1) {
01469     tmp = cur->children;
01470     while (tmp != NULL) {
01471         if ((tmp->type == XML_TEXT_NODE) || 
01472         (tmp->type == XML_ENTITY_REF_NODE)) {
01473         format = 0;
01474         break;
01475         }
01476         tmp = tmp->next;
01477     }
01478     }
01479     xmlOutputBufferWrite(buf, 1, "<");
01480     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
01481         xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
01482     xmlOutputBufferWrite(buf, 1, ":");
01483     }
01484 
01485     xmlOutputBufferWriteString(buf, (const char *)cur->name);
01486     if (cur->nsDef)
01487         xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
01488     if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
01489     (cur->ns == NULL) && (cur->nsDef == NULL))) {
01490     /*
01491      * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
01492      */
01493     xmlOutputBufferWriteString(buf,
01494         " xmlns=\"http://www.w3.org/1999/xhtml\"");
01495     }
01496     if (cur->properties != NULL)
01497         xhtmlAttrListDumpOutput(ctxt, cur->properties);
01498 
01499     if ((cur->type == XML_ELEMENT_NODE) && 
01500         (cur->parent != NULL) && 
01501         (cur->parent->parent == (xmlNodePtr) cur->doc) && 
01502         xmlStrEqual(cur->name, BAD_CAST"head") && 
01503         xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
01504 
01505         tmp = cur->children;
01506         while (tmp != NULL) {
01507             if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
01508                 xmlChar *httpequiv;
01509 
01510                 httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
01511                 if (httpequiv != NULL) {
01512                     if (xmlStrcasecmp(httpequiv, BAD_CAST"Content-Type") == 0) {
01513                         xmlFree(httpequiv);
01514                         break;
01515                     }
01516                     xmlFree(httpequiv);
01517                 }
01518             }
01519             tmp = tmp->next;
01520         }
01521         if (tmp == NULL)
01522             addmeta = 1;
01523     }
01524 
01525     if ((cur->type == XML_ELEMENT_NODE) && (cur->children == NULL)) {
01526     if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
01527         ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) {
01528         /*
01529          * C.2. Empty Elements
01530          */
01531         xmlOutputBufferWrite(buf, 3, " />");
01532     } else {
01533         if (addmeta == 1) {
01534             xmlOutputBufferWrite(buf, 1, ">");
01535             if (ctxt->format == 1) {
01536                 xmlOutputBufferWrite(buf, 1, "\n");
01537                 if (xmlIndentTreeOutput)
01538                     xmlOutputBufferWrite(buf, ctxt->indent_size *
01539                     (ctxt->level + 1 > ctxt->indent_nr ? 
01540                     ctxt->indent_nr : ctxt->level + 1), ctxt->indent);
01541             }
01542             xmlOutputBufferWriteString(buf,
01543                 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
01544             if (ctxt->encoding) {
01545                 xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding);
01546             } else {
01547                 xmlOutputBufferWrite(buf, 5, "UTF-8");
01548             }
01549             xmlOutputBufferWrite(buf, 4, "\" />");
01550             if (ctxt->format == 1)
01551                 xmlOutputBufferWrite(buf, 1, "\n");
01552         } else {
01553             xmlOutputBufferWrite(buf, 1, ">");
01554         }
01555         /*
01556          * C.3. Element Minimization and Empty Element Content
01557          */
01558         xmlOutputBufferWrite(buf, 2, "</");
01559         if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
01560         xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
01561         xmlOutputBufferWrite(buf, 1, ":");
01562         }
01563         xmlOutputBufferWriteString(buf, (const char *)cur->name);
01564         xmlOutputBufferWrite(buf, 1, ">");
01565     }
01566     return;
01567     }
01568     xmlOutputBufferWrite(buf, 1, ">");
01569     if (addmeta == 1) {
01570         if (ctxt->format == 1) {
01571             xmlOutputBufferWrite(buf, 1, "\n");
01572             if (xmlIndentTreeOutput)
01573                 xmlOutputBufferWrite(buf, ctxt->indent_size *
01574                 (ctxt->level + 1 > ctxt->indent_nr ? 
01575                 ctxt->indent_nr : ctxt->level + 1), ctxt->indent);
01576         }
01577         xmlOutputBufferWriteString(buf,
01578             "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
01579         if (ctxt->encoding) {
01580             xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding);
01581         } else {
01582             xmlOutputBufferWrite(buf, 5, "UTF-8");
01583         }
01584         xmlOutputBufferWrite(buf, 4, "\" />");
01585     }
01586     if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
01587     xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
01588     }
01589 
01590 #if 0
01591     /*
01592     * This was removed due to problems with HTML processors.
01593     * See bug #345147.
01594     */
01595     /*
01596      * 4.8. Script and Style elements
01597      */
01598     if ((cur->type == XML_ELEMENT_NODE) &&
01599     ((xmlStrEqual(cur->name, BAD_CAST "script")) ||
01600      (xmlStrEqual(cur->name, BAD_CAST "style"))) &&
01601     ((cur->ns == NULL) ||
01602      (xmlStrEqual(cur->ns->href, XHTML_NS_NAME)))) {
01603     xmlNodePtr child = cur->children;
01604 
01605     while (child != NULL) {
01606         if (child->type == XML_TEXT_NODE) {
01607         if ((xmlStrchr(child->content, '<') == NULL) &&
01608             (xmlStrchr(child->content, '&') == NULL) &&
01609             (xmlStrstr(child->content, BAD_CAST "]]>") == NULL)) {
01610             /* Nothing to escape, so just output as is... */
01611             /* FIXME: Should we do something about "--" also? */
01612             int level = ctxt->level;
01613             int indent = ctxt->format;
01614 
01615             ctxt->level = 0;
01616             ctxt->format = 0;
01617             xmlOutputBufferWriteString(buf, (const char *) child->content);
01618             /* (We cannot use xhtmlNodeDumpOutput() here because
01619              * we wish to leave '>' unescaped!) */
01620             ctxt->level = level;
01621             ctxt->format = indent;
01622         } else {
01623             /* We must use a CDATA section.  Unfortunately,
01624              * this will break CSS and JavaScript when read by
01625              * a browser in HTML4-compliant mode. :-( */
01626             start = end = child->content;
01627             while (*end != '\0') {
01628             if (*end == ']' &&
01629                 *(end + 1) == ']' &&
01630                 *(end + 2) == '>') {
01631                 end = end + 2;
01632                 xmlOutputBufferWrite(buf, 9, "<![CDATA[");
01633                 xmlOutputBufferWrite(buf, end - start,
01634                          (const char *)start);
01635                 xmlOutputBufferWrite(buf, 3, "]]>");
01636                 start = end;
01637             }
01638             end++;
01639             }
01640             if (start != end) {
01641             xmlOutputBufferWrite(buf, 9, "<![CDATA[");
01642             xmlOutputBufferWrite(buf, end - start,
01643                                  (const char *)start);
01644             xmlOutputBufferWrite(buf, 3, "]]>");
01645             }
01646         }
01647         } else {
01648         int level = ctxt->level;
01649         int indent = ctxt->format;
01650 
01651         ctxt->level = 0;
01652         ctxt->format = 0;
01653         xhtmlNodeDumpOutput(ctxt, child);
01654         ctxt->level = level;
01655         ctxt->format = indent;
01656         }
01657         child = child->next;
01658     }
01659     }
01660 #endif
01661 
01662     if (cur->children != NULL) {
01663     int indent = ctxt->format;
01664     
01665     if (format == 1) xmlOutputBufferWrite(buf, 1, "\n");
01666     if (ctxt->level >= 0) ctxt->level++;
01667     ctxt->format = format;
01668     xhtmlNodeListDumpOutput(ctxt, cur->children);
01669     if (ctxt->level > 0) ctxt->level--;
01670     ctxt->format = indent;
01671     if ((xmlIndentTreeOutput) && (format == 1))
01672         xmlOutputBufferWrite(buf, ctxt->indent_size *
01673                              (ctxt->level > ctxt->indent_nr ? 
01674                   ctxt->indent_nr : ctxt->level),
01675                  ctxt->indent);
01676     }
01677     xmlOutputBufferWrite(buf, 2, "</");
01678     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
01679         xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
01680     xmlOutputBufferWrite(buf, 1, ":");
01681     }
01682 
01683     xmlOutputBufferWriteString(buf, (const char *)cur->name);
01684     xmlOutputBufferWrite(buf, 1, ">");
01685 }
01686 #endif
01687 
01688 /************************************************************************
01689  *                                  *
01690  *          Public entry points             *
01691  *                                  *
01692  ************************************************************************/
01693 
01705 xmlSaveCtxtPtr
01706 xmlSaveToFd(int fd, const char *encoding, int options)
01707 {
01708     xmlSaveCtxtPtr ret;
01709 
01710     ret = xmlNewSaveCtxt(encoding, options);
01711     if (ret == NULL) return(NULL);
01712     ret->buf = xmlOutputBufferCreateFd(fd, ret->handler);
01713     if (ret->buf == NULL) {
01714     xmlFreeSaveCtxt(ret);
01715     return(NULL);
01716     }
01717     return(ret);
01718 }
01719 
01732 xmlSaveCtxtPtr
01733 xmlSaveToFilename(const char *filename, const char *encoding, int options)
01734 {
01735     xmlSaveCtxtPtr ret;
01736     int compression = 0; /* TODO handle compression option */
01737 
01738     ret = xmlNewSaveCtxt(encoding, options);
01739     if (ret == NULL) return(NULL);
01740     ret->buf = xmlOutputBufferCreateFilename(filename, ret->handler,
01741                                              compression);
01742     if (ret->buf == NULL) {
01743     xmlFreeSaveCtxt(ret);
01744     return(NULL);
01745     }
01746     return(ret);
01747 }
01748 
01761 xmlSaveCtxtPtr
01762 xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options)
01763 {
01764     xmlSaveCtxtPtr ret;
01765     xmlOutputBufferPtr out_buff;
01766     xmlCharEncodingHandlerPtr handler;
01767 
01768     ret = xmlNewSaveCtxt(encoding, options);
01769     if (ret == NULL) return(NULL);
01770 
01771     if (encoding != NULL) {
01772         handler = xmlFindCharEncodingHandler(encoding);
01773         if (handler == NULL) {
01774             xmlFree(ret);
01775             return(NULL);
01776         }
01777     } else
01778         handler = NULL;
01779     out_buff = xmlOutputBufferCreateBuffer(buffer, handler);
01780     if (out_buff == NULL) {
01781         xmlFree(ret);
01782         if (handler) xmlCharEncCloseFunc(handler);
01783         return(NULL);
01784     }
01785 
01786     ret->buf = out_buff;
01787     return(ret);
01788 }
01789 
01803 xmlSaveCtxtPtr
01804 xmlSaveToIO(xmlOutputWriteCallback iowrite,
01805             xmlOutputCloseCallback ioclose,
01806             void *ioctx, const char *encoding, int options)
01807 {
01808     xmlSaveCtxtPtr ret;
01809 
01810     ret = xmlNewSaveCtxt(encoding, options);
01811     if (ret == NULL) return(NULL);
01812     ret->buf = xmlOutputBufferCreateIO(iowrite, ioclose, ioctx, ret->handler);
01813     if (ret->buf == NULL) {
01814     xmlFreeSaveCtxt(ret);
01815     return(NULL);
01816     }
01817     return(ret);
01818 }
01819 
01831 long
01832 xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc)
01833 {
01834     long ret = 0;
01835 
01836     if ((ctxt == NULL) || (doc == NULL)) return(-1);
01837     if (xmlDocContentDumpOutput(ctxt, doc) < 0)
01838         return(-1);
01839     return(ret);
01840 }
01841 
01853 long
01854 xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr node)
01855 {
01856     long ret = 0;
01857 
01858     if ((ctxt == NULL) || (node == NULL)) return(-1);
01859     xmlNodeDumpOutputInternal(ctxt, node);
01860     return(ret);
01861 }
01862 
01872 int
01873 xmlSaveFlush(xmlSaveCtxtPtr ctxt)
01874 {
01875     if (ctxt == NULL) return(-1);
01876     if (ctxt->buf == NULL) return(-1);
01877     return(xmlOutputBufferFlush(ctxt->buf));
01878 }
01879 
01889 int
01890 xmlSaveClose(xmlSaveCtxtPtr ctxt)
01891 {
01892     int ret;
01893 
01894     if (ctxt == NULL) return(-1);
01895     ret = xmlSaveFlush(ctxt);
01896     xmlFreeSaveCtxt(ctxt);
01897     return(ret);
01898 }
01899 
01909 int
01910 xmlSaveSetEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
01911 {
01912     if (ctxt == NULL) return(-1);
01913     ctxt->escape = escape;
01914     return(0);
01915 }
01916 
01926 int
01927 xmlSaveSetAttrEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
01928 {
01929     if (ctxt == NULL) return(-1);
01930     ctxt->escapeAttr = escape;
01931     return(0);
01932 }
01933 
01934 /************************************************************************
01935  *                                  *
01936  *      Public entry points based on buffers            *
01937  *                                  *
01938  ************************************************************************/
01948 void
01949 xmlAttrSerializeTxtContent(xmlBufferPtr buf, xmlDocPtr doc,
01950                            xmlAttrPtr attr, const xmlChar * string)
01951 {
01952     xmlChar *base, *cur;
01953 
01954     if (string == NULL)
01955         return;
01956     base = cur = (xmlChar *) string;
01957     while (*cur != 0) {
01958         if (*cur == '\n') {
01959             if (base != cur)
01960                 xmlBufferAdd(buf, base, cur - base);
01961             xmlBufferAdd(buf, BAD_CAST "&#10;", 5);
01962             cur++;
01963             base = cur;
01964         } else if (*cur == '\r') {
01965             if (base != cur)
01966                 xmlBufferAdd(buf, base, cur - base);
01967             xmlBufferAdd(buf, BAD_CAST "&#13;", 5);
01968             cur++;
01969             base = cur;
01970         } else if (*cur == '\t') {
01971             if (base != cur)
01972                 xmlBufferAdd(buf, base, cur - base);
01973             xmlBufferAdd(buf, BAD_CAST "&#9;", 4);
01974             cur++;
01975             base = cur;
01976         } else if (*cur == '"') {
01977             if (base != cur)
01978                 xmlBufferAdd(buf, base, cur - base);
01979             xmlBufferAdd(buf, BAD_CAST "&quot;", 6);
01980             cur++;
01981             base = cur;
01982         } else if (*cur == '<') {
01983             if (base != cur)
01984                 xmlBufferAdd(buf, base, cur - base);
01985             xmlBufferAdd(buf, BAD_CAST "&lt;", 4);
01986             cur++;
01987             base = cur;
01988         } else if (*cur == '>') {
01989             if (base != cur)
01990                 xmlBufferAdd(buf, base, cur - base);
01991             xmlBufferAdd(buf, BAD_CAST "&gt;", 4);
01992             cur++;
01993             base = cur;
01994         } else if (*cur == '&') {
01995             if (base != cur)
01996                 xmlBufferAdd(buf, base, cur - base);
01997             xmlBufferAdd(buf, BAD_CAST "&amp;", 5);
01998             cur++;
01999             base = cur;
02000         } else if ((*cur >= 0x80) && ((doc == NULL) ||
02001                                       (doc->encoding == NULL))) {
02002             /*
02003              * We assume we have UTF-8 content.
02004              */
02005             unsigned char tmp[10];
02006             int val = 0, l = 1;
02007 
02008             if (base != cur)
02009                 xmlBufferAdd(buf, base, cur - base);
02010             if (*cur < 0xC0) {
02011                 xmlSaveErr(XML_SAVE_NOT_UTF8, (xmlNodePtr) attr, NULL);
02012                 if (doc != NULL)
02013                     doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
02014         xmlSerializeHexCharRef(tmp, *cur);
02015                 xmlBufferAdd(buf, (xmlChar *) tmp, -1);
02016                 cur++;
02017                 base = cur;
02018                 continue;
02019             } else if (*cur < 0xE0) {
02020                 val = (cur[0]) & 0x1F;
02021                 val <<= 6;
02022                 val |= (cur[1]) & 0x3F;
02023                 l = 2;
02024             } else if (*cur < 0xF0) {
02025                 val = (cur[0]) & 0x0F;
02026                 val <<= 6;
02027                 val |= (cur[1]) & 0x3F;
02028                 val <<= 6;
02029                 val |= (cur[2]) & 0x3F;
02030                 l = 3;
02031             } else if (*cur < 0xF8) {
02032                 val = (cur[0]) & 0x07;
02033                 val <<= 6;
02034                 val |= (cur[1]) & 0x3F;
02035                 val <<= 6;
02036                 val |= (cur[2]) & 0x3F;
02037                 val <<= 6;
02038                 val |= (cur[3]) & 0x3F;
02039                 l = 4;
02040             }
02041             if ((l == 1) || (!IS_CHAR(val))) {
02042                 xmlSaveErr(XML_SAVE_CHAR_INVALID, (xmlNodePtr) attr, NULL);
02043                 if (doc != NULL)
02044                     doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
02045         
02046         xmlSerializeHexCharRef(tmp, *cur);
02047                 xmlBufferAdd(buf, (xmlChar *) tmp, -1);
02048                 cur++;
02049                 base = cur;
02050                 continue;
02051             }
02052             /*
02053              * We could do multiple things here. Just save
02054              * as a char ref
02055              */
02056         xmlSerializeHexCharRef(tmp, val);
02057             xmlBufferAdd(buf, (xmlChar *) tmp, -1);
02058             cur += l;
02059             base = cur;
02060         } else {
02061             cur++;
02062         }
02063     }
02064     if (base != cur)
02065         xmlBufferAdd(buf, base, cur - base);
02066 }
02067 
02082 int
02083 xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
02084             int format)
02085 {
02086     unsigned int use;
02087     int ret;
02088     xmlOutputBufferPtr outbuf;
02089 
02090     xmlInitParser();
02091 
02092     if (cur == NULL) {
02093 #ifdef DEBUG_TREE
02094         xmlGenericError(xmlGenericErrorContext,
02095                         "xmlNodeDump : node == NULL\n");
02096 #endif
02097         return (-1);
02098     }
02099     if (buf == NULL) {
02100 #ifdef DEBUG_TREE
02101         xmlGenericError(xmlGenericErrorContext,
02102                         "xmlNodeDump : buf == NULL\n");
02103 #endif
02104         return (-1);
02105     }
02106     outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
02107     if (outbuf == NULL) {
02108         xmlSaveErrMemory("creating buffer");
02109         return (-1);
02110     }
02111     memset(outbuf, 0, (size_t) sizeof(xmlOutputBuffer));
02112     outbuf->buffer = buf;
02113     outbuf->encoder = NULL;
02114     outbuf->writecallback = NULL;
02115     outbuf->closecallback = NULL;
02116     outbuf->context = NULL;
02117     outbuf->written = 0;
02118 
02119     use = buf->use;
02120     xmlNodeDumpOutput(outbuf, doc, cur, level, format, NULL);
02121     xmlFree(outbuf);
02122     ret = buf->use - use;
02123     return (ret);
02124 }
02125 
02134 void
02135 xmlElemDump(FILE * f, xmlDocPtr doc, xmlNodePtr cur)
02136 {
02137     xmlOutputBufferPtr outbuf;
02138 
02139     xmlInitParser();
02140 
02141     if (cur == NULL) {
02142 #ifdef DEBUG_TREE
02143         xmlGenericError(xmlGenericErrorContext,
02144                         "xmlElemDump : cur == NULL\n");
02145 #endif
02146         return;
02147     }
02148 #ifdef DEBUG_TREE
02149     if (doc == NULL) {
02150         xmlGenericError(xmlGenericErrorContext,
02151                         "xmlElemDump : doc == NULL\n");
02152     }
02153 #endif
02154 
02155     outbuf = xmlOutputBufferCreateFile(f, NULL);
02156     if (outbuf == NULL)
02157         return;
02158     if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
02159 #ifdef LIBXML_HTML_ENABLED
02160         htmlNodeDumpOutput(outbuf, doc, cur, NULL);
02161 #else
02162     xmlSaveErr(XML_ERR_INTERNAL_ERROR, cur, "HTML support not compiled in\n");
02163 #endif /* LIBXML_HTML_ENABLED */
02164     } else
02165         xmlNodeDumpOutput(outbuf, doc, cur, 0, 1, NULL);
02166     xmlOutputBufferClose(outbuf);
02167 }
02168 
02169 /************************************************************************
02170  *                                  *
02171  *      Saving functions front-ends             *
02172  *                                  *
02173  ************************************************************************/
02174 
02188 void
02189 xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
02190                   int level, int format, const char *encoding)
02191 {
02192     xmlSaveCtxt ctxt;
02193 #ifdef LIBXML_HTML_ENABLED
02194     xmlDtdPtr dtd;
02195     int is_xhtml = 0;
02196 #endif
02197 
02198     xmlInitParser();
02199 
02200     if ((buf == NULL) || (cur == NULL)) return;
02201 
02202     if (encoding == NULL)
02203         encoding = "UTF-8";
02204 
02205     memset(&ctxt, 0, sizeof(ctxt));
02206     ctxt.doc = doc;
02207     ctxt.buf = buf;
02208     ctxt.level = level;
02209     ctxt.format = format ? 1 : 0;
02210     ctxt.encoding = (const xmlChar *) encoding;
02211     xmlSaveCtxtInit(&ctxt);
02212     ctxt.options |= XML_SAVE_AS_XML;
02213 
02214 #ifdef LIBXML_HTML_ENABLED
02215     dtd = xmlGetIntSubset(doc);
02216     if (dtd != NULL) {
02217     is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
02218     if (is_xhtml < 0)
02219         is_xhtml = 0;
02220     }
02221 
02222     if (is_xhtml)
02223         xhtmlNodeDumpOutput(&ctxt, cur);
02224     else
02225 #endif
02226         xmlNodeDumpOutputInternal(&ctxt, cur);
02227 }
02228 
02244 void
02245 xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
02246         int * doc_txt_len, const char * txt_encoding,
02247         int format) {
02248     xmlSaveCtxt ctxt;
02249     int                         dummy = 0;
02250     xmlOutputBufferPtr          out_buff = NULL;
02251     xmlCharEncodingHandlerPtr   conv_hdlr = NULL;
02252 
02253     if (doc_txt_len == NULL) {
02254         doc_txt_len = &dummy;   /*  Continue, caller just won't get length */
02255     }
02256 
02257     if (doc_txt_ptr == NULL) {
02258         *doc_txt_len = 0;
02259         return;
02260     }
02261 
02262     *doc_txt_ptr = NULL;
02263     *doc_txt_len = 0;
02264 
02265     if (out_doc == NULL) {
02266         /*  No document, no output  */
02267         return;
02268     }
02269 
02270     /*
02271      *  Validate the encoding value, if provided.
02272      *  This logic is copied from xmlSaveFileEnc.
02273      */
02274 
02275     if (txt_encoding == NULL)
02276     txt_encoding = (const char *) out_doc->encoding;
02277     if (txt_encoding != NULL) {
02278     conv_hdlr = xmlFindCharEncodingHandler(txt_encoding);
02279     if ( conv_hdlr == NULL ) {
02280         xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, (xmlNodePtr) out_doc,
02281                txt_encoding);
02282         return;
02283     }
02284     }
02285 
02286     if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) {
02287         xmlSaveErrMemory("creating buffer");
02288         return;
02289     }
02290 
02291     memset(&ctxt, 0, sizeof(ctxt));
02292     ctxt.doc = out_doc;
02293     ctxt.buf = out_buff;
02294     ctxt.level = 0;
02295     ctxt.format = format ? 1 : 0;
02296     ctxt.encoding = (const xmlChar *) txt_encoding;
02297     xmlSaveCtxtInit(&ctxt);
02298     ctxt.options |= XML_SAVE_AS_XML;
02299     xmlDocContentDumpOutput(&ctxt, out_doc);
02300     xmlOutputBufferFlush(out_buff);
02301     if (out_buff->conv != NULL) {
02302     *doc_txt_len = out_buff->conv->use;
02303     *doc_txt_ptr = xmlStrndup(out_buff->conv->content, *doc_txt_len);
02304     } else {
02305     *doc_txt_len = out_buff->buffer->use;
02306     *doc_txt_ptr = xmlStrndup(out_buff->buffer->content, *doc_txt_len);
02307     }
02308     (void)xmlOutputBufferClose(out_buff);
02309 
02310     if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) {
02311         *doc_txt_len = 0;
02312         xmlSaveErrMemory("creating output");
02313     }
02314 
02315     return;
02316 }
02317 
02329 void
02330 xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
02331     xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, 0);
02332 }
02333 
02347 void
02348 xmlDocDumpFormatMemory(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
02349     xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, format);
02350 }
02351 
02364 void
02365 xmlDocDumpMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
02366                 int * doc_txt_len, const char * txt_encoding) {
02367     xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len,
02368                           txt_encoding, 0);
02369 }
02370 
02383 int
02384 xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) {
02385     xmlSaveCtxt ctxt;
02386     xmlOutputBufferPtr buf;
02387     const char * encoding;
02388     xmlCharEncodingHandlerPtr handler = NULL;
02389     int ret;
02390 
02391     if (cur == NULL) {
02392 #ifdef DEBUG_TREE
02393         xmlGenericError(xmlGenericErrorContext,
02394         "xmlDocDump : document == NULL\n");
02395 #endif
02396     return(-1);
02397     }
02398     encoding = (const char *) cur->encoding;
02399 
02400     if (encoding != NULL) {
02401     handler = xmlFindCharEncodingHandler(encoding);
02402     if (handler == NULL) {
02403         xmlFree((char *) cur->encoding);
02404         cur->encoding = NULL;
02405         encoding = NULL;
02406     }
02407     }
02408     buf = xmlOutputBufferCreateFile(f, handler);
02409     if (buf == NULL) return(-1);
02410     memset(&ctxt, 0, sizeof(ctxt));
02411     ctxt.doc = cur;
02412     ctxt.buf = buf;
02413     ctxt.level = 0;
02414     ctxt.format = format ? 1 : 0;
02415     ctxt.encoding = (const xmlChar *) encoding;
02416     xmlSaveCtxtInit(&ctxt);
02417     ctxt.options |= XML_SAVE_AS_XML;
02418     xmlDocContentDumpOutput(&ctxt, cur);
02419 
02420     ret = xmlOutputBufferClose(buf);
02421     return(ret);
02422 }
02423 
02433 int
02434 xmlDocDump(FILE *f, xmlDocPtr cur) {
02435     return(xmlDocFormatDump (f, cur, 0));
02436 }
02437 
02450 int
02451 xmlSaveFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding) {
02452     xmlSaveCtxt ctxt;
02453     int ret;
02454 
02455     if (buf == NULL) return(-1);
02456     if (cur == NULL) {
02457         xmlOutputBufferClose(buf);
02458     return(-1);
02459     }
02460     memset(&ctxt, 0, sizeof(ctxt));
02461     ctxt.doc = cur;
02462     ctxt.buf = buf;
02463     ctxt.level = 0;
02464     ctxt.format = 0;
02465     ctxt.encoding = (const xmlChar *) encoding;
02466     xmlSaveCtxtInit(&ctxt);
02467     ctxt.options |= XML_SAVE_AS_XML;
02468     xmlDocContentDumpOutput(&ctxt, cur);
02469     ret = xmlOutputBufferClose(buf);
02470     return(ret);
02471 }
02472 
02486 int
02487 xmlSaveFormatFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur,
02488                     const char *encoding, int format)
02489 {
02490     xmlSaveCtxt ctxt;
02491     int ret;
02492 
02493     if (buf == NULL) return(-1);
02494     if ((cur == NULL) ||
02495         ((cur->type != XML_DOCUMENT_NODE) &&
02496      (cur->type != XML_HTML_DOCUMENT_NODE))) {
02497         xmlOutputBufferClose(buf);
02498     return(-1);
02499     }
02500     memset(&ctxt, 0, sizeof(ctxt));
02501     ctxt.doc = cur;
02502     ctxt.buf = buf;
02503     ctxt.level = 0;
02504     ctxt.format = format ? 1 : 0;
02505     ctxt.encoding = (const xmlChar *) encoding;
02506     xmlSaveCtxtInit(&ctxt);
02507     ctxt.options |= XML_SAVE_AS_XML;
02508     xmlDocContentDumpOutput(&ctxt, cur);
02509     ret = xmlOutputBufferClose(buf);
02510     return (ret);
02511 }
02512 
02526 int
02527 xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur,
02528             const char * encoding, int format ) {
02529     xmlSaveCtxt ctxt;
02530     xmlOutputBufferPtr buf;
02531     xmlCharEncodingHandlerPtr handler = NULL;
02532     int ret;
02533 
02534     if (cur == NULL)
02535     return(-1);
02536 
02537     if (encoding == NULL)
02538     encoding = (const char *) cur->encoding;
02539 
02540     if (encoding != NULL) {
02541 
02542         handler = xmlFindCharEncodingHandler(encoding);
02543         if (handler == NULL)
02544         return(-1);
02545     }
02546 
02547 #ifdef HAVE_ZLIB_H
02548     if (cur->compression < 0) cur->compression = xmlGetCompressMode();
02549 #endif
02550     /* 
02551      * save the content to a temp buffer.
02552      */
02553     buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
02554     if (buf == NULL) return(-1);
02555     memset(&ctxt, 0, sizeof(ctxt));
02556     ctxt.doc = cur;
02557     ctxt.buf = buf;
02558     ctxt.level = 0;
02559     ctxt.format = format ? 1 : 0;
02560     ctxt.encoding = (const xmlChar *) encoding;
02561     xmlSaveCtxtInit(&ctxt);
02562     ctxt.options |= XML_SAVE_AS_XML;
02563 
02564     xmlDocContentDumpOutput(&ctxt, cur);
02565 
02566     ret = xmlOutputBufferClose(buf);
02567     return(ret);
02568 }
02569 
02570 
02581 int
02582 xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
02583     return ( xmlSaveFormatFileEnc( filename, cur, encoding, 0 ) );
02584 }
02585 
02600 int
02601 xmlSaveFormatFile(const char *filename, xmlDocPtr cur, int format) {
02602     return ( xmlSaveFormatFileEnc( filename, cur, NULL, format ) );
02603 }
02604 
02615 int
02616 xmlSaveFile(const char *filename, xmlDocPtr cur) {
02617     return(xmlSaveFormatFileEnc(filename, cur, NULL, 0));
02618 }
02619 
02620 #endif /* LIBXML_OUTPUT_ENABLED */
02621 
02622 #define bottom_xmlsave
02623 #include "elfgcchack.h"

Generated on Fri May 25 2012 04:33:17 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.