⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlsave.c

📁 libxml,在UNIX/LINUX下非常重要的一个库,为XML相关应用提供方便.目前上载的是最新版本,若要取得最新版本,请参考里面的readme.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * xmlsave.c: Implemetation of the document serializer * * See Copyright for the status of this software. * * daniel@veillard.com */#define IN_LIBXML#include "libxml.h"#include <string.h>#include <libxml/xmlmemory.h>#include <libxml/parserInternals.h>#include <libxml/tree.h>#include <libxml/xmlsave.h>#define MAX_INDENT 60#include <libxml/HTMLtree.h>/************************************************************************ *									* *			XHTML detection					* *									* ************************************************************************/#define XHTML_STRICT_PUBLIC_ID BAD_CAST \   "-//W3C//DTD XHTML 1.0 Strict//EN"#define XHTML_STRICT_SYSTEM_ID BAD_CAST \   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"#define XHTML_FRAME_PUBLIC_ID BAD_CAST \   "-//W3C//DTD XHTML 1.0 Frameset//EN"#define XHTML_FRAME_SYSTEM_ID BAD_CAST \   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"#define XHTML_TRANS_PUBLIC_ID BAD_CAST \   "-//W3C//DTD XHTML 1.0 Transitional//EN"#define XHTML_TRANS_SYSTEM_ID BAD_CAST \   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"#define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml"/** * xmlIsXHTML: * @systemID:  the system identifier * @publicID:  the public identifier * * Try to find if the document correspond to an XHTML DTD * * Returns 1 if true, 0 if not and -1 in case of error */intxmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) {    if ((systemID == NULL) && (publicID == NULL))	return(-1);    if (publicID != NULL) {	if (xmlStrEqual(publicID, XHTML_STRICT_PUBLIC_ID)) return(1);	if (xmlStrEqual(publicID, XHTML_FRAME_PUBLIC_ID)) return(1);	if (xmlStrEqual(publicID, XHTML_TRANS_PUBLIC_ID)) return(1);    }    if (systemID != NULL) {	if (xmlStrEqual(systemID, XHTML_STRICT_SYSTEM_ID)) return(1);	if (xmlStrEqual(systemID, XHTML_FRAME_SYSTEM_ID)) return(1);	if (xmlStrEqual(systemID, XHTML_TRANS_SYSTEM_ID)) return(1);    }    return(0);}#ifdef LIBXML_OUTPUT_ENABLED#define TODO 								\    xmlGenericError(xmlGenericErrorContext,				\	    "Unimplemented block at %s:%d\n",				\            __FILE__, __LINE__);struct _xmlSaveCtxt {    void *_private;    int type;    int fd;    const xmlChar *filename;    const xmlChar *encoding;    xmlCharEncodingHandlerPtr handler;    xmlOutputBufferPtr buf;    xmlDocPtr doc;    int options;    int level;    int format;    char indent[MAX_INDENT + 1];	/* array for indenting output */    int indent_nr;    int indent_size;    xmlCharEncodingOutputFunc escape;	/* used for element content */    xmlCharEncodingOutputFunc escapeAttr;/* used for attribute content */};/************************************************************************ *									* * 			Output error handlers				* *									* ************************************************************************//** * xmlSaveErrMemory: * @extra:  extra informations * * Handle an out of memory condition */static voidxmlSaveErrMemory(const char *extra){    __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra);}/** * xmlSaveErr: * @code:  the error number * @node:  the location of the error. * @extra:  extra informations * * Handle an out of memory condition */static voidxmlSaveErr(int code, xmlNodePtr node, const char *extra){    const char *msg = NULL;    switch(code) {        case XML_SAVE_NOT_UTF8:	    msg = "string is not in UTF-8";	    break;	case XML_SAVE_CHAR_INVALID:	    msg = "invalid character value";	    break;	case XML_SAVE_UNKNOWN_ENCODING:	    msg = "unknown encoding %s";	    break;	case XML_SAVE_NO_DOCTYPE:	    msg = "document has no DOCTYPE";	    break;	default:	    msg = "unexpected error number";    }    __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra);}/************************************************************************ *									* *			Special escaping routines			* *									* ************************************************************************/static unsigned char *xmlSerializeHexCharRef(unsigned char *out, int val) {    unsigned char *ptr;    *out++ = '&';    *out++ = '#';    *out++ = 'x';    if (val < 0x10) ptr = out;    else if (val < 0x100) ptr = out + 1;    else if (val < 0x1000) ptr = out + 2;    else if (val < 0x10000) ptr = out + 3;    else if (val < 0x100000) ptr = out + 4;    else ptr = out + 5;    out = ptr + 1;    while (val > 0) {	switch (val & 0xF) {	    case 0: *ptr-- = '0'; break;	    case 1: *ptr-- = '1'; break;	    case 2: *ptr-- = '2'; break;	    case 3: *ptr-- = '3'; break;	    case 4: *ptr-- = '4'; break;	    case 5: *ptr-- = '5'; break;	    case 6: *ptr-- = '6'; break;	    case 7: *ptr-- = '7'; break;	    case 8: *ptr-- = '8'; break;	    case 9: *ptr-- = '9'; break;	    case 0xA: *ptr-- = 'A'; break;	    case 0xB: *ptr-- = 'B'; break;	    case 0xC: *ptr-- = 'C'; break;	    case 0xD: *ptr-- = 'D'; break;	    case 0xE: *ptr-- = 'E'; break;	    case 0xF: *ptr-- = 'F'; break;	    default: *ptr-- = '0'; break;	}	val >>= 4;    }    *out++ = ';';    *out = 0;    return(out);}/** * xmlEscapeEntities: * @out:  a pointer to an array of bytes to store the result * @outlen:  the length of @out * @in:  a pointer to an array of unescaped UTF-8 bytes * @inlen:  the length of @in * * Take a block of UTF-8 chars in and escape them. Used when there is no * encoding specified. * * Returns 0 if success, or -1 otherwise * The value of @inlen after return is the number of octets consumed *     if the return value is positive, else unpredictable. * The value of @outlen after return is the number of octets consumed. */static intxmlEscapeEntities(unsigned char* out, int *outlen,                 const xmlChar* in, int *inlen) {    unsigned char* outstart = out;    const unsigned char* base = in;    unsigned char* outend = out + *outlen;    const unsigned char* inend;    int val;    inend = in + (*inlen);        while ((in < inend) && (out < outend)) {    	if (*in == '<') {	    if (outend - out < 4) break;	    *out++ = '&';	    *out++ = 'l';	    *out++ = 't';	    *out++ = ';';	    in++;	    continue;	} else if (*in == '>') {	    if (outend - out < 4) break;	    *out++ = '&';	    *out++ = 'g';	    *out++ = 't';	    *out++ = ';';	    in++;	    continue;	} else if (*in == '&') {	    if (outend - out < 5) break;	    *out++ = '&';	    *out++ = 'a';	    *out++ = 'm';	    *out++ = 'p';	    *out++ = ';';	    in++;	    continue;	} else if (((*in >= 0x20) && (*in < 0x80)) ||	           (*in == '\n') || (*in == '\t')) {	    /*	     * default case, just copy !	     */	    *out++ = *in++;	    continue;	} else if (*in >= 0x80) {	    /*	     * We assume we have UTF-8 input.	     */	    if (outend - out < 10) break;	    if (*in < 0xC0) {		xmlSaveErr(XML_SAVE_NOT_UTF8, NULL, NULL);		in++;		goto error;	    } else if (*in < 0xE0) {		if (inend - in < 2) break;		val = (in[0]) & 0x1F;		val <<= 6;		val |= (in[1]) & 0x3F;		in += 2;	    } else if (*in < 0xF0) {		if (inend - in < 3) break;		val = (in[0]) & 0x0F;		val <<= 6;		val |= (in[1]) & 0x3F;		val <<= 6;		val |= (in[2]) & 0x3F;		in += 3;	    } else if (*in < 0xF8) {		if (inend - in < 4) break;		val = (in[0]) & 0x07;		val <<= 6;		val |= (in[1]) & 0x3F;		val <<= 6;		val |= (in[2]) & 0x3F;		val <<= 6;		val |= (in[3]) & 0x3F;		in += 4;	    } else {		xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);		in++;		goto error;	    }	    if (!IS_CHAR(val)) {		xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);		in++;		goto error;	    }	    /*	     * We could do multiple things here. Just save as a char ref	     */	    out = xmlSerializeHexCharRef(out, val);	} else if (IS_BYTE_CHAR(*in)) {	    if (outend - out < 6) break;	    out = xmlSerializeHexCharRef(out, *in++);	} else {	    xmlGenericError(xmlGenericErrorContext,		"xmlEscapeEntities : char out of range\n");	    in++;	    goto error;	}    }    *outlen = out - outstart;    *inlen = in - base;    return(0);error:    *outlen = out - outstart;    *inlen = in - base;    return(-1);}/************************************************************************ *									* *			Allocation and deallocation			* *									* ************************************************************************//** * xmlSaveCtxtInit: * @ctxt: the saving context * * Initialize a saving context */static voidxmlSaveCtxtInit(xmlSaveCtxtPtr ctxt){    int i;    int len;    if (ctxt == NULL) return;    if ((ctxt->encoding == NULL) && (ctxt->escape == NULL))        ctxt->escape = xmlEscapeEntities;    len = xmlStrlen((xmlChar *)xmlTreeIndentString);    if ((xmlTreeIndentString == NULL) || (len == 0)) {        memset(&ctxt->indent[0], 0, MAX_INDENT + 1);    } else {	ctxt->indent_size = len;	ctxt->indent_nr = MAX_INDENT / ctxt->indent_size;	for (i = 0;i < ctxt->indent_nr;i++)	    memcpy(&ctxt->indent[i * ctxt->indent_size], xmlTreeIndentString,		   ctxt->indent_size);        ctxt->indent[ctxt->indent_nr * ctxt->indent_size] = 0;    }}/** * xmlFreeSaveCtxt: * * Free a saving context, destroying the ouptut in any remaining buffer */static voidxmlFreeSaveCtxt(xmlSaveCtxtPtr ctxt){    if (ctxt == NULL) return;    if (ctxt->encoding != NULL)        xmlFree((char *) ctxt->encoding);    if (ctxt->buf != NULL)        xmlOutputBufferClose(ctxt->buf);    xmlFree(ctxt);}/** * xmlNewSaveCtxt: * * Create a new saving context * * Returns the new structure or NULL in case of error */static xmlSaveCtxtPtrxmlNewSaveCtxt(const char *encoding, int options){    xmlSaveCtxtPtr ret;    ret = (xmlSaveCtxtPtr) xmlMalloc(sizeof(xmlSaveCtxt));    if (ret == NULL) {	xmlSaveErrMemory("creating saving context");	return ( NULL );    }    memset(ret, 0, sizeof(xmlSaveCtxt));    /*     * Use the options     */    ret->options = options;    if (options & XML_SAVE_FORMAT)        ret->format = 1;    if (encoding != NULL) {        ret->handler = xmlFindCharEncodingHandler(encoding);	if (ret->handler == NULL) {	    xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);            xmlFreeSaveCtxt(ret);	    return(NULL);	}        ret->encoding = xmlStrdup((const xmlChar *)encoding);	ret->escape = xmlEscapeEntities;    }    xmlSaveCtxtInit(ret);    return(ret);}/************************************************************************ *									* *   		Dumping XML tree content to a simple buffer		* *									* ************************************************************************//** * xmlAttrSerializeContent: * @buf:  the XML buffer output * @doc:  the document * @attr:  the attribute pointer * * Serialize the attribute in the buffer */static voidxmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr){    xmlNodePtr children;    children = attr->children;    while (children != NULL) {        switch (children->type) {            case XML_TEXT_NODE:	        xmlAttrSerializeTxtContent(buf->buffer, attr->doc,		                           attr, children->content);		break;            case XML_ENTITY_REF_NODE:                xmlBufferAdd(buf->buffer, BAD_CAST "&", 1);                xmlBufferAdd(buf->buffer, children->name,                             xmlStrlen(children->name));                xmlBufferAdd(buf->buffer, BAD_CAST ";", 1);                break;            default:                /* should not happen unless we have a badly built tree */                break;        }        children = children->next;    }}/************************************************************************ *									* *   		Dumping XML tree content to an I/O output buffer	* *									*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -