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