xmlwriter.c 122 KB

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