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

📄 xmlwriter.c

📁 libxml,在UNIX/LINUX下非常重要的一个库,为XML相关应用提供方便.目前上载的是最新版本,若要取得最新版本,请参考里面的readme.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * xmlwriter.c: XML text writer implementation * * For license and disclaimer see the license and disclaimer of * libxml2. * * alfred@mickautsch.de */#define IN_LIBXML#include <string.h>#include "libxml.h"#include <libxml/xmlmemory.h>#include <libxml/parser.h>#include <libxml/uri.h>#include <libxml/HTMLtree.h>#ifdef LIBXML_WRITER_ENABLED#include <libxml/xmlwriter.h>#define B64LINELEN 72#define B64CRLF "\r\n"/* * Types are kept private */typedef enum {    XML_TEXTWRITER_NONE = 0,    XML_TEXTWRITER_NAME,    XML_TEXTWRITER_ATTRIBUTE,    XML_TEXTWRITER_TEXT,    XML_TEXTWRITER_PI,    XML_TEXTWRITER_PI_TEXT,    XML_TEXTWRITER_CDATA,    XML_TEXTWRITER_DTD,    XML_TEXTWRITER_DTD_TEXT,    XML_TEXTWRITER_DTD_ELEM,    XML_TEXTWRITER_DTD_ELEM_TEXT,    XML_TEXTWRITER_DTD_ATTL,    XML_TEXTWRITER_DTD_ATTL_TEXT,    XML_TEXTWRITER_DTD_ENTY,    /* entity */    XML_TEXTWRITER_DTD_ENTY_TEXT,    XML_TEXTWRITER_DTD_PENT,    /* parameter entity */    XML_TEXTWRITER_COMMENT} xmlTextWriterState;typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;struct _xmlTextWriterStackEntry {    xmlChar *name;    xmlTextWriterState state;};typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;struct _xmlTextWriterNsStackEntry {    xmlChar *prefix;    xmlChar *uri;    xmlLinkPtr elem;};struct _xmlTextWriter {    xmlOutputBufferPtr out;     /* output buffer */    xmlListPtr nodes;           /* element name stack */    xmlListPtr nsstack;         /* name spaces stack */    int level;    int indent;                 /* enable indent */    int doindent;               /* internal indent flag */    xmlChar *ichar;             /* indent character */    char qchar;                 /* character used for quoting attribute values */    xmlParserCtxtPtr ctxt;    int no_doc_free;};static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);static int xmlCmpTextWriterStackEntry(const void *data0,                                      const void *data1);static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);static int xmlCmpTextWriterNsStackEntry(const void *data0,                                        const void *data1);static int xmlTextWriterWriteMemCallback(void *context,                                         const xmlChar * str, int len);static int xmlTextWriterCloseMemCallback(void *context);static int xmlTextWriterWriteDocCallback(void *context,                                         const xmlChar * str, int len);static int xmlTextWriterCloseDocCallback(void *context);static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,                                      const unsigned char *data);static void xmlTextWriterStartDocumentCallback(void *ctx);static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);static int  xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,                                       xmlTextWriterStackEntry * p);/** * xmlWriterErrMsg: * @ctxt:  a writer context * @error:  the error number * @msg:  the error message * * Handle a writer error */static voidxmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,               const char *msg){    if (ctxt != NULL) {	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,		    NULL, 0, NULL, NULL, NULL, 0, 0, msg);    } else {	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, msg);    }}/** * xmlWriterErrMsgInt: * @ctxt:  a writer context * @error:  the error number * @msg:  the error message * @val:  an int * * Handle a writer error */static voidxmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,               const char *msg, int val){    if (ctxt != NULL) {	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,		    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);    } else {	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val);    }}/** * xmlNewTextWriter: * @out:  an xmlOutputBufferPtr * * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr * NOTE: the @out parameter will be deallocated when the writer is closed *       (if the call succeed.) * * Returns the new xmlTextWriterPtr or NULL in case of error */xmlTextWriterPtrxmlNewTextWriter(xmlOutputBufferPtr out){    xmlTextWriterPtr ret;    ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));    if (ret == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,                        "xmlNewTextWriter : out of memory!\n");        return NULL;    }    memset(ret, 0, (size_t) sizeof(xmlTextWriter));    ret->nodes = xmlListCreate((xmlListDeallocator)                               xmlFreeTextWriterStackEntry,                               (xmlListDataCompare)                               xmlCmpTextWriterStackEntry);    if (ret->nodes == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,                        "xmlNewTextWriter : out of memory!\n");        xmlFree(ret);        return NULL;    }    ret->nsstack = xmlListCreate((xmlListDeallocator)                                 xmlFreeTextWriterNsStackEntry,                                 (xmlListDataCompare)                                 xmlCmpTextWriterNsStackEntry);    if (ret->nsstack == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,                        "xmlNewTextWriter : out of memory!\n");        xmlListDelete(ret->nodes);        xmlFree(ret);        return NULL;    }    ret->out = out;    ret->ichar = xmlStrdup(BAD_CAST " ");    ret->qchar = '"';    if (!ret->ichar) {        xmlListDelete(ret->nodes);        xmlListDelete(ret->nsstack);        xmlFree(ret);        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,                        "xmlNewTextWriter : out of memory!\n");        return NULL;    }    ret->no_doc_free = 0;    return ret;}/** * xmlNewTextWriterFilename: * @uri:  the URI of the resource for the output * @compression:  compress the output? * * Create a new xmlNewTextWriter structure with @uri as output * * Returns the new xmlTextWriterPtr or NULL in case of error */xmlTextWriterPtrxmlNewTextWriterFilename(const char *uri, int compression){    xmlTextWriterPtr ret;    xmlOutputBufferPtr out;    out = xmlOutputBufferCreateFilename(uri, NULL, compression);    if (out == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,                        "xmlNewTextWriterFilename : out of memory!\n");        return NULL;    }    ret = xmlNewTextWriter(out);    if (ret == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,                        "xmlNewTextWriterFilename : out of memory!\n");        xmlOutputBufferClose(out);        return NULL;    }    ret->indent = 0;    ret->doindent = 0;    return ret;}/** * xmlNewTextWriterMemory: * @buf:  xmlBufferPtr * @compression:  compress the output? * * Create a new xmlNewTextWriter structure with @buf as output * TODO: handle compression * * Returns the new xmlTextWriterPtr or NULL in case of error */xmlTextWriterPtrxmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED){    xmlTextWriterPtr ret;    xmlOutputBufferPtr out;/*::todo handle compression */    out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)                                  xmlTextWriterWriteMemCallback,                                  (xmlOutputCloseCallback)                                  xmlTextWriterCloseMemCallback,                                  (void *) buf, NULL);    if (out == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,                        "xmlNewTextWriterMemory : out of memory!\n");        return NULL;    }    ret = xmlNewTextWriter(out);    if (ret == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,                        "xmlNewTextWriterMemory : out of memory!\n");        xmlOutputBufferClose(out);        return NULL;    }    return ret;}/** * xmlNewTextWriterPushParser: * @ctxt: xmlParserCtxtPtr to hold the new XML document tree * @compression:  compress the output? * * Create a new xmlNewTextWriter structure with @ctxt as output * NOTE: the @ctxt context will be freed with the resulting writer *       (if the call succeeds). * TODO: handle compression * * Returns the new xmlTextWriterPtr or NULL in case of error */xmlTextWriterPtrxmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,                           int compression ATTRIBUTE_UNUSED){    xmlTextWriterPtr ret;    xmlOutputBufferPtr out;    if (ctxt == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,                        "xmlNewTextWriterPushParser : invalid context!\n");        return NULL;    }    out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)                                  xmlTextWriterWriteDocCallback,                                  (xmlOutputCloseCallback)                                  xmlTextWriterCloseDocCallback,                                  (void *) ctxt, NULL);    if (out == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,                        "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");        return NULL;    }    ret = xmlNewTextWriter(out);    if (ret == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,                        "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");        xmlOutputBufferClose(out);        return NULL;    }    ret->ctxt = ctxt;    return ret;}/** * xmlNewTextWriterDoc: * @doc: address of a xmlDocPtr to hold the new XML document tree * @compression:  compress the output? * * Create a new xmlNewTextWriter structure with @*doc as output * * Returns the new xmlTextWriterPtr or NULL in case of error */xmlTextWriterPtrxmlNewTextWriterDoc(xmlDocPtr * doc, int compression){    xmlTextWriterPtr ret;    xmlSAXHandler saxHandler;    xmlParserCtxtPtr ctxt;    memset(&saxHandler, '\0', sizeof(saxHandler));    xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);    saxHandler.startDocument = xmlTextWriterStartDocumentCallback;    saxHandler.startElement = xmlSAX2StartElement;    saxHandler.endElement = xmlSAX2EndElement;    ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);    if (ctxt == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,                        "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");        return NULL;    }    /*     * For some reason this seems to completely break if node names     * are interned.     */    ctxt->dictNames = 0;    ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);    if (ctxt->myDoc == NULL) {        xmlFreeParserCtxt(ctxt);        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,                        "xmlNewTextWriterDoc : error at xmlNewDoc!\n");        return NULL;    }    ret = xmlNewTextWriterPushParser(ctxt, compression);    if (ret == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,                        "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");        return NULL;    }    xmlSetDocCompressMode(ctxt->myDoc, compression);    if (doc != NULL) {        *doc = ctxt->myDoc;	ret->no_doc_free = 1;    }    return ret;}/** * xmlNewTextWriterTree: * @doc: xmlDocPtr * @node: xmlNodePtr or NULL for doc->children * @compression:  compress the output? * * Create a new xmlNewTextWriter structure with @doc as output * starting at @node * * Returns the new xmlTextWriterPtr or NULL in case of error */xmlTextWriterPtrxmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression){    xmlTextWriterPtr ret;    xmlSAXHandler saxHandler;    xmlParserCtxtPtr ctxt;    if (doc == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,                        "xmlNewTextWriterTree : invalid document tree!\n");        return NULL;    }    memset(&saxHandler, '\0', sizeof(saxHandler));    xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);    saxHandler.startDocument = xmlTextWriterStartDocumentCallback;    saxHandler.startElement = xmlSAX2StartElement;    saxHandler.endElement = xmlSAX2EndElement;    ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);    if (ctxt == NULL) {        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,                        "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");        return NULL;    }    /*     * For some reason this seems to completely break if node names     * are interned.     */    ctxt->dictNames = 0;    ret = xmlNewTextWriterPushParser(ctxt, compression);    if (ret == NULL) {        xmlFreeParserCtxt(ctxt);        xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,                        "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");        return NULL;    }    ctxt->myDoc = doc;    ctxt->node = node;    ret->no_doc_free = 1;    xmlSetDocCompressMode(doc, compression);    return ret;}/** * xmlFreeTextWriter: * @writer:  the xmlTextWriterPtr * * Deallocate all the resources associated to the writer */voidxmlFreeTextWriter(xmlTextWriterPtr writer){    if (writer == NULL)        return;    if (writer->out != NULL)        xmlOutputBufferClose(writer->out);    if (writer->nodes != NULL)        xmlListDelete(writer->nodes);    if (writer->nsstack != NULL)        xmlListDelete(writer->nsstack);    if (writer->ctxt != NULL) {        if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {	    xmlFreeDoc(writer->ctxt->myDoc);	    writer->ctxt->myDoc = NULL;	}        xmlFreeParserCtxt(writer->ctxt);    }    if (writer->ichar != NULL)        xmlFree(writer->ichar);    xmlFree(writer);}/** * xmlTextWriterStartDocument: * @writer:  the xmlTextWriterPtr * @version:  the xml version ("1.0") or NULL for default ("1.0") * @encoding:  the encoding or NULL for default * @standalone: "yes" or "no" or NULL for default * * Start a new xml document * * Returns the bytes written (may be 0 because of buffering) or -1 in case of error

⌨️ 快捷键说明

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