📄 xmlsave.c
字号:
#ifdef LIBXML_HTML_ENABLED
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 void xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur);
/**
* xmlNsDumpOutput:
* @buf: the XML buffer output
* @cur: a namespace
*
* Dump a local Namespace definition.
* Should be called in the context of attributes dumps.
*/
static void
xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
if ((cur == NULL) || (buf == NULL)) return;
if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
if (xmlStrEqual(cur->prefix, BAD_CAST "xml"))
return;
/* Within the context of an element attributes */
if (cur->prefix != NULL) {
xmlOutputBufferWrite(buf, 7, " xmlns:");
xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
} else
xmlOutputBufferWrite(buf, 6, " xmlns");
xmlOutputBufferWrite(buf, 1, "=");
xmlBufferWriteQuotedString(buf->buffer, cur->href);
}
}
/**
* xmlNsListDumpOutput:
* @buf: the XML buffer output
* @cur: the first namespace
*
* Dump a list of local Namespace definitions.
* Should be called in the context of attributes dumps.
*/
void
xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
while (cur != NULL) {
xmlNsDumpOutput(buf, cur);
cur = cur->next;
}
}
/**
* xmlDtdDumpOutput:
* @buf: the XML buffer output
* @dtd: the pointer to the DTD
*
* Dump the XML document DTD, if any.
*/
static void
xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
xmlOutputBufferPtr buf;
int format, level;
xmlDocPtr doc;
if (dtd == NULL) return;
if ((ctxt == NULL) || (ctxt->buf == NULL))
return;
buf = ctxt->buf;
xmlOutputBufferWrite(buf, 10, "<!DOCTYPE ");
xmlOutputBufferWriteString(buf, (const char *)dtd->name);
if (dtd->ExternalID != NULL) {
xmlOutputBufferWrite(buf, 8, " PUBLIC ");
xmlBufferWriteQuotedString(buf->buffer, dtd->ExternalID);
xmlOutputBufferWrite(buf, 1, " ");
xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
} else if (dtd->SystemID != NULL) {
xmlOutputBufferWrite(buf, 8, " SYSTEM ");
xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
}
if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
(dtd->attributes == NULL) && (dtd->notations == NULL) &&
(dtd->pentities == NULL)) {
xmlOutputBufferWrite(buf, 1, ">");
return;
}
xmlOutputBufferWrite(buf, 3, " [\n");
/*
* Dump the notations first they are not in the DTD children list
* Do this only on a standalone DTD or on the internal subset though.
*/
if ((dtd->notations != NULL) && ((dtd->doc == NULL) ||
(dtd->doc->intSubset == dtd))) {
xmlDumpNotationTable(buf->buffer, (xmlNotationTablePtr) dtd->notations);
}
format = ctxt->format;
level = ctxt->level;
doc = ctxt->doc;
ctxt->format = 0;
ctxt->level = -1;
ctxt->doc = dtd->doc;
xmlNodeListDumpOutput(ctxt, dtd->children);
ctxt->format = format;
ctxt->level = level;
ctxt->doc = doc;
xmlOutputBufferWrite(buf, 2, "]>");
}
/**
* xmlAttrDumpOutput:
* @buf: the XML buffer output
* @cur: the attribute pointer
*
* Dump an XML attribute
*/
static void
xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
xmlOutputBufferPtr buf;
if (cur == NULL) return;
buf = ctxt->buf;
if (buf == NULL) return;
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);
xmlOutputBufferWrite(buf, 2, "=\"");
xmlAttrSerializeContent(buf, 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) && (xmlIndentTreeOutput) &&
(cur->type == XML_ELEMENT_NODE))
xmlOutputBufferWrite(buf, ctxt->indent_size *
(ctxt->level > ctxt->indent_nr ?
ctxt->indent_nr : ctxt->level),
ctxt->indent);
xmlNodeDumpOutputInternal(ctxt, cur);
if (ctxt->format) {
xmlOutputBufferWrite(buf, 1, "\n");
}
cur = cur->next;
}
}
/**
* xmlNodeDumpOutputInternal:
* @cur: the current node
*
* Dump an XML node, recursive behaviour, children are printed too.
*/
static void
xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
int format;
xmlNodePtr tmp;
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;
}
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) {
xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
return;
}
if (cur->type == XML_ATTRIBUTE_DECL) {
xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
return;
}
if (cur->type == XML_ENTITY_DECL) {
xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
return;
}
if (cur->type == XML_TEXT_NODE) {
if (cur->content != NULL) {
if (cur->name != xmlStringTextNoenc) {
xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
} else {
/*
* Disable escaping, needed for XSLT
*/
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) {
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) {
xmlNsDumpOutput(buf, (xmlNsPtr) cur);
return;
}
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, ":");
}
xmlOutputBufferWriteString(buf, (const char *)cur->name);
if (cur->nsDef)
xmlNsListDumpOutput(buf, cur->nsDef);
if (cur->properties != NULL)
xmlAttrListDumpOutput(ctxt, cur->properties);
if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) &&
(cur->children == NULL) && (!xmlSaveNoEmptyTags)) {
xmlOutputBufferWrite(buf, 2, "/>");
ctxt->format = format;
return;
}
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) xmlOutputBufferWrite(buf, 1, "\n");
if (ctxt->level >= 0) ctxt->level++;
xmlNodeListDumpOutput(ctxt, cur->children);
if (ctxt->level > 0) ctxt->level--;
if ((xmlIndentTreeOutput) && (ctxt->format))
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);
xmlOutputBufferWrite(buf, 1, ">");
ctxt->format = format;
}
/**
* xmlDocContentDumpOutput:
* @cur: the document
*
* Dump an XML document.
*/
static void
xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
#ifdef LIBXML_HTML_ENABLED
xmlDtdPtr dtd;
int is_xhtml = 0;
#endif
const xmlChar *oldenc = cur->encoding;
const xmlChar *encoding = ctxt->encoding;
xmlOutputBufferPtr buf;
xmlInitParser();
if (ctxt->encoding != NULL)
cur->encoding = BAD_CAST ctxt->encoding;
buf = ctxt->buf;
xmlOutputBufferWrite(buf, 14, "<?xml version=");
if (cur->version != NULL)
xmlBufferWriteQuotedString(buf->buffer, cur->version);
else
xmlOutputBufferWrite(buf, 5, "\"1.0\"");
if (ctxt->encoding == NULL) {
if (cur->encoding != NULL)
encoding = cur->encoding;
else if (cur->charset != XML_CHAR_ENCODING_UTF8)
encoding = (const xmlChar *)
xmlGetCharEncodingName((xmlCharEncoding) cur->charset);
}
if (encoding != NULL) {
xmlOutputBufferWrite(buf, 10, " encoding=");
xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
}
switch (cur->standalone) {
case 0:
xmlOutputBufferWrite(buf, 16, " standalone=\"no\"");
break;
case 1:
xmlOutputBufferWrite(buf, 17, " standalone=\"yes\"");
break;
}
xmlOutputBufferWrite(buf, 3, "?>\n");
#ifdef LIBXML_HTML_ENABLED
dtd = xmlGetIntSubset(cur);
if (dtd != NULL) {
is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
if (is_xhtml < 0) is_xhtml = 0;
}
if (is_xhtml) {
if (encoding != NULL)
htmlSetMetaEncoding(cur, (const xmlChar *) ctxt->encoding);
else
htmlSetMetaEncoding(cur, BAD_CAST "UTF-8");
}
#endif
if (cur->children != NULL) {
xmlNodePtr child = cur->children;
while (child != NULL) {
ctxt->level = 0;
#ifdef LIBXML_HTML_ENABLED
if (is_xhtml)
xhtmlNodeDumpOutput(ctxt, child);
else
#endif
xmlNodeDumpOutputInternal(ctxt, child);
xmlOutputBufferWrite(buf, 1, "\n");
child = child->next;
}
}
if (ctxt->encoding != NULL)
cur->encoding = oldenc;
}
#ifdef LIBXML_HTML_ENABLED
/************************************************************************
* *
* Functions specific to XHTML serialization *
* *
************************************************************************/
/**
* xhtmlIsEmpty:
* @node: the node
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -