📄 xmlsave.c
字号:
*
* Check if a node is an empty xhtml node
*
* Returns 1 if the node is an empty node, 0 if not and -1 in case of error
*/
static int
xhtmlIsEmpty(xmlNodePtr node) {
if (node == NULL)
return(-1);
if (node->type != XML_ELEMENT_NODE)
return(0);
if ((node->ns != NULL) && (!xmlStrEqual(node->ns->href, XHTML_NS_NAME)))
return(0);
if (node->children != NULL)
return(0);
switch (node->name[0]) {
case 'a':
if (xmlStrEqual(node->name, BAD_CAST "area"))
return(1);
return(0);
case 'b':
if (xmlStrEqual(node->name, BAD_CAST "br"))
return(1);
if (xmlStrEqual(node->name, BAD_CAST "base"))
return(1);
if (xmlStrEqual(node->name, BAD_CAST "basefont"))
return(1);
return(0);
case 'c':
if (xmlStrEqual(node->name, BAD_CAST "col"))
return(1);
return(0);
case 'f':
if (xmlStrEqual(node->name, BAD_CAST "frame"))
return(1);
return(0);
case 'h':
if (xmlStrEqual(node->name, BAD_CAST "hr"))
return(1);
return(0);
case 'i':
if (xmlStrEqual(node->name, BAD_CAST "img"))
return(1);
if (xmlStrEqual(node->name, BAD_CAST "input"))
return(1);
if (xmlStrEqual(node->name, BAD_CAST "isindex"))
return(1);
return(0);
case 'l':
if (xmlStrEqual(node->name, BAD_CAST "link"))
return(1);
return(0);
case 'm':
if (xmlStrEqual(node->name, BAD_CAST "meta"))
return(1);
return(0);
case 'p':
if (xmlStrEqual(node->name, BAD_CAST "param"))
return(1);
return(0);
}
return(0);
}
/**
* xhtmlAttrListDumpOutput:
* @cur: the first attribute pointer
*
* Dump a list of XML attributes
*/
static void
xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
xmlAttrPtr xml_lang = NULL;
xmlAttrPtr lang = NULL;
xmlAttrPtr name = NULL;
xmlAttrPtr id = NULL;
xmlNodePtr parent;
xmlOutputBufferPtr buf;
if (cur == NULL) return;
buf = ctxt->buf;
parent = cur->parent;
while (cur != NULL) {
if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "id")))
id = cur;
else
if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "name")))
name = cur;
else
if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")))
lang = cur;
else
if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) &&
(xmlStrEqual(cur->ns->prefix, BAD_CAST "xml")))
xml_lang = cur;
else if ((cur->ns == NULL) &&
((cur->children == NULL) ||
(cur->children->content == NULL) ||
(cur->children->content[0] == 0)) &&
(htmlIsBooleanAttr(cur->name))) {
if (cur->children != NULL)
xmlFreeNode(cur->children);
cur->children = xmlNewText(cur->name);
if (cur->children != NULL)
cur->children->parent = (xmlNodePtr) cur;
}
xmlAttrDumpOutput(ctxt, cur);
cur = cur->next;
}
/*
* C.8
*/
if ((name != NULL) && (id == NULL)) {
if ((parent != NULL) && (parent->name != NULL) &&
((xmlStrEqual(parent->name, BAD_CAST "a")) ||
(xmlStrEqual(parent->name, BAD_CAST "p")) ||
(xmlStrEqual(parent->name, BAD_CAST "div")) ||
(xmlStrEqual(parent->name, BAD_CAST "img")) ||
(xmlStrEqual(parent->name, BAD_CAST "map")) ||
(xmlStrEqual(parent->name, BAD_CAST "applet")) ||
(xmlStrEqual(parent->name, BAD_CAST "form")) ||
(xmlStrEqual(parent->name, BAD_CAST "frame")) ||
(xmlStrEqual(parent->name, BAD_CAST "iframe")))) {
xmlOutputBufferWrite(buf, 5, " id=\"");
xmlAttrSerializeContent(buf, name);
xmlOutputBufferWrite(buf, 1, "\"");
}
}
/*
* C.7.
*/
if ((lang != NULL) && (xml_lang == NULL)) {
xmlOutputBufferWrite(buf, 11, " xml:lang=\"");
xmlAttrSerializeContent(buf, lang);
xmlOutputBufferWrite(buf, 1, "\"");
} else
if ((xml_lang != NULL) && (lang == NULL)) {
xmlOutputBufferWrite(buf, 7, " lang=\"");
xmlAttrSerializeContent(buf, xml_lang);
xmlOutputBufferWrite(buf, 1, "\"");
}
}
/**
* 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) && (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) {
xmlOutputBufferWrite(buf, 1, "\n");
}
cur = cur->next;
}
}
/**
* xhtmlNodeDumpOutput:
* @buf: the XML buffer output
* @doc: the XHTML document
* @cur: the current node
* @level: the imbrication level for indenting
* @format: is formatting allowed
* @encoding: an optional encoding string
*
* Dump an XHTML node, recursive behaviour, children are printed too.
*/
static void
xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
int format;
xmlNodePtr tmp;
xmlChar *start, *end;
xmlOutputBufferPtr buf;
if (cur == NULL) return;
if (cur->type == XML_XINCLUDE_START)
return;
if (cur->type == XML_XINCLUDE_END)
return;
if (cur->type == XML_DTD_NODE) {
xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
return;
}
buf = ctxt->buf;
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 == xmlStringText) ||
(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) {
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;
}
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, ":");
}
xmlOutputBufferWriteString(buf, (const char *)cur->name);
if (cur->nsDef)
xmlNsListDumpOutput(buf, 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->children == NULL)) {
if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
(xhtmlIsEmpty(cur) == 1)) {
/*
* C.2. Empty Elements
*/
xmlOutputBufferWrite(buf, 3, " />");
} else {
/*
* C.3. Element Minimization and Empty Element Content
*/
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);
xmlOutputBufferWrite(buf, 1, ">");
}
return;
}
xmlOutputBufferWrite(buf, 1, ">");
if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
}
/*
* 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) ||
(child->type == XML_CDATA_SECTION_NODE)) {
/*
* Apparently CDATA escaping for style just break on IE,
* mozilla and galeon, so ...
*/
if (xmlStrEqual(cur->name, BAD_CAST "style") &&
(xmlStrchr(child->content, '<') == NULL) &&
(xmlStrchr(child->content, '>') == NULL) &&
(xmlStrchr(child->content, '&') == NULL)) {
int level = ctxt->level;
int indent = ctxt->format;
ctxt->level = 0;
ctxt->format = 0;
xhtmlNodeDumpOutput(ctxt, child);
ctxt->level = level;
ctxt->format = indent;
} else {
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;
ctxt->level = 0;
ctxt->format = 0;
xhtmlNodeDumpOutput(ctxt, child);
ctxt->level = level;
ctxt->format = indent;
}
child = child->next;
}
} else if (cur->children != NULL) {
int indent = ctxt->format;
if (format) 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))
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, ">");
}
#endif
/************************************************************************
* *
* Public entry points *
* *
************************************************************************/
/**
* xmlSaveToFd:
* @fd: a file descriptor number
* @encoding: the encoding name to use or NULL
* @options: a set of xmlSaveOptions
*
* Create a document saving context serializing to a file descriptor
* with the encoding and the options given.
*
* Returns a new serialization context or NULL in case of error.
*/
xmlSaveCtxtPtr
xmlSaveToFd(int fd, const char *encoding, int options)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -