Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / gnulib-local / lib / libxml / xmlwriter.c
index 5821056..fac20ac 100644 (file)
@@ -10,7 +10,6 @@
 
 #define IN_LIBXML
 #include "libxml.h"
-
 #include <string.h>
 
 #include <libxml/xmlmemory.h>
 
 #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 (i.e. it may need
- * something involving a memcpy) but (hopefully) will be
- * sufficient for libxml2.
+ * esoteric implementations of va_list but (hopefully) will
+ * be sufficient for libxml2.
  */
 #ifndef VA_COPY
   #ifdef HAVE_VA_COPY
     #ifdef HAVE___VA_COPY
       #define VA_COPY(dest,src) __va_copy(dest, src)
     #else
-      #define VA_COPY(dest,src) (dest) = (src)
+      #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
@@ -98,6 +105,7 @@ struct _xmlTextWriter {
 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);
@@ -129,10 +137,10 @@ xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,
     if (ctxt != NULL) {
        __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
                    NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
-                   NULL, 0, NULL, NULL, NULL, 0, 0, msg);
+                   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, msg);
+                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
     }
 }
 
@@ -242,8 +250,8 @@ xmlNewTextWriterFilename(const char *uri, int compression)
 
     out = xmlOutputBufferCreateFilename(uri, NULL, compression);
     if (out == NULL) {
-        xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
-                        "xmlNewTextWriterFilename : out of memory!\n");
+        xmlWriterErrMsg(NULL, XML_IO_EIO,
+                        "xmlNewTextWriterFilename : cannot open uri\n");
         return NULL;
     }
 
@@ -370,7 +378,7 @@ xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
     ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
     if (ctxt == NULL) {
         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
-                        "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
+                "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
         return NULL;
     }
     /*
@@ -389,8 +397,10 @@ xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
 
     ret = xmlNewTextWriterPushParser(ctxt, compression);
     if (ret == NULL) {
+        xmlFreeDoc(ctxt->myDoc);
+        xmlFreeParserCtxt(ctxt);
         xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
-                        "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
+                "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
         return NULL;
     }
 
@@ -545,8 +555,10 @@ xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
 
     writer->out->encoder = encoder;
     if (encoder != NULL) {
-        writer->out->conv = xmlBufferCreateSize(4000);
-        xmlCharEncOutFunc(encoder, writer->out->conv, 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
@@ -624,9 +636,10 @@ xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
  * xmlTextWriterEndDocument:
  * @writer:  the xmlTextWriterPtr
  *
- * End an xml document. All open elements are closed
+ * End an xml document. All open elements are closed, and
+ * the content is flushed to the output.
  *
- * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
+ * Returns the bytes written or -1 in case of error
  */
 int
 xmlTextWriterEndDocument(xmlTextWriterPtr writer)
@@ -700,6 +713,9 @@ xmlTextWriterEndDocument(xmlTextWriterPtr writer)
             return -1;
         sum += count;
     }
+
+    sum += xmlTextWriterFlush(writer);
+
     return sum;
 }
 
@@ -735,6 +751,11 @@ xmlTextWriterStartComment(xmlTextWriterPtr writer)
                 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;
@@ -887,8 +908,8 @@ xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
     }
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteComment(writer, buf);
 
@@ -966,6 +987,11 @@ xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
                                        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;
@@ -1056,17 +1082,31 @@ xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
     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);
         }
 
-        count = xmlTextWriterWriteAttribute(writer, buf, namespaceURI);
-        xmlFree(buf);
-        if (count < 0)
+        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;
-        sum += count;
+        }
+        p->elem = xmlListFront(writer->nodes);
+
+        xmlListPushFront(writer->nsstack, p);
     }
 
     return sum;
@@ -1092,22 +1132,37 @@ xmlTextWriterEndElement(xmlTextWriterPtr writer)
         return -1;
 
     lk = xmlListFront(writer->nodes);
-    if (lk == 0)
+    if (lk == 0) {
+        xmlListDelete(writer->nsstack);
+        writer->nsstack = NULL;
         return -1;
+    }
 
     p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
-    if (p == 0)
+    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)
+            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, "/>");
@@ -1185,12 +1240,26 @@ xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
             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;
@@ -1209,6 +1278,11 @@ xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
             return -1;
     }
 
+    if (writer->indent) {
+        count = xmlOutputBufferWriteString(writer->out, "\n");
+        sum += count;
+    }
+
     xmlListPopFront(writer->nodes);
     return sum;
 }
@@ -1259,8 +1333,8 @@ xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteRaw(writer, buf);
 
@@ -1388,8 +1462,8 @@ xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteString(writer, buf);
 
@@ -1435,8 +1509,8 @@ xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
                     break;
                 case XML_TEXTWRITER_ATTRIBUTE:
                     buf = NULL;
-                    xmlAttrSerializeTxtContent(writer->out->buffer, writer->doc,
-                                               NULL, content);
+                    xmlBufAttrSerializeTxtContent(writer->out->buffer,
+                                                  writer->doc, NULL, content);
                     break;
                default:
                    break;
@@ -1446,12 +1520,13 @@ xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
 
     if (buf != NULL) {
         count = xmlTextWriterWriteRaw(writer, buf);
-        if (count < 0)
-            return -1;
-        sum += count;
 
         if (buf != content)     /* buf was allocated by us, so free it */
             xmlFree(buf);
+
+        if (count < 0)
+            return -1;
+        sum += count;
     }
 
     return sum;
