Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenxmlsave.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 " ", 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 " ", 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 "	", 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 """, 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 "<", 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 ">", 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 "&", 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
1.7.6.1
|