| |
| /* |
| * xmlwriter.c: XML text writer implementation |
| * |
| * For license and disclaimer see the license and disclaimer of |
| * libxml2. |
| * |
| * alfred@mickautsch.de |
| */ |
| |
| #define IN_LIBXML |
| #include "libxml.h" |
| #include <string.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> |
| |
| #include "buf.h" |
| #include "enc.h" |
| #include "save.h" |
| |
| #define B64LINELEN 72 |
| #define B64CRLF "\r\n" |
| |
| /* |
| * The following VA_COPY was coded following an example in |
| * the Samba project. It may not be sufficient for some |
| * esoteric implementations of va_list but (hopefully) will |
| * be sufficient for libxml2. |
| */ |
| #ifndef VA_COPY |
| #ifdef HAVE_VA_COPY |
| #define VA_COPY(dest, src) va_copy(dest, src) |
| #else |
| #ifdef HAVE___VA_COPY |
| #define VA_COPY(dest,src) __va_copy(dest, src) |
| #else |
| #ifndef VA_LIST_IS_ARRAY |
| #define VA_COPY(dest,src) (dest) = (src) |
| #else |
| #include <string.h> |
| #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list)) |
| #endif |
| #endif |
| #endif |
| #endif |
| |
| /* |
| * 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; |
| xmlDocPtr doc; |
| }; |
| |
| static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk); |
| static int xmlCmpTextWriterStackEntry(const void *data0, |
| const void *data1); |
| static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer); |
| static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk); |
| static int xmlCmpTextWriterNsStackEntry(const void *data0, |
| const void *data1); |
| static int xmlTextWriterWriteDocCallback(void *context, |
| const char *str, int len); |
| static int xmlTextWriterCloseDocCallback(void *context); |
| |
| static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr) LIBXML_ATTR_FORMAT(1,0); |
| 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 void |
| xmlWriterErrMsg(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, "%s", msg); |
| } else { |
| __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error, |
| XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg); |
| } |
| } |
| |
| /** |
| * xmlWriterErrMsgInt: |
| * @ctxt: a writer context |
| * @error: the error number |
| * @msg: the error message |
| * @val: an int |
| * |
| * Handle a writer error |
| */ |
| static void LIBXML_ATTR_FORMAT(3,0) |
| xmlWriterErrMsgInt(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 |
| */ |
| xmlTextWriterPtr |
| xmlNewTextWriter(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(xmlFreeTextWriterStackEntry, |
| xmlCmpTextWriterStackEntry); |
| if (ret->nodes == NULL) { |
| xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, |
| "xmlNewTextWriter : out of memory!\n"); |
| xmlFree(ret); |
| return NULL; |
| } |
| |
| ret->nsstack = xmlListCreate(xmlFreeTextWriterNsStackEntry, |
| 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->doc = xmlNewDoc(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 |
| */ |
| xmlTextWriterPtr |
| xmlNewTextWriterFilename(const char *uri, int compression) |
| { |
| xmlTextWriterPtr ret; |
| xmlOutputBufferPtr out; |
| |
| out = xmlOutputBufferCreateFilename(uri, NULL, compression); |
| if (out == NULL) { |
| xmlWriterErrMsg(NULL, XML_IO_EIO, |
| "xmlNewTextWriterFilename : cannot open uri\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 |
| */ |
| xmlTextWriterPtr |
| xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED) |
| { |
| xmlTextWriterPtr ret; |
| xmlOutputBufferPtr out; |
| |
| /*::todo handle compression */ |
| out = xmlOutputBufferCreateBuffer(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 |
| */ |
| xmlTextWriterPtr |
| xmlNewTextWriterPushParser(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(xmlTextWriterWriteDocCallback, |
| 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 |
| */ |
| xmlTextWriterPtr |
| xmlNewTextWriterDoc(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) { |
| xmlFreeDoc(ctxt->myDoc); |
| xmlFreeParserCtxt(ctxt); |
| 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 |
| */ |
| xmlTextWriterPtr |
| xmlNewTextWriterTree(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 |
| */ |
| void |
| xmlFreeTextWriter(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->doc != NULL) |
| xmlFreeDoc(writer->doc); |
| |
| 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 |
| */ |
| int |
| xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version, |
| const char *encoding, const char *standalone) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlCharEncodingHandlerPtr encoder; |
| |
| if ((writer == NULL) || (writer->out == NULL)) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterStartDocument : invalid writer!\n"); |
| return -1; |
| } |
| |
| lk = xmlListFront(writer->nodes); |
| if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterStartDocument : not allowed in this context!\n"); |
| return -1; |
| } |
| |
| encoder = NULL; |
| if (encoding != NULL) { |
| encoder = xmlFindCharEncodingHandler(encoding); |
| if (encoder == NULL) { |
| xmlWriterErrMsg(writer, XML_ERR_UNSUPPORTED_ENCODING, |
| "xmlTextWriterStartDocument : unsupported encoding\n"); |
| return -1; |
| } |
| } |
| |
| writer->out->encoder = encoder; |
| if (encoder != NULL) { |
| if (writer->out->conv == NULL) { |
| writer->out->conv = xmlBufCreateSize(4000); |
| } |
| xmlCharEncOutput(writer->out, 1); |
| if ((writer->doc != NULL) && (writer->doc->encoding == NULL)) |
| writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name); |
| } else |
| writer->out->conv = NULL; |
| |
| sum = 0; |
| count = xmlOutputBufferWriteString(writer->out, "<?xml version="); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| if (version != 0) |
| count = xmlOutputBufferWriteString(writer->out, version); |
| else |
| count = xmlOutputBufferWriteString(writer->out, "1.0"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| if (writer->out->encoder != 0) { |
| count = xmlOutputBufferWriteString(writer->out, " encoding="); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = |
| xmlOutputBufferWriteString(writer->out, |
| writer->out->encoder->name); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| if (standalone != 0) { |
| count = xmlOutputBufferWriteString(writer->out, " standalone="); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, standalone); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| count = xmlOutputBufferWriteString(writer->out, "?>\n"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterEndDocument: |
| * @writer: the xmlTextWriterPtr |
| * |
| * End an xml document. All open elements are closed, and |
| * the content is flushed to the output. |
| * |
| * Returns the bytes written or -1 in case of error |
| */ |
| int |
| xmlTextWriterEndDocument(xmlTextWriterPtr writer) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterEndDocument : invalid writer!\n"); |
| return -1; |
| } |
| |
| sum = 0; |
| while ((lk = xmlListFront(writer->nodes)) != NULL) { |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p == 0) |
| break; |
| switch (p->state) { |
| case XML_TEXTWRITER_NAME: |
| case XML_TEXTWRITER_ATTRIBUTE: |
| case XML_TEXTWRITER_TEXT: |
| count = xmlTextWriterEndElement(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| case XML_TEXTWRITER_PI: |
| case XML_TEXTWRITER_PI_TEXT: |
| count = xmlTextWriterEndPI(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| case XML_TEXTWRITER_CDATA: |
| count = xmlTextWriterEndCDATA(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| case XML_TEXTWRITER_DTD: |
| case XML_TEXTWRITER_DTD_TEXT: |
| case XML_TEXTWRITER_DTD_ELEM: |
| case XML_TEXTWRITER_DTD_ELEM_TEXT: |
| case XML_TEXTWRITER_DTD_ATTL: |
| case XML_TEXTWRITER_DTD_ATTL_TEXT: |
| case XML_TEXTWRITER_DTD_ENTY: |
| case XML_TEXTWRITER_DTD_ENTY_TEXT: |
| case XML_TEXTWRITER_DTD_PENT: |
| count = xmlTextWriterEndDTD(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| case XML_TEXTWRITER_COMMENT: |
| count = xmlTextWriterEndComment(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| if (!writer->indent) { |
| count = xmlOutputBufferWriteString(writer->out, "\n"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| sum += xmlTextWriterFlush(writer); |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterStartComment: |
| * @writer: the xmlTextWriterPtr |
| * |
| * Start an xml comment. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterStartComment(xmlTextWriterPtr writer) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterStartComment : invalid writer!\n"); |
| return -1; |
| } |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if (lk != 0) { |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p != 0) { |
| switch (p->state) { |
| case XML_TEXTWRITER_TEXT: |
| case XML_TEXTWRITER_NONE: |
| break; |
| case XML_TEXTWRITER_NAME: |
| /* Output namespace declarations */ |
| count = xmlTextWriterOutputNSDecl(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, ">"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| if (writer->indent) { |
| count = |
| xmlOutputBufferWriteString(writer->out, "\n"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| p->state = XML_TEXTWRITER_TEXT; |
| break; |
| default: |
| return -1; |
| } |
| } |
| } |
| |
| p = (xmlTextWriterStackEntry *) |
| xmlMalloc(sizeof(xmlTextWriterStackEntry)); |
| if (p == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartElement : out of memory!\n"); |
| return -1; |
| } |
| |
| p->name = NULL; |
| p->state = XML_TEXTWRITER_COMMENT; |
| |
| xmlListPushFront(writer->nodes, p); |
| |
| if (writer->indent) { |
| count = xmlTextWriterWriteIndent(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| count = xmlOutputBufferWriteString(writer->out, "<!--"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterEndComment: |
| * @writer: the xmlTextWriterPtr |
| * |
| * End the current xml comment. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterEndComment(xmlTextWriterPtr writer) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterEndComment : invalid writer!\n"); |
| return -1; |
| } |
| |
| lk = xmlListFront(writer->nodes); |
| if (lk == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterEndComment : not allowed in this context!\n"); |
| return -1; |
| } |
| |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p == 0) |
| return -1; |
| |
| sum = 0; |
| switch (p->state) { |
| case XML_TEXTWRITER_COMMENT: |
| count = xmlOutputBufferWriteString(writer->out, "-->"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| default: |
| return -1; |
| } |
| |
| if (writer->indent) { |
| count = xmlOutputBufferWriteString(writer->out, "\n"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| xmlListPopFront(writer->nodes); |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteFormatComment: |
| * @writer: the xmlTextWriterPtr |
| * @format: format string (see printf) |
| * @...: extra parameters for the format |
| * |
| * Write an xml comment. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int XMLCDECL |
| xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer, |
| const char *format, ...) |
| { |
| int rc; |
| va_list ap; |
| |
| va_start(ap, format); |
| |
| rc = xmlTextWriterWriteVFormatComment(writer, format, ap); |
| |
| va_end(ap); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteVFormatComment: |
| * @writer: the xmlTextWriterPtr |
| * @format: format string (see printf) |
| * @argptr: pointer to the first member of the variable argument list. |
| * |
| * Write an xml comment. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer, |
| const char *format, va_list argptr) |
| { |
| int rc; |
| xmlChar *buf; |
| |
| if (writer == NULL) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterWriteVFormatComment : invalid writer!\n"); |
| return -1; |
| } |
| |
| buf = xmlTextWriterVSprintf(format, argptr); |
| if (buf == NULL) |
| return -1; |
| |
| rc = xmlTextWriterWriteComment(writer, buf); |
| |
| xmlFree(buf); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteComment: |
| * @writer: the xmlTextWriterPtr |
| * @content: comment string |
| * |
| * Write an xml comment. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content) |
| { |
| int count; |
| int sum; |
| |
| sum = 0; |
| count = xmlTextWriterStartComment(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlTextWriterWriteString(writer, content); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlTextWriterEndComment(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterStartElement: |
| * @writer: the xmlTextWriterPtr |
| * @name: element name |
| * |
| * Start an xml element. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if ((writer == NULL) || (name == NULL) || (*name == '\0')) |
| return -1; |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if (lk != 0) { |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p != 0) { |
| switch (p->state) { |
| case XML_TEXTWRITER_PI: |
| case XML_TEXTWRITER_PI_TEXT: |
| return -1; |
| case XML_TEXTWRITER_NONE: |
| break; |
| case XML_TEXTWRITER_ATTRIBUTE: |
| count = xmlTextWriterEndAttribute(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| /* fallthrough */ |
| case XML_TEXTWRITER_NAME: |
| /* Output namespace declarations */ |
| count = xmlTextWriterOutputNSDecl(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, ">"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| if (writer->indent) |
| count = |
| xmlOutputBufferWriteString(writer->out, "\n"); |
| p->state = XML_TEXTWRITER_TEXT; |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| p = (xmlTextWriterStackEntry *) |
| xmlMalloc(sizeof(xmlTextWriterStackEntry)); |
| if (p == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartElement : out of memory!\n"); |
| return -1; |
| } |
| |
| p->name = xmlStrdup(name); |
| if (p->name == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartElement : out of memory!\n"); |
| xmlFree(p); |
| return -1; |
| } |
| p->state = XML_TEXTWRITER_NAME; |
| |
| xmlListPushFront(writer->nodes, p); |
| |
| if (writer->indent) { |
| count = xmlTextWriterWriteIndent(writer); |
| sum += count; |
| } |
| |
| count = xmlOutputBufferWriteString(writer->out, "<"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = |
| xmlOutputBufferWriteString(writer->out, (const char *) p->name); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterStartElementNS: |
| * @writer: the xmlTextWriterPtr |
| * @prefix: namespace prefix or NULL |
| * @name: element local name |
| * @namespaceURI: namespace URI or NULL |
| * |
| * Start an xml element with namespace support. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterStartElementNS(xmlTextWriterPtr writer, |
| const xmlChar * prefix, const xmlChar * name, |
| const xmlChar * namespaceURI) |
| { |
| int count; |
| int sum; |
| xmlChar *buf; |
| |
| if ((writer == NULL) || (name == NULL) || (*name == '\0')) |
| return -1; |
| |
| buf = NULL; |
| if (prefix != 0) { |
| buf = xmlStrdup(prefix); |
| buf = xmlStrcat(buf, BAD_CAST ":"); |
| } |
| buf = xmlStrcat(buf, name); |
| |
| sum = 0; |
| count = xmlTextWriterStartElement(writer, buf); |
| xmlFree(buf); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| if (namespaceURI != 0) { |
| xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *) |
| xmlMalloc(sizeof(xmlTextWriterNsStackEntry)); |
| if (p == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartElementNS : out of memory!\n"); |
| return -1; |
| } |
| |
| buf = xmlStrdup(BAD_CAST "xmlns"); |
| if (prefix != 0) { |
| buf = xmlStrcat(buf, BAD_CAST ":"); |
| buf = xmlStrcat(buf, prefix); |
| } |
| |
| p->prefix = buf; |
| p->uri = xmlStrdup(namespaceURI); |
| if (p->uri == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartElementNS : out of memory!\n"); |
| xmlFree(p); |
| return -1; |
| } |
| p->elem = xmlListFront(writer->nodes); |
| |
| xmlListPushFront(writer->nsstack, p); |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterEndElement: |
| * @writer: the xmlTextWriterPtr |
| * |
| * End the current xml element. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterEndElement(xmlTextWriterPtr writer) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) |
| return -1; |
| |
| lk = xmlListFront(writer->nodes); |
| if (lk == 0) { |
| xmlListDelete(writer->nsstack); |
| writer->nsstack = NULL; |
| return -1; |
| } |
| |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p == 0) { |
| xmlListDelete(writer->nsstack); |
| writer->nsstack = NULL; |
| return -1; |
| } |
| |
| sum = 0; |
| switch (p->state) { |
| case XML_TEXTWRITER_ATTRIBUTE: |
| count = xmlTextWriterEndAttribute(writer); |
| if (count < 0) { |
| xmlListDelete(writer->nsstack); |
| writer->nsstack = NULL; |
| return -1; |
| } |
| sum += count; |
| /* fallthrough */ |
| case XML_TEXTWRITER_NAME: |
| /* Output namespace declarations */ |
| count = xmlTextWriterOutputNSDecl(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| if (writer->indent) /* next element needs indent */ |
| writer->doindent = 1; |
| count = xmlOutputBufferWriteString(writer->out, "/>"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| case XML_TEXTWRITER_TEXT: |
| if ((writer->indent) && (writer->doindent)) { |
| count = xmlTextWriterWriteIndent(writer); |
| sum += count; |
| writer->doindent = 1; |
| } else |
| writer->doindent = 1; |
| count = xmlOutputBufferWriteString(writer->out, "</"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, |
| (const char *) p->name); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, ">"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| default: |
| return -1; |
| } |
| |
| if (writer->indent) { |
| count = xmlOutputBufferWriteString(writer->out, "\n"); |
| sum += count; |
| } |
| |
| xmlListPopFront(writer->nodes); |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterFullEndElement: |
| * @writer: the xmlTextWriterPtr |
| * |
| * End the current xml element. Writes an end tag even if the element is empty |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterFullEndElement(xmlTextWriterPtr writer) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) |
| return -1; |
| |
| lk = xmlListFront(writer->nodes); |
| if (lk == 0) |
| return -1; |
| |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p == 0) |
| return -1; |
| |
| sum = 0; |
| switch (p->state) { |
| case XML_TEXTWRITER_ATTRIBUTE: |
| count = xmlTextWriterEndAttribute(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| /* fallthrough */ |
| case XML_TEXTWRITER_NAME: |
| /* Output namespace declarations */ |
| count = xmlTextWriterOutputNSDecl(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| count = xmlOutputBufferWriteString(writer->out, ">"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| if (writer->indent) |
| writer->doindent = 0; |
| /* fallthrough */ |
| case XML_TEXTWRITER_TEXT: |
| if ((writer->indent) && (writer->doindent)) { |
| count = xmlTextWriterWriteIndent(writer); |
| sum += count; |
| writer->doindent = 1; |
| } else |
| writer->doindent = 1; |
| count = xmlOutputBufferWriteString(writer->out, "</"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, |
| (const char *) p->name); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, ">"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| default: |
| return -1; |
| } |
| |
| if (writer->indent) { |
| count = xmlOutputBufferWriteString(writer->out, "\n"); |
| sum += count; |
| } |
| |
| xmlListPopFront(writer->nodes); |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteFormatRaw: |
| * @writer: the xmlTextWriterPtr |
| * @format: format string (see printf) |
| * @...: extra parameters for the format |
| * |
| * Write a formatted raw xml text. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int XMLCDECL |
| xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format, |
| ...) |
| { |
| int rc; |
| va_list ap; |
| |
| va_start(ap, format); |
| |
| rc = xmlTextWriterWriteVFormatRaw(writer, format, ap); |
| |
| va_end(ap); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteVFormatRaw: |
| * @writer: the xmlTextWriterPtr |
| * @format: format string (see printf) |
| * @argptr: pointer to the first member of the variable argument list. |
| * |
| * Write a formatted raw xml text. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format, |
| va_list argptr) |
| { |
| int rc; |
| xmlChar *buf; |
| |
| if (writer == NULL) |
| return -1; |
| |
| buf = xmlTextWriterVSprintf(format, argptr); |
| if (buf == NULL) |
| return -1; |
| |
| rc = xmlTextWriterWriteRaw(writer, buf); |
| |
| xmlFree(buf); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteRawLen: |
| * @writer: the xmlTextWriterPtr |
| * @content: text string |
| * @len: length of the text string |
| * |
| * Write an xml text. |
| * TODO: what about entities and special chars?? |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content, |
| int len) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterWriteRawLen : invalid writer!\n"); |
| return -1; |
| } |
| |
| if ((content == NULL) || (len < 0)) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterWriteRawLen : invalid content!\n"); |
| return -1; |
| } |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if (lk != 0) { |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| count = xmlTextWriterHandleStateDependencies(writer, p); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| if (writer->indent) |
| writer->doindent = 0; |
| |
| if (content != NULL) { |
| count = |
| xmlOutputBufferWrite(writer->out, len, (const char *) content); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteRaw: |
| * @writer: the xmlTextWriterPtr |
| * @content: text string |
| * |
| * Write a raw xml text. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content) |
| { |
| return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content)); |
| } |
| |
| /** |
| * xmlTextWriterWriteFormatString: |
| * @writer: the xmlTextWriterPtr |
| * @format: format string (see printf) |
| * @...: extra parameters for the format |
| * |
| * Write a formatted xml text. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int XMLCDECL |
| xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format, |
| ...) |
| { |
| int rc; |
| va_list ap; |
| |
| if ((writer == NULL) || (format == NULL)) |
| return -1; |
| |
| va_start(ap, format); |
| |
| rc = xmlTextWriterWriteVFormatString(writer, format, ap); |
| |
| va_end(ap); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteVFormatString: |
| * @writer: the xmlTextWriterPtr |
| * @format: format string (see printf) |
| * @argptr: pointer to the first member of the variable argument list. |
| * |
| * Write a formatted xml text. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer, |
| const char *format, va_list argptr) |
| { |
| int rc; |
| xmlChar *buf; |
| |
| if ((writer == NULL) || (format == NULL)) |
| return -1; |
| |
| buf = xmlTextWriterVSprintf(format, argptr); |
| if (buf == NULL) |
| return -1; |
| |
| rc = xmlTextWriterWriteString(writer, buf); |
| |
| xmlFree(buf); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteString: |
| * @writer: the xmlTextWriterPtr |
| * @content: text string |
| * |
| * Write an xml text. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| xmlChar *buf; |
| |
| if ((writer == NULL) || (content == NULL)) |
| return -1; |
| |
| sum = 0; |
| buf = (xmlChar *) content; |
| lk = xmlListFront(writer->nodes); |
| if (lk != 0) { |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p != 0) { |
| switch (p->state) { |
| case XML_TEXTWRITER_NAME: |
| case XML_TEXTWRITER_TEXT: |
| #if 0 |
| buf = NULL; |
| xmlOutputBufferWriteEscape(writer->out, content, NULL); |
| #endif |
| buf = xmlEncodeSpecialChars(NULL, content); |
| break; |
| case XML_TEXTWRITER_ATTRIBUTE: |
| buf = NULL; |
| xmlBufAttrSerializeTxtContent(writer->out->buffer, |
| writer->doc, NULL, content); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| if (buf != NULL) { |
| count = xmlTextWriterWriteRaw(writer, buf); |
| |
| if (buf != content) /* buf was allocated by us, so free it */ |
| xmlFree(buf); |
| |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * xmlOutputBufferWriteBase64: |
| * @out: the xmlOutputBufferPtr |
| * @data: binary data |
| * @len: the number of bytes to encode |
| * |
| * Write base64 encoded data to an xmlOutputBuffer. |
| * Adapted from John Walker's base64.c (http://www.fourmilab.ch/). |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| static int |
| xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len, |
| const unsigned char *data) |
| { |
| static unsigned char dtable[64] = |
| {'A','B','C','D','E','F','G','H','I','J','K','L','M', |
| 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', |
| 'a','b','c','d','e','f','g','h','i','j','k','l','m', |
| 'n','o','p','q','r','s','t','u','v','w','x','y','z', |
| '0','1','2','3','4','5','6','7','8','9','+','/'}; |
| |
| int i; |
| int linelen; |
| int count; |
| int sum; |
| |
| if ((out == NULL) || (len < 0) || (data == NULL)) |
| return(-1); |
| |
| linelen = 0; |
| sum = 0; |
| |
| i = 0; |
| while (1) { |
| unsigned char igroup[3]; |
| unsigned char ogroup[4]; |
| int c; |
| int n; |
| |
| igroup[0] = igroup[1] = igroup[2] = 0; |
| for (n = 0; n < 3 && i < len; n++, i++) { |
| c = data[i]; |
| igroup[n] = (unsigned char) c; |
| } |
| |
| if (n > 0) { |
| ogroup[0] = dtable[igroup[0] >> 2]; |
| ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; |
| ogroup[2] = |
| dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; |
| ogroup[3] = dtable[igroup[2] & 0x3F]; |
| |
| if (n < 3) { |
| ogroup[3] = '='; |
| if (n < 2) { |
| ogroup[2] = '='; |
| } |
| } |
| |
| if (linelen >= B64LINELEN) { |
| count = xmlOutputBufferWrite(out, 2, B64CRLF); |
| if (count == -1) |
| return -1; |
| sum += count; |
| linelen = 0; |
| } |
| count = xmlOutputBufferWrite(out, 4, (const char *) ogroup); |
| if (count == -1) |
| return -1; |
| sum += count; |
| |
| linelen += 4; |
| } |
| |
| if (i >= len) |
| break; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteBase64: |
| * @writer: the xmlTextWriterPtr |
| * @data: binary data |
| * @start: the position within the data of the first byte to encode |
| * @len: the number of bytes to encode |
| * |
| * Write an base64 encoded xml text. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data, |
| int start, int len) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0)) |
| return -1; |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if (lk != 0) { |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p != 0) { |
| count = xmlTextWriterHandleStateDependencies(writer, p); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| } |
| |
| if (writer->indent) |
| writer->doindent = 0; |
| |
| count = |
| xmlOutputBufferWriteBase64(writer->out, len, |
| (unsigned char *) data + start); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlOutputBufferWriteBinHex: |
| * @out: the xmlOutputBufferPtr |
| * @data: binary data |
| * @len: the number of bytes to encode |
| * |
| * Write hqx encoded data to an xmlOutputBuffer. |
| * ::todo |
| * |
| * Returns the bytes written (may be 0 because of buffering) |
| * or -1 in case of error |
| */ |
| static int |
| xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out, |
| int len, const unsigned char *data) |
| { |
| int count; |
| int sum; |
| static char hex[16] = |
| {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; |
| int i; |
| |
| if ((out == NULL) || (data == NULL) || (len < 0)) { |
| return -1; |
| } |
| |
| sum = 0; |
| for (i = 0; i < len; i++) { |
| count = |
| xmlOutputBufferWrite(out, 1, |
| (const char *) &hex[data[i] >> 4]); |
| if (count == -1) |
| return -1; |
| sum += count; |
| count = |
| xmlOutputBufferWrite(out, 1, |
| (const char *) &hex[data[i] & 0xF]); |
| if (count == -1) |
| return -1; |
| sum += count; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteBinHex: |
| * @writer: the xmlTextWriterPtr |
| * @data: binary data |
| * @start: the position within the data of the first byte to encode |
| * @len: the number of bytes to encode |
| * |
| * Write a BinHex encoded xml text. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data, |
| int start, int len) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0)) |
| return -1; |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if (lk != 0) { |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p != 0) { |
| count = xmlTextWriterHandleStateDependencies(writer, p); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| } |
| |
| if (writer->indent) |
| writer->doindent = 0; |
| |
| count = |
| xmlOutputBufferWriteBinHex(writer->out, len, |
| (unsigned char *) data + start); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterStartAttribute: |
| * @writer: the xmlTextWriterPtr |
| * @name: element name |
| * |
| * Start an xml attribute. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if ((writer == NULL) || (name == NULL) || (*name == '\0')) |
| return -1; |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if (lk == 0) |
| return -1; |
| |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p == 0) |
| return -1; |
| |
| switch (p->state) { |
| case XML_TEXTWRITER_ATTRIBUTE: |
| count = xmlTextWriterEndAttribute(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| /* fallthrough */ |
| case XML_TEXTWRITER_NAME: |
| count = xmlOutputBufferWriteString(writer->out, " "); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = |
| xmlOutputBufferWriteString(writer->out, |
| (const char *) name); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, "="); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| p->state = XML_TEXTWRITER_ATTRIBUTE; |
| break; |
| default: |
| return -1; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterStartAttributeNS: |
| * @writer: the xmlTextWriterPtr |
| * @prefix: namespace prefix or NULL |
| * @name: element local name |
| * @namespaceURI: namespace URI or NULL |
| * |
| * Start an xml attribute with namespace support. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer, |
| const xmlChar * prefix, const xmlChar * name, |
| const xmlChar * namespaceURI) |
| { |
| int count; |
| int sum; |
| xmlChar *buf; |
| xmlTextWriterNsStackEntry *p; |
| |
| if ((writer == NULL) || (name == NULL) || (*name == '\0')) |
| return -1; |
| |
| /* Handle namespace first in case of error */ |
| if (namespaceURI != 0) { |
| xmlTextWriterNsStackEntry nsentry, *curns; |
| |
| buf = xmlStrdup(BAD_CAST "xmlns"); |
| if (prefix != 0) { |
| buf = xmlStrcat(buf, BAD_CAST ":"); |
| buf = xmlStrcat(buf, prefix); |
| } |
| |
| nsentry.prefix = buf; |
| nsentry.uri = (xmlChar *)namespaceURI; |
| nsentry.elem = xmlListFront(writer->nodes); |
| |
| curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack, |
| (void *)&nsentry); |
| if ((curns != NULL)) { |
| xmlFree(buf); |
| if (xmlStrcmp(curns->uri, namespaceURI) == 0) { |
| /* Namespace already defined on element skip */ |
| buf = NULL; |
| } else { |
| /* Prefix mismatch so error out */ |
| return -1; |
| } |
| } |
| |
| /* Do not add namespace decl to list - it is already there */ |
| if (buf != NULL) { |
| p = (xmlTextWriterNsStackEntry *) |
| xmlMalloc(sizeof(xmlTextWriterNsStackEntry)); |
| if (p == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartAttributeNS : out of memory!\n"); |
| return -1; |
| } |
| |
| p->prefix = buf; |
| p->uri = xmlStrdup(namespaceURI); |
| if (p->uri == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartAttributeNS : out of memory!\n"); |
| xmlFree(p); |
| return -1; |
| } |
| p->elem = xmlListFront(writer->nodes); |
| |
| xmlListPushFront(writer->nsstack, p); |
| } |
| } |
| |
| buf = NULL; |
| if (prefix != 0) { |
| buf = xmlStrdup(prefix); |
| buf = xmlStrcat(buf, BAD_CAST ":"); |
| } |
| buf = xmlStrcat(buf, name); |
| |
| sum = 0; |
| count = xmlTextWriterStartAttribute(writer, buf); |
| xmlFree(buf); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterEndAttribute: |
| * @writer: the xmlTextWriterPtr |
| * |
| * End the current xml element. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterEndAttribute(xmlTextWriterPtr writer) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) |
| return -1; |
| |
| lk = xmlListFront(writer->nodes); |
| if (lk == 0) { |
| return -1; |
| } |
| |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p == 0) { |
| return -1; |
| } |
| |
| sum = 0; |
| switch (p->state) { |
| case XML_TEXTWRITER_ATTRIBUTE: |
| p->state = XML_TEXTWRITER_NAME; |
| |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) { |
| return -1; |
| } |
| sum += count; |
| break; |
| default: |
| return -1; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteFormatAttribute: |
| * @writer: the xmlTextWriterPtr |
| * @name: attribute name |
| * @format: format string (see printf) |
| * @...: extra parameters for the format |
| * |
| * Write a formatted xml attribute. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int XMLCDECL |
| xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer, |
| const xmlChar * name, const char *format, |
| ...) |
| { |
| int rc; |
| va_list ap; |
| |
| va_start(ap, format); |
| |
| rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap); |
| |
| va_end(ap); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteVFormatAttribute: |
| * @writer: the xmlTextWriterPtr |
| * @name: attribute name |
| * @format: format string (see printf) |
| * @argptr: pointer to the first member of the variable argument list. |
| * |
| * Write a formatted xml attribute. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer, |
| const xmlChar * name, |
| const char *format, va_list argptr) |
| { |
| int rc; |
| xmlChar *buf; |
| |
| if (writer == NULL) |
| return -1; |
| |
| buf = xmlTextWriterVSprintf(format, argptr); |
| if (buf == NULL) |
| return -1; |
| |
| rc = xmlTextWriterWriteAttribute(writer, name, buf); |
| |
| xmlFree(buf); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteAttribute: |
| * @writer: the xmlTextWriterPtr |
| * @name: attribute name |
| * @content: attribute content |
| * |
| * Write an xml attribute. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name, |
| const xmlChar * content) |
| { |
| int count; |
| int sum; |
| |
| sum = 0; |
| count = xmlTextWriterStartAttribute(writer, name); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlTextWriterWriteString(writer, content); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlTextWriterEndAttribute(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteFormatAttributeNS: |
| * @writer: the xmlTextWriterPtr |
| * @prefix: namespace prefix |
| * @name: attribute local name |
| * @namespaceURI: namespace URI |
| * @format: format string (see printf) |
| * @...: extra parameters for the format |
| * |
| * Write a formatted xml attribute.with namespace support |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int XMLCDECL |
| xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer, |
| const xmlChar * prefix, |
| const xmlChar * name, |
| const xmlChar * namespaceURI, |
| const char *format, ...) |
| { |
| int rc; |
| va_list ap; |
| |
| va_start(ap, format); |
| |
| rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name, |
| namespaceURI, format, ap); |
| |
| va_end(ap); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteVFormatAttributeNS: |
| * @writer: the xmlTextWriterPtr |
| * @prefix: namespace prefix |
| * @name: attribute local name |
| * @namespaceURI: namespace URI |
| * @format: format string (see printf) |
| * @argptr: pointer to the first member of the variable argument list. |
| * |
| * Write a formatted xml attribute.with namespace support |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer, |
| const xmlChar * prefix, |
| const xmlChar * name, |
| const xmlChar * namespaceURI, |
| const char *format, va_list argptr) |
| { |
| int rc; |
| xmlChar *buf; |
| |
| if (writer == NULL) |
| return -1; |
| |
| buf = xmlTextWriterVSprintf(format, argptr); |
| if (buf == NULL) |
| return -1; |
| |
| rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI, |
| buf); |
| |
| xmlFree(buf); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteAttributeNS: |
| * @writer: the xmlTextWriterPtr |
| * @prefix: namespace prefix |
| * @name: attribute local name |
| * @namespaceURI: namespace URI |
| * @content: attribute content |
| * |
| * Write an xml attribute. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer, |
| const xmlChar * prefix, const xmlChar * name, |
| const xmlChar * namespaceURI, |
| const xmlChar * content) |
| { |
| int count; |
| int sum; |
| |
| if ((writer == NULL) || (name == NULL) || (*name == '\0')) |
| return -1; |
| |
| sum = 0; |
| count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlTextWriterWriteString(writer, content); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlTextWriterEndAttribute(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteFormatElement: |
| * @writer: the xmlTextWriterPtr |
| * @name: element name |
| * @format: format string (see printf) |
| * @...: extra parameters for the format |
| * |
| * Write a formatted xml element. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int XMLCDECL |
| xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer, |
| const xmlChar * name, const char *format, |
| ...) |
| { |
| int rc; |
| va_list ap; |
| |
| va_start(ap, format); |
| |
| rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap); |
| |
| va_end(ap); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteVFormatElement: |
| * @writer: the xmlTextWriterPtr |
| * @name: element name |
| * @format: format string (see printf) |
| * @argptr: pointer to the first member of the variable argument list. |
| * |
| * Write a formatted xml element. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer, |
| const xmlChar * name, const char *format, |
| va_list argptr) |
| { |
| int rc; |
| xmlChar *buf; |
| |
| if (writer == NULL) |
| return -1; |
| |
| buf = xmlTextWriterVSprintf(format, argptr); |
| if (buf == NULL) |
| return -1; |
| |
| rc = xmlTextWriterWriteElement(writer, name, buf); |
| |
| xmlFree(buf); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteElement: |
| * @writer: the xmlTextWriterPtr |
| * @name: element name |
| * @content: element content |
| * |
| * Write an xml element. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name, |
| const xmlChar * content) |
| { |
| int count; |
| int sum; |
| |
| sum = 0; |
| count = xmlTextWriterStartElement(writer, name); |
| if (count == -1) |
| return -1; |
| sum += count; |
| if (content != NULL) { |
| count = xmlTextWriterWriteString(writer, content); |
| if (count == -1) |
| return -1; |
| sum += count; |
| } |
| count = xmlTextWriterEndElement(writer); |
| if (count == -1) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteFormatElementNS: |
| * @writer: the xmlTextWriterPtr |
| * @prefix: namespace prefix |
| * @name: element local name |
| * @namespaceURI: namespace URI |
| * @format: format string (see printf) |
| * @...: extra parameters for the format |
| * |
| * Write a formatted xml element with namespace support. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int XMLCDECL |
| xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer, |
| const xmlChar * prefix, |
| const xmlChar * name, |
| const xmlChar * namespaceURI, |
| const char *format, ...) |
| { |
| int rc; |
| va_list ap; |
| |
| va_start(ap, format); |
| |
| rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name, |
| namespaceURI, format, ap); |
| |
| va_end(ap); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteVFormatElementNS: |
| * @writer: the xmlTextWriterPtr |
| * @prefix: namespace prefix |
| * @name: element local name |
| * @namespaceURI: namespace URI |
| * @format: format string (see printf) |
| * @argptr: pointer to the first member of the variable argument list. |
| * |
| * Write a formatted xml element with namespace support. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer, |
| const xmlChar * prefix, |
| const xmlChar * name, |
| const xmlChar * namespaceURI, |
| const char *format, va_list argptr) |
| { |
| int rc; |
| xmlChar *buf; |
| |
| if (writer == NULL) |
| return -1; |
| |
| buf = xmlTextWriterVSprintf(format, argptr); |
| if (buf == NULL) |
| return -1; |
| |
| rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI, |
| buf); |
| |
| xmlFree(buf); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteElementNS: |
| * @writer: the xmlTextWriterPtr |
| * @prefix: namespace prefix |
| * @name: element local name |
| * @namespaceURI: namespace URI |
| * @content: element content |
| * |
| * Write an xml element with namespace support. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteElementNS(xmlTextWriterPtr writer, |
| const xmlChar * prefix, const xmlChar * name, |
| const xmlChar * namespaceURI, |
| const xmlChar * content) |
| { |
| int count; |
| int sum; |
| |
| if ((writer == NULL) || (name == NULL) || (*name == '\0')) |
| return -1; |
| |
| sum = 0; |
| count = |
| xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlTextWriterWriteString(writer, content); |
| if (count == -1) |
| return -1; |
| sum += count; |
| count = xmlTextWriterEndElement(writer); |
| if (count == -1) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterStartPI: |
| * @writer: the xmlTextWriterPtr |
| * @target: PI target |
| * |
| * Start an xml PI. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if ((writer == NULL) || (target == NULL) || (*target == '\0')) |
| return -1; |
| |
| if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n"); |
| return -1; |
| } |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if (lk != 0) { |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p != 0) { |
| switch (p->state) { |
| case XML_TEXTWRITER_ATTRIBUTE: |
| count = xmlTextWriterEndAttribute(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| /* fallthrough */ |
| case XML_TEXTWRITER_NAME: |
| /* Output namespace declarations */ |
| count = xmlTextWriterOutputNSDecl(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, ">"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| p->state = XML_TEXTWRITER_TEXT; |
| break; |
| case XML_TEXTWRITER_NONE: |
| case XML_TEXTWRITER_TEXT: |
| case XML_TEXTWRITER_DTD: |
| break; |
| case XML_TEXTWRITER_PI: |
| case XML_TEXTWRITER_PI_TEXT: |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterStartPI : nested PI!\n"); |
| return -1; |
| default: |
| return -1; |
| } |
| } |
| } |
| |
| p = (xmlTextWriterStackEntry *) |
| xmlMalloc(sizeof(xmlTextWriterStackEntry)); |
| if (p == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartPI : out of memory!\n"); |
| return -1; |
| } |
| |
| p->name = xmlStrdup(target); |
| if (p->name == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartPI : out of memory!\n"); |
| xmlFree(p); |
| return -1; |
| } |
| p->state = XML_TEXTWRITER_PI; |
| |
| xmlListPushFront(writer->nodes, p); |
| |
| count = xmlOutputBufferWriteString(writer->out, "<?"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = |
| xmlOutputBufferWriteString(writer->out, (const char *) p->name); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterEndPI: |
| * @writer: the xmlTextWriterPtr |
| * |
| * End the current xml PI. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterEndPI(xmlTextWriterPtr writer) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) |
| return -1; |
| |
| lk = xmlListFront(writer->nodes); |
| if (lk == 0) |
| return 0; |
| |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p == 0) |
| return 0; |
| |
| sum = 0; |
| switch (p->state) { |
| case XML_TEXTWRITER_PI: |
| case XML_TEXTWRITER_PI_TEXT: |
| count = xmlOutputBufferWriteString(writer->out, "?>"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| default: |
| return -1; |
| } |
| |
| if (writer->indent) { |
| count = xmlOutputBufferWriteString(writer->out, "\n"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| xmlListPopFront(writer->nodes); |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteFormatPI: |
| * @writer: the xmlTextWriterPtr |
| * @target: PI target |
| * @format: format string (see printf) |
| * @...: extra parameters for the format |
| * |
| * Write a formatted PI. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int XMLCDECL |
| xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target, |
| const char *format, ...) |
| { |
| int rc; |
| va_list ap; |
| |
| va_start(ap, format); |
| |
| rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap); |
| |
| va_end(ap); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteVFormatPI: |
| * @writer: the xmlTextWriterPtr |
| * @target: PI target |
| * @format: format string (see printf) |
| * @argptr: pointer to the first member of the variable argument list. |
| * |
| * Write a formatted xml PI. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer, |
| const xmlChar * target, const char *format, |
| va_list argptr) |
| { |
| int rc; |
| xmlChar *buf; |
| |
| if (writer == NULL) |
| return -1; |
| |
| buf = xmlTextWriterVSprintf(format, argptr); |
| if (buf == NULL) |
| return -1; |
| |
| rc = xmlTextWriterWritePI(writer, target, buf); |
| |
| xmlFree(buf); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWritePI: |
| * @writer: the xmlTextWriterPtr |
| * @target: PI target |
| * @content: PI content |
| * |
| * Write an xml PI. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target, |
| const xmlChar * content) |
| { |
| int count; |
| int sum; |
| |
| sum = 0; |
| count = xmlTextWriterStartPI(writer, target); |
| if (count == -1) |
| return -1; |
| sum += count; |
| if (content != 0) { |
| count = xmlTextWriterWriteString(writer, content); |
| if (count == -1) |
| return -1; |
| sum += count; |
| } |
| count = xmlTextWriterEndPI(writer); |
| if (count == -1) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterStartCDATA: |
| * @writer: the xmlTextWriterPtr |
| * |
| * Start an xml CDATA section. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterStartCDATA(xmlTextWriterPtr writer) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) |
| return -1; |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if (lk != 0) { |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p != 0) { |
| switch (p->state) { |
| case XML_TEXTWRITER_NONE: |
| case XML_TEXTWRITER_TEXT: |
| case XML_TEXTWRITER_PI: |
| case XML_TEXTWRITER_PI_TEXT: |
| break; |
| case XML_TEXTWRITER_ATTRIBUTE: |
| count = xmlTextWriterEndAttribute(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| /* fallthrough */ |
| case XML_TEXTWRITER_NAME: |
| /* Output namespace declarations */ |
| count = xmlTextWriterOutputNSDecl(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, ">"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| p->state = XML_TEXTWRITER_TEXT; |
| break; |
| case XML_TEXTWRITER_CDATA: |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n"); |
| return -1; |
| default: |
| return -1; |
| } |
| } |
| } |
| |
| p = (xmlTextWriterStackEntry *) |
| xmlMalloc(sizeof(xmlTextWriterStackEntry)); |
| if (p == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartCDATA : out of memory!\n"); |
| return -1; |
| } |
| |
| p->name = NULL; |
| p->state = XML_TEXTWRITER_CDATA; |
| |
| xmlListPushFront(writer->nodes, p); |
| |
| count = xmlOutputBufferWriteString(writer->out, "<![CDATA["); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterEndCDATA: |
| * @writer: the xmlTextWriterPtr |
| * |
| * End an xml CDATA section. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterEndCDATA(xmlTextWriterPtr writer) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) |
| return -1; |
| |
| lk = xmlListFront(writer->nodes); |
| if (lk == 0) |
| return -1; |
| |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p == 0) |
| return -1; |
| |
| sum = 0; |
| switch (p->state) { |
| case XML_TEXTWRITER_CDATA: |
| count = xmlOutputBufferWriteString(writer->out, "]]>"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| break; |
| default: |
| return -1; |
| } |
| |
| xmlListPopFront(writer->nodes); |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteFormatCDATA: |
| * @writer: the xmlTextWriterPtr |
| * @format: format string (see printf) |
| * @...: extra parameters for the format |
| * |
| * Write a formatted xml CDATA. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int XMLCDECL |
| xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format, |
| ...) |
| { |
| int rc; |
| va_list ap; |
| |
| va_start(ap, format); |
| |
| rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap); |
| |
| va_end(ap); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteVFormatCDATA: |
| * @writer: the xmlTextWriterPtr |
| * @format: format string (see printf) |
| * @argptr: pointer to the first member of the variable argument list. |
| * |
| * Write a formatted xml CDATA. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format, |
| va_list argptr) |
| { |
| int rc; |
| xmlChar *buf; |
| |
| if (writer == NULL) |
| return -1; |
| |
| buf = xmlTextWriterVSprintf(format, argptr); |
| if (buf == NULL) |
| return -1; |
| |
| rc = xmlTextWriterWriteCDATA(writer, buf); |
| |
| xmlFree(buf); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteCDATA: |
| * @writer: the xmlTextWriterPtr |
| * @content: CDATA content |
| * |
| * Write an xml CDATA. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content) |
| { |
| int count; |
| int sum; |
| |
| sum = 0; |
| count = xmlTextWriterStartCDATA(writer); |
| if (count == -1) |
| return -1; |
| sum += count; |
| if (content != 0) { |
| count = xmlTextWriterWriteString(writer, content); |
| if (count == -1) |
| return -1; |
| sum += count; |
| } |
| count = xmlTextWriterEndCDATA(writer); |
| if (count == -1) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterStartDTD: |
| * @writer: the xmlTextWriterPtr |
| * @name: the name of the DTD |
| * @pubid: the public identifier, which is an alternative to the system identifier |
| * @sysid: the system identifier, which is the URI of the DTD |
| * |
| * Start an xml DTD. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterStartDTD(xmlTextWriterPtr writer, |
| const xmlChar * name, |
| const xmlChar * pubid, const xmlChar * sysid) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL || name == NULL || *name == '\0') |
| return -1; |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterStartDTD : DTD allowed only in prolog!\n"); |
| return -1; |
| } |
| |
| p = (xmlTextWriterStackEntry *) |
| xmlMalloc(sizeof(xmlTextWriterStackEntry)); |
| if (p == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartDTD : out of memory!\n"); |
| return -1; |
| } |
| |
| p->name = xmlStrdup(name); |
| if (p->name == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartDTD : out of memory!\n"); |
| xmlFree(p); |
| return -1; |
| } |
| p->state = XML_TEXTWRITER_DTD; |
| |
| xmlListPushFront(writer->nodes, p); |
| |
| count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE "); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, (const char *) name); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| if (pubid != 0) { |
| if (sysid == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
| "xmlTextWriterStartDTD : system identifier needed!\n"); |
| return -1; |
| } |
| |
| if (writer->indent) |
| count = xmlOutputBufferWrite(writer->out, 1, "\n"); |
| else |
| count = xmlOutputBufferWrite(writer->out, 1, " "); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| count = xmlOutputBufferWriteString(writer->out, "PUBLIC "); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| count = |
| xmlOutputBufferWriteString(writer->out, (const char *) pubid); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| if (sysid != 0) { |
| if (pubid == 0) { |
| if (writer->indent) |
| count = xmlOutputBufferWrite(writer->out, 1, "\n"); |
| else |
| count = xmlOutputBufferWrite(writer->out, 1, " "); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, "SYSTEM "); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } else { |
| if (writer->indent) |
| count = xmlOutputBufferWriteString(writer->out, "\n "); |
| else |
| count = xmlOutputBufferWrite(writer->out, 1, " "); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| count = |
| xmlOutputBufferWriteString(writer->out, (const char *) sysid); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterEndDTD: |
| * @writer: the xmlTextWriterPtr |
| * |
| * End an xml DTD. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterEndDTD(xmlTextWriterPtr writer) |
| { |
| int loop; |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) |
| return -1; |
| |
| sum = 0; |
| loop = 1; |
| while (loop) { |
| lk = xmlListFront(writer->nodes); |
| if (lk == NULL) |
| break; |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p == 0) |
| break; |
| switch (p->state) { |
| case XML_TEXTWRITER_DTD_TEXT: |
| count = xmlOutputBufferWriteString(writer->out, "]"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| /* fallthrough */ |
| case XML_TEXTWRITER_DTD: |
| count = xmlOutputBufferWriteString(writer->out, ">"); |
| |
| if (writer->indent) { |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, "\n"); |
| } |
| |
| xmlListPopFront(writer->nodes); |
| break; |
| case XML_TEXTWRITER_DTD_ELEM: |
| case XML_TEXTWRITER_DTD_ELEM_TEXT: |
| count = xmlTextWriterEndDTDElement(writer); |
| break; |
| case XML_TEXTWRITER_DTD_ATTL: |
| case XML_TEXTWRITER_DTD_ATTL_TEXT: |
| count = xmlTextWriterEndDTDAttlist(writer); |
| break; |
| case XML_TEXTWRITER_DTD_ENTY: |
| case XML_TEXTWRITER_DTD_PENT: |
| case XML_TEXTWRITER_DTD_ENTY_TEXT: |
| count = xmlTextWriterEndDTDEntity(writer); |
| break; |
| case XML_TEXTWRITER_COMMENT: |
| count = xmlTextWriterEndComment(writer); |
| break; |
| default: |
| loop = 0; |
| continue; |
| } |
| |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterWriteFormatDTD: |
| * @writer: the xmlTextWriterPtr |
| * @name: the name of the DTD |
| * @pubid: the public identifier, which is an alternative to the system identifier |
| * @sysid: the system identifier, which is the URI of the DTD |
| * @format: format string (see printf) |
| * @...: extra parameters for the format |
| * |
| * Write a DTD with a formatted markup declarations part. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int XMLCDECL |
| xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer, |
| const xmlChar * name, |
| const xmlChar * pubid, |
| const xmlChar * sysid, const char *format, ...) |
| { |
| int rc; |
| va_list ap; |
| |
| va_start(ap, format); |
| |
| rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format, |
| ap); |
| |
| va_end(ap); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteVFormatDTD: |
| * @writer: the xmlTextWriterPtr |
| * @name: the name of the DTD |
| * @pubid: the public identifier, which is an alternative to the system identifier |
| * @sysid: the system identifier, which is the URI of the DTD |
| * @format: format string (see printf) |
| * @argptr: pointer to the first member of the variable argument list. |
| * |
| * Write a DTD with a formatted markup declarations part. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer, |
| const xmlChar * name, |
| const xmlChar * pubid, |
| const xmlChar * sysid, |
| const char *format, va_list argptr) |
| { |
| int rc; |
| xmlChar *buf; |
| |
| if (writer == NULL) |
| return -1; |
| |
| buf = xmlTextWriterVSprintf(format, argptr); |
| if (buf == NULL) |
| return -1; |
| |
| rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf); |
| |
| xmlFree(buf); |
| return rc; |
| } |
| |
| /** |
| * xmlTextWriterWriteDTD: |
| * @writer: the xmlTextWriterPtr |
| * @name: the name of the DTD |
| * @pubid: the public identifier, which is an alternative to the system identifier |
| * @sysid: the system identifier, which is the URI of the DTD |
| * @subset: string content of the DTD |
| * |
| * Write a DTD. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterWriteDTD(xmlTextWriterPtr writer, |
| const xmlChar * name, |
| const xmlChar * pubid, |
| const xmlChar * sysid, const xmlChar * subset) |
| { |
| int count; |
| int sum; |
| |
| sum = 0; |
| count = xmlTextWriterStartDTD(writer, name, pubid, sysid); |
| if (count == -1) |
| return -1; |
| sum += count; |
| if (subset != 0) { |
| count = xmlTextWriterWriteString(writer, subset); |
| if (count == -1) |
| return -1; |
| sum += count; |
| } |
| count = xmlTextWriterEndDTD(writer); |
| if (count == -1) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterStartDTDElement: |
| * @writer: the xmlTextWriterPtr |
| * @name: the name of the DTD element |
| * |
| * Start an xml DTD element. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL || name == NULL || *name == '\0') |
| return -1; |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if (lk == 0) { |
| return -1; |
| } |
| |
| p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
| if (p != 0) { |
| switch (p->state) { |
| case XML_TEXTWRITER_DTD: |
| count = xmlOutputBufferWriteString(writer->out, " ["); |
| if (count < 0) |
| return -1; |
| sum += count; |
| if (writer->indent) { |
| count = xmlOutputBufferWriteString(writer->out, "\n"); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| p->state = XML_TEXTWRITER_DTD_TEXT; |
| /* fallthrough */ |
| case XML_TEXTWRITER_DTD_TEXT: |
| case XML_TEXTWRITER_NONE: |
| break; |
| default: |
| return -1; |
| } |
| } |
| |
| p = (xmlTextWriterStackEntry *) |
| xmlMalloc(sizeof(xmlTextWriterStackEntry)); |
| if (p == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartDTDElement : out of memory!\n"); |
| return -1; |
| } |
| |
| p->name = xmlStrdup(name); |
| if (p->name == 0) { |
| xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
| "xmlTextWriterStartDTDElement : out of memory!\n"); |
| xmlFree(p); |
| return -1; |
| } |
| p->state = XML_TEXTWRITER_DTD_ELEM; |
| |
| xmlListPushFront(writer->nodes, p); |
| |
| if (writer->indent) { |
| count = xmlTextWriterWriteIndent(writer); |
| if (count < 0) |
| return -1; |
| sum += count; |
| } |
| |
| count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT "); |
| if (count < 0) |
| return -1; |
| sum += count; |
| count = xmlOutputBufferWriteString(writer->out, (const char *) name); |
| if (count < 0) |
| return -1; |
| sum += count; |
| |
| return sum; |
| } |
| |
| /** |
| * xmlTextWriterEndDTDElement: |
| * @writer: the xmlTextWriterPtr |
| * |
| * End an xml DTD element. |
| * |
| * Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
| */ |
| int |
| xmlTextWriterEndDTDElement(xmlTextWriterPtr writer) |
| { |
| int count; |
| int sum; |
| xmlLinkPtr lk; |
| xmlTextWriterStackEntry *p; |
| |
| if (writer == NULL) |
| return -1; |
| |
| sum = 0; |
| lk = xmlListFront(writer->nodes); |
| if (lk == 0) |
| return -1; |
| |
| p |