/ libxml2 / xmlwriter.c
xmlwriter.c
   1  
   2  /*
   3   * xmlwriter.c: XML text writer implementation
   4   *
   5   * For license and disclaimer see the license and disclaimer of
   6   * libxml2.
   7   *
   8   * alfred@mickautsch.de
   9   */
  10  
  11  #define IN_LIBXML
  12  #include "libxml.h"
  13  #include <string.h>
  14  
  15  #include <libxml/xmlmemory.h>
  16  #include <libxml/parser.h>
  17  #include <libxml/uri.h>
  18  #include <libxml/HTMLtree.h>
  19  
  20  #ifdef LIBXML_WRITER_ENABLED
  21  
  22  #include <libxml/xmlwriter.h>
  23  
  24  #include "buf.h"
  25  #include "enc.h"
  26  #include "save.h"
  27  
  28  #define B64LINELEN 72
  29  #define B64CRLF "\r\n"
  30  
  31  /*
  32   * The following VA_COPY was coded following an example in
  33   * the Samba project.  It may not be sufficient for some
  34   * esoteric implementations of va_list but (hopefully) will
  35   * be sufficient for libxml2.
  36   */
  37  #ifndef VA_COPY
  38    #ifdef HAVE_VA_COPY
  39      #define VA_COPY(dest, src) va_copy(dest, src)
  40    #else
  41      #ifdef HAVE___VA_COPY
  42        #define VA_COPY(dest,src) __va_copy(dest, src)
  43      #else
  44        #ifndef VA_LIST_IS_ARRAY
  45          #define VA_COPY(dest,src) (dest) = (src)
  46        #else
  47          #include <string.h>
  48          #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
  49        #endif
  50      #endif
  51    #endif
  52  #endif
  53  
  54  /*
  55   * Types are kept private
  56   */
  57  typedef enum {
  58      XML_TEXTWRITER_NONE = 0,
  59      XML_TEXTWRITER_NAME,
  60      XML_TEXTWRITER_ATTRIBUTE,
  61      XML_TEXTWRITER_TEXT,
  62      XML_TEXTWRITER_PI,
  63      XML_TEXTWRITER_PI_TEXT,
  64      XML_TEXTWRITER_CDATA,
  65      XML_TEXTWRITER_DTD,
  66      XML_TEXTWRITER_DTD_TEXT,
  67      XML_TEXTWRITER_DTD_ELEM,
  68      XML_TEXTWRITER_DTD_ELEM_TEXT,
  69      XML_TEXTWRITER_DTD_ATTL,
  70      XML_TEXTWRITER_DTD_ATTL_TEXT,
  71      XML_TEXTWRITER_DTD_ENTY,    /* entity */
  72      XML_TEXTWRITER_DTD_ENTY_TEXT,
  73      XML_TEXTWRITER_DTD_PENT,    /* parameter entity */
  74      XML_TEXTWRITER_COMMENT
  75  } xmlTextWriterState;
  76  
  77  typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry;
  78  
  79  struct _xmlTextWriterStackEntry {
  80      xmlChar *name;
  81      xmlTextWriterState state;
  82  };
  83  
  84  typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry;
  85  struct _xmlTextWriterNsStackEntry {
  86      xmlChar *prefix;
  87      xmlChar *uri;
  88      xmlLinkPtr elem;
  89  };
  90  
  91  struct _xmlTextWriter {
  92      xmlOutputBufferPtr out;     /* output buffer */
  93      xmlListPtr nodes;           /* element name stack */
  94      xmlListPtr nsstack;         /* name spaces stack */
  95      int level;
  96      int indent;                 /* enable indent */
  97      int doindent;               /* internal indent flag */
  98      xmlChar *ichar;             /* indent character */
  99      char qchar;                 /* character used for quoting attribute values */
 100      xmlParserCtxtPtr ctxt;
 101      int no_doc_free;
 102      xmlDocPtr doc;
 103  };
 104  
 105  static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk);
 106  static int xmlCmpTextWriterStackEntry(const void *data0,
 107                                        const void *data1);
 108  static int xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer);
 109  static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk);
 110  static int xmlCmpTextWriterNsStackEntry(const void *data0,
 111                                          const void *data1);
 112  static int xmlTextWriterWriteDocCallback(void *context,
 113                                           const xmlChar * str, int len);
 114  static int xmlTextWriterCloseDocCallback(void *context);
 115  
 116  static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr) LIBXML_ATTR_FORMAT(1,0);
 117  static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
 118                                        const unsigned char *data);
 119  static void xmlTextWriterStartDocumentCallback(void *ctx);
 120  static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer);
 121  static int
 122    xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
 123                                         xmlTextWriterStackEntry * p);
 124  
 125  /**
 126   * xmlWriterErrMsg:
 127   * @ctxt:  a writer context
 128   * @error:  the error number
 129   * @msg:  the error message
 130   *
 131   * Handle a writer error
 132   */
 133  static void
 134  xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error,
 135                 const char *msg)
 136  {
 137      if (ctxt != NULL) {
 138  	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
 139  	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
 140  		    NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
 141      } else {
 142  	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
 143                      XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
 144      }
 145  }
 146  
 147  /**
 148   * xmlWriterErrMsgInt:
 149   * @ctxt:  a writer context
 150   * @error:  the error number
 151   * @msg:  the error message
 152   * @val:  an int
 153   *
 154   * Handle a writer error
 155   */
 156  static void LIBXML_ATTR_FORMAT(3,0)
 157  xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,
 158                 const char *msg, int val)
 159  {
 160      if (ctxt != NULL) {
 161  #pragma clang diagnostic push
 162  #pragma clang diagnostic ignored "-Wformat-nonliteral"
 163  	__xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt,
 164  	            NULL, XML_FROM_WRITER, error, XML_ERR_FATAL,
 165  		    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
 166  #pragma clang diagnostic pop
 167      } else {
 168  #pragma clang diagnostic push
 169  #pragma clang diagnostic ignored "-Wformat-nonliteral"
 170  	__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error,
 171                      XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
 172  #pragma clang diagnostic pop
 173      }
 174  }
 175  
 176  /**
 177   * xmlNewTextWriter:
 178   * @out:  an xmlOutputBufferPtr
 179   *
 180   * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr
 181   * NOTE: the @out parameter will be deallocated when the writer is closed
 182   *       (if the call succeed.)
 183   *
 184   * Returns the new xmlTextWriterPtr or NULL in case of error
 185   */
 186  xmlTextWriterPtr
 187  xmlNewTextWriter(xmlOutputBufferPtr out)
 188  {
 189      xmlTextWriterPtr ret;
 190  
 191      ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter));
 192      if (ret == NULL) {
 193          xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
 194                          "xmlNewTextWriter : out of memory!\n");
 195          return NULL;
 196      }
 197      memset(ret, 0, (size_t) sizeof(xmlTextWriter));
 198  
 199      ret->nodes = xmlListCreate((xmlListDeallocator)
 200                                 xmlFreeTextWriterStackEntry,
 201                                 (xmlListDataCompare)
 202                                 xmlCmpTextWriterStackEntry);
 203      if (ret->nodes == NULL) {
 204          xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
 205                          "xmlNewTextWriter : out of memory!\n");
 206          xmlFree(ret);
 207          return NULL;
 208      }
 209  
 210      ret->nsstack = xmlListCreate((xmlListDeallocator)
 211                                   xmlFreeTextWriterNsStackEntry,
 212                                   (xmlListDataCompare)
 213                                   xmlCmpTextWriterNsStackEntry);
 214      if (ret->nsstack == NULL) {
 215          xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
 216                          "xmlNewTextWriter : out of memory!\n");
 217          xmlListDelete(ret->nodes);
 218          xmlFree(ret);
 219          return NULL;
 220      }
 221  
 222      ret->out = out;
 223      ret->ichar = xmlStrdup(BAD_CAST " ");
 224      ret->qchar = '"';
 225  
 226      if (!ret->ichar) {
 227          xmlListDelete(ret->nodes);
 228          xmlListDelete(ret->nsstack);
 229          xmlFree(ret);
 230          xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
 231                          "xmlNewTextWriter : out of memory!\n");
 232          return NULL;
 233      }
 234  
 235      ret->doc = xmlNewDoc(NULL);
 236  
 237      ret->no_doc_free = 0;
 238  
 239      return ret;
 240  }
 241  
 242  /**
 243   * xmlNewTextWriterFilename:
 244   * @uri:  the URI of the resource for the output
 245   * @compression:  compress the output?
 246   *
 247   * Create a new xmlNewTextWriter structure with @uri as output
 248   *
 249   * Returns the new xmlTextWriterPtr or NULL in case of error
 250   */
 251  xmlTextWriterPtr
 252  xmlNewTextWriterFilename(const char *uri, int compression)
 253  {
 254      xmlTextWriterPtr ret;
 255      xmlOutputBufferPtr out;
 256  
 257      out = xmlOutputBufferCreateFilename(uri, NULL, compression);
 258      if (out == NULL) {
 259          xmlWriterErrMsg(NULL, XML_IO_EIO,
 260                          "xmlNewTextWriterFilename : cannot open uri\n");
 261          return NULL;
 262      }
 263  
 264      ret = xmlNewTextWriter(out);
 265      if (ret == NULL) {
 266          xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
 267                          "xmlNewTextWriterFilename : out of memory!\n");
 268          xmlOutputBufferClose(out);
 269          return NULL;
 270      }
 271  
 272      ret->indent = 0;
 273      ret->doindent = 0;
 274      return ret;
 275  }
 276  
 277  /**
 278   * xmlNewTextWriterMemory:
 279   * @buf:  xmlBufferPtr
 280   * @compression:  compress the output?
 281   *
 282   * Create a new xmlNewTextWriter structure with @buf as output
 283   * TODO: handle compression
 284   *
 285   * Returns the new xmlTextWriterPtr or NULL in case of error
 286   */
 287  xmlTextWriterPtr
 288  xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED)
 289  {
 290      xmlTextWriterPtr ret;
 291      xmlOutputBufferPtr out;
 292  
 293  /*::todo handle compression */
 294      out = xmlOutputBufferCreateBuffer(buf, NULL);
 295  
 296      if (out == NULL) {
 297          xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
 298                          "xmlNewTextWriterMemory : out of memory!\n");
 299          return NULL;
 300      }
 301  
 302      ret = xmlNewTextWriter(out);
 303      if (ret == NULL) {
 304          xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
 305                          "xmlNewTextWriterMemory : out of memory!\n");
 306          xmlOutputBufferClose(out);
 307          return NULL;
 308      }
 309  
 310      return ret;
 311  }
 312  
 313  /**
 314   * xmlNewTextWriterPushParser:
 315   * @ctxt: xmlParserCtxtPtr to hold the new XML document tree
 316   * @compression:  compress the output?
 317   *
 318   * Create a new xmlNewTextWriter structure with @ctxt as output
 319   * NOTE: the @ctxt context will be freed with the resulting writer
 320   *       (if the call succeeds).
 321   * TODO: handle compression
 322   *
 323   * Returns the new xmlTextWriterPtr or NULL in case of error
 324   */
 325  xmlTextWriterPtr
 326  xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt,
 327                             int compression ATTRIBUTE_UNUSED)
 328  {
 329      xmlTextWriterPtr ret;
 330      xmlOutputBufferPtr out;
 331  
 332      if (ctxt == NULL) {
 333          xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
 334                          "xmlNewTextWriterPushParser : invalid context!\n");
 335          return NULL;
 336      }
 337  
 338      out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
 339                                    xmlTextWriterWriteDocCallback,
 340                                    (xmlOutputCloseCallback)
 341                                    xmlTextWriterCloseDocCallback,
 342                                    (void *) ctxt, NULL);
 343      if (out == NULL) {
 344          xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
 345                          "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n");
 346          return NULL;
 347      }
 348  
 349      ret = xmlNewTextWriter(out);
 350      if (ret == NULL) {
 351          xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
 352                          "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n");
 353          xmlOutputBufferClose(out);
 354          return NULL;
 355      }
 356  
 357      ret->ctxt = ctxt;
 358  
 359      return ret;
 360  }
 361  
 362  /**
 363   * xmlNewTextWriterDoc:
 364   * @doc: address of a xmlDocPtr to hold the new XML document tree
 365   * @compression:  compress the output?
 366   *
 367   * Create a new xmlNewTextWriter structure with @*doc as output
 368   *
 369   * Returns the new xmlTextWriterPtr or NULL in case of error
 370   */
 371  xmlTextWriterPtr
 372  xmlNewTextWriterDoc(xmlDocPtr * doc, int compression)
 373  {
 374      xmlTextWriterPtr ret;
 375      xmlSAXHandler saxHandler;
 376      xmlParserCtxtPtr ctxt;
 377  
 378      memset(&saxHandler, '\0', sizeof(saxHandler));
 379      xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
 380      saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
 381      saxHandler.startElement = xmlSAX2StartElement;
 382      saxHandler.endElement = xmlSAX2EndElement;
 383  
 384      ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
 385      if (ctxt == NULL) {
 386          xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
 387                  "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
 388          return NULL;
 389      }
 390      /*
 391       * For some reason this seems to completely break if node names
 392       * are interned.
 393       */
 394      ctxt->dictNames = 0;
 395  
 396      ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
 397      if (ctxt->myDoc == NULL) {
 398          xmlFreeParserCtxt(ctxt);
 399          xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
 400                          "xmlNewTextWriterDoc : error at xmlNewDoc!\n");
 401          return NULL;
 402      }
 403  
 404      ret = xmlNewTextWriterPushParser(ctxt, compression);
 405      if (ret == NULL) {
 406          xmlFreeDoc(ctxt->myDoc);
 407          xmlFreeParserCtxt(ctxt);
 408          xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
 409                  "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
 410          return NULL;
 411      }
 412  
 413      xmlSetDocCompressMode(ctxt->myDoc, compression);
 414  
 415      if (doc != NULL) {
 416          *doc = ctxt->myDoc;
 417  	ret->no_doc_free = 1;
 418      }
 419  
 420      return ret;
 421  }
 422  
 423  /**
 424   * xmlNewTextWriterTree:
 425   * @doc: xmlDocPtr
 426   * @node: xmlNodePtr or NULL for doc->children
 427   * @compression:  compress the output?
 428   *
 429   * Create a new xmlNewTextWriter structure with @doc as output
 430   * starting at @node
 431   *
 432   * Returns the new xmlTextWriterPtr or NULL in case of error
 433   */
 434  xmlTextWriterPtr
 435  xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression)
 436  {
 437      xmlTextWriterPtr ret;
 438      xmlSAXHandler saxHandler;
 439      xmlParserCtxtPtr ctxt;
 440  
 441      if (doc == NULL) {
 442          xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
 443                          "xmlNewTextWriterTree : invalid document tree!\n");
 444          return NULL;
 445      }
 446  
 447      memset(&saxHandler, '\0', sizeof(saxHandler));
 448      xmlSAX2InitDefaultSAXHandler(&saxHandler, 1);
 449      saxHandler.startDocument = xmlTextWriterStartDocumentCallback;
 450      saxHandler.startElement = xmlSAX2StartElement;
 451      saxHandler.endElement = xmlSAX2EndElement;
 452  
 453      ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL);
 454      if (ctxt == NULL) {
 455          xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
 456                          "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
 457          return NULL;
 458      }
 459      /*
 460       * For some reason this seems to completely break if node names
 461       * are interned.
 462       */
 463      ctxt->dictNames = 0;
 464  
 465      ret = xmlNewTextWriterPushParser(ctxt, compression);
 466      if (ret == NULL) {
 467          xmlFreeParserCtxt(ctxt);
 468          xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
 469                          "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n");
 470          return NULL;
 471      }
 472  
 473      ctxt->myDoc = doc;
 474      ctxt->node = node;
 475      ret->no_doc_free = 1;
 476  
 477      xmlSetDocCompressMode(doc, compression);
 478  
 479      return ret;
 480  }
 481  
 482  /**
 483   * xmlFreeTextWriter:
 484   * @writer:  the xmlTextWriterPtr
 485   *
 486   * Deallocate all the resources associated to the writer
 487   */
 488  void
 489  xmlFreeTextWriter(xmlTextWriterPtr writer)
 490  {
 491      if (writer == NULL)
 492          return;
 493  
 494      if (writer->out != NULL)
 495          xmlOutputBufferClose(writer->out);
 496  
 497      if (writer->nodes != NULL)
 498          xmlListDelete(writer->nodes);
 499  
 500      if (writer->nsstack != NULL)
 501          xmlListDelete(writer->nsstack);
 502  
 503      if (writer->ctxt != NULL) {
 504          if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) {
 505  	    xmlFreeDoc(writer->ctxt->myDoc);
 506  	    writer->ctxt->myDoc = NULL;
 507  	}
 508          xmlFreeParserCtxt(writer->ctxt);
 509      }
 510  
 511      if (writer->doc != NULL)
 512          xmlFreeDoc(writer->doc);
 513  
 514      if (writer->ichar != NULL)
 515          xmlFree(writer->ichar);
 516      xmlFree(writer);
 517  }
 518  
 519  /**
 520   * xmlTextWriterStartDocument:
 521   * @writer:  the xmlTextWriterPtr
 522   * @version:  the xml version ("1.0") or NULL for default ("1.0")
 523   * @encoding:  the encoding or NULL for default
 524   * @standalone: "yes" or "no" or NULL for default
 525   *
 526   * Start a new xml document
 527   *
 528   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
 529   */
 530  int
 531  xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
 532                             const char *encoding, const char *standalone)
 533  {
 534      int count;
 535      int sum;
 536      xmlLinkPtr lk;
 537      xmlCharEncodingHandlerPtr encoder;
 538  
 539      if ((writer == NULL) || (writer->out == NULL)) {
 540          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
 541                          "xmlTextWriterStartDocument : invalid writer!\n");
 542          return -1;
 543      }
 544  
 545      lk = xmlListFront(writer->nodes);
 546      if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
 547          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
 548                          "xmlTextWriterStartDocument : not allowed in this context!\n");
 549          return -1;
 550      }
 551  
 552      encoder = NULL;
 553      if (encoding != NULL) {
 554          encoder = xmlFindCharEncodingHandler(encoding);
 555          if (encoder == NULL) {
 556              xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
 557                              "xmlTextWriterStartDocument : out of memory!\n");
 558              return -1;
 559          }
 560      }
 561  
 562      writer->out->encoder = encoder;
 563      if (encoder != NULL) {
 564  	if (writer->out->conv == NULL) {
 565  	    writer->out->conv = xmlBufCreateSize(4000);
 566  	}
 567          xmlCharEncOutput(writer->out, 1);
 568          if ((writer->doc != NULL) && (writer->doc->encoding == NULL))
 569              writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name);
 570      } else
 571          writer->out->conv = NULL;
 572  
 573      sum = 0;
 574      count = xmlOutputBufferWriteString(writer->out, "<?xml version=");
 575      if (count < 0)
 576          return -1;
 577      sum += count;
 578      count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
 579      if (count < 0)
 580          return -1;
 581      sum += count;
 582      if (version != 0)
 583          count = xmlOutputBufferWriteString(writer->out, version);
 584      else
 585          count = xmlOutputBufferWriteString(writer->out, "1.0");
 586      if (count < 0)
 587          return -1;
 588      sum += count;
 589      count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
 590      if (count < 0)
 591          return -1;
 592      sum += count;
 593      if (writer->out->encoder != 0) {
 594          count = xmlOutputBufferWriteString(writer->out, " encoding=");
 595          if (count < 0)
 596              return -1;
 597          sum += count;
 598          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
 599          if (count < 0)
 600              return -1;
 601          sum += count;
 602          count =
 603              xmlOutputBufferWriteString(writer->out,
 604                                         writer->out->encoder->name);
 605          if (count < 0)
 606              return -1;
 607          sum += count;
 608          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
 609          if (count < 0)
 610              return -1;
 611          sum += count;
 612      }
 613  
 614      if (standalone != 0) {
 615          count = xmlOutputBufferWriteString(writer->out, " standalone=");
 616          if (count < 0)
 617              return -1;
 618          sum += count;
 619          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
 620          if (count < 0)
 621              return -1;
 622          sum += count;
 623          count = xmlOutputBufferWriteString(writer->out, standalone);
 624          if (count < 0)
 625              return -1;
 626          sum += count;
 627          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
 628          if (count < 0)
 629              return -1;
 630          sum += count;
 631      }
 632  
 633      count = xmlOutputBufferWriteString(writer->out, "?>\n");
 634      if (count < 0)
 635          return -1;
 636      sum += count;
 637  
 638      return sum;
 639  }
 640  
 641  /**
 642   * xmlTextWriterEndDocument:
 643   * @writer:  the xmlTextWriterPtr
 644   *
 645   * End an xml document. All open elements are closed, and
 646   * the content is flushed to the output.
 647   *
 648   * Returns the bytes written or -1 in case of error
 649   */
 650  int
 651  xmlTextWriterEndDocument(xmlTextWriterPtr writer)
 652  {
 653      int count;
 654      int sum;
 655      xmlLinkPtr lk;
 656      xmlTextWriterStackEntry *p;
 657  
 658      if (writer == NULL) {
 659          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
 660                          "xmlTextWriterEndDocument : invalid writer!\n");
 661          return -1;
 662      }
 663  
 664      sum = 0;
 665      while ((lk = xmlListFront(writer->nodes)) != NULL) {
 666          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
 667          if (p == 0)
 668              break;
 669          switch (p->state) {
 670              case XML_TEXTWRITER_NAME:
 671              case XML_TEXTWRITER_ATTRIBUTE:
 672              case XML_TEXTWRITER_TEXT:
 673                  count = xmlTextWriterEndElement(writer);
 674                  if (count < 0)
 675                      return -1;
 676                  sum += count;
 677                  break;
 678              case XML_TEXTWRITER_PI:
 679              case XML_TEXTWRITER_PI_TEXT:
 680                  count = xmlTextWriterEndPI(writer);
 681                  if (count < 0)
 682                      return -1;
 683                  sum += count;
 684                  break;
 685              case XML_TEXTWRITER_CDATA:
 686                  count = xmlTextWriterEndCDATA(writer);
 687                  if (count < 0)
 688                      return -1;
 689                  sum += count;
 690                  break;
 691              case XML_TEXTWRITER_DTD:
 692              case XML_TEXTWRITER_DTD_TEXT:
 693              case XML_TEXTWRITER_DTD_ELEM:
 694              case XML_TEXTWRITER_DTD_ELEM_TEXT:
 695              case XML_TEXTWRITER_DTD_ATTL:
 696              case XML_TEXTWRITER_DTD_ATTL_TEXT:
 697              case XML_TEXTWRITER_DTD_ENTY:
 698              case XML_TEXTWRITER_DTD_ENTY_TEXT:
 699              case XML_TEXTWRITER_DTD_PENT:
 700                  count = xmlTextWriterEndDTD(writer);
 701                  if (count < 0)
 702                      return -1;
 703                  sum += count;
 704                  break;
 705              case XML_TEXTWRITER_COMMENT:
 706                  count = xmlTextWriterEndComment(writer);
 707                  if (count < 0)
 708                      return -1;
 709                  sum += count;
 710                  break;
 711              default:
 712                  break;
 713          }
 714      }
 715  
 716      if (!writer->indent) {
 717          count = xmlOutputBufferWriteString(writer->out, "\n");
 718          if (count < 0)
 719              return -1;
 720          sum += count;
 721      }
 722  
 723      sum += xmlTextWriterFlush(writer);
 724  
 725      return sum;
 726  }
 727  
 728  /**
 729   * xmlTextWriterStartComment:
 730   * @writer:  the xmlTextWriterPtr
 731   *
 732   * Start an xml comment.
 733   *
 734   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
 735   */
 736  int
 737  xmlTextWriterStartComment(xmlTextWriterPtr writer)
 738  {
 739      int count;
 740      int sum;
 741      xmlLinkPtr lk;
 742      xmlTextWriterStackEntry *p;
 743  
 744      if (writer == NULL) {
 745          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
 746                          "xmlTextWriterStartComment : invalid writer!\n");
 747          return -1;
 748      }
 749  
 750      sum = 0;
 751      lk = xmlListFront(writer->nodes);
 752      if (lk != 0) {
 753          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
 754          if (p != 0) {
 755              switch (p->state) {
 756                  case XML_TEXTWRITER_TEXT:
 757                  case XML_TEXTWRITER_NONE:
 758                      break;
 759                  case XML_TEXTWRITER_NAME:
 760                      /* Output namespace declarations */
 761                      count = xmlTextWriterOutputNSDecl(writer);
 762                      if (count < 0)
 763                          return -1;
 764                      sum += count;
 765                      count = xmlOutputBufferWriteString(writer->out, ">");
 766                      if (count < 0)
 767                          return -1;
 768                      sum += count;
 769                      if (writer->indent) {
 770                          count =
 771                              xmlOutputBufferWriteString(writer->out, "\n");
 772                          if (count < 0)
 773                              return -1;
 774                          sum += count;
 775                      }
 776                      p->state = XML_TEXTWRITER_TEXT;
 777                      break;
 778                  default:
 779                      return -1;
 780              }
 781          }
 782      }
 783  
 784      p = (xmlTextWriterStackEntry *)
 785          xmlMalloc(sizeof(xmlTextWriterStackEntry));
 786      if (p == 0) {
 787          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
 788                          "xmlTextWriterStartElement : out of memory!\n");
 789          return -1;
 790      }
 791  
 792      p->name = NULL;
 793      p->state = XML_TEXTWRITER_COMMENT;
 794  
 795      xmlListPushFront(writer->nodes, p);
 796  
 797      if (writer->indent) {
 798          count = xmlTextWriterWriteIndent(writer);
 799          if (count < 0)
 800              return -1;
 801          sum += count;
 802      }
 803  
 804      count = xmlOutputBufferWriteString(writer->out, "<!--");
 805      if (count < 0)
 806          return -1;
 807      sum += count;
 808  
 809      return sum;
 810  }
 811  
 812  /**
 813   * xmlTextWriterEndComment:
 814   * @writer:  the xmlTextWriterPtr
 815   *
 816   * End the current xml coment.
 817   *
 818   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
 819   */
 820  int
 821  xmlTextWriterEndComment(xmlTextWriterPtr writer)
 822  {
 823      int count;
 824      int sum;
 825      xmlLinkPtr lk;
 826      xmlTextWriterStackEntry *p;
 827  
 828      if (writer == NULL) {
 829          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
 830                          "xmlTextWriterEndComment : invalid writer!\n");
 831          return -1;
 832      }
 833  
 834      lk = xmlListFront(writer->nodes);
 835      if (lk == 0) {
 836          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
 837                          "xmlTextWriterEndComment : not allowed in this context!\n");
 838          return -1;
 839      }
 840  
 841      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
 842      if (p == 0)
 843          return -1;
 844  
 845      sum = 0;
 846      switch (p->state) {
 847          case XML_TEXTWRITER_COMMENT:
 848              count = xmlOutputBufferWriteString(writer->out, "-->");
 849              if (count < 0)
 850                  return -1;
 851              sum += count;
 852              break;
 853          default:
 854              return -1;
 855      }
 856  
 857      if (writer->indent) {
 858          count = xmlOutputBufferWriteString(writer->out, "\n");
 859          if (count < 0)
 860              return -1;
 861          sum += count;
 862      }
 863  
 864      xmlListPopFront(writer->nodes);
 865      return sum;
 866  }
 867  
 868  /**
 869   * xmlTextWriterWriteFormatComment:
 870   * @writer:  the xmlTextWriterPtr
 871   * @format:  format string (see printf)
 872   * @...:  extra parameters for the format
 873   *
 874   * Write an xml comment.
 875   *
 876   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
 877   */
 878  int XMLCDECL
 879  xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer,
 880                                  const char *format, ...)
 881  {
 882      int rc;
 883      va_list ap;
 884  
 885      va_start(ap, format);
 886  
 887      rc = xmlTextWriterWriteVFormatComment(writer, format, ap);
 888  
 889      va_end(ap);
 890      return rc;
 891  }
 892  
 893  /**
 894   * xmlTextWriterWriteVFormatComment:
 895   * @writer:  the xmlTextWriterPtr
 896   * @format:  format string (see printf)
 897   * @argptr:  pointer to the first member of the variable argument list.
 898   *
 899   * Write an xml comment.
 900   *
 901   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
 902   */
 903  int
 904  xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer,
 905                                   const char *format, va_list argptr)
 906  {
 907      int rc;
 908      xmlChar *buf;
 909  
 910      if (writer == NULL) {
 911          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
 912                          "xmlTextWriterWriteVFormatComment : invalid writer!\n");
 913          return -1;
 914      }
 915  
 916      buf = xmlTextWriterVSprintf(format, argptr);
 917      if (buf == NULL)
 918          return -1;
 919  
 920      rc = xmlTextWriterWriteComment(writer, buf);
 921  
 922      xmlFree(buf);
 923      return rc;
 924  }
 925  
 926  /**
 927   * xmlTextWriterWriteComment:
 928   * @writer:  the xmlTextWriterPtr
 929   * @content:  comment string
 930   *
 931   * Write an xml comment.
 932   *
 933   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
 934   */
 935  int
 936  xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content)
 937  {
 938      int count;
 939      int sum;
 940  
 941      sum = 0;
 942      count = xmlTextWriterStartComment(writer);
 943      if (count < 0)
 944          return -1;
 945      sum += count;
 946      count = xmlTextWriterWriteString(writer, content);
 947      if (count < 0)
 948          return -1;
 949      sum += count;
 950      count = xmlTextWriterEndComment(writer);
 951      if (count < 0)
 952          return -1;
 953      sum += count;
 954  
 955      return sum;
 956  }
 957  
 958  /**
 959   * xmlTextWriterStartElement:
 960   * @writer:  the xmlTextWriterPtr
 961   * @name:  element name
 962   *
 963   * Start an xml element.
 964   *
 965   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
 966   */
 967  int
 968  xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name)
 969  {
 970      int count;
 971      int sum;
 972      xmlLinkPtr lk;
 973      xmlTextWriterStackEntry *p;
 974  
 975      if ((writer == NULL) || (name == NULL) || (*name == '\0'))
 976          return -1;
 977  
 978      sum = 0;
 979      lk = xmlListFront(writer->nodes);
 980      if (lk != 0) {
 981          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
 982          if (p != 0) {
 983              switch (p->state) {
 984                  case XML_TEXTWRITER_PI:
 985                  case XML_TEXTWRITER_PI_TEXT:
 986                      return -1;
 987                  case XML_TEXTWRITER_NONE:
 988                      break;
 989  				case XML_TEXTWRITER_ATTRIBUTE:
 990  					count = xmlTextWriterEndAttribute(writer);
 991  					if (count < 0)
 992  						return -1;
 993  					sum += count;
 994  					/* fallthrough */
 995                  case XML_TEXTWRITER_NAME:
 996                      /* Output namespace declarations */
 997                      count = xmlTextWriterOutputNSDecl(writer);
 998                      if (count < 0)
 999                          return -1;
1000                      sum += count;
1001                      count = xmlOutputBufferWriteString(writer->out, ">");
1002                      if (count < 0)
1003                          return -1;
1004                      sum += count;
1005                      if (writer->indent)
1006                          count =
1007                              xmlOutputBufferWriteString(writer->out, "\n");
1008                      p->state = XML_TEXTWRITER_TEXT;
1009                      break;
1010                  default:
1011                      break;
1012              }
1013          }
1014      }
1015  
1016      p = (xmlTextWriterStackEntry *)
1017          xmlMalloc(sizeof(xmlTextWriterStackEntry));
1018      if (p == 0) {
1019          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1020                          "xmlTextWriterStartElement : out of memory!\n");
1021          return -1;
1022      }
1023  
1024      p->name = xmlStrdup(name);
1025      if (p->name == 0) {
1026          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1027                          "xmlTextWriterStartElement : out of memory!\n");
1028          xmlFree(p);
1029          return -1;
1030      }
1031      p->state = XML_TEXTWRITER_NAME;
1032  
1033      xmlListPushFront(writer->nodes, p);
1034  
1035      if (writer->indent) {
1036          count = xmlTextWriterWriteIndent(writer);
1037          sum += count;
1038      }
1039  
1040      count = xmlOutputBufferWriteString(writer->out, "<");
1041      if (count < 0)
1042          return -1;
1043      sum += count;
1044      count =
1045          xmlOutputBufferWriteString(writer->out, (const char *) p->name);
1046      if (count < 0)
1047          return -1;
1048      sum += count;
1049  
1050      return sum;
1051  }
1052  
1053  /**
1054   * xmlTextWriterStartElementNS:
1055   * @writer:  the xmlTextWriterPtr
1056   * @prefix:  namespace prefix or NULL
1057   * @name:  element local name
1058   * @namespaceURI:  namespace URI or NULL
1059   *
1060   * Start an xml element with namespace support.
1061   *
1062   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1063   */
1064  int
1065  xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
1066                              const xmlChar * prefix, const xmlChar * name,
1067                              const xmlChar * namespaceURI)
1068  {
1069      int count;
1070      int sum;
1071      xmlChar *buf;
1072  
1073      if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1074          return -1;
1075  
1076      buf = NULL;
1077      if (prefix != 0) {
1078          buf = xmlStrdup(prefix);
1079          buf = xmlStrcat(buf, BAD_CAST ":");
1080      }
1081      buf = xmlStrcat(buf, name);
1082  
1083      sum = 0;
1084      count = xmlTextWriterStartElement(writer, buf);
1085      xmlFree(buf);
1086      if (count < 0)
1087          return -1;
1088      sum += count;
1089  
1090      if (namespaceURI != 0) {
1091          xmlTextWriterNsStackEntry *p = (xmlTextWriterNsStackEntry *)
1092          xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1093          if (p == 0) {
1094              xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1095                              "xmlTextWriterStartElementNS : out of memory!\n");
1096              return -1;
1097          }
1098  
1099          buf = xmlStrdup(BAD_CAST "xmlns");
1100          if (prefix != 0) {
1101              buf = xmlStrcat(buf, BAD_CAST ":");
1102              buf = xmlStrcat(buf, prefix);
1103          }
1104  
1105          p->prefix = buf;
1106          p->uri = xmlStrdup(namespaceURI);
1107          if (p->uri == 0) {
1108              xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1109                              "xmlTextWriterStartElementNS : out of memory!\n");
1110              xmlFree(p);
1111              return -1;
1112          }
1113          p->elem = xmlListFront(writer->nodes);
1114  
1115          xmlListPushFront(writer->nsstack, p);
1116      }
1117  
1118      return sum;
1119  }
1120  
1121  /**
1122   * xmlTextWriterEndElement:
1123   * @writer:  the xmlTextWriterPtr
1124   *
1125   * End the current xml element.
1126   *
1127   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1128   */
1129  int
1130  xmlTextWriterEndElement(xmlTextWriterPtr writer)
1131  {
1132      int count;
1133      int sum;
1134      xmlLinkPtr lk;
1135      xmlTextWriterStackEntry *p;
1136  
1137      if (writer == NULL)
1138          return -1;
1139  
1140      lk = xmlListFront(writer->nodes);
1141      if (lk == 0) {
1142          xmlListDelete(writer->nsstack);
1143          writer->nsstack = NULL;
1144          return -1;
1145      }
1146  
1147      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1148      if (p == 0) {
1149          xmlListDelete(writer->nsstack);
1150          writer->nsstack = NULL;
1151          return -1;
1152      }
1153  
1154      sum = 0;
1155      switch (p->state) {
1156          case XML_TEXTWRITER_ATTRIBUTE:
1157              count = xmlTextWriterEndAttribute(writer);
1158              if (count < 0) {
1159                  xmlListDelete(writer->nsstack);
1160                  writer->nsstack = NULL;
1161                  return -1;
1162              }
1163              sum += count;
1164              /* fallthrough */
1165          case XML_TEXTWRITER_NAME:
1166              /* Output namespace declarations */
1167              count = xmlTextWriterOutputNSDecl(writer);
1168              if (count < 0)
1169                  return -1;
1170              sum += count;
1171  
1172              if (writer->indent) /* next element needs indent */
1173                  writer->doindent = 1;
1174              count = xmlOutputBufferWriteString(writer->out, "/>");
1175              if (count < 0)
1176                  return -1;
1177              sum += count;
1178              break;
1179          case XML_TEXTWRITER_TEXT:
1180              if ((writer->indent) && (writer->doindent)) {
1181                  count = xmlTextWriterWriteIndent(writer);
1182                  sum += count;
1183                  writer->doindent = 1;
1184              } else
1185                  writer->doindent = 1;
1186              count = xmlOutputBufferWriteString(writer->out, "</");
1187              if (count < 0)
1188                  return -1;
1189              sum += count;
1190              count = xmlOutputBufferWriteString(writer->out,
1191                                                 (const char *) p->name);
1192              if (count < 0)
1193                  return -1;
1194              sum += count;
1195              count = xmlOutputBufferWriteString(writer->out, ">");
1196              if (count < 0)
1197                  return -1;
1198              sum += count;
1199              break;
1200          default:
1201              return -1;
1202      }
1203  
1204      if (writer->indent) {
1205          count = xmlOutputBufferWriteString(writer->out, "\n");
1206          sum += count;
1207      }
1208  
1209      xmlListPopFront(writer->nodes);
1210      return sum;
1211  }
1212  
1213  /**
1214   * xmlTextWriterFullEndElement:
1215   * @writer:  the xmlTextWriterPtr
1216   *
1217   * End the current xml element. Writes an end tag even if the element is empty
1218   *
1219   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1220   */
1221  int
1222  xmlTextWriterFullEndElement(xmlTextWriterPtr writer)
1223  {
1224      int count;
1225      int sum;
1226      xmlLinkPtr lk;
1227      xmlTextWriterStackEntry *p;
1228  
1229      if (writer == NULL)
1230          return -1;
1231  
1232      lk = xmlListFront(writer->nodes);
1233      if (lk == 0)
1234          return -1;
1235  
1236      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1237      if (p == 0)
1238          return -1;
1239  
1240      sum = 0;
1241      switch (p->state) {
1242          case XML_TEXTWRITER_ATTRIBUTE:
1243              count = xmlTextWriterEndAttribute(writer);
1244              if (count < 0)
1245                  return -1;
1246              sum += count;
1247              /* fallthrough */
1248          case XML_TEXTWRITER_NAME:
1249              /* Output namespace declarations */
1250              count = xmlTextWriterOutputNSDecl(writer);
1251              if (count < 0)
1252                  return -1;
1253              sum += count;
1254  
1255              count = xmlOutputBufferWriteString(writer->out, ">");
1256              if (count < 0)
1257                  return -1;
1258              sum += count;
1259              if (writer->indent)
1260                  writer->doindent = 0;
1261              /* fallthrough */
1262          case XML_TEXTWRITER_TEXT:
1263              if ((writer->indent) && (writer->doindent)) {
1264                  count = xmlTextWriterWriteIndent(writer);
1265                  sum += count;
1266                  writer->doindent = 1;
1267              } else
1268                  writer->doindent = 1;
1269              count = xmlOutputBufferWriteString(writer->out, "</");
1270              if (count < 0)
1271                  return -1;
1272              sum += count;
1273              count = xmlOutputBufferWriteString(writer->out,
1274                                                 (const char *) p->name);
1275              if (count < 0)
1276                  return -1;
1277              sum += count;
1278              count = xmlOutputBufferWriteString(writer->out, ">");
1279              if (count < 0)
1280                  return -1;
1281              sum += count;
1282              break;
1283          default:
1284              return -1;
1285      }
1286  
1287      if (writer->indent) {
1288          count = xmlOutputBufferWriteString(writer->out, "\n");
1289          sum += count;
1290      }
1291  
1292      xmlListPopFront(writer->nodes);
1293      return sum;
1294  }
1295  
1296  /**
1297   * xmlTextWriterWriteFormatRaw:
1298   * @writer:  the xmlTextWriterPtr
1299   * @format:  format string (see printf)
1300   * @...:  extra parameters for the format
1301   *
1302   * Write a formatted raw xml text.
1303   *
1304   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1305   */
1306  int XMLCDECL
1307  xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format,
1308                              ...)
1309  {
1310      int rc;
1311      va_list ap;
1312  
1313      va_start(ap, format);
1314  
1315      rc = xmlTextWriterWriteVFormatRaw(writer, format, ap);
1316  
1317      va_end(ap);
1318      return rc;
1319  }
1320  
1321  /**
1322   * xmlTextWriterWriteVFormatRaw:
1323   * @writer:  the xmlTextWriterPtr
1324   * @format:  format string (see printf)
1325   * @argptr:  pointer to the first member of the variable argument list.
1326   *
1327   * Write a formatted raw xml text.
1328   *
1329   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1330   */
1331  int
1332  xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format,
1333                               va_list argptr)
1334  {
1335      int rc;
1336      xmlChar *buf;
1337  
1338      if (writer == NULL)
1339          return -1;
1340  
1341      buf = xmlTextWriterVSprintf(format, argptr);
1342      if (buf == NULL)
1343          return -1;
1344  
1345      rc = xmlTextWriterWriteRaw(writer, buf);
1346  
1347      xmlFree(buf);
1348      return rc;
1349  }
1350  
1351  /**
1352   * xmlTextWriterWriteRawLen:
1353   * @writer:  the xmlTextWriterPtr
1354   * @content:  text string
1355   * @len:  length of the text string
1356   *
1357   * Write an xml text.
1358   * TODO: what about entities and special chars??
1359   *
1360   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1361   */
1362  int
1363  xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content,
1364                           int len)
1365  {
1366      int count;
1367      int sum;
1368      xmlLinkPtr lk;
1369      xmlTextWriterStackEntry *p;
1370  
1371      if (writer == NULL) {
1372          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
1373                          "xmlTextWriterWriteRawLen : invalid writer!\n");
1374          return -1;
1375      }
1376  
1377      if ((content == NULL) || (len < 0)) {
1378          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
1379                          "xmlTextWriterWriteRawLen : invalid content!\n");
1380          return -1;
1381      }
1382  
1383      sum = 0;
1384      lk = xmlListFront(writer->nodes);
1385      if (lk != 0) {
1386          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1387          count = xmlTextWriterHandleStateDependencies(writer, p);
1388          if (count < 0)
1389              return -1;
1390          sum += count;
1391      }
1392  
1393      if (writer->indent)
1394          writer->doindent = 0;
1395  
1396      if (content != NULL) {
1397          count =
1398              xmlOutputBufferWrite(writer->out, len, (const char *) content);
1399          if (count < 0)
1400              return -1;
1401          sum += count;
1402      }
1403  
1404      return sum;
1405  }
1406  
1407  /**
1408   * xmlTextWriterWriteRaw:
1409   * @writer:  the xmlTextWriterPtr
1410   * @content:  text string
1411   *
1412   * Write a raw xml text.
1413   *
1414   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1415   */
1416  int
1417  xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content)
1418  {
1419      return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content));
1420  }
1421  
1422  /**
1423   * xmlTextWriterWriteFormatString:
1424   * @writer:  the xmlTextWriterPtr
1425   * @format:  format string (see printf)
1426   * @...:  extra parameters for the format
1427   *
1428   * Write a formatted xml text.
1429   *
1430   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1431   */
1432  int XMLCDECL
1433  xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format,
1434                                 ...)
1435  {
1436      int rc;
1437      va_list ap;
1438  
1439      if ((writer == NULL) || (format == NULL))
1440          return -1;
1441  
1442      va_start(ap, format);
1443  
1444      rc = xmlTextWriterWriteVFormatString(writer, format, ap);
1445  
1446      va_end(ap);
1447      return rc;
1448  }
1449  
1450  /**
1451   * xmlTextWriterWriteVFormatString:
1452   * @writer:  the xmlTextWriterPtr
1453   * @format:  format string (see printf)
1454   * @argptr:  pointer to the first member of the variable argument list.
1455   *
1456   * Write a formatted xml text.
1457   *
1458   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1459   */
1460  int
1461  xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer,
1462                                  const char *format, va_list argptr)
1463  {
1464      int rc;
1465      xmlChar *buf;
1466  
1467      if ((writer == NULL) || (format == NULL))
1468          return -1;
1469  
1470      buf = xmlTextWriterVSprintf(format, argptr);
1471      if (buf == NULL)
1472          return -1;
1473  
1474      rc = xmlTextWriterWriteString(writer, buf);
1475  
1476      xmlFree(buf);
1477      return rc;
1478  }
1479  
1480  /**
1481   * xmlTextWriterWriteString:
1482   * @writer:  the xmlTextWriterPtr
1483   * @content:  text string
1484   *
1485   * Write an xml text.
1486   *
1487   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1488   */
1489  int
1490  xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content)
1491  {
1492      int count;
1493      int sum;
1494      xmlLinkPtr lk;
1495      xmlTextWriterStackEntry *p;
1496      xmlChar *buf;
1497  
1498      if ((writer == NULL) || (content == NULL))
1499          return -1;
1500  
1501      sum = 0;
1502      buf = (xmlChar *) content;
1503      lk = xmlListFront(writer->nodes);
1504      if (lk != 0) {
1505          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1506          if (p != 0) {
1507              switch (p->state) {
1508                  case XML_TEXTWRITER_NAME:
1509                  case XML_TEXTWRITER_TEXT:
1510  #if 0
1511                      buf = NULL;
1512  		    xmlOutputBufferWriteEscape(writer->out, content, NULL);
1513  #endif
1514                      buf = xmlEncodeSpecialChars(NULL, content);
1515                      break;
1516                  case XML_TEXTWRITER_ATTRIBUTE:
1517                      buf = NULL;
1518                      xmlBufAttrSerializeTxtContent(writer->out->buffer,
1519                                                    writer->doc, NULL, content);
1520                      break;
1521  		default:
1522  		    break;
1523              }
1524          }
1525      }
1526  
1527      if (buf != NULL) {
1528          count = xmlTextWriterWriteRaw(writer, buf);
1529  
1530          if (buf != content)     /* buf was allocated by us, so free it */
1531              xmlFree(buf);
1532  
1533          if (count < 0)
1534              return -1;
1535          sum += count;
1536      }
1537  
1538      return sum;
1539  }
1540  
1541  /**
1542   * xmlOutputBufferWriteBase64:
1543   * @out: the xmlOutputBufferPtr
1544   * @data:   binary data
1545   * @len:  the number of bytes to encode
1546   *
1547   * Write base64 encoded data to an xmlOutputBuffer.
1548   * Adapted from John Walker's base64.c (http://www.fourmilab.ch/).
1549   *
1550   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1551   */
1552  static int
1553  xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
1554                             const unsigned char *data)
1555  {
1556      static unsigned char const dtable[64] =
1557              {'A','B','C','D','E','F','G','H','I','J','K','L','M',
1558  	     'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1559  	     'a','b','c','d','e','f','g','h','i','j','k','l','m',
1560  	     'n','o','p','q','r','s','t','u','v','w','x','y','z',
1561  	     '0','1','2','3','4','5','6','7','8','9','+','/'};
1562  
1563      int i;
1564      int linelen;
1565      int count;
1566      int sum;
1567  
1568      if ((out == NULL) || (len < 0) || (data == NULL))
1569          return(-1);
1570  
1571      linelen = 0;
1572      sum = 0;
1573  
1574      i = 0;
1575      while (1) {
1576          unsigned char igroup[3];
1577          unsigned char ogroup[4];
1578          int c;
1579          int n;
1580  
1581          igroup[0] = igroup[1] = igroup[2] = 0;
1582          for (n = 0; n < 3 && i < len; n++, i++) {
1583              c = data[i];
1584              igroup[n] = (unsigned char) c;
1585          }
1586  
1587          if (n > 0) {
1588              ogroup[0] = dtable[igroup[0] >> 2];
1589              ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
1590              ogroup[2] =
1591                  dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
1592              ogroup[3] = dtable[igroup[2] & 0x3F];
1593  
1594              if (n < 3) {
1595                  ogroup[3] = '=';
1596                  if (n < 2) {
1597                      ogroup[2] = '=';
1598                  }
1599              }
1600  
1601              if (linelen >= B64LINELEN) {
1602                  count = xmlOutputBufferWrite(out, 2, B64CRLF);
1603                  if (count == -1)
1604                      return -1;
1605                  sum += count;
1606                  linelen = 0;
1607              }
1608              count = xmlOutputBufferWrite(out, 4, (const char *) ogroup);
1609              if (count == -1)
1610                  return -1;
1611              sum += count;
1612  
1613              linelen += 4;
1614          }
1615  
1616          if (i >= len)
1617              break;
1618      }
1619  
1620      return sum;
1621  }
1622  
1623  /**
1624   * xmlTextWriterWriteBase64:
1625   * @writer: the xmlTextWriterPtr
1626   * @data:   binary data
1627   * @start:  the position within the data of the first byte to encode
1628   * @len:  the number of bytes to encode
1629   *
1630   * Write an base64 encoded xml text.
1631   *
1632   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1633   */
1634  int
1635  xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data,
1636                           int start, int len)
1637  {
1638      int count;
1639      int sum;
1640      xmlLinkPtr lk;
1641      xmlTextWriterStackEntry *p;
1642  
1643      if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
1644          return -1;
1645  
1646      sum = 0;
1647      lk = xmlListFront(writer->nodes);
1648      if (lk != 0) {
1649          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1650          if (p != 0) {
1651              count = xmlTextWriterHandleStateDependencies(writer, p);
1652              if (count < 0)
1653                  return -1;
1654              sum += count;
1655          }
1656      }
1657  
1658      if (writer->indent)
1659          writer->doindent = 0;
1660  
1661      count =
1662          xmlOutputBufferWriteBase64(writer->out, len,
1663                                     (unsigned char *) data + start);
1664      if (count < 0)
1665          return -1;
1666      sum += count;
1667  
1668      return sum;
1669  }
1670  
1671  /**
1672   * xmlOutputBufferWriteBinHex:
1673   * @out: the xmlOutputBufferPtr
1674   * @data:   binary data
1675   * @len:  the number of bytes to encode
1676   *
1677   * Write hqx encoded data to an xmlOutputBuffer.
1678   * ::todo
1679   *
1680   * Returns the bytes written (may be 0 because of buffering)
1681   * or -1 in case of error
1682   */
1683  static int
1684  xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out,
1685                             int len, const unsigned char *data)
1686  {
1687      int count;
1688      int sum;
1689      static char const hex[16] =
1690  	{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
1691      int i;
1692  
1693      if ((out == NULL) || (data == NULL) || (len < 0)) {
1694          return -1;
1695      }
1696  
1697      sum = 0;
1698      for (i = 0; i < len; i++) {
1699          count =
1700              xmlOutputBufferWrite(out, 1,
1701                                   (const char *) &hex[data[i] >> 4]);
1702          if (count == -1)
1703              return -1;
1704          sum += count;
1705          count =
1706              xmlOutputBufferWrite(out, 1,
1707                                   (const char *) &hex[data[i] & 0xF]);
1708          if (count == -1)
1709              return -1;
1710          sum += count;
1711      }
1712  
1713      return sum;
1714  }
1715  
1716  /**
1717   * xmlTextWriterWriteBinHex:
1718   * @writer: the xmlTextWriterPtr
1719   * @data:   binary data
1720   * @start:  the position within the data of the first byte to encode
1721   * @len:  the number of bytes to encode
1722   *
1723   * Write a BinHex encoded xml text.
1724   *
1725   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1726   */
1727  int
1728  xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data,
1729                           int start, int len)
1730  {
1731      int count;
1732      int sum;
1733      xmlLinkPtr lk;
1734      xmlTextWriterStackEntry *p;
1735  
1736      if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0))
1737          return -1;
1738  
1739      sum = 0;
1740      lk = xmlListFront(writer->nodes);
1741      if (lk != 0) {
1742          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1743          if (p != 0) {
1744              count = xmlTextWriterHandleStateDependencies(writer, p);
1745              if (count < 0)
1746                  return -1;
1747              sum += count;
1748          }
1749      }
1750  
1751      if (writer->indent)
1752          writer->doindent = 0;
1753  
1754      count =
1755          xmlOutputBufferWriteBinHex(writer->out, len,
1756                                     (unsigned char *) data + start);
1757      if (count < 0)
1758          return -1;
1759      sum += count;
1760  
1761      return sum;
1762  }
1763  
1764  /**
1765   * xmlTextWriterStartAttribute:
1766   * @writer:  the xmlTextWriterPtr
1767   * @name:  element name
1768   *
1769   * Start an xml attribute.
1770   *
1771   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1772   */
1773  int
1774  xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name)
1775  {
1776      int count;
1777      int sum;
1778      xmlLinkPtr lk;
1779      xmlTextWriterStackEntry *p;
1780  
1781      if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1782          return -1;
1783  
1784      sum = 0;
1785      lk = xmlListFront(writer->nodes);
1786      if (lk == 0)
1787          return -1;
1788  
1789      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1790      if (p == 0)
1791          return -1;
1792  
1793      switch (p->state) {
1794          case XML_TEXTWRITER_ATTRIBUTE:
1795              count = xmlTextWriterEndAttribute(writer);
1796              if (count < 0)
1797                  return -1;
1798              sum += count;
1799              /* fallthrough */
1800          case XML_TEXTWRITER_NAME:
1801              count = xmlOutputBufferWriteString(writer->out, " ");
1802              if (count < 0)
1803                  return -1;
1804              sum += count;
1805              count =
1806                  xmlOutputBufferWriteString(writer->out,
1807                                             (const char *) name);
1808              if (count < 0)
1809                  return -1;
1810              sum += count;
1811              count = xmlOutputBufferWriteString(writer->out, "=");
1812              if (count < 0)
1813                  return -1;
1814              sum += count;
1815              count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1816              if (count < 0)
1817                  return -1;
1818              sum += count;
1819              p->state = XML_TEXTWRITER_ATTRIBUTE;
1820              break;
1821          default:
1822              return -1;
1823      }
1824  
1825      return sum;
1826  }
1827  
1828  /**
1829   * xmlTextWriterStartAttributeNS:
1830   * @writer:  the xmlTextWriterPtr
1831   * @prefix:  namespace prefix or NULL
1832   * @name:  element local name
1833   * @namespaceURI:  namespace URI or NULL
1834   *
1835   * Start an xml attribute with namespace support.
1836   *
1837   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1838   */
1839  int
1840  xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
1841                                const xmlChar * prefix, const xmlChar * name,
1842                                const xmlChar * namespaceURI)
1843  {
1844      int count;
1845      int sum;
1846      xmlChar *buf;
1847      xmlTextWriterNsStackEntry *p;
1848  
1849      if ((writer == NULL) || (name == NULL) || (*name == '\0'))
1850          return -1;
1851  
1852      /* Handle namespace first in case of error */
1853      if (namespaceURI != 0) {
1854          xmlTextWriterNsStackEntry nsentry, *curns;
1855  
1856          buf = xmlStrdup(BAD_CAST "xmlns");
1857          if (prefix != 0) {
1858              buf = xmlStrcat(buf, BAD_CAST ":");
1859              buf = xmlStrcat(buf, prefix);
1860          }
1861  
1862          nsentry.prefix = buf;
1863          nsentry.uri = (xmlChar *)namespaceURI;
1864          nsentry.elem = xmlListFront(writer->nodes);
1865  
1866          curns = (xmlTextWriterNsStackEntry *)xmlListSearch(writer->nsstack,
1867                                                             (void *)&nsentry);
1868          if ((curns != NULL)) {
1869              xmlFree(buf);
1870              if (xmlStrcmp(curns->uri, namespaceURI) == 0) {
1871                  /* Namespace already defined on element skip */
1872                  buf = NULL;
1873              } else {
1874                  /* Prefix mismatch so error out */
1875                  return -1;
1876              }
1877          }
1878  
1879          /* Do not add namespace decl to list - it is already there */
1880          if (buf != NULL) {
1881              p = (xmlTextWriterNsStackEntry *)
1882                  xmlMalloc(sizeof(xmlTextWriterNsStackEntry));
1883              if (p == 0) {
1884                  xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1885  								        "xmlTextWriterStartAttributeNS : out of memory!\n");
1886                  return -1;
1887              }
1888  
1889              p->prefix = buf;
1890              p->uri = xmlStrdup(namespaceURI);
1891              if (p->uri == 0) {
1892                  xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
1893                          "xmlTextWriterStartAttributeNS : out of memory!\n");
1894                  xmlFree(p);
1895                  return -1;
1896              }
1897              p->elem = xmlListFront(writer->nodes);
1898  
1899              xmlListPushFront(writer->nsstack, p);
1900          }
1901      }
1902  
1903      buf = NULL;
1904      if (prefix != 0) {
1905          buf = xmlStrdup(prefix);
1906          buf = xmlStrcat(buf, BAD_CAST ":");
1907      }
1908      buf = xmlStrcat(buf, name);
1909  
1910      sum = 0;
1911      count = xmlTextWriterStartAttribute(writer, buf);
1912      xmlFree(buf);
1913      if (count < 0)
1914          return -1;
1915      sum += count;
1916  
1917      return sum;
1918  }
1919  
1920  /**
1921   * xmlTextWriterEndAttribute:
1922   * @writer:  the xmlTextWriterPtr
1923   *
1924   * End the current xml element.
1925   *
1926   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1927   */
1928  int
1929  xmlTextWriterEndAttribute(xmlTextWriterPtr writer)
1930  {
1931      int count;
1932      int sum;
1933      xmlLinkPtr lk;
1934      xmlTextWriterStackEntry *p;
1935  
1936      if (writer == NULL)
1937          return -1;
1938  
1939      lk = xmlListFront(writer->nodes);
1940      if (lk == 0) {
1941          return -1;
1942      }
1943  
1944      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
1945      if (p == 0) {
1946          return -1;
1947      }
1948  
1949      sum = 0;
1950      switch (p->state) {
1951          case XML_TEXTWRITER_ATTRIBUTE:
1952              p->state = XML_TEXTWRITER_NAME;
1953  
1954              count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
1955              if (count < 0) {
1956                  return -1;
1957              }
1958              sum += count;
1959              break;
1960          default:
1961              return -1;
1962      }
1963  
1964      return sum;
1965  }
1966  
1967  /**
1968   * xmlTextWriterWriteFormatAttribute:
1969   * @writer:  the xmlTextWriterPtr
1970   * @name:  attribute name
1971   * @format:  format string (see printf)
1972   * @...:  extra parameters for the format
1973   *
1974   * Write a formatted xml attribute.
1975   *
1976   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
1977   */
1978  int XMLCDECL
1979  xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer,
1980                                    const xmlChar * name, const char *format,
1981                                    ...)
1982  {
1983      int rc;
1984      va_list ap;
1985  
1986      va_start(ap, format);
1987  
1988      rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap);
1989  
1990      va_end(ap);
1991      return rc;
1992  }
1993  
1994  /**
1995   * xmlTextWriterWriteVFormatAttribute:
1996   * @writer:  the xmlTextWriterPtr
1997   * @name:  attribute name
1998   * @format:  format string (see printf)
1999   * @argptr:  pointer to the first member of the variable argument list.
2000   *
2001   * Write a formatted xml attribute.
2002   *
2003   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2004   */
2005  int
2006  xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer,
2007                                     const xmlChar * name,
2008                                     const char *format, va_list argptr)
2009  {
2010      int rc;
2011      xmlChar *buf;
2012  
2013      if (writer == NULL)
2014          return -1;
2015  
2016      buf = xmlTextWriterVSprintf(format, argptr);
2017      if (buf == NULL)
2018          return -1;
2019  
2020      rc = xmlTextWriterWriteAttribute(writer, name, buf);
2021  
2022      xmlFree(buf);
2023      return rc;
2024  }
2025  
2026  /**
2027   * xmlTextWriterWriteAttribute:
2028   * @writer:  the xmlTextWriterPtr
2029   * @name:  attribute name
2030   * @content:  attribute content
2031   *
2032   * Write an xml attribute.
2033   *
2034   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2035   */
2036  int
2037  xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name,
2038                              const xmlChar * content)
2039  {
2040      int count;
2041      int sum;
2042  
2043      sum = 0;
2044      count = xmlTextWriterStartAttribute(writer, name);
2045      if (count < 0)
2046          return -1;
2047      sum += count;
2048      count = xmlTextWriterWriteString(writer, content);
2049      if (count < 0)
2050          return -1;
2051      sum += count;
2052      count = xmlTextWriterEndAttribute(writer);
2053      if (count < 0)
2054          return -1;
2055      sum += count;
2056  
2057      return sum;
2058  }
2059  
2060  /**
2061   * xmlTextWriterWriteFormatAttributeNS:
2062   * @writer:  the xmlTextWriterPtr
2063   * @prefix:  namespace prefix
2064   * @name:  attribute local name
2065   * @namespaceURI:  namespace URI
2066   * @format:  format string (see printf)
2067   * @...:  extra parameters for the format
2068   *
2069   * Write a formatted xml attribute.with namespace support
2070   *
2071   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2072   */
2073  int XMLCDECL
2074  xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer,
2075                                      const xmlChar * prefix,
2076                                      const xmlChar * name,
2077                                      const xmlChar * namespaceURI,
2078                                      const char *format, ...)
2079  {
2080      int rc;
2081      va_list ap;
2082  
2083      va_start(ap, format);
2084  
2085      rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name,
2086                                                namespaceURI, format, ap);
2087  
2088      va_end(ap);
2089      return rc;
2090  }
2091  
2092  /**
2093   * xmlTextWriterWriteVFormatAttributeNS:
2094   * @writer:  the xmlTextWriterPtr
2095   * @prefix:  namespace prefix
2096   * @name:  attribute local name
2097   * @namespaceURI:  namespace URI
2098   * @format:  format string (see printf)
2099   * @argptr:  pointer to the first member of the variable argument list.
2100   *
2101   * Write a formatted xml attribute.with namespace support
2102   *
2103   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2104   */
2105  int
2106  xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer,
2107                                       const xmlChar * prefix,
2108                                       const xmlChar * name,
2109                                       const xmlChar * namespaceURI,
2110                                       const char *format, va_list argptr)
2111  {
2112      int rc;
2113      xmlChar *buf;
2114  
2115      if (writer == NULL)
2116          return -1;
2117  
2118      buf = xmlTextWriterVSprintf(format, argptr);
2119      if (buf == NULL)
2120          return -1;
2121  
2122      rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI,
2123                                         buf);
2124  
2125      xmlFree(buf);
2126      return rc;
2127  }
2128  
2129  /**
2130   * xmlTextWriterWriteAttributeNS:
2131   * @writer:  the xmlTextWriterPtr
2132   * @prefix:  namespace prefix
2133   * @name:  attribute local name
2134   * @namespaceURI:  namespace URI
2135   * @content:  attribute content
2136   *
2137   * Write an xml attribute.
2138   *
2139   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2140   */
2141  int
2142  xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
2143                                const xmlChar * prefix, const xmlChar * name,
2144                                const xmlChar * namespaceURI,
2145                                const xmlChar * content)
2146  {
2147      int count;
2148      int sum;
2149  
2150      if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2151          return -1;
2152  
2153      sum = 0;
2154      count = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI);
2155      if (count < 0)
2156          return -1;
2157      sum += count;
2158      count = xmlTextWriterWriteString(writer, content);
2159      if (count < 0)
2160          return -1;
2161      sum += count;
2162      count = xmlTextWriterEndAttribute(writer);
2163      if (count < 0)
2164          return -1;
2165      sum += count;
2166  
2167      return sum;
2168  }
2169  
2170  /**
2171   * xmlTextWriterWriteFormatElement:
2172   * @writer:  the xmlTextWriterPtr
2173   * @name:  element name
2174   * @format:  format string (see printf)
2175   * @...:  extra parameters for the format
2176   *
2177   * Write a formatted xml element.
2178   *
2179   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2180   */
2181  int XMLCDECL
2182  xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer,
2183                                  const xmlChar * name, const char *format,
2184                                  ...)
2185  {
2186      int rc;
2187      va_list ap;
2188  
2189      va_start(ap, format);
2190  
2191      rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap);
2192  
2193      va_end(ap);
2194      return rc;
2195  }
2196  
2197  /**
2198   * xmlTextWriterWriteVFormatElement:
2199   * @writer:  the xmlTextWriterPtr
2200   * @name:  element name
2201   * @format:  format string (see printf)
2202   * @argptr:  pointer to the first member of the variable argument list.
2203   *
2204   * Write a formatted xml element.
2205   *
2206   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2207   */
2208  int
2209  xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer,
2210                                   const xmlChar * name, const char *format,
2211                                   va_list argptr)
2212  {
2213      int rc;
2214      xmlChar *buf;
2215  
2216      if (writer == NULL)
2217          return -1;
2218  
2219      buf = xmlTextWriterVSprintf(format, argptr);
2220      if (buf == NULL)
2221          return -1;
2222  
2223      rc = xmlTextWriterWriteElement(writer, name, buf);
2224  
2225      xmlFree(buf);
2226      return rc;
2227  }
2228  
2229  /**
2230   * xmlTextWriterWriteElement:
2231   * @writer:  the xmlTextWriterPtr
2232   * @name:  element name
2233   * @content:  element content
2234   *
2235   * Write an xml element.
2236   *
2237   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2238   */
2239  int
2240  xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name,
2241                            const xmlChar * content)
2242  {
2243      int count;
2244      int sum;
2245  
2246      sum = 0;
2247      count = xmlTextWriterStartElement(writer, name);
2248      if (count == -1)
2249          return -1;
2250      sum += count;
2251      if (content != NULL) {
2252  	count = xmlTextWriterWriteString(writer, content);
2253  	if (count == -1)
2254  	    return -1;
2255  	sum += count;
2256      }
2257      count = xmlTextWriterEndElement(writer);
2258      if (count == -1)
2259          return -1;
2260      sum += count;
2261  
2262      return sum;
2263  }
2264  
2265  /**
2266   * xmlTextWriterWriteFormatElementNS:
2267   * @writer:  the xmlTextWriterPtr
2268   * @prefix:  namespace prefix
2269   * @name:  element local name
2270   * @namespaceURI:  namespace URI
2271   * @format:  format string (see printf)
2272   * @...:  extra parameters for the format
2273   *
2274   * Write a formatted xml element with namespace support.
2275   *
2276   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2277   */
2278  int XMLCDECL
2279  xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer,
2280                                    const xmlChar * prefix,
2281                                    const xmlChar * name,
2282                                    const xmlChar * namespaceURI,
2283                                    const char *format, ...)
2284  {
2285      int rc;
2286      va_list ap;
2287  
2288      va_start(ap, format);
2289  
2290      rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name,
2291                                              namespaceURI, format, ap);
2292  
2293      va_end(ap);
2294      return rc;
2295  }
2296  
2297  /**
2298   * xmlTextWriterWriteVFormatElementNS:
2299   * @writer:  the xmlTextWriterPtr
2300   * @prefix:  namespace prefix
2301   * @name:  element local name
2302   * @namespaceURI:  namespace URI
2303   * @format:  format string (see printf)
2304   * @argptr:  pointer to the first member of the variable argument list.
2305   *
2306   * Write a formatted xml element with namespace support.
2307   *
2308   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2309   */
2310  int
2311  xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer,
2312                                     const xmlChar * prefix,
2313                                     const xmlChar * name,
2314                                     const xmlChar * namespaceURI,
2315                                     const char *format, va_list argptr)
2316  {
2317      int rc;
2318      xmlChar *buf;
2319  
2320      if (writer == NULL)
2321          return -1;
2322  
2323      buf = xmlTextWriterVSprintf(format, argptr);
2324      if (buf == NULL)
2325          return -1;
2326  
2327      rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI,
2328                                       buf);
2329  
2330      xmlFree(buf);
2331      return rc;
2332  }
2333  
2334  /**
2335   * xmlTextWriterWriteElementNS:
2336   * @writer:  the xmlTextWriterPtr
2337   * @prefix:  namespace prefix
2338   * @name:  element local name
2339   * @namespaceURI:  namespace URI
2340   * @content:  element content
2341   *
2342   * Write an xml element with namespace support.
2343   *
2344   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2345   */
2346  int
2347  xmlTextWriterWriteElementNS(xmlTextWriterPtr writer,
2348                              const xmlChar * prefix, const xmlChar * name,
2349                              const xmlChar * namespaceURI,
2350                              const xmlChar * content)
2351  {
2352      int count;
2353      int sum;
2354  
2355      if ((writer == NULL) || (name == NULL) || (*name == '\0'))
2356          return -1;
2357  
2358      sum = 0;
2359      count =
2360          xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI);
2361      if (count < 0)
2362          return -1;
2363      sum += count;
2364      count = xmlTextWriterWriteString(writer, content);
2365      if (count == -1)
2366          return -1;
2367      sum += count;
2368      count = xmlTextWriterEndElement(writer);
2369      if (count == -1)
2370          return -1;
2371      sum += count;
2372  
2373      return sum;
2374  }
2375  
2376  /**
2377   * xmlTextWriterStartPI:
2378   * @writer:  the xmlTextWriterPtr
2379   * @target:  PI target
2380   *
2381   * Start an xml PI.
2382   *
2383   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2384   */
2385  int
2386  xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target)
2387  {
2388      int count;
2389      int sum;
2390      xmlLinkPtr lk;
2391      xmlTextWriterStackEntry *p;
2392  
2393      if ((writer == NULL) || (target == NULL) || (*target == '\0'))
2394          return -1;
2395  
2396      if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) {
2397          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2398                          "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n");
2399          return -1;
2400      }
2401  
2402      sum = 0;
2403      lk = xmlListFront(writer->nodes);
2404      if (lk != 0) {
2405          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2406          if (p != 0) {
2407              switch (p->state) {
2408                  case XML_TEXTWRITER_ATTRIBUTE:
2409                      count = xmlTextWriterEndAttribute(writer);
2410                      if (count < 0)
2411                          return -1;
2412                      sum += count;
2413                      /* fallthrough */
2414                  case XML_TEXTWRITER_NAME:
2415                      /* Output namespace declarations */
2416                      count = xmlTextWriterOutputNSDecl(writer);
2417                      if (count < 0)
2418                          return -1;
2419                      sum += count;
2420                      count = xmlOutputBufferWriteString(writer->out, ">");
2421                      if (count < 0)
2422                          return -1;
2423                      sum += count;
2424                      p->state = XML_TEXTWRITER_TEXT;
2425                      break;
2426                  case XML_TEXTWRITER_NONE:
2427                  case XML_TEXTWRITER_TEXT:
2428                  case XML_TEXTWRITER_DTD:
2429                      break;
2430                  case XML_TEXTWRITER_PI:
2431                  case XML_TEXTWRITER_PI_TEXT:
2432                      xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2433                                      "xmlTextWriterStartPI : nested PI!\n");
2434                      return -1;
2435                  default:
2436                      return -1;
2437              }
2438          }
2439      }
2440  
2441      p = (xmlTextWriterStackEntry *)
2442          xmlMalloc(sizeof(xmlTextWriterStackEntry));
2443      if (p == 0) {
2444          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2445                          "xmlTextWriterStartPI : out of memory!\n");
2446          return -1;
2447      }
2448  
2449      p->name = xmlStrdup(target);
2450      if (p->name == 0) {
2451          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2452                          "xmlTextWriterStartPI : out of memory!\n");
2453          xmlFree(p);
2454          return -1;
2455      }
2456      p->state = XML_TEXTWRITER_PI;
2457  
2458      xmlListPushFront(writer->nodes, p);
2459  
2460      count = xmlOutputBufferWriteString(writer->out, "<?");
2461      if (count < 0)
2462          return -1;
2463      sum += count;
2464      count =
2465          xmlOutputBufferWriteString(writer->out, (const char *) p->name);
2466      if (count < 0)
2467          return -1;
2468      sum += count;
2469  
2470      return sum;
2471  }
2472  
2473  /**
2474   * xmlTextWriterEndPI:
2475   * @writer:  the xmlTextWriterPtr
2476   *
2477   * End the current xml PI.
2478   *
2479   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2480   */
2481  int
2482  xmlTextWriterEndPI(xmlTextWriterPtr writer)
2483  {
2484      int count;
2485      int sum;
2486      xmlLinkPtr lk;
2487      xmlTextWriterStackEntry *p;
2488  
2489      if (writer == NULL)
2490          return -1;
2491  
2492      lk = xmlListFront(writer->nodes);
2493      if (lk == 0)
2494          return 0;
2495  
2496      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2497      if (p == 0)
2498          return 0;
2499  
2500      sum = 0;
2501      switch (p->state) {
2502          case XML_TEXTWRITER_PI:
2503          case XML_TEXTWRITER_PI_TEXT:
2504              count = xmlOutputBufferWriteString(writer->out, "?>");
2505              if (count < 0)
2506                  return -1;
2507              sum += count;
2508              break;
2509          default:
2510              return -1;
2511      }
2512  
2513      if (writer->indent) {
2514          count = xmlOutputBufferWriteString(writer->out, "\n");
2515  	if (count < 0)
2516  	return -1;
2517          sum += count;
2518      }
2519  
2520      xmlListPopFront(writer->nodes);
2521      return sum;
2522  }
2523  
2524  /**
2525   * xmlTextWriterWriteFormatPI:
2526   * @writer:  the xmlTextWriterPtr
2527   * @target:  PI target
2528   * @format:  format string (see printf)
2529   * @...:  extra parameters for the format
2530   *
2531   * Write a formatted PI.
2532   *
2533   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2534   */
2535  int XMLCDECL
2536  xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target,
2537                             const char *format, ...)
2538  {
2539      int rc;
2540      va_list ap;
2541  
2542      va_start(ap, format);
2543  
2544      rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap);
2545  
2546      va_end(ap);
2547      return rc;
2548  }
2549  
2550  /**
2551   * xmlTextWriterWriteVFormatPI:
2552   * @writer:  the xmlTextWriterPtr
2553   * @target:  PI target
2554   * @format:  format string (see printf)
2555   * @argptr:  pointer to the first member of the variable argument list.
2556   *
2557   * Write a formatted xml PI.
2558   *
2559   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2560   */
2561  int
2562  xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer,
2563                              const xmlChar * target, const char *format,
2564                              va_list argptr)
2565  {
2566      int rc;
2567      xmlChar *buf;
2568  
2569      if (writer == NULL)
2570          return -1;
2571  
2572      buf = xmlTextWriterVSprintf(format, argptr);
2573      if (buf == NULL)
2574          return -1;
2575  
2576      rc = xmlTextWriterWritePI(writer, target, buf);
2577  
2578      xmlFree(buf);
2579      return rc;
2580  }
2581  
2582  /**
2583   * xmlTextWriterWritePI:
2584   * @writer:  the xmlTextWriterPtr
2585   * @target:  PI target
2586   * @content:  PI content
2587   *
2588   * Write an xml PI.
2589   *
2590   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2591   */
2592  int
2593  xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target,
2594                       const xmlChar * content)
2595  {
2596      int count;
2597      int sum;
2598  
2599      sum = 0;
2600      count = xmlTextWriterStartPI(writer, target);
2601      if (count == -1)
2602          return -1;
2603      sum += count;
2604      if (content != 0) {
2605          count = xmlTextWriterWriteString(writer, content);
2606          if (count == -1)
2607              return -1;
2608          sum += count;
2609      }
2610      count = xmlTextWriterEndPI(writer);
2611      if (count == -1)
2612          return -1;
2613      sum += count;
2614  
2615      return sum;
2616  }
2617  
2618  /**
2619   * xmlTextWriterStartCDATA:
2620   * @writer:  the xmlTextWriterPtr
2621   *
2622   * Start an xml CDATA section.
2623   *
2624   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2625   */
2626  int
2627  xmlTextWriterStartCDATA(xmlTextWriterPtr writer)
2628  {
2629      int count;
2630      int sum;
2631      xmlLinkPtr lk;
2632      xmlTextWriterStackEntry *p;
2633  
2634      if (writer == NULL)
2635          return -1;
2636  
2637      sum = 0;
2638      lk = xmlListFront(writer->nodes);
2639      if (lk != 0) {
2640          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2641          if (p != 0) {
2642              switch (p->state) {
2643                  case XML_TEXTWRITER_NONE:
2644  		case XML_TEXTWRITER_TEXT:
2645                  case XML_TEXTWRITER_PI:
2646                  case XML_TEXTWRITER_PI_TEXT:
2647                      break;
2648                  case XML_TEXTWRITER_ATTRIBUTE:
2649                      count = xmlTextWriterEndAttribute(writer);
2650                      if (count < 0)
2651                          return -1;
2652                      sum += count;
2653                      /* fallthrough */
2654                  case XML_TEXTWRITER_NAME:
2655                      /* Output namespace declarations */
2656                      count = xmlTextWriterOutputNSDecl(writer);
2657                      if (count < 0)
2658                          return -1;
2659                      sum += count;
2660                      count = xmlOutputBufferWriteString(writer->out, ">");
2661                      if (count < 0)
2662                          return -1;
2663                      sum += count;
2664                      p->state = XML_TEXTWRITER_TEXT;
2665                      break;
2666                  case XML_TEXTWRITER_CDATA:
2667                      xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2668                                      "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n");
2669                      return -1;
2670                  default:
2671                      return -1;
2672              }
2673          }
2674      }
2675  
2676      p = (xmlTextWriterStackEntry *)
2677          xmlMalloc(sizeof(xmlTextWriterStackEntry));
2678      if (p == 0) {
2679          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2680                          "xmlTextWriterStartCDATA : out of memory!\n");
2681          return -1;
2682      }
2683  
2684      p->name = NULL;
2685      p->state = XML_TEXTWRITER_CDATA;
2686  
2687      xmlListPushFront(writer->nodes, p);
2688  
2689      count = xmlOutputBufferWriteString(writer->out, "<![CDATA[");
2690      if (count < 0)
2691          return -1;
2692      sum += count;
2693  
2694      return sum;
2695  }
2696  
2697  /**
2698   * xmlTextWriterEndCDATA:
2699   * @writer:  the xmlTextWriterPtr
2700   *
2701   * End an xml CDATA section.
2702   *
2703   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2704   */
2705  int
2706  xmlTextWriterEndCDATA(xmlTextWriterPtr writer)
2707  {
2708      int count;
2709      int sum;
2710      xmlLinkPtr lk;
2711      xmlTextWriterStackEntry *p;
2712  
2713      if (writer == NULL)
2714          return -1;
2715  
2716      lk = xmlListFront(writer->nodes);
2717      if (lk == 0)
2718          return -1;
2719  
2720      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2721      if (p == 0)
2722          return -1;
2723  
2724      sum = 0;
2725      switch (p->state) {
2726          case XML_TEXTWRITER_CDATA:
2727              count = xmlOutputBufferWriteString(writer->out, "]]>");
2728              if (count < 0)
2729                  return -1;
2730              sum += count;
2731              break;
2732          default:
2733              return -1;
2734      }
2735  
2736      xmlListPopFront(writer->nodes);
2737      return sum;
2738  }
2739  
2740  /**
2741   * xmlTextWriterWriteFormatCDATA:
2742   * @writer:  the xmlTextWriterPtr
2743   * @format:  format string (see printf)
2744   * @...:  extra parameters for the format
2745   *
2746   * Write a formatted xml CDATA.
2747   *
2748   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2749   */
2750  int XMLCDECL
2751  xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format,
2752                                ...)
2753  {
2754      int rc;
2755      va_list ap;
2756  
2757      va_start(ap, format);
2758  
2759      rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap);
2760  
2761      va_end(ap);
2762      return rc;
2763  }
2764  
2765  /**
2766   * xmlTextWriterWriteVFormatCDATA:
2767   * @writer:  the xmlTextWriterPtr
2768   * @format:  format string (see printf)
2769   * @argptr:  pointer to the first member of the variable argument list.
2770   *
2771   * Write a formatted xml CDATA.
2772   *
2773   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2774   */
2775  int
2776  xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format,
2777                                 va_list argptr)
2778  {
2779      int rc;
2780      xmlChar *buf;
2781  
2782      if (writer == NULL)
2783          return -1;
2784  
2785      buf = xmlTextWriterVSprintf(format, argptr);
2786      if (buf == NULL)
2787          return -1;
2788  
2789      rc = xmlTextWriterWriteCDATA(writer, buf);
2790  
2791      xmlFree(buf);
2792      return rc;
2793  }
2794  
2795  /**
2796   * xmlTextWriterWriteCDATA:
2797   * @writer:  the xmlTextWriterPtr
2798   * @content:  CDATA content
2799   *
2800   * Write an xml CDATA.
2801   *
2802   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2803   */
2804  int
2805  xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content)
2806  {
2807      int count;
2808      int sum;
2809  
2810      sum = 0;
2811      count = xmlTextWriterStartCDATA(writer);
2812      if (count == -1)
2813          return -1;
2814      sum += count;
2815      if (content != 0) {
2816          count = xmlTextWriterWriteString(writer, content);
2817          if (count == -1)
2818              return -1;
2819          sum += count;
2820      }
2821      count = xmlTextWriterEndCDATA(writer);
2822      if (count == -1)
2823          return -1;
2824      sum += count;
2825  
2826      return sum;
2827  }
2828  
2829  /**
2830   * xmlTextWriterStartDTD:
2831   * @writer:  the xmlTextWriterPtr
2832   * @name:  the name of the DTD
2833   * @pubid:  the public identifier, which is an alternative to the system identifier
2834   * @sysid:  the system identifier, which is the URI of the DTD
2835   *
2836   * Start an xml DTD.
2837   *
2838   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2839   */
2840  int
2841  xmlTextWriterStartDTD(xmlTextWriterPtr writer,
2842                        const xmlChar * name,
2843                        const xmlChar * pubid, const xmlChar * sysid)
2844  {
2845      int count;
2846      int sum;
2847      xmlLinkPtr lk;
2848      xmlTextWriterStackEntry *p;
2849  
2850      if (writer == NULL || name == NULL || *name == '\0')
2851          return -1;
2852  
2853      sum = 0;
2854      lk = xmlListFront(writer->nodes);
2855      if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) {
2856          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2857                          "xmlTextWriterStartDTD : DTD allowed only in prolog!\n");
2858          return -1;
2859      }
2860  
2861      p = (xmlTextWriterStackEntry *)
2862          xmlMalloc(sizeof(xmlTextWriterStackEntry));
2863      if (p == 0) {
2864          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2865                          "xmlTextWriterStartDTD : out of memory!\n");
2866          return -1;
2867      }
2868  
2869      p->name = xmlStrdup(name);
2870      if (p->name == 0) {
2871          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
2872                          "xmlTextWriterStartDTD : out of memory!\n");
2873          xmlFree(p);
2874          return -1;
2875      }
2876      p->state = XML_TEXTWRITER_DTD;
2877  
2878      xmlListPushFront(writer->nodes, p);
2879  
2880      count = xmlOutputBufferWriteString(writer->out, "<!DOCTYPE ");
2881      if (count < 0)
2882          return -1;
2883      sum += count;
2884      count = xmlOutputBufferWriteString(writer->out, (const char *) name);
2885      if (count < 0)
2886          return -1;
2887      sum += count;
2888  
2889      if (pubid != 0) {
2890          if (sysid == 0) {
2891              xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
2892                              "xmlTextWriterStartDTD : system identifier needed!\n");
2893              return -1;
2894          }
2895  
2896          if (writer->indent)
2897              count = xmlOutputBufferWrite(writer->out, 1, "\n");
2898          else
2899              count = xmlOutputBufferWrite(writer->out, 1, " ");
2900          if (count < 0)
2901              return -1;
2902          sum += count;
2903  
2904          count = xmlOutputBufferWriteString(writer->out, "PUBLIC ");
2905          if (count < 0)
2906              return -1;
2907          sum += count;
2908  
2909          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2910          if (count < 0)
2911              return -1;
2912          sum += count;
2913  
2914          count =
2915              xmlOutputBufferWriteString(writer->out, (const char *) pubid);
2916          if (count < 0)
2917              return -1;
2918          sum += count;
2919  
2920          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2921          if (count < 0)
2922              return -1;
2923          sum += count;
2924      }
2925  
2926      if (sysid != 0) {
2927          if (pubid == 0) {
2928              if (writer->indent)
2929                  count = xmlOutputBufferWrite(writer->out, 1, "\n");
2930              else
2931                  count = xmlOutputBufferWrite(writer->out, 1, " ");
2932              if (count < 0)
2933                  return -1;
2934              sum += count;
2935              count = xmlOutputBufferWriteString(writer->out, "SYSTEM ");
2936              if (count < 0)
2937                  return -1;
2938              sum += count;
2939          } else {
2940  			if (writer->indent)
2941              count = xmlOutputBufferWriteString(writer->out, "\n       ");
2942              else
2943                  count = xmlOutputBufferWrite(writer->out, 1, " ");
2944              if (count < 0)
2945                  return -1;
2946              sum += count;
2947          }
2948  
2949          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2950          if (count < 0)
2951              return -1;
2952          sum += count;
2953  
2954          count =
2955              xmlOutputBufferWriteString(writer->out, (const char *) sysid);
2956          if (count < 0)
2957              return -1;
2958          sum += count;
2959  
2960          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
2961          if (count < 0)
2962              return -1;
2963          sum += count;
2964      }
2965  
2966      return sum;
2967  }
2968  
2969  /**
2970   * xmlTextWriterEndDTD:
2971   * @writer:  the xmlTextWriterPtr
2972   *
2973   * End an xml DTD.
2974   *
2975   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
2976   */
2977  int
2978  xmlTextWriterEndDTD(xmlTextWriterPtr writer)
2979  {
2980      int loop;
2981      int count;
2982      int sum;
2983      xmlLinkPtr lk;
2984      xmlTextWriterStackEntry *p;
2985  
2986      if (writer == NULL)
2987          return -1;
2988  
2989      sum = 0;
2990      loop = 1;
2991      while (loop) {
2992          lk = xmlListFront(writer->nodes);
2993          if (lk == NULL)
2994              break;
2995          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
2996          if (p == 0)
2997              break;
2998          switch (p->state) {
2999              case XML_TEXTWRITER_DTD_TEXT:
3000                  count = xmlOutputBufferWriteString(writer->out, "]");
3001                  if (count < 0)
3002                      return -1;
3003                  sum += count;
3004                  /* fallthrough */
3005              case XML_TEXTWRITER_DTD:
3006                  count = xmlOutputBufferWriteString(writer->out, ">");
3007  
3008                  if (writer->indent) {
3009                      if (count < 0)
3010                          return -1;
3011                      sum += count;
3012                      count = xmlOutputBufferWriteString(writer->out, "\n");
3013                  }
3014  
3015                  xmlListPopFront(writer->nodes);
3016                  break;
3017              case XML_TEXTWRITER_DTD_ELEM:
3018              case XML_TEXTWRITER_DTD_ELEM_TEXT:
3019                  count = xmlTextWriterEndDTDElement(writer);
3020                  break;
3021              case XML_TEXTWRITER_DTD_ATTL:
3022              case XML_TEXTWRITER_DTD_ATTL_TEXT:
3023                  count = xmlTextWriterEndDTDAttlist(writer);
3024                  break;
3025              case XML_TEXTWRITER_DTD_ENTY:
3026              case XML_TEXTWRITER_DTD_PENT:
3027              case XML_TEXTWRITER_DTD_ENTY_TEXT:
3028                  count = xmlTextWriterEndDTDEntity(writer);
3029                  break;
3030              case XML_TEXTWRITER_COMMENT:
3031                  count = xmlTextWriterEndComment(writer);
3032                  break;
3033              default:
3034                  loop = 0;
3035                  continue;
3036          }
3037  
3038          if (count < 0)
3039              return -1;
3040          sum += count;
3041      }
3042  
3043      return sum;
3044  }
3045  
3046  /**
3047   * xmlTextWriterWriteFormatDTD:
3048   * @writer:  the xmlTextWriterPtr
3049   * @name:  the name of the DTD
3050   * @pubid:  the public identifier, which is an alternative to the system identifier
3051   * @sysid:  the system identifier, which is the URI of the DTD
3052   * @format:  format string (see printf)
3053   * @...:  extra parameters for the format
3054   *
3055   * Write a DTD with a formatted markup declarations part.
3056   *
3057   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3058   */
3059  int XMLCDECL
3060  xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer,
3061                              const xmlChar * name,
3062                              const xmlChar * pubid,
3063                              const xmlChar * sysid, const char *format, ...)
3064  {
3065      int rc;
3066      va_list ap;
3067  
3068      va_start(ap, format);
3069  
3070      rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format,
3071                                        ap);
3072  
3073      va_end(ap);
3074      return rc;
3075  }
3076  
3077  /**
3078   * xmlTextWriterWriteVFormatDTD:
3079   * @writer:  the xmlTextWriterPtr
3080   * @name:  the name of the DTD
3081   * @pubid:  the public identifier, which is an alternative to the system identifier
3082   * @sysid:  the system identifier, which is the URI of the DTD
3083   * @format:  format string (see printf)
3084   * @argptr:  pointer to the first member of the variable argument list.
3085   *
3086   * Write a DTD with a formatted markup declarations part.
3087   *
3088   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3089   */
3090  int
3091  xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer,
3092                               const xmlChar * name,
3093                               const xmlChar * pubid,
3094                               const xmlChar * sysid,
3095                               const char *format, va_list argptr)
3096  {
3097      int rc;
3098      xmlChar *buf;
3099  
3100      if (writer == NULL)
3101          return -1;
3102  
3103      buf = xmlTextWriterVSprintf(format, argptr);
3104      if (buf == NULL)
3105          return -1;
3106  
3107      rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf);
3108  
3109      xmlFree(buf);
3110      return rc;
3111  }
3112  
3113  /**
3114   * xmlTextWriterWriteDTD:
3115   * @writer:  the xmlTextWriterPtr
3116   * @name:  the name of the DTD
3117   * @pubid:  the public identifier, which is an alternative to the system identifier
3118   * @sysid:  the system identifier, which is the URI of the DTD
3119   * @subset:  string content of the DTD
3120   *
3121   * Write a DTD.
3122   *
3123   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3124   */
3125  int
3126  xmlTextWriterWriteDTD(xmlTextWriterPtr writer,
3127                        const xmlChar * name,
3128                        const xmlChar * pubid,
3129                        const xmlChar * sysid, const xmlChar * subset)
3130  {
3131      int count;
3132      int sum;
3133  
3134      sum = 0;
3135      count = xmlTextWriterStartDTD(writer, name, pubid, sysid);
3136      if (count == -1)
3137          return -1;
3138      sum += count;
3139      if (subset != 0) {
3140          count = xmlTextWriterWriteString(writer, subset);
3141          if (count == -1)
3142              return -1;
3143          sum += count;
3144      }
3145      count = xmlTextWriterEndDTD(writer);
3146      if (count == -1)
3147          return -1;
3148      sum += count;
3149  
3150      return sum;
3151  }
3152  
3153  /**
3154   * xmlTextWriterStartDTDElement:
3155   * @writer:  the xmlTextWriterPtr
3156   * @name:  the name of the DTD element
3157   *
3158   * Start an xml DTD element.
3159   *
3160   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3161   */
3162  int
3163  xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name)
3164  {
3165      int count;
3166      int sum;
3167      xmlLinkPtr lk;
3168      xmlTextWriterStackEntry *p;
3169  
3170      if (writer == NULL || name == NULL || *name == '\0')
3171          return -1;
3172  
3173      sum = 0;
3174      lk = xmlListFront(writer->nodes);
3175      if (lk == 0) {
3176          return -1;
3177      }
3178  
3179      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3180      if (p != 0) {
3181          switch (p->state) {
3182              case XML_TEXTWRITER_DTD:
3183                  count = xmlOutputBufferWriteString(writer->out, " [");
3184                  if (count < 0)
3185                      return -1;
3186                  sum += count;
3187                  if (writer->indent) {
3188                      count = xmlOutputBufferWriteString(writer->out, "\n");
3189                      if (count < 0)
3190                          return -1;
3191                      sum += count;
3192                  }
3193                  p->state = XML_TEXTWRITER_DTD_TEXT;
3194                  /* fallthrough */
3195              case XML_TEXTWRITER_DTD_TEXT:
3196              case XML_TEXTWRITER_NONE:
3197                  break;
3198              default:
3199                  return -1;
3200          }
3201      }
3202  
3203      p = (xmlTextWriterStackEntry *)
3204          xmlMalloc(sizeof(xmlTextWriterStackEntry));
3205      if (p == 0) {
3206          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3207                          "xmlTextWriterStartDTDElement : out of memory!\n");
3208          return -1;
3209      }
3210  
3211      p->name = xmlStrdup(name);
3212      if (p->name == 0) {
3213          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3214                          "xmlTextWriterStartDTDElement : out of memory!\n");
3215          xmlFree(p);
3216          return -1;
3217      }
3218      p->state = XML_TEXTWRITER_DTD_ELEM;
3219  
3220      xmlListPushFront(writer->nodes, p);
3221  
3222      if (writer->indent) {
3223          count = xmlTextWriterWriteIndent(writer);
3224          if (count < 0)
3225              return -1;
3226          sum += count;
3227      }
3228  
3229      count = xmlOutputBufferWriteString(writer->out, "<!ELEMENT ");
3230      if (count < 0)
3231          return -1;
3232      sum += count;
3233      count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3234      if (count < 0)
3235          return -1;
3236      sum += count;
3237  
3238      return sum;
3239  }
3240  
3241  /**
3242   * xmlTextWriterEndDTDElement:
3243   * @writer:  the xmlTextWriterPtr
3244   *
3245   * End an xml DTD element.
3246   *
3247   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3248   */
3249  int
3250  xmlTextWriterEndDTDElement(xmlTextWriterPtr writer)
3251  {
3252      int count;
3253      int sum;
3254      xmlLinkPtr lk;
3255      xmlTextWriterStackEntry *p;
3256  
3257      if (writer == NULL)
3258          return -1;
3259  
3260      sum = 0;
3261      lk = xmlListFront(writer->nodes);
3262      if (lk == 0)
3263          return -1;
3264  
3265      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3266      if (p == 0)
3267          return -1;
3268  
3269      switch (p->state) {
3270          case XML_TEXTWRITER_DTD_ELEM:
3271          case XML_TEXTWRITER_DTD_ELEM_TEXT:
3272              count = xmlOutputBufferWriteString(writer->out, ">");
3273              if (count < 0)
3274                  return -1;
3275              sum += count;
3276              break;
3277          default:
3278              return -1;
3279      }
3280  
3281      if (writer->indent) {
3282          count = xmlOutputBufferWriteString(writer->out, "\n");
3283          if (count < 0)
3284              return -1;
3285          sum += count;
3286      }
3287  
3288      xmlListPopFront(writer->nodes);
3289      return sum;
3290  }
3291  
3292  /**
3293   * xmlTextWriterWriteFormatDTDElement:
3294   * @writer:  the xmlTextWriterPtr
3295   * @name:  the name of the DTD element
3296   * @format:  format string (see printf)
3297   * @...:  extra parameters for the format
3298   *
3299   * Write a formatted DTD element.
3300   *
3301   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3302   */
3303  int XMLCDECL
3304  xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer,
3305                                     const xmlChar * name,
3306                                     const char *format, ...)
3307  {
3308      int rc;
3309      va_list ap;
3310  
3311      va_start(ap, format);
3312  
3313      rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap);
3314  
3315      va_end(ap);
3316      return rc;
3317  }
3318  
3319  /**
3320   * xmlTextWriterWriteVFormatDTDElement:
3321   * @writer:  the xmlTextWriterPtr
3322   * @name:  the name of the DTD element
3323   * @format:  format string (see printf)
3324   * @argptr:  pointer to the first member of the variable argument list.
3325   *
3326   * Write a formatted DTD element.
3327   *
3328   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3329   */
3330  int
3331  xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer,
3332                                      const xmlChar * name,
3333                                      const char *format, va_list argptr)
3334  {
3335      int rc;
3336      xmlChar *buf;
3337  
3338      if (writer == NULL)
3339          return -1;
3340  
3341      buf = xmlTextWriterVSprintf(format, argptr);
3342      if (buf == NULL)
3343          return -1;
3344  
3345      rc = xmlTextWriterWriteDTDElement(writer, name, buf);
3346  
3347      xmlFree(buf);
3348      return rc;
3349  }
3350  
3351  /**
3352   * xmlTextWriterWriteDTDElement:
3353   * @writer:  the xmlTextWriterPtr
3354   * @name:  the name of the DTD element
3355   * @content:  content of the element
3356   *
3357   * Write a DTD element.
3358   *
3359   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3360   */
3361  int
3362  xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer,
3363                               const xmlChar * name, const xmlChar * content)
3364  {
3365      int count;
3366      int sum;
3367  
3368      if (content == NULL)
3369          return -1;
3370  
3371      sum = 0;
3372      count = xmlTextWriterStartDTDElement(writer, name);
3373      if (count == -1)
3374          return -1;
3375      sum += count;
3376  
3377      count = xmlTextWriterWriteString(writer, content);
3378      if (count == -1)
3379          return -1;
3380      sum += count;
3381  
3382      count = xmlTextWriterEndDTDElement(writer);
3383      if (count == -1)
3384          return -1;
3385      sum += count;
3386  
3387      return sum;
3388  }
3389  
3390  /**
3391   * xmlTextWriterStartDTDAttlist:
3392   * @writer:  the xmlTextWriterPtr
3393   * @name:  the name of the DTD ATTLIST
3394   *
3395   * Start an xml DTD ATTLIST.
3396   *
3397   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3398   */
3399  int
3400  xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name)
3401  {
3402      int count;
3403      int sum;
3404      xmlLinkPtr lk;
3405      xmlTextWriterStackEntry *p;
3406  
3407      if (writer == NULL || name == NULL || *name == '\0')
3408          return -1;
3409  
3410      sum = 0;
3411      lk = xmlListFront(writer->nodes);
3412      if (lk == 0) {
3413          return -1;
3414      }
3415  
3416      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3417      if (p != 0) {
3418          switch (p->state) {
3419              case XML_TEXTWRITER_DTD:
3420                  count = xmlOutputBufferWriteString(writer->out, " [");
3421                  if (count < 0)
3422                      return -1;
3423                  sum += count;
3424                  if (writer->indent) {
3425                      count = xmlOutputBufferWriteString(writer->out, "\n");
3426                      if (count < 0)
3427                          return -1;
3428                      sum += count;
3429                  }
3430                  p->state = XML_TEXTWRITER_DTD_TEXT;
3431                  /* fallthrough */
3432              case XML_TEXTWRITER_DTD_TEXT:
3433              case XML_TEXTWRITER_NONE:
3434                  break;
3435              default:
3436                  return -1;
3437          }
3438      }
3439  
3440      p = (xmlTextWriterStackEntry *)
3441          xmlMalloc(sizeof(xmlTextWriterStackEntry));
3442      if (p == 0) {
3443          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3444                          "xmlTextWriterStartDTDAttlist : out of memory!\n");
3445          return -1;
3446      }
3447  
3448      p->name = xmlStrdup(name);
3449      if (p->name == 0) {
3450          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3451                          "xmlTextWriterStartDTDAttlist : out of memory!\n");
3452          xmlFree(p);
3453          return -1;
3454      }
3455      p->state = XML_TEXTWRITER_DTD_ATTL;
3456  
3457      xmlListPushFront(writer->nodes, p);
3458  
3459      if (writer->indent) {
3460          count = xmlTextWriterWriteIndent(writer);
3461          if (count < 0)
3462              return -1;
3463          sum += count;
3464      }
3465  
3466      count = xmlOutputBufferWriteString(writer->out, "<!ATTLIST ");
3467      if (count < 0)
3468          return -1;
3469      sum += count;
3470      count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3471      if (count < 0)
3472          return -1;
3473      sum += count;
3474  
3475      return sum;
3476  }
3477  
3478  /**
3479   * xmlTextWriterEndDTDAttlist:
3480   * @writer:  the xmlTextWriterPtr
3481   *
3482   * End an xml DTD attribute list.
3483   *
3484   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3485   */
3486  int
3487  xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer)
3488  {
3489      int count;
3490      int sum;
3491      xmlLinkPtr lk;
3492      xmlTextWriterStackEntry *p;
3493  
3494      if (writer == NULL)
3495          return -1;
3496  
3497      sum = 0;
3498      lk = xmlListFront(writer->nodes);
3499      if (lk == 0)
3500          return -1;
3501  
3502      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3503      if (p == 0)
3504          return -1;
3505  
3506      switch (p->state) {
3507          case XML_TEXTWRITER_DTD_ATTL:
3508          case XML_TEXTWRITER_DTD_ATTL_TEXT:
3509              count = xmlOutputBufferWriteString(writer->out, ">");
3510              if (count < 0)
3511                  return -1;
3512              sum += count;
3513              break;
3514          default:
3515              return -1;
3516      }
3517  
3518      if (writer->indent) {
3519          count = xmlOutputBufferWriteString(writer->out, "\n");
3520          if (count < 0)
3521              return -1;
3522          sum += count;
3523      }
3524  
3525      xmlListPopFront(writer->nodes);
3526      return sum;
3527  }
3528  
3529  /**
3530   * xmlTextWriterWriteFormatDTDAttlist:
3531   * @writer:  the xmlTextWriterPtr
3532   * @name:  the name of the DTD ATTLIST
3533   * @format:  format string (see printf)
3534   * @...:  extra parameters for the format
3535   *
3536   * Write a formatted DTD ATTLIST.
3537   *
3538   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3539   */
3540  int XMLCDECL
3541  xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer,
3542                                     const xmlChar * name,
3543                                     const char *format, ...)
3544  {
3545      int rc;
3546      va_list ap;
3547  
3548      va_start(ap, format);
3549  
3550      rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap);
3551  
3552      va_end(ap);
3553      return rc;
3554  }
3555  
3556  /**
3557   * xmlTextWriterWriteVFormatDTDAttlist:
3558   * @writer:  the xmlTextWriterPtr
3559   * @name:  the name of the DTD ATTLIST
3560   * @format:  format string (see printf)
3561   * @argptr:  pointer to the first member of the variable argument list.
3562   *
3563   * Write a formatted DTD ATTLIST.
3564   *
3565   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3566   */
3567  int
3568  xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer,
3569                                      const xmlChar * name,
3570                                      const char *format, va_list argptr)
3571  {
3572      int rc;
3573      xmlChar *buf;
3574  
3575      if (writer == NULL)
3576          return -1;
3577  
3578      buf = xmlTextWriterVSprintf(format, argptr);
3579      if (buf == NULL)
3580          return -1;
3581  
3582      rc = xmlTextWriterWriteDTDAttlist(writer, name, buf);
3583  
3584      xmlFree(buf);
3585      return rc;
3586  }
3587  
3588  /**
3589   * xmlTextWriterWriteDTDAttlist:
3590   * @writer:  the xmlTextWriterPtr
3591   * @name:  the name of the DTD ATTLIST
3592   * @content:  content of the ATTLIST
3593   *
3594   * Write a DTD ATTLIST.
3595   *
3596   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3597   */
3598  int
3599  xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer,
3600                               const xmlChar * name, const xmlChar * content)
3601  {
3602      int count;
3603      int sum;
3604  
3605      if (content == NULL)
3606          return -1;
3607  
3608      sum = 0;
3609      count = xmlTextWriterStartDTDAttlist(writer, name);
3610      if (count == -1)
3611          return -1;
3612      sum += count;
3613  
3614      count = xmlTextWriterWriteString(writer, content);
3615      if (count == -1)
3616          return -1;
3617      sum += count;
3618  
3619      count = xmlTextWriterEndDTDAttlist(writer);
3620      if (count == -1)
3621          return -1;
3622      sum += count;
3623  
3624      return sum;
3625  }
3626  
3627  /**
3628   * xmlTextWriterStartDTDEntity:
3629   * @writer:  the xmlTextWriterPtr
3630   * @pe:  TRUE if this is a parameter entity, FALSE if not
3631   * @name:  the name of the DTD ATTLIST
3632   *
3633   * Start an xml DTD ATTLIST.
3634   *
3635   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3636   */
3637  int
3638  xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer,
3639                              int pe, const xmlChar * name)
3640  {
3641      int count;
3642      int sum;
3643      xmlLinkPtr lk;
3644      xmlTextWriterStackEntry *p;
3645  
3646      if (writer == NULL || name == NULL || *name == '\0')
3647          return -1;
3648  
3649      sum = 0;
3650      lk = xmlListFront(writer->nodes);
3651      if (lk != 0) {
3652  
3653          p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3654          if (p != 0) {
3655              switch (p->state) {
3656                  case XML_TEXTWRITER_DTD:
3657                      count = xmlOutputBufferWriteString(writer->out, " [");
3658                      if (count < 0)
3659                          return -1;
3660                      sum += count;
3661                      if (writer->indent) {
3662                          count =
3663                              xmlOutputBufferWriteString(writer->out, "\n");
3664                          if (count < 0)
3665                              return -1;
3666                          sum += count;
3667                      }
3668                      p->state = XML_TEXTWRITER_DTD_TEXT;
3669                      /* fallthrough */
3670                  case XML_TEXTWRITER_DTD_TEXT:
3671                  case XML_TEXTWRITER_NONE:
3672                      break;
3673                  default:
3674                      return -1;
3675              }
3676          }
3677      }
3678  
3679      p = (xmlTextWriterStackEntry *)
3680          xmlMalloc(sizeof(xmlTextWriterStackEntry));
3681      if (p == 0) {
3682          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3683                          "xmlTextWriterStartDTDElement : out of memory!\n");
3684          return -1;
3685      }
3686  
3687      p->name = xmlStrdup(name);
3688      if (p->name == 0) {
3689          xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY,
3690                          "xmlTextWriterStartDTDElement : out of memory!\n");
3691          xmlFree(p);
3692          return -1;
3693      }
3694  
3695      if (pe != 0)
3696          p->state = XML_TEXTWRITER_DTD_PENT;
3697      else
3698          p->state = XML_TEXTWRITER_DTD_ENTY;
3699  
3700      xmlListPushFront(writer->nodes, p);
3701  
3702      if (writer->indent) {
3703          count = xmlTextWriterWriteIndent(writer);
3704          if (count < 0)
3705              return -1;
3706          sum += count;
3707      }
3708  
3709      count = xmlOutputBufferWriteString(writer->out, "<!ENTITY ");
3710      if (count < 0)
3711          return -1;
3712      sum += count;
3713  
3714      if (pe != 0) {
3715          count = xmlOutputBufferWriteString(writer->out, "% ");
3716          if (count < 0)
3717              return -1;
3718          sum += count;
3719      }
3720  
3721      count = xmlOutputBufferWriteString(writer->out, (const char *) name);
3722      if (count < 0)
3723          return -1;
3724      sum += count;
3725  
3726      return sum;
3727  }
3728  
3729  /**
3730   * xmlTextWriterEndDTDEntity:
3731   * @writer:  the xmlTextWriterPtr
3732   *
3733   * End an xml DTD entity.
3734   *
3735   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3736   */
3737  int
3738  xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer)
3739  {
3740      int count;
3741      int sum;
3742      xmlLinkPtr lk;
3743      xmlTextWriterStackEntry *p;
3744  
3745      if (writer == NULL)
3746          return -1;
3747  
3748      sum = 0;
3749      lk = xmlListFront(writer->nodes);
3750      if (lk == 0)
3751          return -1;
3752  
3753      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
3754      if (p == 0)
3755          return -1;
3756  
3757      switch (p->state) {
3758          case XML_TEXTWRITER_DTD_ENTY_TEXT:
3759              count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
3760              if (count < 0)
3761                  return -1;
3762              sum += count;
3763          case XML_TEXTWRITER_DTD_ENTY:
3764          case XML_TEXTWRITER_DTD_PENT:
3765              count = xmlOutputBufferWriteString(writer->out, ">");
3766              if (count < 0)
3767                  return -1;
3768              sum += count;
3769              break;
3770          default:
3771              return -1;
3772      }
3773  
3774      if (writer->indent) {
3775          count = xmlOutputBufferWriteString(writer->out, "\n");
3776          if (count < 0)
3777              return -1;
3778          sum += count;
3779      }
3780  
3781      xmlListPopFront(writer->nodes);
3782      return sum;
3783  }
3784  
3785  /**
3786   * xmlTextWriterWriteFormatDTDInternalEntity:
3787   * @writer:  the xmlTextWriterPtr
3788   * @pe:  TRUE if this is a parameter entity, FALSE if not
3789   * @name:  the name of the DTD entity
3790   * @format:  format string (see printf)
3791   * @...:  extra parameters for the format
3792   *
3793   * Write a formatted DTD internal entity.
3794   *
3795   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3796   */
3797  int XMLCDECL
3798  xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer,
3799                                            int pe,
3800                                            const xmlChar * name,
3801                                            const char *format, ...)
3802  {
3803      int rc;
3804      va_list ap;
3805  
3806      va_start(ap, format);
3807  
3808      rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name,
3809                                                      format, ap);
3810  
3811      va_end(ap);
3812      return rc;
3813  }
3814  
3815  /**
3816   * xmlTextWriterWriteVFormatDTDInternalEntity:
3817   * @writer:  the xmlTextWriterPtr
3818   * @pe:  TRUE if this is a parameter entity, FALSE if not
3819   * @name:  the name of the DTD entity
3820   * @format:  format string (see printf)
3821   * @argptr:  pointer to the first member of the variable argument list.
3822   *
3823   * Write a formatted DTD internal entity.
3824   *
3825   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3826   */
3827  int
3828  xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer,
3829                                             int pe,
3830                                             const xmlChar * name,
3831                                             const char *format,
3832                                             va_list argptr)
3833  {
3834      int rc;
3835      xmlChar *buf;
3836  
3837      if (writer == NULL)
3838          return -1;
3839  
3840      buf = xmlTextWriterVSprintf(format, argptr);
3841      if (buf == NULL)
3842          return -1;
3843  
3844      rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf);
3845  
3846      xmlFree(buf);
3847      return rc;
3848  }
3849  
3850  /**
3851   * xmlTextWriterWriteDTDEntity:
3852   * @writer:  the xmlTextWriterPtr
3853   * @pe:  TRUE if this is a parameter entity, FALSE if not
3854   * @name:  the name of the DTD entity
3855   * @pubid:  the public identifier, which is an alternative to the system identifier
3856   * @sysid:  the system identifier, which is the URI of the DTD
3857   * @ndataid:  the xml notation name.
3858   * @content:  content of the entity
3859   *
3860   * Write a DTD entity.
3861   *
3862   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3863   */
3864  int
3865  xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer,
3866                              int pe,
3867                              const xmlChar * name,
3868                              const xmlChar * pubid,
3869                              const xmlChar * sysid,
3870                              const xmlChar * ndataid,
3871                              const xmlChar * content)
3872  {
3873      if ((content == NULL) && (pubid == NULL) && (sysid == NULL))
3874          return -1;
3875      if ((pe != 0) && (ndataid != NULL))
3876          return -1;
3877  
3878      if ((pubid == NULL) && (sysid == NULL))
3879          return xmlTextWriterWriteDTDInternalEntity(writer, pe, name,
3880                                                     content);
3881  
3882      return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid,
3883                                                 sysid, ndataid);
3884  }
3885  
3886  /**
3887   * xmlTextWriterWriteDTDInternalEntity:
3888   * @writer:  the xmlTextWriterPtr
3889   * @pe:  TRUE if this is a parameter entity, FALSE if not
3890   * @name:  the name of the DTD entity
3891   * @content:  content of the entity
3892   *
3893   * Write a DTD internal entity.
3894   *
3895   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3896   */
3897  int
3898  xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer,
3899                                      int pe,
3900                                      const xmlChar * name,
3901                                      const xmlChar * content)
3902  {
3903      int count;
3904      int sum;
3905  
3906      if ((name == NULL) || (*name == '\0') || (content == NULL))
3907          return -1;
3908  
3909      sum = 0;
3910      count = xmlTextWriterStartDTDEntity(writer, pe, name);
3911      if (count == -1)
3912          return -1;
3913      sum += count;
3914  
3915      count = xmlTextWriterWriteString(writer, content);
3916      if (count == -1)
3917          return -1;
3918      sum += count;
3919  
3920      count = xmlTextWriterEndDTDEntity(writer);
3921      if (count == -1)
3922          return -1;
3923      sum += count;
3924  
3925      return sum;
3926  }
3927  
3928  /**
3929   * xmlTextWriterWriteDTDExternalEntity:
3930   * @writer:  the xmlTextWriterPtr
3931   * @pe:  TRUE if this is a parameter entity, FALSE if not
3932   * @name:  the name of the DTD entity
3933   * @pubid:  the public identifier, which is an alternative to the system identifier
3934   * @sysid:  the system identifier, which is the URI of the DTD
3935   * @ndataid:  the xml notation name.
3936   *
3937   * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity
3938   *
3939   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3940   */
3941  int
3942  xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer,
3943                                      int pe,
3944                                      const xmlChar * name,
3945                                      const xmlChar * pubid,
3946                                      const xmlChar * sysid,
3947                                      const xmlChar * ndataid)
3948  {
3949      int count;
3950      int sum;
3951  
3952      if (((pubid == NULL) && (sysid == NULL)))
3953          return -1;
3954      if ((pe != 0) && (ndataid != NULL))
3955          return -1;
3956  
3957      sum = 0;
3958      count = xmlTextWriterStartDTDEntity(writer, pe, name);
3959      if (count == -1)
3960          return -1;
3961      sum += count;
3962  
3963      count =
3964          xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid,
3965                                                      ndataid);
3966      if (count < 0)
3967          return -1;
3968      sum += count;
3969  
3970      count = xmlTextWriterEndDTDEntity(writer);
3971      if (count == -1)
3972          return -1;
3973      sum += count;
3974  
3975      return sum;
3976  }
3977  
3978  /**
3979   * xmlTextWriterWriteDTDExternalEntityContents:
3980   * @writer:  the xmlTextWriterPtr
3981   * @pubid:  the public identifier, which is an alternative to the system identifier
3982   * @sysid:  the system identifier, which is the URI of the DTD
3983   * @ndataid:  the xml notation name.
3984   *
3985   * Write the contents of a DTD external entity.
3986   *
3987   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
3988   */
3989  int
3990  xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer,
3991                                              const xmlChar * pubid,
3992                                              const xmlChar * sysid,
3993                                              const xmlChar * ndataid)
3994  {
3995      int count;
3996      int sum;
3997      xmlLinkPtr lk;
3998      xmlTextWriterStackEntry *p;
3999  
4000      if (writer == NULL) {
4001          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4002                          "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n");
4003          return -1;
4004      }
4005  
4006      sum = 0;
4007      lk = xmlListFront(writer->nodes);
4008      if (lk == 0) {
4009          xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4010                          "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4011          return -1;
4012      }
4013  
4014      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4015      if (p == 0)
4016          return -1;
4017  
4018      switch (p->state) {
4019          case XML_TEXTWRITER_DTD_ENTY:
4020              break;
4021          case XML_TEXTWRITER_DTD_PENT:
4022              if (ndataid != NULL) {
4023                  xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4024                                  "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n");
4025                  return -1;
4026              }
4027              break;
4028          default:
4029              xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4030                              "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n");
4031              return -1;
4032      }
4033  
4034      if (pubid != 0) {
4035          if (sysid == 0) {
4036              xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
4037                              "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n");
4038              return -1;
4039          }
4040  
4041          count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4042          if (count < 0)
4043              return -1;
4044          sum += count;
4045  
4046          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4047          if (count < 0)
4048              return -1;
4049          sum += count;
4050  
4051          count =
4052              xmlOutputBufferWriteString(writer->out, (const char *) pubid);
4053          if (count < 0)
4054              return -1;
4055          sum += count;
4056  
4057          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4058          if (count < 0)
4059              return -1;
4060          sum += count;
4061      }
4062  
4063      if (sysid != 0) {
4064          if (pubid == 0) {
4065              count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4066              if (count < 0)
4067                  return -1;
4068              sum += count;
4069          }
4070  
4071          count = xmlOutputBufferWriteString(writer->out, " ");
4072          if (count < 0)
4073              return -1;
4074          sum += count;
4075  
4076          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4077          if (count < 0)
4078              return -1;
4079          sum += count;
4080  
4081          count =
4082              xmlOutputBufferWriteString(writer->out, (const char *) sysid);
4083          if (count < 0)
4084              return -1;
4085          sum += count;
4086  
4087          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4088          if (count < 0)
4089              return -1;
4090          sum += count;
4091      }
4092  
4093      if (ndataid != NULL) {
4094          count = xmlOutputBufferWriteString(writer->out, " NDATA ");
4095          if (count < 0)
4096              return -1;
4097          sum += count;
4098  
4099          count =
4100              xmlOutputBufferWriteString(writer->out,
4101                                         (const char *) ndataid);
4102          if (count < 0)
4103              return -1;
4104          sum += count;
4105      }
4106  
4107      return sum;
4108  }
4109  
4110  /**
4111   * xmlTextWriterWriteDTDNotation:
4112   * @writer:  the xmlTextWriterPtr
4113   * @name:  the name of the xml notation
4114   * @pubid:  the public identifier, which is an alternative to the system identifier
4115   * @sysid:  the system identifier, which is the URI of the DTD
4116   *
4117   * Write a DTD entity.
4118   *
4119   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4120   */
4121  int
4122  xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer,
4123                                const xmlChar * name,
4124                                const xmlChar * pubid, const xmlChar * sysid)
4125  {
4126      int count;
4127      int sum;
4128      xmlLinkPtr lk;
4129      xmlTextWriterStackEntry *p;
4130  
4131      if (writer == NULL || name == NULL || *name == '\0')
4132          return -1;
4133  
4134      sum = 0;
4135      lk = xmlListFront(writer->nodes);
4136      if (lk == 0) {
4137          return -1;
4138      }
4139  
4140      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4141      if (p != 0) {
4142          switch (p->state) {
4143              case XML_TEXTWRITER_DTD:
4144                  count = xmlOutputBufferWriteString(writer->out, " [");
4145                  if (count < 0)
4146                      return -1;
4147                  sum += count;
4148                  if (writer->indent) {
4149                      count = xmlOutputBufferWriteString(writer->out, "\n");
4150                      if (count < 0)
4151                          return -1;
4152                      sum += count;
4153                  }
4154                  p->state = XML_TEXTWRITER_DTD_TEXT;
4155                  /* fallthrough */
4156              case XML_TEXTWRITER_DTD_TEXT:
4157                  break;
4158              default:
4159                  return -1;
4160          }
4161      }
4162  
4163      if (writer->indent) {
4164          count = xmlTextWriterWriteIndent(writer);
4165          if (count < 0)
4166              return -1;
4167          sum += count;
4168      }
4169  
4170      count = xmlOutputBufferWriteString(writer->out, "<!NOTATION ");
4171      if (count < 0)
4172          return -1;
4173      sum += count;
4174      count = xmlOutputBufferWriteString(writer->out, (const char *) name);
4175      if (count < 0)
4176          return -1;
4177      sum += count;
4178  
4179      if (pubid != 0) {
4180          count = xmlOutputBufferWriteString(writer->out, " PUBLIC ");
4181          if (count < 0)
4182              return -1;
4183          sum += count;
4184          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4185          if (count < 0)
4186              return -1;
4187          sum += count;
4188          count =
4189              xmlOutputBufferWriteString(writer->out, (const char *) pubid);
4190          if (count < 0)
4191              return -1;
4192          sum += count;
4193          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4194          if (count < 0)
4195              return -1;
4196          sum += count;
4197      }
4198  
4199      if (sysid != 0) {
4200          if (pubid == 0) {
4201              count = xmlOutputBufferWriteString(writer->out, " SYSTEM");
4202              if (count < 0)
4203                  return -1;
4204              sum += count;
4205          }
4206          count = xmlOutputBufferWriteString(writer->out, " ");
4207          if (count < 0)
4208              return -1;
4209          sum += count;
4210          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4211          if (count < 0)
4212              return -1;
4213          sum += count;
4214          count =
4215              xmlOutputBufferWriteString(writer->out, (const char *) sysid);
4216          if (count < 0)
4217              return -1;
4218          sum += count;
4219          count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar);
4220          if (count < 0)
4221              return -1;
4222          sum += count;
4223      }
4224  
4225      count = xmlOutputBufferWriteString(writer->out, ">");
4226      if (count < 0)
4227          return -1;
4228      sum += count;
4229  
4230      return sum;
4231  }
4232  
4233  /**
4234   * xmlTextWriterFlush:
4235   * @writer:  the xmlTextWriterPtr
4236   *
4237   * Flush the output buffer.
4238   *
4239   * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
4240   */
4241  int
4242  xmlTextWriterFlush(xmlTextWriterPtr writer)
4243  {
4244      int count;
4245  
4246      if (writer == NULL)
4247          return -1;
4248  
4249      if (writer->out == NULL)
4250          count = 0;
4251      else
4252          count = xmlOutputBufferFlush(writer->out);
4253  
4254      return count;
4255  }
4256  
4257  /**
4258   * misc
4259   */
4260  
4261  /**
4262   * xmlFreeTextWriterStackEntry:
4263   * @lk:  the xmlLinkPtr
4264   *
4265   * Free callback for the xmlList.
4266   */
4267  static void
4268  xmlFreeTextWriterStackEntry(xmlLinkPtr lk)
4269  {
4270      xmlTextWriterStackEntry *p;
4271  
4272      p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
4273      if (p == 0)
4274          return;
4275  
4276      if (p->name != 0)
4277          xmlFree(p->name);
4278      xmlFree(p);
4279  }
4280  
4281  /**
4282   * xmlCmpTextWriterStackEntry:
4283   * @data0:  the first data
4284   * @data1:  the second data
4285   *
4286   * Compare callback for the xmlList.
4287   *
4288   * Returns -1, 0, 1
4289   */
4290  static int
4291  xmlCmpTextWriterStackEntry(const void *data0, const void *data1)
4292  {
4293      xmlTextWriterStackEntry *p0;
4294      xmlTextWriterStackEntry *p1;
4295  
4296      if (data0 == data1)
4297          return 0;
4298  
4299      if (data0 == 0)
4300          return -1;
4301  
4302      if (data1 == 0)
4303          return 1;
4304  
4305      p0 = (xmlTextWriterStackEntry *) data0;
4306      p1 = (xmlTextWriterStackEntry *) data1;
4307  
4308      return xmlStrcmp(p0->name, p1->name);
4309  }
4310  
4311  /**
4312   * misc
4313   */
4314  
4315  /**
4316   * xmlTextWriterOutputNSDecl:
4317   * @writer:  the xmlTextWriterPtr
4318   *
4319   * Output the current namespace declarations.
4320   */
4321  static int
4322  xmlTextWriterOutputNSDecl(xmlTextWriterPtr writer)
4323  {
4324      xmlLinkPtr lk;
4325      xmlTextWriterNsStackEntry *np;
4326      int count;
4327      int sum;
4328  
4329      sum = 0;
4330      while (!xmlListEmpty(writer->nsstack)) {
4331          xmlChar *namespaceURI = NULL;
4332          xmlChar *prefix = NULL;
4333  
4334          lk = xmlListFront(writer->nsstack);
4335          np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4336  
4337          if (np != 0) {
4338              namespaceURI = xmlStrdup(np->uri);
4339              prefix = xmlStrdup(np->prefix);
4340          }
4341  
4342          xmlListPopFront(writer->nsstack);
4343  
4344          if (np != 0) {
4345              count = xmlTextWriterWriteAttribute(writer, prefix, namespaceURI);
4346              xmlFree(namespaceURI);
4347              xmlFree(prefix);
4348  
4349              if (count < 0) {
4350                  xmlListDelete(writer->nsstack);
4351                  writer->nsstack = NULL;
4352                  return -1;
4353              }
4354              sum += count;
4355          }
4356      }
4357      return sum;
4358  }
4359  
4360  /**
4361   * xmlFreeTextWriterNsStackEntry:
4362   * @lk:  the xmlLinkPtr
4363   *
4364   * Free callback for the xmlList.
4365   */
4366  static void
4367  xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk)
4368  {
4369      xmlTextWriterNsStackEntry *p;
4370  
4371      p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk);
4372      if (p == 0)
4373          return;
4374  
4375      if (p->prefix != 0)
4376          xmlFree(p->prefix);
4377      if (p->uri != 0)
4378          xmlFree(p->uri);
4379  
4380      xmlFree(p);
4381  }
4382  
4383  /**
4384   * xmlCmpTextWriterNsStackEntry:
4385   * @data0:  the first data
4386   * @data1:  the second data
4387   *
4388   * Compare callback for the xmlList.
4389   *
4390   * Returns -1, 0, 1
4391   */
4392  static int
4393  xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1)
4394  {
4395      xmlTextWriterNsStackEntry *p0;
4396      xmlTextWriterNsStackEntry *p1;
4397      int rc;
4398  
4399      if (data0 == data1)
4400          return 0;
4401  
4402      if (data0 == 0)
4403          return -1;
4404  
4405      if (data1 == 0)
4406          return 1;
4407  
4408      p0 = (xmlTextWriterNsStackEntry *) data0;
4409      p1 = (xmlTextWriterNsStackEntry *) data1;
4410  
4411      rc = xmlStrcmp(p0->prefix, p1->prefix);
4412  
4413      if ((rc != 0) || (p0->elem != p1->elem))
4414          rc = -1;
4415  
4416      return rc;
4417  }
4418  
4419  /**
4420   * xmlTextWriterWriteDocCallback:
4421   * @context:  the xmlBufferPtr
4422   * @str:  the data to write
4423   * @len:  the length of the data
4424   *
4425   * Write callback for the xmlOutputBuffer with target xmlBuffer
4426   *
4427   * Returns -1, 0, 1
4428   */
4429  static int
4430  xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
4431  {
4432      xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4433      int rc;
4434  
4435      if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
4436          xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
4437                          "xmlTextWriterWriteDocCallback : XML error %d !\n",
4438                          rc);
4439          return -1;
4440      }
4441  
4442      return len;
4443  }
4444  
4445  /**
4446   * xmlTextWriterCloseDocCallback:
4447   * @context:  the xmlBufferPtr
4448   *
4449   * Close callback for the xmlOutputBuffer with target xmlBuffer
4450   *
4451   * Returns -1, 0, 1
4452   */
4453  static int
4454  xmlTextWriterCloseDocCallback(void *context)
4455  {
4456      xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
4457      int rc;
4458  
4459      if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
4460          xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
4461                          "xmlTextWriterWriteDocCallback : XML error %d !\n",
4462                          rc);
4463          return -1;
4464      }
4465  
4466      return 0;
4467  }
4468  
4469  /**
4470   * xmlTextWriterVSprintf:
4471   * @format:  see printf
4472   * @argptr:  pointer to the first member of the variable argument list.
4473   *
4474   * Utility function for formatted output
4475   *
4476   * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
4477   */
4478  static xmlChar *
4479  xmlTextWriterVSprintf(const char *format, va_list argptr)
4480  {
4481      int size;
4482      int count;
4483      xmlChar *buf;
4484      va_list locarg;
4485  
4486      size = BUFSIZ;
4487      buf = (xmlChar *) xmlMalloc(size);
4488      if (buf == NULL) {
4489          xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
4490                          "xmlTextWriterVSprintf : out of memory!\n");
4491          return NULL;
4492      }
4493  
4494      VA_COPY(locarg, argptr);
4495      while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0)
4496             || (count == size - 1) || (count == size) || (count > size)) {
4497  	va_end(locarg);
4498          xmlFree(buf);
4499          size += BUFSIZ;
4500          buf = (xmlChar *) xmlMalloc(size);
4501          if (buf == NULL) {
4502              xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
4503                              "xmlTextWriterVSprintf : out of memory!\n");
4504              return NULL;
4505          }
4506  	VA_COPY(locarg, argptr);
4507      }
4508      va_end(locarg);
4509  
4510      return buf;
4511  }
4512  
4513  /**
4514   * xmlTextWriterStartDocumentCallback:
4515   * @ctx: the user data (XML parser context)
4516   *
4517   * called at the start of document processing.
4518   */
4519  static void
4520  xmlTextWriterStartDocumentCallback(void *ctx)
4521  {
4522      xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
4523      xmlDocPtr doc;
4524  
4525      if (ctxt->html) {
4526  #ifdef LIBXML_HTML_ENABLED
4527          if (ctxt->myDoc == NULL)
4528              ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
4529          if (ctxt->myDoc == NULL) {
4530              if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4531                  ctxt->sax->error(ctxt->userData,
4532                                   "SAX.startDocument(): out of memory\n");
4533              ctxt->errNo = XML_ERR_NO_MEMORY;
4534              ctxt->instate = XML_PARSER_EOF;
4535              ctxt->disableSAX = 1;
4536              return;
4537          }
4538  #else
4539          xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR,
4540                          "libxml2 built without HTML support\n");
4541          ctxt->errNo = XML_ERR_INTERNAL_ERROR;
4542          ctxt->instate = XML_PARSER_EOF;
4543          ctxt->disableSAX = 1;
4544          return;
4545  #endif
4546      } else {
4547          doc = ctxt->myDoc;
4548          if (doc == NULL)
4549              doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
4550          if (doc != NULL) {
4551              if (doc->children == NULL) {
4552                  if (ctxt->encoding != NULL)
4553                      doc->encoding = xmlStrdup(ctxt->encoding);
4554                  else
4555                      doc->encoding = NULL;
4556                  doc->standalone = ctxt->standalone;
4557              }
4558          } else {
4559              if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4560                  ctxt->sax->error(ctxt->userData,
4561                                   "SAX.startDocument(): out of memory\n");
4562              ctxt->errNo = XML_ERR_NO_MEMORY;
4563              ctxt->instate = XML_PARSER_EOF;
4564              ctxt->disableSAX = 1;
4565              return;
4566          }
4567      }
4568      if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
4569          (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
4570          ctxt->myDoc->URL =
4571              xmlCanonicPath((const xmlChar *) ctxt->input->filename);
4572          if (ctxt->myDoc->URL == NULL)
4573              ctxt->myDoc->URL =
4574                  xmlStrdup((const xmlChar *) ctxt->input->filename);
4575      }
4576  }
4577  
4578  /**
4579   * xmlTextWriterSetIndent:
4580   * @writer:  the xmlTextWriterPtr
4581   * @indent:  do indentation?
4582   *
4583   * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation.
4584   *
4585   * Returns -1 on error or 0 otherwise.
4586   */
4587  int
4588  xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent)
4589  {
4590      if ((writer == NULL) || (indent < 0))
4591          return -1;
4592  
4593      writer->indent = indent;
4594      writer->doindent = 1;
4595  
4596      return 0;
4597  }
4598  
4599  /**
4600   * xmlTextWriterSetIndentString:
4601   * @writer:  the xmlTextWriterPtr
4602   * @str:  the xmlChar string
4603   *
4604   * Set string indentation.
4605   *
4606   * Returns -1 on error or 0 otherwise.
4607   */
4608  int
4609  xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str)
4610  {
4611      if ((writer == NULL) || (!str))
4612          return -1;
4613  
4614      if (writer->ichar != NULL)
4615          xmlFree(writer->ichar);
4616      writer->ichar = xmlStrdup(str);
4617  
4618      if (!writer->ichar)
4619          return -1;
4620      else
4621          return 0;
4622  }
4623  
4624  /**
4625   * xmlTextWriterSetQuoteChar:
4626   * @writer:  the xmlTextWriterPtr
4627   * @quotechar:  the quote character
4628   *
4629   * Set the character used for quoting attributes.
4630   *
4631   * Returns -1 on error or 0 otherwise.
4632   */
4633  int
4634  xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar)
4635  {
4636      if ((writer == NULL) || ((quotechar != '\'') && (quotechar != '"')))
4637          return -1;
4638  
4639      writer->qchar = quotechar;
4640  
4641      return 0;
4642  }
4643  
4644  /**
4645   * xmlTextWriterWriteIndent:
4646   * @writer:  the xmlTextWriterPtr
4647   *
4648   * Write indent string.
4649   *
4650   * Returns -1 on error or the number of strings written.
4651   */
4652  static int
4653  xmlTextWriterWriteIndent(xmlTextWriterPtr writer)
4654  {
4655      int lksize;
4656      int i;
4657      int ret;
4658  
4659      lksize = xmlListSize(writer->nodes);
4660      if (lksize < 1)
4661          return (-1);            /* list is empty */
4662      for (i = 0; i < (lksize - 1); i++) {
4663          ret = xmlOutputBufferWriteString(writer->out,
4664                                           (const char *) writer->ichar);
4665          if (ret == -1)
4666              return (-1);
4667      }
4668  
4669      return (lksize - 1);
4670  }
4671  
4672  /**
4673   * xmlTextWriterHandleStateDependencies:
4674   * @writer:  the xmlTextWriterPtr
4675   * @p:  the xmlTextWriterStackEntry
4676   *
4677   * Write state dependent strings.
4678   *
4679   * Returns -1 on error or the number of characters written.
4680   */
4681  static int
4682  xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer,
4683                                       xmlTextWriterStackEntry * p)
4684  {
4685      int count;
4686      int sum;
4687      char extra[3];
4688  
4689      if (writer == NULL)
4690          return -1;
4691  
4692      if (p == NULL)
4693          return 0;
4694  
4695      sum = 0;
4696      extra[0] = extra[1] = extra[2] = '\0';
4697      if (p != 0) {
4698          sum = 0;
4699          switch (p->state) {
4700              case XML_TEXTWRITER_NAME:
4701                  /* Output namespace declarations */
4702                  count = xmlTextWriterOutputNSDecl(writer);
4703                  if (count < 0)
4704                      return -1;
4705                  sum += count;
4706                  extra[0] = '>';
4707                  p->state = XML_TEXTWRITER_TEXT;
4708                  break;
4709              case XML_TEXTWRITER_PI:
4710                  extra[0] = ' ';
4711                  p->state = XML_TEXTWRITER_PI_TEXT;
4712                  break;
4713              case XML_TEXTWRITER_DTD:
4714                  extra[0] = ' ';
4715                  extra[1] = '[';
4716                  p->state = XML_TEXTWRITER_DTD_TEXT;
4717                  break;
4718              case XML_TEXTWRITER_DTD_ELEM:
4719                  extra[0] = ' ';
4720                  p->state = XML_TEXTWRITER_DTD_ELEM_TEXT;
4721                  break;
4722              case XML_TEXTWRITER_DTD_ATTL:
4723                  extra[0] = ' ';
4724                  p->state = XML_TEXTWRITER_DTD_ATTL_TEXT;
4725                  break;
4726              case XML_TEXTWRITER_DTD_ENTY:
4727              case XML_TEXTWRITER_DTD_PENT:
4728                  extra[0] = ' ';
4729                  extra[1] = writer->qchar;
4730                  p->state = XML_TEXTWRITER_DTD_ENTY_TEXT;
4731                  break;
4732              default:
4733                  break;
4734          }
4735      }
4736  
4737      if (*extra != '\0') {
4738          count = xmlOutputBufferWriteString(writer->out, extra);
4739          if (count < 0)
4740              return -1;
4741          sum += count;
4742      }
4743  
4744      return sum;
4745  }
4746  
4747  #define bottom_xmlwriter
4748  #include "elfgcchack.h"
4749  #endif