@@ -1596,7 +1671,7 @@ xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
  * Write hqx encoded data to an xmlOutputBuffer.
  * ::todo
  *
- * Returns the bytes written (may be 0 because of buffering) 
+ * Returns the bytes written (may be 0 because of buffering)
  * or -1 in case of error
  */
 static int
@@ -1605,8 +1680,8 @@ xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
 {
     int count;
     int sum;
-    static char hex[16] = 
-       {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+    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)) {
@@ -1768,6 +1843,57 @@ xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
     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);
@@ -1782,34 +1908,6 @@ xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
         return -1;
     sum += count;
 
-    if (namespaceURI != 0) {
-        buf = xmlStrdup(BAD_CAST "xmlns");
-        if (prefix != 0) {
-            buf = xmlStrcat(buf, BAD_CAST ":");
-            buf = xmlStrcat(buf, prefix);
-        }
-
-        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);
-    }
-
     return sum;
 }
 
@@ -1828,22 +1926,17 @@ xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
     int sum;
     xmlLinkPtr lk;
     xmlTextWriterStackEntry *p;
-    xmlTextWriterNsStackEntry *np;
 
     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;
     }
 
@@ -1854,45 +1947,11 @@ xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
 
             count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
             if (count < 0) {
-                xmlListDelete(writer->nsstack);
-               writer->nsstack = NULL;
                 return -1;
             }
             sum += count;
-
-            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;
-                }
-            }
             break;
-
         default:
-            xmlListClear(writer->nsstack);
             return -1;
     }
 
@@ -1949,8 +2008,8 @@ xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteAttribute(writer, name, buf);
 
@@ -2051,8 +2110,8 @@ xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
                                        buf);
@@ -2081,38 +2140,24 @@ xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
 {
     int count;
     int sum;
-    xmlChar *buf;
 
     if ((writer == NULL) || (name == NULL) || (*name == '\0'))
         return -1;
 
-    buf = NULL;
-    if (prefix != NULL) {
-        buf = xmlStrdup(prefix);
-        buf = xmlStrcat(buf, BAD_CAST ":");
-    }
-    buf = xmlStrcat(buf, name);
-
     sum = 0;
-    count = xmlTextWriterWriteAttribute(writer, buf, content);
-    xmlFree(buf);
+    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;
 
-    if (namespaceURI != NULL) {
-        buf = NULL;
-        buf = xmlStrdup(BAD_CAST "xmlns");
-        if (prefix != NULL) {
-            buf = xmlStrcat(buf, BAD_CAST ":");
-            buf = xmlStrcat(buf, prefix);
-        }
-        count = xmlTextWriterWriteAttribute(writer, buf, namespaceURI);
-        xmlFree(buf);
-        if (count < 0)
-            return -1;
-        sum += count;
-    }
     return sum;
 }
 
@@ -2166,8 +2211,8 @@ xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteElement(writer, name, buf);
 
@@ -2197,10 +2242,12 @@ xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
     if (count == -1)
         return -1;
     sum += count;
-    count = xmlTextWriterWriteString(writer, content);
-    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;
@@ -2268,8 +2315,8 @@ xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
                                      buf);
@@ -2359,6 +2406,11 @@ xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
                     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;
@@ -2454,8 +2506,8 @@ xmlTextWriterEndPI(xmlTextWriterPtr writer)
 
     if (writer->indent) {
         count = xmlOutputBufferWriteString(writer->out, "\n");
-       if (count < 0)
-               return -1;
+       if (count < 0)
+       return -1;
         sum += count;
     }
 
@@ -2512,8 +2564,8 @@ xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWritePI(writer, target, buf);
 
@@ -2583,6 +2635,7 @@ xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
         if (p != 0) {
             switch (p->state) {
                 case XML_TEXTWRITER_NONE:
+               case XML_TEXTWRITER_TEXT:
                 case XML_TEXTWRITER_PI:
                 case XML_TEXTWRITER_PI_TEXT:
                     break;
@@ -2593,6 +2646,11 @@ xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
                     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;
@@ -2719,8 +2777,8 @@ xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteCDATA(writer, buf);
 
@@ -3037,8 +3095,8 @@ xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
 
@@ -3275,8 +3333,8 @@ xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteDTDElement(writer, name, buf);
 
@@ -3512,8 +3570,8 @@ xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
 
@@ -3774,8 +3832,8 @@ xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
         return -1;
 
     buf = xmlTextWriterVSprintf(format, argptr);
-    if (buf == 0)
-        return 0;
+    if (buf == NULL)
+        return -1;
 
     rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
 
@@ -4249,6 +4307,51 @@ xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
  */
 
 /**
+ * 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
  *
@@ -4301,8 +4404,8 @@ xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
 
     rc = xmlStrcmp(p0->prefix, p1->prefix);
 
-    if (rc == 0)
-        rc = p0->elem == p1->elem;
+    if ((rc != 0) || (p0->elem != p1->elem))
+        rc = -1;
 
     return rc;
 }
@@ -4513,6 +4616,26 @@ xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
 }
 
 /**
+ * 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
  *
@@ -4569,6 +4692,11 @@ xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
         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;