You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4738 lines
122 KiB
4738 lines
122 KiB
|
|
/* |
|
* 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_NO_MEMORY, |
|
"xmlTextWriterStartDocument : out of memory!\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 coment. |
|
* |
|
* 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 = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
|
if (p == 0) |
|
return -1; |
|
|
|
switch (p->state) { |
|
case XML_TEXTWRITER_DTD_ELEM: |
|
case XML_TEXTWRITER_DTD_ELEM_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; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteFormatDTDElement: |
|
* @writer: the xmlTextWriterPtr |
|
* @name: the name of the DTD element |
|
* @format: format string (see printf) |
|
* @...: extra parameters for the format |
|
* |
|
* Write a formatted DTD element. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int XMLCDECL |
|
xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer, |
|
const xmlChar * name, |
|
const char *format, ...) |
|
{ |
|
int rc; |
|
va_list ap; |
|
|
|
va_start(ap, format); |
|
|
|
rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap); |
|
|
|
va_end(ap); |
|
return rc; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteVFormatDTDElement: |
|
* @writer: the xmlTextWriterPtr |
|
* @name: the name of the DTD element |
|
* @format: format string (see printf) |
|
* @argptr: pointer to the first member of the variable argument list. |
|
* |
|
* Write a formatted DTD element. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterWriteVFormatDTDElement(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 = xmlTextWriterWriteDTDElement(writer, name, buf); |
|
|
|
xmlFree(buf); |
|
return rc; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteDTDElement: |
|
* @writer: the xmlTextWriterPtr |
|
* @name: the name of the DTD element |
|
* @content: content of the element |
|
* |
|
* Write a DTD element. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer, |
|
const xmlChar * name, const xmlChar * content) |
|
{ |
|
int count; |
|
int sum; |
|
|
|
if (content == NULL) |
|
return -1; |
|
|
|
sum = 0; |
|
count = xmlTextWriterStartDTDElement(writer, name); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
count = xmlTextWriterWriteString(writer, content); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
count = xmlTextWriterEndDTDElement(writer); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
return sum; |
|
} |
|
|
|
/** |
|
* xmlTextWriterStartDTDAttlist: |
|
* @writer: the xmlTextWriterPtr |
|
* @name: the name of the DTD ATTLIST |
|
* |
|
* Start an xml DTD ATTLIST. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterStartDTDAttlist(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, |
|
"xmlTextWriterStartDTDAttlist : out of memory!\n"); |
|
return -1; |
|
} |
|
|
|
p->name = xmlStrdup(name); |
|
if (p->name == 0) { |
|
xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, |
|
"xmlTextWriterStartDTDAttlist : out of memory!\n"); |
|
xmlFree(p); |
|
return -1; |
|
} |
|
p->state = XML_TEXTWRITER_DTD_ATTL; |
|
|
|
xmlListPushFront(writer->nodes, p); |
|
|
|
if (writer->indent) { |
|
count = xmlTextWriterWriteIndent(writer); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
} |
|
|
|
count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST "); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
count = xmlOutputBufferWriteString(writer->out, (const char *) name); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
|
|
return sum; |
|
} |
|
|
|
/** |
|
* xmlTextWriterEndDTDAttlist: |
|
* @writer: the xmlTextWriterPtr |
|
* |
|
* End an xml DTD attribute list. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterEndDTDAttlist(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 = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
|
if (p == 0) |
|
return -1; |
|
|
|
switch (p->state) { |
|
case XML_TEXTWRITER_DTD_ATTL: |
|
case XML_TEXTWRITER_DTD_ATTL_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; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteFormatDTDAttlist: |
|
* @writer: the xmlTextWriterPtr |
|
* @name: the name of the DTD ATTLIST |
|
* @format: format string (see printf) |
|
* @...: extra parameters for the format |
|
* |
|
* Write a formatted DTD ATTLIST. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int XMLCDECL |
|
xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer, |
|
const xmlChar * name, |
|
const char *format, ...) |
|
{ |
|
int rc; |
|
va_list ap; |
|
|
|
va_start(ap, format); |
|
|
|
rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap); |
|
|
|
va_end(ap); |
|
return rc; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteVFormatDTDAttlist: |
|
* @writer: the xmlTextWriterPtr |
|
* @name: the name of the DTD ATTLIST |
|
* @format: format string (see printf) |
|
* @argptr: pointer to the first member of the variable argument list. |
|
* |
|
* Write a formatted DTD ATTLIST. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterWriteVFormatDTDAttlist(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 = xmlTextWriterWriteDTDAttlist(writer, name, buf); |
|
|
|
xmlFree(buf); |
|
return rc; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteDTDAttlist: |
|
* @writer: the xmlTextWriterPtr |
|
* @name: the name of the DTD ATTLIST |
|
* @content: content of the ATTLIST |
|
* |
|
* Write a DTD ATTLIST. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer, |
|
const xmlChar * name, const xmlChar * content) |
|
{ |
|
int count; |
|
int sum; |
|
|
|
if (content == NULL) |
|
return -1; |
|
|
|
sum = 0; |
|
count = xmlTextWriterStartDTDAttlist(writer, name); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
count = xmlTextWriterWriteString(writer, content); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
count = xmlTextWriterEndDTDAttlist(writer); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
return sum; |
|
} |
|
|
|
/** |
|
* xmlTextWriterStartDTDEntity: |
|
* @writer: the xmlTextWriterPtr |
|
* @pe: TRUE if this is a parameter entity, FALSE if not |
|
* @name: the name of the DTD ATTLIST |
|
* |
|
* Start an xml DTD ATTLIST. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer, |
|
int pe, 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_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; |
|
} |
|
|
|
if (pe != 0) |
|
p->state = XML_TEXTWRITER_DTD_PENT; |
|
else |
|
p->state = XML_TEXTWRITER_DTD_ENTY; |
|
|
|
xmlListPushFront(writer->nodes, p); |
|
|
|
if (writer->indent) { |
|
count = xmlTextWriterWriteIndent(writer); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
} |
|
|
|
count = xmlOutputBufferWriteString(writer->out, "<!ENTITY "); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
|
|
if (pe != 0) { |
|
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; |
|
|
|
return sum; |
|
} |
|
|
|
/** |
|
* xmlTextWriterEndDTDEntity: |
|
* @writer: the xmlTextWriterPtr |
|
* |
|
* End an xml DTD entity. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterEndDTDEntity(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 = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
|
if (p == 0) |
|
return -1; |
|
|
|
switch (p->state) { |
|
case XML_TEXTWRITER_DTD_ENTY_TEXT: |
|
count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
/* Falls through. */ |
|
case XML_TEXTWRITER_DTD_ENTY: |
|
case XML_TEXTWRITER_DTD_PENT: |
|
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; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteFormatDTDInternalEntity: |
|
* @writer: the xmlTextWriterPtr |
|
* @pe: TRUE if this is a parameter entity, FALSE if not |
|
* @name: the name of the DTD entity |
|
* @format: format string (see printf) |
|
* @...: extra parameters for the format |
|
* |
|
* Write a formatted DTD internal entity. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int XMLCDECL |
|
xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer, |
|
int pe, |
|
const xmlChar * name, |
|
const char *format, ...) |
|
{ |
|
int rc; |
|
va_list ap; |
|
|
|
va_start(ap, format); |
|
|
|
rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name, |
|
format, ap); |
|
|
|
va_end(ap); |
|
return rc; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteVFormatDTDInternalEntity: |
|
* @writer: the xmlTextWriterPtr |
|
* @pe: TRUE if this is a parameter entity, FALSE if not |
|
* @name: the name of the DTD entity |
|
* @format: format string (see printf) |
|
* @argptr: pointer to the first member of the variable argument list. |
|
* |
|
* Write a formatted DTD internal entity. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer, |
|
int pe, |
|
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 = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf); |
|
|
|
xmlFree(buf); |
|
return rc; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteDTDEntity: |
|
* @writer: the xmlTextWriterPtr |
|
* @pe: TRUE if this is a parameter entity, FALSE if not |
|
* @name: the name of the DTD entity |
|
* @pubid: the public identifier, which is an alternative to the system identifier |
|
* @sysid: the system identifier, which is the URI of the DTD |
|
* @ndataid: the xml notation name. |
|
* @content: content of the entity |
|
* |
|
* Write a DTD entity. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer, |
|
int pe, |
|
const xmlChar * name, |
|
const xmlChar * pubid, |
|
const xmlChar * sysid, |
|
const xmlChar * ndataid, |
|
const xmlChar * content) |
|
{ |
|
if ((content == NULL) && (pubid == NULL) && (sysid == NULL)) |
|
return -1; |
|
if ((pe != 0) && (ndataid != NULL)) |
|
return -1; |
|
|
|
if ((pubid == NULL) && (sysid == NULL)) |
|
return xmlTextWriterWriteDTDInternalEntity(writer, pe, name, |
|
content); |
|
|
|
return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid, |
|
sysid, ndataid); |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteDTDInternalEntity: |
|
* @writer: the xmlTextWriterPtr |
|
* @pe: TRUE if this is a parameter entity, FALSE if not |
|
* @name: the name of the DTD entity |
|
* @content: content of the entity |
|
* |
|
* Write a DTD internal entity. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer, |
|
int pe, |
|
const xmlChar * name, |
|
const xmlChar * content) |
|
{ |
|
int count; |
|
int sum; |
|
|
|
if ((name == NULL) || (*name == '\0') || (content == NULL)) |
|
return -1; |
|
|
|
sum = 0; |
|
count = xmlTextWriterStartDTDEntity(writer, pe, name); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
count = xmlTextWriterWriteString(writer, content); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
count = xmlTextWriterEndDTDEntity(writer); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
return sum; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteDTDExternalEntity: |
|
* @writer: the xmlTextWriterPtr |
|
* @pe: TRUE if this is a parameter entity, FALSE if not |
|
* @name: the name of the DTD entity |
|
* @pubid: the public identifier, which is an alternative to the system identifier |
|
* @sysid: the system identifier, which is the URI of the DTD |
|
* @ndataid: the xml notation name. |
|
* |
|
* Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer, |
|
int pe, |
|
const xmlChar * name, |
|
const xmlChar * pubid, |
|
const xmlChar * sysid, |
|
const xmlChar * ndataid) |
|
{ |
|
int count; |
|
int sum; |
|
|
|
if (((pubid == NULL) && (sysid == NULL))) |
|
return -1; |
|
if ((pe != 0) && (ndataid != NULL)) |
|
return -1; |
|
|
|
sum = 0; |
|
count = xmlTextWriterStartDTDEntity(writer, pe, name); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
count = |
|
xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid, |
|
ndataid); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
|
|
count = xmlTextWriterEndDTDEntity(writer); |
|
if (count == -1) |
|
return -1; |
|
sum += count; |
|
|
|
return sum; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteDTDExternalEntityContents: |
|
* @writer: the xmlTextWriterPtr |
|
* @pubid: the public identifier, which is an alternative to the system identifier |
|
* @sysid: the system identifier, which is the URI of the DTD |
|
* @ndataid: the xml notation name. |
|
* |
|
* Write the contents of a DTD external entity. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer, |
|
const xmlChar * pubid, |
|
const xmlChar * sysid, |
|
const xmlChar * ndataid) |
|
{ |
|
int count; |
|
int sum; |
|
xmlLinkPtr lk; |
|
xmlTextWriterStackEntry *p; |
|
|
|
if (writer == NULL) { |
|
xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
|
"xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n"); |
|
return -1; |
|
} |
|
|
|
sum = 0; |
|
lk = xmlListFront(writer->nodes); |
|
if (lk == 0) { |
|
xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
|
"xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n"); |
|
return -1; |
|
} |
|
|
|
p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
|
if (p == 0) |
|
return -1; |
|
|
|
switch (p->state) { |
|
case XML_TEXTWRITER_DTD_ENTY: |
|
break; |
|
case XML_TEXTWRITER_DTD_PENT: |
|
if (ndataid != NULL) { |
|
xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
|
"xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n"); |
|
return -1; |
|
} |
|
break; |
|
default: |
|
xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
|
"xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n"); |
|
return -1; |
|
} |
|
|
|
if (pubid != 0) { |
|
if (sysid == 0) { |
|
xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, |
|
"xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n"); |
|
return -1; |
|
} |
|
|
|
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) { |
|
count = xmlOutputBufferWriteString(writer->out, " SYSTEM"); |
|
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; |
|
|
|
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; |
|
} |
|
|
|
if (ndataid != NULL) { |
|
count = xmlOutputBufferWriteString(writer->out, " NDATA "); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
|
|
count = |
|
xmlOutputBufferWriteString(writer->out, |
|
(const char *) ndataid); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
} |
|
|
|
return sum; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteDTDNotation: |
|
* @writer: the xmlTextWriterPtr |
|
* @name: the name of the xml notation |
|
* @pubid: the public identifier, which is an alternative to the system identifier |
|
* @sysid: the system identifier, which is the URI of the DTD |
|
* |
|
* Write a DTD entity. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterWriteDTDNotation(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 == 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: |
|
break; |
|
default: |
|
return -1; |
|
} |
|
} |
|
|
|
if (writer->indent) { |
|
count = xmlTextWriterWriteIndent(writer); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
} |
|
|
|
count = xmlOutputBufferWriteString(writer->out, "<!NOTATION "); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
count = xmlOutputBufferWriteString(writer->out, (const char *) name); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
|
|
if (pubid != 0) { |
|
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) { |
|
count = xmlOutputBufferWriteString(writer->out, " SYSTEM"); |
|
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; |
|
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; |
|
} |
|
|
|
count = xmlOutputBufferWriteString(writer->out, ">"); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
|
|
return sum; |
|
} |
|
|
|
/** |
|
* xmlTextWriterFlush: |
|
* @writer: the xmlTextWriterPtr |
|
* |
|
* Flush the output buffer. |
|
* |
|
* Returns the bytes written (may be 0 because of buffering) or -1 in case of error |
|
*/ |
|
int |
|
xmlTextWriterFlush(xmlTextWriterPtr writer) |
|
{ |
|
int count; |
|
|
|
if (writer == NULL) |
|
return -1; |
|
|
|
if (writer->out == NULL) |
|
count = 0; |
|
else |
|
count = xmlOutputBufferFlush(writer->out); |
|
|
|
return count; |
|
} |
|
|
|
/** |
|
* misc |
|
*/ |
|
|
|
/** |
|
* xmlFreeTextWriterStackEntry: |
|
* @lk: the xmlLinkPtr |
|
* |
|
* Free callback for the xmlList. |
|
*/ |
|
static void |
|
xmlFreeTextWriterStackEntry(xmlLinkPtr lk) |
|
{ |
|
xmlTextWriterStackEntry *p; |
|
|
|
p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); |
|
if (p == 0) |
|
return; |
|
|
|
if (p->name != 0) |
|
xmlFree(p->name); |
|
xmlFree(p); |
|
} |
|
|
|
/** |
|
* xmlCmpTextWriterStackEntry: |
|
* @data0: the first data |
|
* @data1: the second data |
|
* |
|
* Compare callback for the xmlList. |
|
* |
|
* Returns -1, 0, 1 |
|
*/ |
|
static int |
|
xmlCmpTextWriterStackEntry(const void *data0, const void *data1) |
|
{ |
|
xmlTextWriterStackEntry *p0; |
|
xmlTextWriterStackEntry *p1; |
|
|
|
if (data0 == data1) |
|
return 0; |
|
|
|
if (data0 == 0) |
|
return -1; |
|
|
|
if (data1 == 0) |
|
return 1; |
|
|
|
p0 = (xmlTextWriterStackEntry *) data0; |
|
p1 = (xmlTextWriterStackEntry *) data1; |
|
|
|
return xmlStrcmp(p0->name, p1->name); |
|
} |
|
|
|
/** |
|
* misc |
|
*/ |
|
|
|
/** |
|
* xmlTextWriterOutputNSDecl: |
|
* @writer: the xmlTextWriterPtr |
|
* |
|
* Output the current namespace declarations. |
|
*/ |
|
static int |
|
xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer) |
|
{ |
|
xmlLinkPtr lk; |
|
xmlTextWriterNsStackEntry *np; |
|
int count; |
|
int sum; |
|
|
|
sum = 0; |
|
while (!xmlListEmpty(writer->nsstack)) { |
|
xmlChar *namespaceURI = NULL; |
|
xmlChar *prefix = NULL; |
|
|
|
lk = xmlListFront(writer->nsstack); |
|
np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk); |
|
|
|
if (np != 0) { |
|
namespaceURI = xmlStrdup(np->uri); |
|
prefix = xmlStrdup(np->prefix); |
|
} |
|
|
|
xmlListPopFront(writer->nsstack); |
|
|
|
if (np != 0) { |
|
count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI); |
|
xmlFree(namespaceURI); |
|
xmlFree(prefix); |
|
|
|
if (count < 0) { |
|
xmlListDelete(writer->nsstack); |
|
writer->nsstack = NULL; |
|
return -1; |
|
} |
|
sum += count; |
|
} |
|
} |
|
return sum; |
|
} |
|
|
|
/** |
|
* xmlFreeTextWriterNsStackEntry: |
|
* @lk: the xmlLinkPtr |
|
* |
|
* Free callback for the xmlList. |
|
*/ |
|
static void |
|
xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk) |
|
{ |
|
xmlTextWriterNsStackEntry *p; |
|
|
|
p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk); |
|
if (p == 0) |
|
return; |
|
|
|
if (p->prefix != 0) |
|
xmlFree(p->prefix); |
|
if (p->uri != 0) |
|
xmlFree(p->uri); |
|
|
|
xmlFree(p); |
|
} |
|
|
|
/** |
|
* xmlCmpTextWriterNsStackEntry: |
|
* @data0: the first data |
|
* @data1: the second data |
|
* |
|
* Compare callback for the xmlList. |
|
* |
|
* Returns -1, 0, 1 |
|
*/ |
|
static int |
|
xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1) |
|
{ |
|
xmlTextWriterNsStackEntry *p0; |
|
xmlTextWriterNsStackEntry *p1; |
|
int rc; |
|
|
|
if (data0 == data1) |
|
return 0; |
|
|
|
if (data0 == 0) |
|
return -1; |
|
|
|
if (data1 == 0) |
|
return 1; |
|
|
|
p0 = (xmlTextWriterNsStackEntry *) data0; |
|
p1 = (xmlTextWriterNsStackEntry *) data1; |
|
|
|
rc = xmlStrcmp(p0->prefix, p1->prefix); |
|
|
|
if ((rc != 0) || (p0->elem != p1->elem)) |
|
rc = -1; |
|
|
|
return rc; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteDocCallback: |
|
* @context: the xmlBufferPtr |
|
* @str: the data to write |
|
* @len: the length of the data |
|
* |
|
* Write callback for the xmlOutputBuffer with target xmlBuffer |
|
* |
|
* Returns -1, 0, 1 |
|
*/ |
|
static int |
|
xmlTextWriterWriteDocCallback(void *context, const char *str, int len) |
|
{ |
|
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context; |
|
int rc; |
|
|
|
if ((rc = xmlParseChunk(ctxt, str, len, 0)) != 0) { |
|
xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR, |
|
"xmlTextWriterWriteDocCallback : XML error %d !\n", |
|
rc); |
|
return -1; |
|
} |
|
|
|
return len; |
|
} |
|
|
|
/** |
|
* xmlTextWriterCloseDocCallback: |
|
* @context: the xmlBufferPtr |
|
* |
|
* Close callback for the xmlOutputBuffer with target xmlBuffer |
|
* |
|
* Returns -1, 0, 1 |
|
*/ |
|
static int |
|
xmlTextWriterCloseDocCallback(void *context) |
|
{ |
|
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context; |
|
int rc; |
|
|
|
if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) { |
|
xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR, |
|
"xmlTextWriterCloseDocCallback : XML error %d !\n", |
|
rc); |
|
return -1; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
/** |
|
* xmlTextWriterVSprintf: |
|
* @format: see printf |
|
* @argptr: pointer to the first member of the variable argument list. |
|
* |
|
* Utility function for formatted output |
|
* |
|
* Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed. |
|
*/ |
|
static xmlChar * |
|
xmlTextWriterVSprintf(const char *format, va_list argptr) |
|
{ |
|
int size; |
|
int count; |
|
xmlChar *buf; |
|
va_list locarg; |
|
|
|
size = BUFSIZ; |
|
buf = (xmlChar *) xmlMalloc(size); |
|
if (buf == NULL) { |
|
xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, |
|
"xmlTextWriterVSprintf : out of memory!\n"); |
|
return NULL; |
|
} |
|
|
|
VA_COPY(locarg, argptr); |
|
while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0) |
|
|| (count == size - 1) || (count == size) || (count > size)) { |
|
va_end(locarg); |
|
xmlFree(buf); |
|
size += BUFSIZ; |
|
buf = (xmlChar *) xmlMalloc(size); |
|
if (buf == NULL) { |
|
xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, |
|
"xmlTextWriterVSprintf : out of memory!\n"); |
|
return NULL; |
|
} |
|
VA_COPY(locarg, argptr); |
|
} |
|
va_end(locarg); |
|
|
|
return buf; |
|
} |
|
|
|
/** |
|
* xmlTextWriterStartDocumentCallback: |
|
* @ctx: the user data (XML parser context) |
|
* |
|
* called at the start of document processing. |
|
*/ |
|
static void |
|
xmlTextWriterStartDocumentCallback(void *ctx) |
|
{ |
|
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
xmlDocPtr doc; |
|
|
|
if (ctxt->html) { |
|
#ifdef LIBXML_HTML_ENABLED |
|
if (ctxt->myDoc == NULL) |
|
ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL); |
|
if (ctxt->myDoc == NULL) { |
|
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
ctxt->sax->error(ctxt->userData, |
|
"SAX.startDocument(): out of memory\n"); |
|
ctxt->errNo = XML_ERR_NO_MEMORY; |
|
ctxt->instate = XML_PARSER_EOF; |
|
ctxt->disableSAX = 1; |
|
return; |
|
} |
|
#else |
|
xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, |
|
"libxml2 built without HTML support\n"); |
|
ctxt->errNo = XML_ERR_INTERNAL_ERROR; |
|
ctxt->instate = XML_PARSER_EOF; |
|
ctxt->disableSAX = 1; |
|
return; |
|
#endif |
|
} else { |
|
doc = ctxt->myDoc; |
|
if (doc == NULL) |
|
doc = ctxt->myDoc = xmlNewDoc(ctxt->version); |
|
if (doc != NULL) { |
|
if (doc->children == NULL) { |
|
if (ctxt->encoding != NULL) |
|
doc->encoding = xmlStrdup(ctxt->encoding); |
|
else |
|
doc->encoding = NULL; |
|
doc->standalone = ctxt->standalone; |
|
} |
|
} else { |
|
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
ctxt->sax->error(ctxt->userData, |
|
"SAX.startDocument(): out of memory\n"); |
|
ctxt->errNo = XML_ERR_NO_MEMORY; |
|
ctxt->instate = XML_PARSER_EOF; |
|
ctxt->disableSAX = 1; |
|
return; |
|
} |
|
} |
|
if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) && |
|
(ctxt->input != NULL) && (ctxt->input->filename != NULL)) { |
|
ctxt->myDoc->URL = |
|
xmlCanonicPath((const xmlChar *) ctxt->input->filename); |
|
if (ctxt->myDoc->URL == NULL) |
|
ctxt->myDoc->URL = |
|
xmlStrdup((const xmlChar *) ctxt->input->filename); |
|
} |
|
} |
|
|
|
/** |
|
* xmlTextWriterSetIndent: |
|
* @writer: the xmlTextWriterPtr |
|
* @indent: do indentation? |
|
* |
|
* Set indentation output. indent = 0 do not indentation. indent > 0 do indentation. |
|
* |
|
* Returns -1 on error or 0 otherwise. |
|
*/ |
|
int |
|
xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent) |
|
{ |
|
if ((writer == NULL) || (indent < 0)) |
|
return -1; |
|
|
|
writer->indent = indent; |
|
writer->doindent = 1; |
|
|
|
return 0; |
|
} |
|
|
|
/** |
|
* xmlTextWriterSetIndentString: |
|
* @writer: the xmlTextWriterPtr |
|
* @str: the xmlChar string |
|
* |
|
* Set string indentation. |
|
* |
|
* Returns -1 on error or 0 otherwise. |
|
*/ |
|
int |
|
xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str) |
|
{ |
|
if ((writer == NULL) || (!str)) |
|
return -1; |
|
|
|
if (writer->ichar != NULL) |
|
xmlFree(writer->ichar); |
|
writer->ichar = xmlStrdup(str); |
|
|
|
if (!writer->ichar) |
|
return -1; |
|
else |
|
return 0; |
|
} |
|
|
|
/** |
|
* xmlTextWriterSetQuoteChar: |
|
* @writer: the xmlTextWriterPtr |
|
* @quotechar: the quote character |
|
* |
|
* Set the character used for quoting attributes. |
|
* |
|
* Returns -1 on error or 0 otherwise. |
|
*/ |
|
int |
|
xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar) |
|
{ |
|
if ((writer == NULL) || ((quotechar != '\'') && (quotechar != '"'))) |
|
return -1; |
|
|
|
writer->qchar = quotechar; |
|
|
|
return 0; |
|
} |
|
|
|
/** |
|
* xmlTextWriterWriteIndent: |
|
* @writer: the xmlTextWriterPtr |
|
* |
|
* Write indent string. |
|
* |
|
* Returns -1 on error or the number of strings written. |
|
*/ |
|
static int |
|
xmlTextWriterWriteIndent(xmlTextWriterPtr writer) |
|
{ |
|
int lksize; |
|
int i; |
|
int ret; |
|
|
|
lksize = xmlListSize(writer->nodes); |
|
if (lksize < 1) |
|
return (-1); /* list is empty */ |
|
for (i = 0; i < (lksize - 1); i++) { |
|
ret = xmlOutputBufferWriteString(writer->out, |
|
(const char *) writer->ichar); |
|
if (ret == -1) |
|
return (-1); |
|
} |
|
|
|
return (lksize - 1); |
|
} |
|
|
|
/** |
|
* xmlTextWriterHandleStateDependencies: |
|
* @writer: the xmlTextWriterPtr |
|
* @p: the xmlTextWriterStackEntry |
|
* |
|
* Write state dependent strings. |
|
* |
|
* Returns -1 on error or the number of characters written. |
|
*/ |
|
static int |
|
xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer, |
|
xmlTextWriterStackEntry * p) |
|
{ |
|
int count; |
|
int sum; |
|
char extra[3]; |
|
|
|
if (writer == NULL) |
|
return -1; |
|
|
|
if (p == NULL) |
|
return 0; |
|
|
|
sum = 0; |
|
extra[0] = extra[1] = extra[2] = '\0'; |
|
if (p != 0) { |
|
sum = 0; |
|
switch (p->state) { |
|
case XML_TEXTWRITER_NAME: |
|
/* Output namespace declarations */ |
|
count = xmlTextWriterOutputNSDecl(writer); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
extra[0] = '>'; |
|
p->state = XML_TEXTWRITER_TEXT; |
|
break; |
|
case XML_TEXTWRITER_PI: |
|
extra[0] = ' '; |
|
p->state = XML_TEXTWRITER_PI_TEXT; |
|
break; |
|
case XML_TEXTWRITER_DTD: |
|
extra[0] = ' '; |
|
extra[1] = '['; |
|
p->state = XML_TEXTWRITER_DTD_TEXT; |
|
break; |
|
case XML_TEXTWRITER_DTD_ELEM: |
|
extra[0] = ' '; |
|
p->state = XML_TEXTWRITER_DTD_ELEM_TEXT; |
|
break; |
|
case XML_TEXTWRITER_DTD_ATTL: |
|
extra[0] = ' '; |
|
p->state = XML_TEXTWRITER_DTD_ATTL_TEXT; |
|
break; |
|
case XML_TEXTWRITER_DTD_ENTY: |
|
case XML_TEXTWRITER_DTD_PENT: |
|
extra[0] = ' '; |
|
extra[1] = writer->qchar; |
|
p->state = XML_TEXTWRITER_DTD_ENTY_TEXT; |
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
|
|
if (*extra != '\0') { |
|
count = xmlOutputBufferWriteString(writer->out, extra); |
|
if (count < 0) |
|
return -1; |
|
sum += count; |
|
} |
|
|
|
return sum; |
|
} |
|
|
|
#define bottom_xmlwriter |
|
#include "elfgcchack.h" |
|
#endif
|
|
|