diff options
author | setser <[email protected]> | 2022-05-09 00:13:37 +0300 |
---|---|---|
committer | setser <[email protected]> | 2022-05-09 00:13:37 +0300 |
commit | e87e3fc8d0e04eb7ba3eee221bb91613b527ad85 (patch) | |
tree | 5279c128bdbdf902b9a08d9fae8e55b91910a553 /contrib/libs/libxml/xmlsave.c | |
parent | f4f3e4024a1f32bd0bc3fa20239025a1b179e42d (diff) |
Update libxml to 2.9.13
ref:f572491d236694e847142c36f0f5546c649e05d7
Diffstat (limited to 'contrib/libs/libxml/xmlsave.c')
-rw-r--r-- | contrib/libs/libxml/xmlsave.c | 1154 |
1 files changed, 560 insertions, 594 deletions
diff --git a/contrib/libs/libxml/xmlsave.c b/contrib/libs/libxml/xmlsave.c index fa009153718..489505f4865 100644 --- a/contrib/libs/libxml/xmlsave.c +++ b/contrib/libs/libxml/xmlsave.c @@ -100,7 +100,7 @@ struct _xmlSaveCtxt { ************************************************************************/ /** * xmlSaveErrMemory: - * @extra: extra informations + * @extra: extra information * * Handle an out of memory condition */ @@ -114,7 +114,7 @@ xmlSaveErrMemory(const char *extra) * xmlSaveErr: * @code: the error number * @node: the location of the error. - * @extra: extra informations + * @extra: extra information * * Handle an out of memory condition */ @@ -590,7 +590,6 @@ static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) { static void xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur); #endif -static void xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur); static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur); void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur); static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur); @@ -705,6 +704,7 @@ xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) { static void xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) { xmlOutputBufferPtr buf; + xmlNodePtr cur; int format, level; if (dtd == NULL) return; @@ -742,7 +742,9 @@ xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) { level = ctxt->level; ctxt->format = 0; ctxt->level = -1; - xmlNodeListDumpOutput(ctxt, dtd->children); + for (cur = dtd->children; cur != NULL; cur = cur->next) { + xmlNodeDumpOutputInternal(ctxt, cur); + } ctxt->format = format; ctxt->level = level; xmlOutputBufferWrite(buf, 2, "]>"); @@ -776,58 +778,9 @@ xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) { xmlOutputBufferWrite(buf, 1, "\""); } -/** - * xmlAttrListDumpOutput: - * @buf: the XML buffer output - * @doc: the document - * @cur: the first attribute pointer - * @encoding: an optional encoding string - * - * Dump a list of XML attributes - */ -static void -xmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) { - if (cur == NULL) return; - while (cur != NULL) { - xmlAttrDumpOutput(ctxt, cur); - cur = cur->next; - } -} - - - -/** - * xmlNodeListDumpOutput: - * @cur: the first node - * - * Dump an XML node list, recursive behaviour, children are printed too. - */ -static void -xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { - xmlOutputBufferPtr buf; - - if (cur == NULL) return; - buf = ctxt->buf; - while (cur != NULL) { - if ((ctxt->format == 1) && (xmlIndentTreeOutput) && - ((cur->type == XML_ELEMENT_NODE) || - (cur->type == XML_COMMENT_NODE) || - (cur->type == XML_PI_NODE))) - xmlOutputBufferWrite(buf, ctxt->indent_size * - (ctxt->level > ctxt->indent_nr ? - ctxt->indent_nr : ctxt->level), - ctxt->indent); - xmlNodeDumpOutputInternal(ctxt, cur); - if (ctxt->format == 1) { - xmlOutputBufferWrite(buf, 1, "\n"); - } - cur = cur->next; - } -} - #ifdef LIBXML_HTML_ENABLED /** - * xmlNodeDumpOutputInternal: + * htmlNodeDumpOutputInternal: * @cur: the current node * * Dump an HTML node, recursive behaviour, children are printed too. @@ -893,57 +846,126 @@ htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { */ static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { - int format; - xmlNodePtr tmp; + int format = ctxt->format; + xmlNodePtr tmp, root, unformattedNode = NULL, parent; + xmlAttrPtr attr; xmlChar *start, *end; xmlOutputBufferPtr buf; if (cur == NULL) return; buf = ctxt->buf; - if (cur->type == XML_XINCLUDE_START) - return; - if (cur->type == XML_XINCLUDE_END) - return; - if ((cur->type == XML_DOCUMENT_NODE) || - (cur->type == XML_HTML_DOCUMENT_NODE)) { - xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur); - return; - } -#ifdef LIBXML_HTML_ENABLED - if (ctxt->options & XML_SAVE_XHTML) { - xhtmlNodeDumpOutput(ctxt, cur); - return; - } - if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) && - (cur->doc->type == XML_HTML_DOCUMENT_NODE) && - ((ctxt->options & XML_SAVE_AS_XML) == 0)) || - (ctxt->options & XML_SAVE_AS_HTML)) { - htmlNodeDumpOutputInternal(ctxt, cur); - return; - } -#endif - if (cur->type == XML_DTD_NODE) { - xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur); - return; - } - if (cur->type == XML_DOCUMENT_FRAG_NODE) { - xmlNodeListDumpOutput(ctxt, cur->children); - return; - } - if (cur->type == XML_ELEMENT_DECL) { - xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur); - return; - } - if (cur->type == XML_ATTRIBUTE_DECL) { - xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur); - return; - } - if (cur->type == XML_ENTITY_DECL) { - xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur); - return; - } - if (cur->type == XML_TEXT_NODE) { - if (cur->content != NULL) { + + root = cur; + parent = cur->parent; + while (1) { + switch (cur->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur); + break; + + case XML_DTD_NODE: + xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur); + break; + + case XML_DOCUMENT_FRAG_NODE: + /* Always validate cur->parent when descending. */ + if ((cur->parent == parent) && (cur->children != NULL)) { + parent = cur; + cur = cur->children; + continue; + } + break; + + case XML_ELEMENT_DECL: + xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur); + break; + + case XML_ATTRIBUTE_DECL: + xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur); + break; + + case XML_ENTITY_DECL: + xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur); + break; + + case XML_ELEMENT_NODE: + if ((cur != root) && (ctxt->format == 1) && + (xmlIndentTreeOutput)) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level), + ctxt->indent); + + /* + * Some users like lxml are known to pass nodes with a corrupted + * tree structure. Fall back to a recursive call to handle this + * case. + */ + if ((cur->parent != parent) && (cur->children != NULL)) { + xmlNodeDumpOutputInternal(ctxt, cur); + break; + } + + xmlOutputBufferWrite(buf, 1, "<"); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + xmlOutputBufferWriteString(buf, (const char *)cur->name); + if (cur->nsDef) + xmlNsListDumpOutputCtxt(ctxt, cur->nsDef); + for (attr = cur->properties; attr != NULL; attr = attr->next) + xmlAttrDumpOutput(ctxt, attr); + + if (cur->children == NULL) { + if ((ctxt->options & XML_SAVE_NO_EMPTY) == 0) { + if (ctxt->format == 2) + xmlOutputBufferWriteWSNonSig(ctxt, 0); + xmlOutputBufferWrite(buf, 2, "/>"); + } else { + if (ctxt->format == 2) + xmlOutputBufferWriteWSNonSig(ctxt, 1); + xmlOutputBufferWrite(buf, 3, "></"); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, + (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + xmlOutputBufferWriteString(buf, (const char *)cur->name); + if (ctxt->format == 2) + xmlOutputBufferWriteWSNonSig(ctxt, 0); + xmlOutputBufferWrite(buf, 1, ">"); + } + } else { + if (ctxt->format == 1) { + tmp = cur->children; + while (tmp != NULL) { + if ((tmp->type == XML_TEXT_NODE) || + (tmp->type == XML_CDATA_SECTION_NODE) || + (tmp->type == XML_ENTITY_REF_NODE)) { + ctxt->format = 0; + unformattedNode = cur; + break; + } + tmp = tmp->next; + } + } + if (ctxt->format == 2) + xmlOutputBufferWriteWSNonSig(ctxt, 1); + xmlOutputBufferWrite(buf, 1, ">"); + if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n"); + if (ctxt->level >= 0) ctxt->level++; + parent = cur; + cur = cur->children; + continue; + } + + break; + + case XML_TEXT_NODE: + if (cur->content == NULL) + break; if (cur->name != xmlStringTextNoenc) { xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape); } else { @@ -952,139 +974,136 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { */ xmlOutputBufferWriteString(buf, (const char *) cur->content); } - } + break; - return; - } - if (cur->type == XML_PI_NODE) { - if (cur->content != NULL) { - xmlOutputBufferWrite(buf, 2, "<?"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - if (cur->content != NULL) { - if (ctxt->format == 2) - xmlOutputBufferWriteWSNonSig(ctxt, 0); - else - xmlOutputBufferWrite(buf, 1, " "); - xmlOutputBufferWriteString(buf, (const char *)cur->content); - } - xmlOutputBufferWrite(buf, 2, "?>"); - } else { - xmlOutputBufferWrite(buf, 2, "<?"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - if (ctxt->format == 2) - xmlOutputBufferWriteWSNonSig(ctxt, 0); - xmlOutputBufferWrite(buf, 2, "?>"); - } - return; - } - if (cur->type == XML_COMMENT_NODE) { - if (cur->content != NULL) { - xmlOutputBufferWrite(buf, 4, "<!--"); - xmlOutputBufferWriteString(buf, (const char *)cur->content); - xmlOutputBufferWrite(buf, 3, "-->"); - } - return; - } - if (cur->type == XML_ENTITY_REF_NODE) { - xmlOutputBufferWrite(buf, 1, "&"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWrite(buf, 1, ";"); - return; - } - if (cur->type == XML_CDATA_SECTION_NODE) { - if (cur->content == NULL || *cur->content == '\0') { - xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>"); - } else { - start = end = cur->content; - while (*end != '\0') { - if ((*end == ']') && (*(end + 1) == ']') && - (*(end + 2) == '>')) { - end = end + 2; - xmlOutputBufferWrite(buf, 9, "<![CDATA["); - xmlOutputBufferWrite(buf, end - start, (const char *)start); - xmlOutputBufferWrite(buf, 3, "]]>"); - start = end; - } - end++; - } - if (start != end) { - xmlOutputBufferWrite(buf, 9, "<![CDATA["); - xmlOutputBufferWriteString(buf, (const char *)start); - xmlOutputBufferWrite(buf, 3, "]]>"); - } - } - return; - } - if (cur->type == XML_ATTRIBUTE_NODE) { - xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur); - return; - } - if (cur->type == XML_NAMESPACE_DECL) { - xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur); - return; - } + case XML_PI_NODE: + if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput)) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level), + ctxt->indent); + + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 2, "<?"); + xmlOutputBufferWriteString(buf, (const char *)cur->name); + if (cur->content != NULL) { + if (ctxt->format == 2) + xmlOutputBufferWriteWSNonSig(ctxt, 0); + else + xmlOutputBufferWrite(buf, 1, " "); + xmlOutputBufferWriteString(buf, + (const char *)cur->content); + } + xmlOutputBufferWrite(buf, 2, "?>"); + } else { + xmlOutputBufferWrite(buf, 2, "<?"); + xmlOutputBufferWriteString(buf, (const char *)cur->name); + if (ctxt->format == 2) + xmlOutputBufferWriteWSNonSig(ctxt, 0); + xmlOutputBufferWrite(buf, 2, "?>"); + } + break; + + case XML_COMMENT_NODE: + if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput)) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level), + ctxt->indent); + + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 4, "<!--"); + xmlOutputBufferWriteString(buf, (const char *)cur->content); + xmlOutputBufferWrite(buf, 3, "-->"); + } + break; + + case XML_ENTITY_REF_NODE: + xmlOutputBufferWrite(buf, 1, "&"); + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 1, ";"); + break; + + case XML_CDATA_SECTION_NODE: + if (cur->content == NULL || *cur->content == '\0') { + xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>"); + } else { + start = end = cur->content; + while (*end != '\0') { + if ((*end == ']') && (*(end + 1) == ']') && + (*(end + 2) == '>')) { + end = end + 2; + xmlOutputBufferWrite(buf, 9, "<![CDATA["); + xmlOutputBufferWrite(buf, end - start, + (const char *)start); + xmlOutputBufferWrite(buf, 3, "]]>"); + start = end; + } + end++; + } + if (start != end) { + xmlOutputBufferWrite(buf, 9, "<![CDATA["); + xmlOutputBufferWriteString(buf, (const char *)start); + xmlOutputBufferWrite(buf, 3, "]]>"); + } + } + break; - format = ctxt->format; - if (format == 1) { - tmp = cur->children; - while (tmp != NULL) { - if ((tmp->type == XML_TEXT_NODE) || - (tmp->type == XML_CDATA_SECTION_NODE) || - (tmp->type == XML_ENTITY_REF_NODE)) { - ctxt->format = 0; - break; - } - tmp = tmp->next; - } - } - xmlOutputBufferWrite(buf, 1, "<"); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWrite(buf, 1, ":"); - } + case XML_ATTRIBUTE_NODE: + xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur); + break; - xmlOutputBufferWriteString(buf, (const char *)cur->name); - if (cur->nsDef) - xmlNsListDumpOutputCtxt(ctxt, cur->nsDef); - if (cur->properties != NULL) - xmlAttrListDumpOutput(ctxt, cur->properties); - - if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) && - (cur->children == NULL) && ((ctxt->options & XML_SAVE_NO_EMPTY) == 0)) { - if (ctxt->format == 2) - xmlOutputBufferWriteWSNonSig(ctxt, 0); - xmlOutputBufferWrite(buf, 2, "/>"); - ctxt->format = format; - return; - } - if (ctxt->format == 2) - xmlOutputBufferWriteWSNonSig(ctxt, 1); - xmlOutputBufferWrite(buf, 1, ">"); - if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { - xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape); - } - if (cur->children != NULL) { - if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n"); - if (ctxt->level >= 0) ctxt->level++; - xmlNodeListDumpOutput(ctxt, cur->children); - if (ctxt->level > 0) ctxt->level--; - if ((xmlIndentTreeOutput) && (ctxt->format == 1)) - xmlOutputBufferWrite(buf, ctxt->indent_size * - (ctxt->level > ctxt->indent_nr ? - ctxt->indent_nr : ctxt->level), - ctxt->indent); - } - xmlOutputBufferWrite(buf, 2, "</"); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWrite(buf, 1, ":"); - } + case XML_NAMESPACE_DECL: + xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur); + break; - xmlOutputBufferWriteString(buf, (const char *)cur->name); - if (ctxt->format == 2) - xmlOutputBufferWriteWSNonSig(ctxt, 0); - xmlOutputBufferWrite(buf, 1, ">"); - ctxt->format = format; + default: + break; + } + + while (1) { + if (cur == root) + return; + if ((ctxt->format == 1) && + (cur->type != XML_XINCLUDE_START) && + (cur->type != XML_XINCLUDE_END)) + xmlOutputBufferWrite(buf, 1, "\n"); + if (cur->next != NULL) { + cur = cur->next; + break; + } + + cur = parent; + /* cur->parent was validated when descending. */ + parent = cur->parent; + + if (cur->type == XML_ELEMENT_NODE) { + if (ctxt->level > 0) ctxt->level--; + if ((xmlIndentTreeOutput) && (ctxt->format == 1)) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level), + ctxt->indent); + + xmlOutputBufferWrite(buf, 2, "</"); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, + (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + + xmlOutputBufferWriteString(buf, (const char *)cur->name); + if (ctxt->format == 2) + xmlOutputBufferWriteWSNonSig(ctxt, 0); + xmlOutputBufferWrite(buf, 1, ">"); + + if (cur == unformattedNode) { + ctxt->format = format; + unformattedNode = NULL; + } + } + } + } } /** @@ -1224,7 +1243,9 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) { else #endif xmlNodeDumpOutputInternal(ctxt, child); - xmlOutputBufferWrite(buf, 1, "\n"); + if ((child->type != XML_XINCLUDE_START) && + (child->type != XML_XINCLUDE_END)) + xmlOutputBufferWrite(buf, 1, "\n"); child = child->next; } } @@ -1396,40 +1417,6 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) { } /** - * xhtmlNodeListDumpOutput: - * @buf: the XML buffer output - * @doc: the XHTML document - * @cur: the first node - * @level: the imbrication level for indenting - * @format: is formatting allowed - * @encoding: an optional encoding string - * - * Dump an XML node list, recursive behaviour, children are printed too. - * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1 - * or xmlKeepBlanksDefault(0) was called - */ -static void -xhtmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { - xmlOutputBufferPtr buf; - - if (cur == NULL) return; - buf = ctxt->buf; - while (cur != NULL) { - if ((ctxt->format == 1) && (xmlIndentTreeOutput) && - (cur->type == XML_ELEMENT_NODE)) - xmlOutputBufferWrite(buf, ctxt->indent_size * - (ctxt->level > ctxt->indent_nr ? - ctxt->indent_nr : ctxt->level), - ctxt->indent); - xhtmlNodeDumpOutput(ctxt, cur); - if (ctxt->format == 1) { - xmlOutputBufferWrite(buf, 1, "\n"); - } - cur = cur->next; - } -} - -/** * xhtmlNodeDumpOutput: * @buf: the XML buffer output * @doc: the XHTML document @@ -1442,48 +1429,195 @@ xhtmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { */ static void xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { - int format, addmeta = 0; - xmlNodePtr tmp; + int format = ctxt->format, addmeta; + xmlNodePtr tmp, root, unformattedNode = NULL; xmlChar *start, *end; - xmlOutputBufferPtr buf; + xmlOutputBufferPtr buf = ctxt->buf; if (cur == NULL) return; - if ((cur->type == XML_DOCUMENT_NODE) || - (cur->type == XML_HTML_DOCUMENT_NODE)) { - xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur); - return; - } - if (cur->type == XML_XINCLUDE_START) - return; - if (cur->type == XML_XINCLUDE_END) - return; - if (cur->type == XML_NAMESPACE_DECL) { - xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur); - return; - } - if (cur->type == XML_DTD_NODE) { - xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur); - return; - } - if (cur->type == XML_DOCUMENT_FRAG_NODE) { - xhtmlNodeListDumpOutput(ctxt, cur->children); - return; - } - buf = ctxt->buf; - if (cur->type == XML_ELEMENT_DECL) { - xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur); - return; - } - if (cur->type == XML_ATTRIBUTE_DECL) { - xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur); - return; - } - if (cur->type == XML_ENTITY_DECL) { - xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur); - return; - } - if (cur->type == XML_TEXT_NODE) { - if (cur->content != NULL) { + + root = cur; + while (1) { + switch (cur->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur); + break; + + case XML_NAMESPACE_DECL: + xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur); + break; + + case XML_DTD_NODE: + xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur); + break; + + case XML_DOCUMENT_FRAG_NODE: + if (cur->children) { + cur = cur->children; + continue; + } + break; + + case XML_ELEMENT_DECL: + xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur); + break; + + case XML_ATTRIBUTE_DECL: + xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur); + break; + + case XML_ENTITY_DECL: + xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur); + break; + + case XML_ELEMENT_NODE: + addmeta = 0; + + if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput)) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level), + ctxt->indent); + + xmlOutputBufferWrite(buf, 1, "<"); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + + xmlOutputBufferWriteString(buf, (const char *)cur->name); + if (cur->nsDef) + xmlNsListDumpOutputCtxt(ctxt, cur->nsDef); + if ((xmlStrEqual(cur->name, BAD_CAST "html") && + (cur->ns == NULL) && (cur->nsDef == NULL))) { + /* + * 3.1.1. Strictly Conforming Documents A.3.1.1 3/ + */ + xmlOutputBufferWriteString(buf, + " xmlns=\"http://www.w3.org/1999/xhtml\""); + } + if (cur->properties != NULL) + xhtmlAttrListDumpOutput(ctxt, cur->properties); + + if ((cur->parent != NULL) && + (cur->parent->parent == (xmlNodePtr) cur->doc) && + xmlStrEqual(cur->name, BAD_CAST"head") && + xmlStrEqual(cur->parent->name, BAD_CAST"html")) { + + tmp = cur->children; + while (tmp != NULL) { + if (xmlStrEqual(tmp->name, BAD_CAST"meta")) { + xmlChar *httpequiv; + + httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv"); + if (httpequiv != NULL) { + if (xmlStrcasecmp(httpequiv, + BAD_CAST"Content-Type") == 0) { + xmlFree(httpequiv); + break; + } + xmlFree(httpequiv); + } + } + tmp = tmp->next; + } + if (tmp == NULL) + addmeta = 1; + } + + if (cur->children == NULL) { + if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) && + ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) { + /* + * C.2. Empty Elements + */ + xmlOutputBufferWrite(buf, 3, " />"); + } else { + if (addmeta == 1) { + xmlOutputBufferWrite(buf, 1, ">"); + if (ctxt->format == 1) { + xmlOutputBufferWrite(buf, 1, "\n"); + if (xmlIndentTreeOutput) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level + 1 > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level + 1), + ctxt->indent); + } + xmlOutputBufferWriteString(buf, + "<meta http-equiv=\"Content-Type\" " + "content=\"text/html; charset="); + if (ctxt->encoding) { + xmlOutputBufferWriteString(buf, + (const char *)ctxt->encoding); + } else { + xmlOutputBufferWrite(buf, 5, "UTF-8"); + } + xmlOutputBufferWrite(buf, 4, "\" />"); + if (ctxt->format == 1) + xmlOutputBufferWrite(buf, 1, "\n"); + } else { + xmlOutputBufferWrite(buf, 1, ">"); + } + /* + * C.3. Element Minimization and Empty Element Content + */ + xmlOutputBufferWrite(buf, 2, "</"); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, + (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 1, ">"); + } + } else { + xmlOutputBufferWrite(buf, 1, ">"); + if (addmeta == 1) { + if (ctxt->format == 1) { + xmlOutputBufferWrite(buf, 1, "\n"); + if (xmlIndentTreeOutput) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level + 1 > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level + 1), + ctxt->indent); + } + xmlOutputBufferWriteString(buf, + "<meta http-equiv=\"Content-Type\" " + "content=\"text/html; charset="); + if (ctxt->encoding) { + xmlOutputBufferWriteString(buf, + (const char *)ctxt->encoding); + } else { + xmlOutputBufferWrite(buf, 5, "UTF-8"); + } + xmlOutputBufferWrite(buf, 4, "\" />"); + } + + if (ctxt->format == 1) { + tmp = cur->children; + while (tmp != NULL) { + if ((tmp->type == XML_TEXT_NODE) || + (tmp->type == XML_ENTITY_REF_NODE)) { + unformattedNode = cur; + ctxt->format = 0; + break; + } + tmp = tmp->next; + } + } + + if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n"); + if (ctxt->level >= 0) ctxt->level++; + cur = cur->children; + continue; + } + + break; + + case XML_TEXT_NODE: + if (cur->content == NULL) + break; if ((cur->name == xmlStringText) || (cur->name != xmlStringTextNoenc)) { xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape); @@ -1493,286 +1627,115 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { */ xmlOutputBufferWriteString(buf, (const char *) cur->content); } - } - - return; - } - if (cur->type == XML_PI_NODE) { - if (cur->content != NULL) { - xmlOutputBufferWrite(buf, 2, "<?"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - if (cur->content != NULL) { - xmlOutputBufferWrite(buf, 1, " "); - xmlOutputBufferWriteString(buf, (const char *)cur->content); - } - xmlOutputBufferWrite(buf, 2, "?>"); - } else { - xmlOutputBufferWrite(buf, 2, "<?"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWrite(buf, 2, "?>"); - } - return; - } - if (cur->type == XML_COMMENT_NODE) { - if (cur->content != NULL) { - xmlOutputBufferWrite(buf, 4, "<!--"); - xmlOutputBufferWriteString(buf, (const char *)cur->content); - xmlOutputBufferWrite(buf, 3, "-->"); - } - return; - } - if (cur->type == XML_ENTITY_REF_NODE) { - xmlOutputBufferWrite(buf, 1, "&"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWrite(buf, 1, ";"); - return; - } - if (cur->type == XML_CDATA_SECTION_NODE) { - if (cur->content == NULL || *cur->content == '\0') { - xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>"); - } else { - start = end = cur->content; - while (*end != '\0') { - if (*end == ']' && *(end + 1) == ']' && *(end + 2) == '>') { - end = end + 2; - xmlOutputBufferWrite(buf, 9, "<![CDATA["); - xmlOutputBufferWrite(buf, end - start, (const char *)start); - xmlOutputBufferWrite(buf, 3, "]]>"); - start = end; - } - end++; - } - if (start != end) { - xmlOutputBufferWrite(buf, 9, "<![CDATA["); - xmlOutputBufferWriteString(buf, (const char *)start); - xmlOutputBufferWrite(buf, 3, "]]>"); - } - } - return; - } - if (cur->type == XML_ATTRIBUTE_NODE) { - xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur); - return; - } + break; - format = ctxt->format; - if (format == 1) { - tmp = cur->children; - while (tmp != NULL) { - if ((tmp->type == XML_TEXT_NODE) || - (tmp->type == XML_ENTITY_REF_NODE)) { - format = 0; - break; - } - tmp = tmp->next; - } - } - xmlOutputBufferWrite(buf, 1, "<"); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWrite(buf, 1, ":"); - } + case XML_PI_NODE: + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 2, "<?"); + xmlOutputBufferWriteString(buf, (const char *)cur->name); + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 1, " "); + xmlOutputBufferWriteString(buf, + (const char *)cur->content); + } + xmlOutputBufferWrite(buf, 2, "?>"); + } else { + xmlOutputBufferWrite(buf, 2, "<?"); + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 2, "?>"); + } + break; - xmlOutputBufferWriteString(buf, (const char *)cur->name); - if (cur->nsDef) - xmlNsListDumpOutputCtxt(ctxt, cur->nsDef); - if ((xmlStrEqual(cur->name, BAD_CAST "html") && - (cur->ns == NULL) && (cur->nsDef == NULL))) { - /* - * 3.1.1. Strictly Conforming Documents A.3.1.1 3/ - */ - xmlOutputBufferWriteString(buf, - " xmlns=\"http://www.w3.org/1999/xhtml\""); - } - if (cur->properties != NULL) - xhtmlAttrListDumpOutput(ctxt, cur->properties); - - if ((cur->type == XML_ELEMENT_NODE) && - (cur->parent != NULL) && - (cur->parent->parent == (xmlNodePtr) cur->doc) && - xmlStrEqual(cur->name, BAD_CAST"head") && - xmlStrEqual(cur->parent->name, BAD_CAST"html")) { - - tmp = cur->children; - while (tmp != NULL) { - if (xmlStrEqual(tmp->name, BAD_CAST"meta")) { - xmlChar *httpequiv; - - httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv"); - if (httpequiv != NULL) { - if (xmlStrcasecmp(httpequiv, BAD_CAST"Content-Type") == 0) { - xmlFree(httpequiv); - break; + case XML_COMMENT_NODE: + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 4, "<!--"); + xmlOutputBufferWriteString(buf, (const char *)cur->content); + xmlOutputBufferWrite(buf, 3, "-->"); + } + break; + + case XML_ENTITY_REF_NODE: + xmlOutputBufferWrite(buf, 1, "&"); + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 1, ";"); + break; + + case XML_CDATA_SECTION_NODE: + if (cur->content == NULL || *cur->content == '\0') { + xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>"); + } else { + start = end = cur->content; + while (*end != '\0') { + if (*end == ']' && *(end + 1) == ']' && + *(end + 2) == '>') { + end = end + 2; + xmlOutputBufferWrite(buf, 9, "<![CDATA["); + xmlOutputBufferWrite(buf, end - start, + (const char *)start); + xmlOutputBufferWrite(buf, 3, "]]>"); + start = end; } - xmlFree(httpequiv); + end++; + } + if (start != end) { + xmlOutputBufferWrite(buf, 9, "<![CDATA["); + xmlOutputBufferWriteString(buf, (const char *)start); + xmlOutputBufferWrite(buf, 3, "]]>"); } } - tmp = tmp->next; + break; + + case XML_ATTRIBUTE_NODE: + xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur); + break; + + default: + break; } - if (tmp == NULL) - addmeta = 1; - } - if ((cur->type == XML_ELEMENT_NODE) && (cur->children == NULL)) { - if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) && - ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) { - /* - * C.2. Empty Elements - */ - xmlOutputBufferWrite(buf, 3, " />"); - } else { - if (addmeta == 1) { - xmlOutputBufferWrite(buf, 1, ">"); - if (ctxt->format == 1) { - xmlOutputBufferWrite(buf, 1, "\n"); - if (xmlIndentTreeOutput) - xmlOutputBufferWrite(buf, ctxt->indent_size * - (ctxt->level + 1 > ctxt->indent_nr ? - ctxt->indent_nr : ctxt->level + 1), ctxt->indent); - } - xmlOutputBufferWriteString(buf, - "<meta http-equiv=\"Content-Type\" content=\"text/html; charset="); - if (ctxt->encoding) { - xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding); - } else { - xmlOutputBufferWrite(buf, 5, "UTF-8"); - } - xmlOutputBufferWrite(buf, 4, "\" />"); - if (ctxt->format == 1) - xmlOutputBufferWrite(buf, 1, "\n"); - } else { - xmlOutputBufferWrite(buf, 1, ">"); - } - /* - * C.3. Element Minimization and Empty Element Content - */ - xmlOutputBufferWrite(buf, 2, "</"); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWrite(buf, 1, ":"); - } - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWrite(buf, 1, ">"); - } - return; - } - xmlOutputBufferWrite(buf, 1, ">"); - if (addmeta == 1) { - if (ctxt->format == 1) { - xmlOutputBufferWrite(buf, 1, "\n"); - if (xmlIndentTreeOutput) - xmlOutputBufferWrite(buf, ctxt->indent_size * - (ctxt->level + 1 > ctxt->indent_nr ? - ctxt->indent_nr : ctxt->level + 1), ctxt->indent); - } - xmlOutputBufferWriteString(buf, - "<meta http-equiv=\"Content-Type\" content=\"text/html; charset="); - if (ctxt->encoding) { - xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding); - } else { - xmlOutputBufferWrite(buf, 5, "UTF-8"); - } - xmlOutputBufferWrite(buf, 4, "\" />"); - } - if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { - xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape); - } + while (1) { + if (cur == root) + return; + if (ctxt->format == 1) + xmlOutputBufferWrite(buf, 1, "\n"); + if (cur->next != NULL) { + cur = cur->next; + break; + } -#if 0 - /* - * This was removed due to problems with HTML processors. - * See bug #345147. - */ - /* - * 4.8. Script and Style elements - */ - if ((cur->type == XML_ELEMENT_NODE) && - ((xmlStrEqual(cur->name, BAD_CAST "script")) || - (xmlStrEqual(cur->name, BAD_CAST "style"))) && - ((cur->ns == NULL) || - (xmlStrEqual(cur->ns->href, XHTML_NS_NAME)))) { - xmlNodePtr child = cur->children; - - while (child != NULL) { - if (child->type == XML_TEXT_NODE) { - if ((xmlStrchr(child->content, '<') == NULL) && - (xmlStrchr(child->content, '&') == NULL) && - (xmlStrstr(child->content, BAD_CAST "]]>") == NULL)) { - /* Nothing to escape, so just output as is... */ - /* FIXME: Should we do something about "--" also? */ - int level = ctxt->level; - int indent = ctxt->format; - - ctxt->level = 0; - ctxt->format = 0; - xmlOutputBufferWriteString(buf, (const char *) child->content); - /* (We cannot use xhtmlNodeDumpOutput() here because - * we wish to leave '>' unescaped!) */ - ctxt->level = level; - ctxt->format = indent; - } else { - /* We must use a CDATA section. Unfortunately, - * this will break CSS and JavaScript when read by - * a browser in HTML4-compliant mode. :-( */ - start = end = child->content; - while (*end != '\0') { - if (*end == ']' && - *(end + 1) == ']' && - *(end + 2) == '>') { - end = end + 2; - xmlOutputBufferWrite(buf, 9, "<![CDATA["); - xmlOutputBufferWrite(buf, end - start, - (const char *)start); - xmlOutputBufferWrite(buf, 3, "]]>"); - start = end; - } - end++; - } - if (start != end) { - xmlOutputBufferWrite(buf, 9, "<![CDATA["); - xmlOutputBufferWrite(buf, end - start, - (const char *)start); - xmlOutputBufferWrite(buf, 3, "]]>"); - } - } - } else { - int level = ctxt->level; - int indent = ctxt->format; + /* + * The parent should never be NULL here but we want to handle + * corrupted documents gracefully. + */ + if (cur->parent == NULL) + return; + cur = cur->parent; + + if (cur->type == XML_ELEMENT_NODE) { + if (ctxt->level > 0) ctxt->level--; + if ((xmlIndentTreeOutput) && (ctxt->format == 1)) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level), + ctxt->indent); + + xmlOutputBufferWrite(buf, 2, "</"); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, + (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } - ctxt->level = 0; - ctxt->format = 0; - xhtmlNodeDumpOutput(ctxt, child); - ctxt->level = level; - ctxt->format = indent; - } - child = child->next; - } - } -#endif + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 1, ">"); - if (cur->children != NULL) { - int indent = ctxt->format; - - if (format == 1) xmlOutputBufferWrite(buf, 1, "\n"); - if (ctxt->level >= 0) ctxt->level++; - ctxt->format = format; - xhtmlNodeListDumpOutput(ctxt, cur->children); - if (ctxt->level > 0) ctxt->level--; - ctxt->format = indent; - if ((xmlIndentTreeOutput) && (format == 1)) - xmlOutputBufferWrite(buf, ctxt->indent_size * - (ctxt->level > ctxt->indent_nr ? - ctxt->indent_nr : ctxt->level), - ctxt->indent); - } - xmlOutputBufferWrite(buf, 2, "</"); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWrite(buf, 1, ":"); + if (cur == unformattedNode) { + ctxt->format = format; + unformattedNode = NULL; + } + } + } } - - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWrite(buf, 1, ">"); } #endif @@ -1802,6 +1765,7 @@ xmlSaveToFd(int fd, const char *encoding, int options) if (ret == NULL) return(NULL); ret->buf = xmlOutputBufferCreateFd(fd, ret->handler); if (ret->buf == NULL) { + xmlCharEncCloseFunc(ret->handler); xmlFreeSaveCtxt(ret); return(NULL); } @@ -1831,6 +1795,7 @@ xmlSaveToFilename(const char *filename, const char *encoding, int options) ret->buf = xmlOutputBufferCreateFilename(filename, ret->handler, compression); if (ret->buf == NULL) { + xmlCharEncCloseFunc(ret->handler); xmlFreeSaveCtxt(ret); return(NULL); } @@ -1853,28 +1818,15 @@ xmlSaveCtxtPtr xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options) { xmlSaveCtxtPtr ret; - xmlOutputBufferPtr out_buff; - xmlCharEncodingHandlerPtr handler; ret = xmlNewSaveCtxt(encoding, options); if (ret == NULL) return(NULL); - - if (encoding != NULL) { - handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) { - xmlFree(ret); - return(NULL); - } - } else - handler = NULL; - out_buff = xmlOutputBufferCreateBuffer(buffer, handler); - if (out_buff == NULL) { - xmlFree(ret); - if (handler) xmlCharEncCloseFunc(handler); - return(NULL); + ret->buf = xmlOutputBufferCreateBuffer(buffer, ret->handler); + if (ret->buf == NULL) { + xmlCharEncCloseFunc(ret->handler); + xmlFreeSaveCtxt(ret); + return(NULL); } - - ret->buf = out_buff; return(ret); } @@ -1902,6 +1854,7 @@ xmlSaveToIO(xmlOutputWriteCallback iowrite, if (ret == NULL) return(NULL); ret->buf = xmlOutputBufferCreateIO(iowrite, ioclose, ioctx, ret->handler); if (ret->buf == NULL) { + xmlCharEncCloseFunc(ret->handler); xmlFreeSaveCtxt(ret); return(NULL); } @@ -1942,12 +1895,25 @@ xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc) * Returns the number of byte written or -1 in case of error */ long -xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr node) +xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { long ret = 0; - if ((ctxt == NULL) || (node == NULL)) return(-1); - xmlNodeDumpOutputInternal(ctxt, node); + if ((ctxt == NULL) || (cur == NULL)) return(-1); +#ifdef LIBXML_HTML_ENABLED + if (ctxt->options & XML_SAVE_XHTML) { + xhtmlNodeDumpOutput(ctxt, cur); + return(ret); + } + if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) && + (cur->doc->type == XML_HTML_DOCUMENT_NODE) && + ((ctxt->options & XML_SAVE_AS_XML) == 0)) || + (ctxt->options & XML_SAVE_AS_HTML)) { + htmlNodeDumpOutputInternal(ctxt, cur); + return(ret); + } +#endif + xmlNodeDumpOutputInternal(ctxt, cur); return(ret); } @@ -2197,7 +2163,7 @@ xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format) { xmlBufPtr buffer; - int ret; + size_t ret; if ((buf == NULL) || (cur == NULL)) return(-1); |