Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829/* * xmlreader.c: implements the xmlTextReader streaming node API * * NOTE: * XmlTextReader.Normalization Property won't be supported, since * it makes the parser non compliant to the XML recommendation * * See Copyright for the status of this software. * * daniel@veillard.com */
/* * TODOs: * - XML Schemas validation */#define IN_LIBXML#include "libxml.h"
#ifdef LIBXML_READER_ENABLED#include <string.h> /* for memset() only ! */#include <stdarg.h>#include <ctype.h>#include <stdlib.h>
#include <libxml/xmlmemory.h>#include <libxml/xmlIO.h>#include <libxml/xmlreader.h>#include <libxml/parserInternals.h>#ifdef LIBXML_SCHEMAS_ENABLED#include <libxml/relaxng.h>#include <libxml/xmlschemas.h>#endif#include <libxml/uri.h>#ifdef LIBXML_XINCLUDE_ENABLED#include <libxml/xinclude.h>#endif#ifdef LIBXML_PATTERN_ENABLED#include <libxml/pattern.h>#endif
#include "private/buf.h"#include "private/parser.h"#include "private/tree.h"#ifdef LIBXML_XINCLUDE_ENABLED#include "private/xinclude.h"#endif
#define MAX_ERR_MSG_SIZE 64000
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION/* Keeping free objects can hide memory errors. */#define MAX_FREE_NODES 1#else#define MAX_FREE_NODES 100#endif
/* * The following VA_COPY was coded following an example in * the Samba project. It may not be sufficient for some * esoteric implementations of va_list but (hopefully) will * be sufficient for libxml2. */#ifndef VA_COPY #ifdef HAVE_VA_COPY #define VA_COPY(dest, src) va_copy(dest, src) #else #ifdef HAVE___VA_COPY #define VA_COPY(dest,src) __va_copy(dest, src) #else #ifndef VA_LIST_IS_ARRAY #define VA_COPY(dest,src) (dest) = (src) #else #include <string.h> #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list)) #endif #endif #endif#endif
/** * TODO: * * macro to flag unimplemented blocks */#define TODO \ xmlGenericError(xmlGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__);
#define CHUNK_SIZE 512/************************************************************************ * * * The parser: maps the Text Reader API on top of the existing * * parsing routines building a tree * * * ************************************************************************/
#define XML_TEXTREADER_INPUT 1#define XML_TEXTREADER_CTXT 2
typedef enum { XML_TEXTREADER_NONE = -1, XML_TEXTREADER_START= 0, XML_TEXTREADER_ELEMENT= 1, XML_TEXTREADER_END= 2, XML_TEXTREADER_EMPTY= 3, XML_TEXTREADER_BACKTRACK= 4, XML_TEXTREADER_DONE= 5, XML_TEXTREADER_ERROR= 6} xmlTextReaderState;
typedef enum { XML_TEXTREADER_NOT_VALIDATE = 0, XML_TEXTREADER_VALIDATE_DTD = 1, XML_TEXTREADER_VALIDATE_RNG = 2, XML_TEXTREADER_VALIDATE_XSD = 4} xmlTextReaderValidate;
struct _xmlTextReader { int mode; /* the parsing mode */ xmlDocPtr doc; /* when walking an existing doc */ xmlTextReaderValidate validate;/* is there any validation */ int allocs; /* what structure were deallocated */ xmlTextReaderState state; xmlParserCtxtPtr ctxt; /* the parser context */ xmlSAXHandlerPtr sax; /* the parser SAX callbacks */ xmlParserInputBufferPtr input; /* the input */ startElementSAXFunc startElement;/* initial SAX callbacks */ endElementSAXFunc endElement; /* idem */ startElementNsSAX2Func startElementNs;/* idem */ endElementNsSAX2Func endElementNs; /* idem */ charactersSAXFunc characters; cdataBlockSAXFunc cdataBlock; unsigned int base; /* base of the segment in the input */ unsigned int cur; /* current position in the input */ xmlNodePtr node; /* current node */ xmlNodePtr curnode;/* current attribute node */ int depth; /* depth of the current node */ xmlNodePtr faketext;/* fake xmlNs chld */ int preserve;/* preserve the resulting document */ xmlBufPtr buffer; /* used to return const xmlChar * */ xmlDictPtr dict; /* the context dictionary */
/* entity stack when traversing entities content */ xmlNodePtr ent; /* Current Entity Ref Node */ int entNr; /* Depth of the entities stack */ int entMax; /* Max depth of the entities stack */ xmlNodePtr *entTab; /* array of entities */
/* error handling */ xmlTextReaderErrorFunc errorFunc; /* callback function */ void *errorFuncArg; /* callback function user argument */
#ifdef LIBXML_SCHEMAS_ENABLED /* Handling of RelaxNG validation */ xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */ xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */ int rngPreserveCtxt; /* 1 if the context was provided by the user */ int rngValidErrors;/* The number of errors detected */ xmlNodePtr rngFullNode; /* the node if RNG not progressive */ /* Handling of Schemas validation */ xmlSchemaPtr xsdSchemas; /* The Schemas schemas */ xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */ int xsdPreserveCtxt; /* 1 if the context was provided by the user */ int xsdValidErrors;/* The number of errors detected */ xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */#endif#ifdef LIBXML_XINCLUDE_ENABLED /* Handling of XInclude processing */ int xinclude; /* is xinclude asked for */ const xmlChar * xinclude_name; /* the xinclude name from dict */ xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */ int in_xinclude; /* counts for xinclude */#endif#ifdef LIBXML_PATTERN_ENABLED int patternNr; /* number of preserve patterns */ int patternMax; /* max preserve patterns */ xmlPatternPtr *patternTab; /* array of preserve patterns */#endif int preserves; /* level of preserves */ int parserFlags; /* the set of options set */ /* Structured error handling */ xmlStructuredErrorFunc sErrorFunc; /* callback function */};
#define NODE_IS_EMPTY 0x1#define NODE_IS_PRESERVED 0x2#define NODE_IS_SPRESERVED 0x4
/** * CONSTSTR: * * Macro used to return an interned string */#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
static int xmlTextReaderReadTree(xmlTextReaderPtr reader);static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
/************************************************************************ * * * Our own version of the freeing routines as we recycle nodes * * * ************************************************************************//** * DICT_FREE: * @str: a string * * Free a string if it is not owned by the "dict" dictionary in the * current scope */#define DICT_FREE(str) \ if ((str) && ((!dict) || \ (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ xmlFree((char *)(str));
static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
/** * xmlTextReaderFreeProp: * @reader: the xmlTextReaderPtr used * @cur: the node * * Free a node. */static voidxmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) { xmlDictPtr dict;
if ((reader != NULL) && (reader->ctxt != NULL)) dict = reader->ctxt->dict; else dict = NULL; if (cur == NULL) return;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
DICT_FREE(cur->name); if ((reader != NULL) && (reader->ctxt != NULL) && (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) { cur->next = reader->ctxt->freeAttrs; reader->ctxt->freeAttrs = cur; reader->ctxt->freeAttrsNr++; } else { xmlFree(cur); }}
/** * xmlTextReaderFreePropList: * @reader: the xmlTextReaderPtr used * @cur: the first property in the list * * Free a property and all its siblings, all the children are freed too. */static voidxmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) { xmlAttrPtr next;
while (cur != NULL) { next = cur->next; xmlTextReaderFreeProp(reader, cur); cur = next; }}
/** * xmlTextReaderFreeNodeList: * @reader: the xmlTextReaderPtr used * @cur: the first node in the list * * Free a node and all its siblings, this is a recursive behaviour, all * the children are freed too. */static voidxmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) { xmlNodePtr next; xmlNodePtr parent; xmlDictPtr dict; size_t depth = 0;
if ((reader != NULL) && (reader->ctxt != NULL)) dict = reader->ctxt->dict; else dict = NULL; if (cur == NULL) return; if (cur->type == XML_NAMESPACE_DECL) { xmlFreeNsList((xmlNsPtr) cur); return; } if ((cur->type == XML_DOCUMENT_NODE) || (cur->type == XML_HTML_DOCUMENT_NODE)) { xmlFreeDoc((xmlDocPtr) cur); return; } while (1) { while ((cur->type != XML_DTD_NODE) && (cur->type != XML_ENTITY_REF_NODE) && (cur->children != NULL) && (cur->children->parent == cur)) { cur = cur->children; depth += 1; }
next = cur->next; parent = cur->parent;
/* unroll to speed up freeing the document */ if (cur->type != XML_DTD_NODE) {
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) xmlDeregisterNodeDefaultValue(cur);
if (((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_XINCLUDE_START) || (cur->type == XML_XINCLUDE_END)) && (cur->properties != NULL)) xmlTextReaderFreePropList(reader, cur->properties); if ((cur->content != (xmlChar *) &(cur->properties)) && (cur->type != XML_ELEMENT_NODE) && (cur->type != XML_XINCLUDE_START) && (cur->type != XML_XINCLUDE_END) && (cur->type != XML_ENTITY_REF_NODE)) { DICT_FREE(cur->content); } if (((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_XINCLUDE_START) || (cur->type == XML_XINCLUDE_END)) && (cur->nsDef != NULL)) xmlFreeNsList(cur->nsDef);
/* * we don't free element names here they are interned now */ if ((cur->type != XML_TEXT_NODE) && (cur->type != XML_COMMENT_NODE)) DICT_FREE(cur->name); if (((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_TEXT_NODE)) && (reader != NULL) && (reader->ctxt != NULL) && (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) { cur->next = reader->ctxt->freeElems; reader->ctxt->freeElems = cur; reader->ctxt->freeElemsNr++; } else { xmlFree(cur); } }
if (next != NULL) { cur = next; } else { if ((depth == 0) || (parent == NULL)) break; depth -= 1; cur = parent; cur->children = NULL; } }}
/** * xmlTextReaderFreeNode: * @reader: the xmlTextReaderPtr used * @cur: the node * * Free a node, this is a recursive behaviour, all the children are freed too. * This doesn't unlink the child from the list, use xmlUnlinkNode() first. */static voidxmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) { xmlDictPtr dict;
if ((reader != NULL) && (reader->ctxt != NULL)) dict = reader->ctxt->dict; else dict = NULL; if (cur->type == XML_DTD_NODE) { xmlFreeDtd((xmlDtdPtr) cur); return; } if (cur->type == XML_NAMESPACE_DECL) { xmlFreeNs((xmlNsPtr) cur); return; } if (cur->type == XML_ATTRIBUTE_NODE) { xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur); return; }
if ((cur->children != NULL) && (cur->type != XML_ENTITY_REF_NODE)) { if (cur->children->parent == cur) xmlTextReaderFreeNodeList(reader, cur->children); cur->children = NULL; }
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) xmlDeregisterNodeDefaultValue(cur);
if (((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_XINCLUDE_START) || (cur->type == XML_XINCLUDE_END)) && (cur->properties != NULL)) xmlTextReaderFreePropList(reader, cur->properties); if ((cur->content != (xmlChar *) &(cur->properties)) && (cur->type != XML_ELEMENT_NODE) && (cur->type != XML_XINCLUDE_START) && (cur->type != XML_XINCLUDE_END) && (cur->type != XML_ENTITY_REF_NODE)) { DICT_FREE(cur->content); } if (((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_XINCLUDE_START) || (cur->type == XML_XINCLUDE_END)) && (cur->nsDef != NULL)) xmlFreeNsList(cur->nsDef);
/* * we don't free names here they are interned now */ if ((cur->type != XML_TEXT_NODE) && (cur->type != XML_COMMENT_NODE)) DICT_FREE(cur->name);
if (((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_TEXT_NODE)) && (reader != NULL) && (reader->ctxt != NULL) && (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) { cur->next = reader->ctxt->freeElems; reader->ctxt->freeElems = cur; reader->ctxt->freeElemsNr++; } else { xmlFree(cur); }}
/** * xmlTextReaderFreeDoc: * @reader: the xmlTextReaderPtr used * @cur: pointer to the document * * Free up all the structures used by a document, tree included. */static voidxmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) { xmlDtdPtr extSubset, intSubset;
if (cur == NULL) return;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
/* * Do this before freeing the children list to avoid ID lookups */ if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids); cur->ids = NULL; if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs); cur->refs = NULL; extSubset = cur->extSubset; intSubset = cur->intSubset; if (intSubset == extSubset) extSubset = NULL; if (extSubset != NULL) { xmlUnlinkNode((xmlNodePtr) cur->extSubset); cur->extSubset = NULL; xmlFreeDtd(extSubset); } if (intSubset != NULL) { xmlUnlinkNode((xmlNodePtr) cur->intSubset); cur->intSubset = NULL; xmlFreeDtd(intSubset); }
if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
if (cur->version != NULL) xmlFree((char *) cur->version); if (cur->name != NULL) xmlFree((char *) cur->name); if (cur->encoding != NULL) xmlFree((char *) cur->encoding); if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs); if (cur->URL != NULL) xmlFree((char *) cur->URL); if (cur->dict != NULL) xmlDictFree(cur->dict);
xmlFree(cur);}
/************************************************************************ * * * The reader core parser * * * ************************************************************************/
/** * xmlTextReaderEntPush: * @reader: the xmlTextReaderPtr used * @value: the entity reference node * * Pushes a new entity reference node on top of the entities stack * * Returns -1 in case of error, the index in the stack otherwise */static intxmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value){ if (reader->entNr >= reader->entMax) { size_t newSize = reader->entMax == 0 ? 10 : reader->entMax * 2; xmlNodePtr *tmp;
tmp = (xmlNodePtr *) xmlRealloc(reader->entTab, newSize * sizeof(*tmp)); if (tmp == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); return (-1); } reader->entTab = tmp; reader->entMax = newSize; } reader->entTab[reader->entNr] = value; reader->ent = value; return (reader->entNr++);}
/** * xmlTextReaderEntPop: * @reader: the xmlTextReaderPtr used * * Pops the top element entity from the entities stack * * Returns the entity just removed */static xmlNodePtrxmlTextReaderEntPop(xmlTextReaderPtr reader){ xmlNodePtr ret;
if (reader->entNr <= 0) return (NULL); reader->entNr--; if (reader->entNr > 0) reader->ent = reader->entTab[reader->entNr - 1]; else reader->ent = NULL; ret = reader->entTab[reader->entNr]; reader->entTab[reader->entNr] = NULL; return (ret);}
/** * xmlTextReaderStartElement: * @ctx: the user data (XML parser context) * @fullname: The element name, including namespace prefix * @atts: An array of name/value attributes pairs, NULL terminated * * called when an opening tag has been processed. */static voidxmlTextReaderStartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
if ((reader != NULL) && (reader->startElement != NULL)) { reader->startElement(ctx, fullname, atts); if ((ctxt->node != NULL) && (ctxt->input != NULL) && (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') && (ctxt->input->cur[1] == '>')) ctxt->node->extra = NODE_IS_EMPTY; } if (reader != NULL) reader->state = XML_TEXTREADER_ELEMENT;}
/** * xmlTextReaderEndElement: * @ctx: the user data (XML parser context) * @fullname: The element name, including namespace prefix * * called when an ending tag has been processed. */static voidxmlTextReaderEndElement(void *ctx, const xmlChar *fullname) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
if ((reader != NULL) && (reader->endElement != NULL)) { reader->endElement(ctx, fullname); }}
/** * xmlTextReaderStartElementNs: * @ctx: the user data (XML parser context) * @localname: the local name of the element * @prefix: the element namespace prefix if available * @URI: the element namespace name if available * @nb_namespaces: number of namespace definitions on that node * @namespaces: pointer to the array of prefix/URI pairs namespace definitions * @nb_attributes: the number of attributes on that node * nb_defaulted: the number of defaulted attributes. * @attributes: pointer to the array of (localname/prefix/URI/value/end) * attribute values. * * called when an opening tag has been processed. */static voidxmlTextReaderStartElementNs(void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
if ((reader != NULL) && (reader->startElementNs != NULL)) { reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces, namespaces, nb_attributes, nb_defaulted, attributes); if ((ctxt->node != NULL) && (ctxt->input != NULL) && (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') && (ctxt->input->cur[1] == '>')) ctxt->node->extra = NODE_IS_EMPTY; } if (reader != NULL) reader->state = XML_TEXTREADER_ELEMENT;}
/** * xmlTextReaderEndElementNs: * @ctx: the user data (XML parser context) * @localname: the local name of the element * @prefix: the element namespace prefix if available * @URI: the element namespace name if available * * called when an ending tag has been processed. */static voidxmlTextReaderEndElementNs(void *ctx, const xmlChar * localname, const xmlChar * prefix, const xmlChar * URI){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
if ((reader != NULL) && (reader->endElementNs != NULL)) { reader->endElementNs(ctx, localname, prefix, URI); }}
/** * xmlTextReaderCharacters: * @ctx: the user data (XML parser context) * @ch: a xmlChar string * @len: the number of xmlChar * * receiving some chars from the parser. */static voidxmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
if ((reader != NULL) && (reader->characters != NULL)) { reader->characters(ctx, ch, len); }}
/** * xmlTextReaderCDataBlock: * @ctx: the user data (XML parser context) * @value: The pcdata content * @len: the block length * * called when a pcdata block has been parsed */static voidxmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
if ((reader != NULL) && (reader->cdataBlock != NULL)) { reader->cdataBlock(ctx, ch, len); }}
/** * xmlTextReaderPushData: * @reader: the xmlTextReaderPtr used * * Push data down the progressive parser until a significant callback * got raised. * * Returns -1 in case of failure, 0 otherwise */static intxmlTextReaderPushData(xmlTextReaderPtr reader) { xmlBufPtr inbuf; int val, s; xmlTextReaderState oldstate;
if ((reader->input == NULL) || (reader->input->buffer == NULL)) return(-1);
oldstate = reader->state; reader->state = XML_TEXTREADER_NONE; inbuf = reader->input->buffer;
while (reader->state == XML_TEXTREADER_NONE) { if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) { /* * Refill the buffer unless we are at the end of the stream */ if (reader->mode != XML_TEXTREADER_MODE_EOF) { val = xmlParserInputBufferRead(reader->input, 4096); if (val == 0) { if (xmlBufUse(inbuf) == reader->cur) { reader->mode = XML_TEXTREADER_MODE_EOF; break; } } else if (val < 0) { xmlGenericError(xmlGenericErrorContext, "xmlParserInputBufferRead failed\n"); reader->mode = XML_TEXTREADER_MODE_EOF; reader->state = oldstate; return(val); }
} else break; } /* * parse by block of CHUNK_SIZE bytes, various tests show that * it's the best tradeoff at least on a 1.2GH Duron */ if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) { val = xmlParseChunk(reader->ctxt, (const char *) xmlBufContent(inbuf) + reader->cur, CHUNK_SIZE, 0); reader->cur += CHUNK_SIZE; if (val != 0) reader->ctxt->wellFormed = 0; if (reader->ctxt->wellFormed == 0) break; } else { s = xmlBufUse(inbuf) - reader->cur; val = xmlParseChunk(reader->ctxt, (const char *) xmlBufContent(inbuf) + reader->cur, s, 0); reader->cur += s; if (val != 0) reader->ctxt->wellFormed = 0; break; } } reader->state = oldstate;
/* * Discard the consumed input when needed and possible */ if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) { if (reader->input->readcallback != NULL) { if ((reader->cur >= 4096) && (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) { val = xmlBufShrink(inbuf, reader->cur); if (val >= 0) { reader->cur -= val; } } } }
/* * At the end of the stream signal that the work is done to the Push * parser. */ else if (reader->mode == XML_TEXTREADER_MODE_EOF) { if (reader->state != XML_TEXTREADER_DONE) { s = xmlBufUse(inbuf) - reader->cur; val = xmlParseChunk(reader->ctxt, (const char *) xmlBufContent(inbuf) + reader->cur, s, 1); reader->cur = xmlBufUse(inbuf); reader->state = XML_TEXTREADER_DONE; if (val != 0) { if (reader->ctxt->wellFormed) reader->ctxt->wellFormed = 0; else return(-1); } } } if (reader->ctxt->wellFormed == 0) { reader->mode = XML_TEXTREADER_MODE_EOF; return(-1); }
return(0);}
#ifdef LIBXML_REGEXP_ENABLED/** * xmlTextReaderValidatePush: * @reader: the xmlTextReaderPtr used * * Push the current node for validation */static voidxmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { xmlNodePtr node = reader->node;
#ifdef LIBXML_VALID_ENABLED if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) && (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) { if ((node->ns == NULL) || (node->ns->prefix == NULL)) { reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt, reader->ctxt->myDoc, node, node->name); } else { /* TODO use the BuildQName interface */ xmlChar *qname;
qname = xmlStrdup(node->ns->prefix); qname = xmlStrcat(qname, BAD_CAST ":"); qname = xmlStrcat(qname, node->name); reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt, reader->ctxt->myDoc, node, qname); if (qname != NULL) xmlFree(qname); } }#endif /* LIBXML_VALID_ENABLED */#ifdef LIBXML_SCHEMAS_ENABLED if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) && (reader->rngValidCtxt != NULL)) { int ret;
if (reader->rngFullNode != NULL) return; ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt, reader->ctxt->myDoc, node); if (ret == 0) { /* * this element requires a full tree */ node = xmlTextReaderExpand(reader); if (node == NULL) { ret = -1; } else { ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt, reader->ctxt->myDoc, node); reader->rngFullNode = node; } } if (ret != 1) reader->rngValidErrors++; }#endif}
/** * xmlTextReaderValidateCData: * @reader: the xmlTextReaderPtr used * @data: pointer to the CData * @len: length of the CData block in bytes. * * Push some CData for validation */static voidxmlTextReaderValidateCData(xmlTextReaderPtr reader, const xmlChar *data, int len) {#ifdef LIBXML_VALID_ENABLED if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) && (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) { reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt, data, len); }#endif /* LIBXML_VALID_ENABLED */#ifdef LIBXML_SCHEMAS_ENABLED if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) && (reader->rngValidCtxt != NULL)) { int ret;
if (reader->rngFullNode != NULL) return; ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len); if (ret != 1) reader->rngValidErrors++; }#endif}
/** * xmlTextReaderValidatePop: * @reader: the xmlTextReaderPtr used * * Pop the current node from validation */static voidxmlTextReaderValidatePop(xmlTextReaderPtr reader) { xmlNodePtr node = reader->node;
#ifdef LIBXML_VALID_ENABLED if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) && (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) { if ((node->ns == NULL) || (node->ns->prefix == NULL)) { reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt, reader->ctxt->myDoc, node, node->name); } else { /* TODO use the BuildQName interface */ xmlChar *qname;
qname = xmlStrdup(node->ns->prefix); qname = xmlStrcat(qname, BAD_CAST ":"); qname = xmlStrcat(qname, node->name); reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt, reader->ctxt->myDoc, node, qname); if (qname != NULL) xmlFree(qname); } }#endif /* LIBXML_VALID_ENABLED */#ifdef LIBXML_SCHEMAS_ENABLED if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) && (reader->rngValidCtxt != NULL)) { int ret;
if (reader->rngFullNode != NULL) { if (node == reader->rngFullNode) reader->rngFullNode = NULL; return; } ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt, reader->ctxt->myDoc, node); if (ret != 1) reader->rngValidErrors++; }#endif}
/** * xmlTextReaderValidateEntity: * @reader: the xmlTextReaderPtr used * * Handle the validation when an entity reference is encountered and * entity substitution is not activated. As a result the parser interface * must walk through the entity and do the validation calls */static voidxmlTextReaderValidateEntity(xmlTextReaderPtr reader) { xmlNodePtr oldnode = reader->node; xmlNodePtr node = reader->node;
do { if (node->type == XML_ENTITY_REF_NODE) { if ((node->children != NULL) && (node->children->type == XML_ENTITY_DECL) && (node->children->children != NULL)) { if (xmlTextReaderEntPush(reader, node) < 0) { if (node == oldnode) break; goto skip_children; } node = node->children->children; continue; } else { /* * The error has probably been raised already. */ if (node == oldnode) break; goto skip_children; }#ifdef LIBXML_REGEXP_ENABLED } else if (node->type == XML_ELEMENT_NODE) { reader->node = node; xmlTextReaderValidatePush(reader); } else if ((node->type == XML_TEXT_NODE) || (node->type == XML_CDATA_SECTION_NODE)) { xmlTextReaderValidateCData(reader, node->content, xmlStrlen(node->content));#endif }
/* * go to next node */ if (node->children != NULL) { node = node->children; continue; } else if (node->type == XML_ELEMENT_NODE) { xmlTextReaderValidatePop(reader); }skip_children: if (node->next != NULL) { node = node->next; continue; } do { node = node->parent; if (node->type == XML_ELEMENT_NODE) { xmlNodePtr tmp; if (reader->entNr == 0) { while ((tmp = node->last) != NULL) { if ((tmp->extra & NODE_IS_PRESERVED) == 0) { xmlUnlinkNode(tmp); xmlTextReaderFreeNode(reader, tmp); } else break; } } reader->node = node; xmlTextReaderValidatePop(reader); } if ((node->type == XML_ENTITY_DECL) && (reader->ent != NULL) && (reader->ent->children == node)) { node = xmlTextReaderEntPop(reader); } if (node == oldnode) break; if (node->next != NULL) { node = node->next; break; } } while ((node != NULL) && (node != oldnode)); } while ((node != NULL) && (node != oldnode)); reader->node = oldnode;}#endif /* LIBXML_REGEXP_ENABLED */
/** * xmlTextReaderGetSuccessor: * @cur: the current node * * Get the successor of a node if available. * * Returns the successor node or NULL */static xmlNodePtrxmlTextReaderGetSuccessor(xmlNodePtr cur) { if (cur == NULL) return(NULL) ; /* ERROR */ if (cur->next != NULL) return(cur->next) ; do { cur = cur->parent; if (cur == NULL) break; if (cur->next != NULL) return(cur->next); } while (cur != NULL); return(cur);}
/** * xmlTextReaderDoExpand: * @reader: the xmlTextReaderPtr used * * Makes sure that the current node is fully read as well as all its * descendant. It means the full DOM subtree must be available at the * end of the call. * * Returns 1 if the node was expanded successfully, 0 if there is no more * nodes to read, or -1 in case of error */static intxmlTextReaderDoExpand(xmlTextReaderPtr reader) { int val;
if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL)) return(-1); do { if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
if (xmlTextReaderGetSuccessor(reader->node) != NULL) return(1); if (reader->ctxt->nodeNr < reader->depth) return(1); if (reader->mode == XML_TEXTREADER_MODE_EOF) return(1); val = xmlTextReaderPushData(reader); if (val < 0){ reader->mode = XML_TEXTREADER_MODE_ERROR; return(-1); } } while(reader->mode != XML_TEXTREADER_MODE_EOF); return(1);}
/** * xmlTextReaderCollectSiblings: * @node: the first child * * Traverse depth-first through all sibling nodes and their children * nodes and concatenate their content. This is an auxiliary function * to xmlTextReaderReadString. * * Returns a string containing the content, or NULL in case of error. */static xmlChar *xmlTextReaderCollectSiblings(xmlNodePtr node){ xmlBufferPtr buffer; xmlChar *ret;
if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) return(NULL);
buffer = xmlBufferCreate(); if (buffer == NULL) return NULL; xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
for ( ; node != NULL; node = node->next) { switch (node->type) { case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: xmlBufferCat(buffer, node->content); break; case XML_ELEMENT_NODE: { xmlChar *tmp;
tmp = xmlTextReaderCollectSiblings(node->children); xmlBufferCat(buffer, tmp); xmlFree(tmp); break; } default: break; } } ret = buffer->content; buffer->content = NULL; xmlBufferFree(buffer); return(ret);}
/** * xmlTextReaderRead: * @reader: the xmlTextReaderPtr used * * Moves the position of the current instance to the next node in * the stream, exposing its properties. * * Returns 1 if the node was read successfully, 0 if there is no more * nodes to read, or -1 in case of error */intxmlTextReaderRead(xmlTextReaderPtr reader) { int val, olddepth = 0; xmlTextReaderState oldstate = XML_TEXTREADER_START; xmlNodePtr oldnode = NULL;
if (reader == NULL) return(-1); reader->curnode = NULL; if (reader->doc != NULL) return(xmlTextReaderReadTree(reader)); if (reader->ctxt == NULL) return(-1);
if (reader->mode == XML_TEXTREADER_MODE_INITIAL) { reader->mode = XML_TEXTREADER_MODE_INTERACTIVE; /* * Initial state */ do { val = xmlTextReaderPushData(reader); if (val < 0){ reader->mode = XML_TEXTREADER_MODE_ERROR; reader->state = XML_TEXTREADER_ERROR; return(-1); } } while ((reader->ctxt->node == NULL) && ((reader->mode != XML_TEXTREADER_MODE_EOF) && (reader->state != XML_TEXTREADER_DONE))); if (reader->ctxt->node == NULL) { if (reader->ctxt->myDoc != NULL) { reader->node = reader->ctxt->myDoc->children; } if (reader->node == NULL){ reader->mode = XML_TEXTREADER_MODE_ERROR; reader->state = XML_TEXTREADER_ERROR; return(-1); } reader->state = XML_TEXTREADER_ELEMENT; } else { if (reader->ctxt->myDoc != NULL) { reader->node = reader->ctxt->myDoc->children; } if (reader->node == NULL) reader->node = reader->ctxt->nodeTab[0]; reader->state = XML_TEXTREADER_ELEMENT; } reader->depth = 0; reader->ctxt->parseMode = XML_PARSE_READER; goto node_found; } oldstate = reader->state; olddepth = reader->ctxt->nodeNr; oldnode = reader->node;
get_next_node: if (reader->node == NULL) { if (reader->mode == XML_TEXTREADER_MODE_EOF) return(0); else return(-1); }
/* * If we are not backtracking on ancestors or examined nodes, * that the parser didn't finished or that we aren't at the end * of stream, continue processing. */ while ((reader->node != NULL) && (reader->node->next == NULL) && (reader->ctxt->nodeNr == olddepth) && ((oldstate == XML_TEXTREADER_BACKTRACK) || (reader->node->children == NULL) || (reader->node->type == XML_ENTITY_REF_NODE) || ((reader->node->children != NULL) && (reader->node->children->type == XML_TEXT_NODE) && (reader->node->children->next == NULL)) || (reader->node->type == XML_DTD_NODE) || (reader->node->type == XML_DOCUMENT_NODE) || (reader->node->type == XML_HTML_DOCUMENT_NODE)) && ((reader->ctxt->node == NULL) || (reader->ctxt->node == reader->node) || (reader->ctxt->node == reader->node->parent)) && (reader->ctxt->instate != XML_PARSER_EOF)) { val = xmlTextReaderPushData(reader); if (val < 0){ reader->mode = XML_TEXTREADER_MODE_ERROR; reader->state = XML_TEXTREADER_ERROR; return(-1); } if (reader->node == NULL) goto node_end; } if (oldstate != XML_TEXTREADER_BACKTRACK) { if ((reader->node->children != NULL) && (reader->node->type != XML_ENTITY_REF_NODE) && (reader->node->type != XML_XINCLUDE_START) && (reader->node->type != XML_DTD_NODE)) { reader->node = reader->node->children; reader->depth++; reader->state = XML_TEXTREADER_ELEMENT; goto node_found; } } if (reader->node->next != NULL) { if ((oldstate == XML_TEXTREADER_ELEMENT) && (reader->node->type == XML_ELEMENT_NODE) && (reader->node->children == NULL) && ((reader->node->extra & NODE_IS_EMPTY) == 0)#ifdef LIBXML_XINCLUDE_ENABLED && (reader->in_xinclude <= 0)#endif ) { reader->state = XML_TEXTREADER_END; goto node_found; }#ifdef LIBXML_REGEXP_ENABLED if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE)) xmlTextReaderValidatePop(reader);#endif /* LIBXML_REGEXP_ENABLED */ if ((reader->preserves > 0) && (reader->node->extra & NODE_IS_SPRESERVED)) reader->preserves--; reader->node = reader->node->next; reader->state = XML_TEXTREADER_ELEMENT;
/* * Cleanup of the old node */ if ((reader->preserves == 0) &&#ifdef LIBXML_XINCLUDE_ENABLED (reader->in_xinclude == 0) &&#endif (reader->entNr == 0) && (reader->node->prev != NULL) && (reader->node->prev->type != XML_DTD_NODE)) { xmlNodePtr tmp = reader->node->prev; if ((tmp->extra & NODE_IS_PRESERVED) == 0) { if (oldnode == tmp) oldnode = NULL; xmlUnlinkNode(tmp); xmlTextReaderFreeNode(reader, tmp); } }
goto node_found; } if ((oldstate == XML_TEXTREADER_ELEMENT) && (reader->node->type == XML_ELEMENT_NODE) && (reader->node->children == NULL) && ((reader->node->extra & NODE_IS_EMPTY) == 0)) {; reader->state = XML_TEXTREADER_END; goto node_found; }#ifdef LIBXML_REGEXP_ENABLED if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE)) xmlTextReaderValidatePop(reader);#endif /* LIBXML_REGEXP_ENABLED */ if ((reader->preserves > 0) && (reader->node->extra & NODE_IS_SPRESERVED)) reader->preserves--; reader->node = reader->node->parent; if ((reader->node == NULL) || (reader->node->type == XML_DOCUMENT_NODE) || (reader->node->type == XML_HTML_DOCUMENT_NODE)) { if (reader->mode != XML_TEXTREADER_MODE_EOF) { val = xmlParseChunk(reader->ctxt, "", 0, 1); reader->state = XML_TEXTREADER_DONE; if (val != 0) return(-1); } reader->node = NULL; reader->depth = -1;
/* * Cleanup of the old node */ if ((oldnode != NULL) && (reader->preserves == 0) &&#ifdef LIBXML_XINCLUDE_ENABLED (reader->in_xinclude == 0) &&#endif (reader->entNr == 0) && (oldnode->type != XML_DTD_NODE) && ((oldnode->extra & NODE_IS_PRESERVED) == 0)) { xmlUnlinkNode(oldnode); xmlTextReaderFreeNode(reader, oldnode); }
goto node_end; } if ((reader->preserves == 0) &&#ifdef LIBXML_XINCLUDE_ENABLED (reader->in_xinclude == 0) &&#endif (reader->entNr == 0) && (reader->node->last != NULL) && ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) { xmlNodePtr tmp = reader->node->last; xmlUnlinkNode(tmp); xmlTextReaderFreeNode(reader, tmp); } reader->depth--; reader->state = XML_TEXTREADER_BACKTRACK;
node_found: /* * If we are in the middle of a piece of CDATA make sure it's finished */ if ((reader->node != NULL) && (reader->node->next == NULL) && ((reader->node->type == XML_TEXT_NODE) || (reader->node->type == XML_CDATA_SECTION_NODE))) { if (xmlTextReaderExpand(reader) == NULL) return -1; }
#ifdef LIBXML_XINCLUDE_ENABLED /* * Handle XInclude if asked for */ if ((reader->xinclude) && (reader->in_xinclude == 0) && (reader->state != XML_TEXTREADER_BACKTRACK) && (reader->node != NULL) && (reader->node->type == XML_ELEMENT_NODE) && (reader->node->ns != NULL) && ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) || (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) { if (reader->xincctxt == NULL) { reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc); xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags & (~XML_PARSE_NOXINCNODE)); xmlXIncludeSetStreamingMode(reader->xincctxt, 1); } /* * expand that node and process it */ if (xmlTextReaderExpand(reader) == NULL) return -1; xmlXIncludeProcessNode(reader->xincctxt, reader->node); } if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) { reader->in_xinclude++; goto get_next_node; } if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) { reader->in_xinclude--; goto get_next_node; }#endif /* * Handle entities enter and exit when in entity replacement mode */ if ((reader->node != NULL) && (reader->node->type == XML_ENTITY_REF_NODE) && (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) { if ((reader->node->children != NULL) && (reader->node->children->type == XML_ENTITY_DECL) && (reader->node->children->children != NULL)) { if (xmlTextReaderEntPush(reader, reader->node) < 0) goto get_next_node; reader->node = reader->node->children->children; }#ifdef LIBXML_REGEXP_ENABLED } else if ((reader->node != NULL) && (reader->node->type == XML_ENTITY_REF_NODE) && (reader->ctxt != NULL) && (reader->validate)) { xmlTextReaderValidateEntity(reader);#endif /* LIBXML_REGEXP_ENABLED */ } if ((reader->node != NULL) && (reader->node->type == XML_ENTITY_DECL) && (reader->ent != NULL) && (reader->ent->children == reader->node)) { reader->node = xmlTextReaderEntPop(reader); reader->depth++; goto get_next_node; }#ifdef LIBXML_REGEXP_ENABLED if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) { xmlNodePtr node = reader->node;
if ((node->type == XML_ELEMENT_NODE) && ((reader->state != XML_TEXTREADER_END) && (reader->state != XML_TEXTREADER_BACKTRACK))) { xmlTextReaderValidatePush(reader); } else if ((node->type == XML_TEXT_NODE) || (node->type == XML_CDATA_SECTION_NODE)) { xmlTextReaderValidateCData(reader, node->content, xmlStrlen(node->content)); } }#endif /* LIBXML_REGEXP_ENABLED */#ifdef LIBXML_PATTERN_ENABLED if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) && (reader->state != XML_TEXTREADER_BACKTRACK)) { int i; for (i = 0;i < reader->patternNr;i++) { if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) { xmlTextReaderPreserve(reader); break; } } }#endif /* LIBXML_PATTERN_ENABLED */#ifdef LIBXML_SCHEMAS_ENABLED if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) && (reader->xsdValidErrors == 0) && (reader->xsdValidCtxt != NULL)) { reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt); }#endif /* LIBXML_PATTERN_ENABLED */ return(1);node_end: reader->state = XML_TEXTREADER_DONE; return(0);}
/** * xmlTextReaderReadState: * @reader: the xmlTextReaderPtr used * * Gets the read state of the reader. * * Returns the state value, or -1 in case of error */intxmlTextReaderReadState(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); return(reader->mode);}
/** * xmlTextReaderExpand: * @reader: the xmlTextReaderPtr used * * Reads the contents of the current node and the full subtree. It then makes * the subtree available until the next xmlTextReaderRead() call * * Returns a node pointer valid until the next xmlTextReaderRead() call * or NULL in case of error. */xmlNodePtrxmlTextReaderExpand(xmlTextReaderPtr reader) { if ((reader == NULL) || (reader->node == NULL)) return(NULL); if (reader->doc != NULL) return(reader->node); if (reader->ctxt == NULL) return(NULL); if (xmlTextReaderDoExpand(reader) < 0) return(NULL); return(reader->node);}
/** * xmlTextReaderNext: * @reader: the xmlTextReaderPtr used * * Skip to the node following the current one in document order while * avoiding the subtree if any. * * Returns 1 if the node was read successfully, 0 if there is no more * nodes to read, or -1 in case of error */intxmlTextReaderNext(xmlTextReaderPtr reader) { int ret; xmlNodePtr cur;
if (reader == NULL) return(-1); if (reader->doc != NULL) return(xmlTextReaderNextTree(reader)); cur = reader->node; if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE)) return(xmlTextReaderRead(reader)); if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK) return(xmlTextReaderRead(reader)); if (cur->extra & NODE_IS_EMPTY) return(xmlTextReaderRead(reader)); do { ret = xmlTextReaderRead(reader); if (ret != 1) return(ret); } while (reader->node != cur); return(xmlTextReaderRead(reader));}
#ifdef LIBXML_WRITER_ENABLED/** * xmlTextReaderReadInnerXml: * @reader: the xmlTextReaderPtr used * * Reads the contents of the current node, including child nodes and markup. * * Returns a string containing the XML content, or NULL if the current node * is neither an element nor attribute, or has no child nodes. The * string must be deallocated by the caller. */xmlChar *xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED){ xmlChar *resbuf; xmlNodePtr node, cur_node; xmlBufferPtr buff, buff2; xmlDocPtr doc;
if (xmlTextReaderExpand(reader) == NULL) { return NULL; } doc = reader->node->doc; buff = xmlBufferCreate(); if (buff == NULL) return NULL; xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT); for (cur_node = reader->node->children; cur_node != NULL; cur_node = cur_node->next) { /* XXX: Why is the node copied? */ node = xmlDocCopyNode(cur_node, doc, 1); /* XXX: Why do we need a second buffer? */ buff2 = xmlBufferCreate(); xmlBufferSetAllocationScheme(buff2, XML_BUFFER_ALLOC_DOUBLEIT); if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) { xmlFreeNode(node); xmlBufferFree(buff2); xmlBufferFree(buff); return NULL; } xmlBufferCat(buff, buff2->content); xmlFreeNode(node); xmlBufferFree(buff2); } resbuf = buff->content; buff->content = NULL;
xmlBufferFree(buff); return resbuf;}#endif
#ifdef LIBXML_WRITER_ENABLED/** * xmlTextReaderReadOuterXml: * @reader: the xmlTextReaderPtr used * * Reads the contents of the current node, including child nodes and markup. * * Returns a string containing the node and any XML content, or NULL if the * current node cannot be serialized. The string must be deallocated * by the caller. */xmlChar *xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED){ xmlChar *resbuf; xmlNodePtr node; xmlBufferPtr buff; xmlDocPtr doc;
if (xmlTextReaderExpand(reader) == NULL) { return NULL; } node = reader->node; doc = node->doc; /* XXX: Why is the node copied? */ if (node->type == XML_DTD_NODE) { node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node); } else { node = xmlDocCopyNode(node, doc, 1); } buff = xmlBufferCreate(); xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT); if (xmlNodeDump(buff, doc, node, 0, 0) == -1) { xmlFreeNode(node); xmlBufferFree(buff); return NULL; }
resbuf = buff->content; buff->content = NULL;
xmlFreeNode(node); xmlBufferFree(buff); return resbuf;}#endif
/** * xmlTextReaderReadString: * @reader: the xmlTextReaderPtr used * * Reads the contents of an element or a text node as a string. * * Returns a string containing the contents of the Element or Text node, * or NULL if the reader is positioned on any other type of node. * The string must be deallocated by the caller. */xmlChar *xmlTextReaderReadString(xmlTextReaderPtr reader){ xmlNodePtr node;
if ((reader == NULL) || (reader->node == NULL)) return(NULL);
node = (reader->curnode != NULL) ? reader->curnode : reader->node; switch (node->type) { case XML_TEXT_NODE: if (node->content != NULL) return(xmlStrdup(node->content)); break; case XML_ELEMENT_NODE: if (xmlTextReaderDoExpand(reader) != -1) { return xmlTextReaderCollectSiblings(node->children); } break; case XML_ATTRIBUTE_NODE: TODO break; default: break; } return(NULL);}
#if 0/** * xmlTextReaderReadBase64: * @reader: the xmlTextReaderPtr used * @array: a byte array to store the content. * @offset: the zero-based index into array where the method should * begin to write. * @len: the number of bytes to write. * * Reads and decodes the Base64 encoded contents of an element and * stores the result in a byte buffer. * * Returns the number of bytes written to array, or zero if the current * instance is not positioned on an element or -1 in case of error. */intxmlTextReaderReadBase64(xmlTextReaderPtr reader, unsigned char *array ATTRIBUTE_UNUSED, int offset ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) { if ((reader == NULL) || (reader->ctxt == NULL)) return(-1); if (reader->ctxt->wellFormed != 1) return(-1);
if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) return(0); TODO return(0);}
/** * xmlTextReaderReadBinHex: * @reader: the xmlTextReaderPtr used * @array: a byte array to store the content. * @offset: the zero-based index into array where the method should * begin to write. * @len: the number of bytes to write. * * Reads and decodes the BinHex encoded contents of an element and * stores the result in a byte buffer. * * Returns the number of bytes written to array, or zero if the current * instance is not positioned on an element or -1 in case of error. */intxmlTextReaderReadBinHex(xmlTextReaderPtr reader, unsigned char *array ATTRIBUTE_UNUSED, int offset ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) { if ((reader == NULL) || (reader->ctxt == NULL)) return(-1); if (reader->ctxt->wellFormed != 1) return(-1);
if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) return(0); TODO return(0);}#endif
/************************************************************************ * * * Operating on a preparsed tree * * * ************************************************************************/static intxmlTextReaderNextTree(xmlTextReaderPtr reader){ if (reader == NULL) return(-1);
if (reader->state == XML_TEXTREADER_END) return(0);
if (reader->node == NULL) { if (reader->doc->children == NULL) { reader->state = XML_TEXTREADER_END; return(0); }
reader->node = reader->doc->children; reader->state = XML_TEXTREADER_START; return(1); }
if (reader->state != XML_TEXTREADER_BACKTRACK) { /* Here removed traversal to child, because we want to skip the subtree, replace with traversal to sibling to skip subtree */ if (reader->node->next != 0) { /* Move to sibling if present,skipping sub-tree */ reader->node = reader->node->next; reader->state = XML_TEXTREADER_START; return(1); }
/* if reader->node->next is NULL mean no subtree for current node, so need to move to sibling of parent node if present */ reader->state = XML_TEXTREADER_BACKTRACK; /* This will move to parent if present */ xmlTextReaderRead(reader); }
if (reader->node->next != 0) { reader->node = reader->node->next; reader->state = XML_TEXTREADER_START; return(1); }
if (reader->node->parent != 0) { if (reader->node->parent->type == XML_DOCUMENT_NODE) { reader->state = XML_TEXTREADER_END; return(0); }
reader->node = reader->node->parent; reader->depth--; reader->state = XML_TEXTREADER_BACKTRACK; /* Repeat process to move to sibling of parent node if present */ xmlTextReaderNextTree(reader); }
reader->state = XML_TEXTREADER_END;
return(1);}
/** * xmlTextReaderReadTree: * @reader: the xmlTextReaderPtr used * * Moves the position of the current instance to the next node in * the stream, exposing its properties. * * Returns 1 if the node was read successfully, 0 if there is no more * nodes to read, or -1 in case of error */static intxmlTextReaderReadTree(xmlTextReaderPtr reader) { if (reader->state == XML_TEXTREADER_END) return(0);
next_node: if (reader->node == NULL) { if (reader->doc->children == NULL) { reader->state = XML_TEXTREADER_END; return(0); }
reader->node = reader->doc->children; reader->state = XML_TEXTREADER_START; goto found_node; }
if ((reader->state != XML_TEXTREADER_BACKTRACK) && (reader->node->type != XML_DTD_NODE) && (reader->node->type != XML_XINCLUDE_START) && (reader->node->type != XML_ENTITY_REF_NODE)) { if (reader->node->children != NULL) { reader->node = reader->node->children; reader->depth++; reader->state = XML_TEXTREADER_START; goto found_node; }
if (reader->node->type == XML_ATTRIBUTE_NODE) { reader->state = XML_TEXTREADER_BACKTRACK; goto found_node; } }
if (reader->node->next != NULL) { reader->node = reader->node->next; reader->state = XML_TEXTREADER_START; goto found_node; }
if (reader->node->parent != NULL) { if ((reader->node->parent->type == XML_DOCUMENT_NODE) || (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) { reader->state = XML_TEXTREADER_END; return(0); }
reader->node = reader->node->parent; reader->depth--; reader->state = XML_TEXTREADER_BACKTRACK; goto found_node; }
reader->state = XML_TEXTREADER_END;
found_node: if ((reader->node->type == XML_XINCLUDE_START) || (reader->node->type == XML_XINCLUDE_END)) goto next_node;
return(1);}
/** * xmlTextReaderNextSibling: * @reader: the xmlTextReaderPtr used * * Skip to the node following the current one in document order while * avoiding the subtree if any. * Currently implemented only for Readers built on a document * * Returns 1 if the node was read successfully, 0 if there is no more * nodes to read, or -1 in case of error */intxmlTextReaderNextSibling(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); if (reader->doc == NULL) { /* TODO */ return(-1); }
if (reader->state == XML_TEXTREADER_END) return(0);
if (reader->node == NULL) return(xmlTextReaderNextTree(reader));
if (reader->node->next != NULL) { reader->node = reader->node->next; reader->state = XML_TEXTREADER_START; return(1); }
return(0);}
/************************************************************************ * * * Constructor and destructors * * * ************************************************************************//** * xmlNewTextReader: * @input: the xmlParserInputBufferPtr used to read data * @URI: the URI information for the source if available * * Create an xmlTextReader structure fed with @input * * Returns the new xmlTextReaderPtr or NULL in case of error */xmlTextReaderPtrxmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { xmlTextReaderPtr ret;
if (input == NULL) return(NULL); ret = xmlMalloc(sizeof(xmlTextReader)); if (ret == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); return(NULL); } memset(ret, 0, sizeof(xmlTextReader)); ret->doc = NULL; ret->entTab = NULL; ret->entMax = 0; ret->entNr = 0; ret->input = input; ret->buffer = xmlBufCreateSize(100); if (ret->buffer == NULL) { xmlFree(ret); xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); return(NULL); } /* no operation on a reader should require a huge buffer */ xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT); ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); if (ret->sax == NULL) { xmlBufFree(ret->buffer); xmlFree(ret); xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); return(NULL); } xmlSAXVersion(ret->sax, 2); ret->startElement = ret->sax->startElement; ret->sax->startElement = xmlTextReaderStartElement; ret->endElement = ret->sax->endElement; ret->sax->endElement = xmlTextReaderEndElement;#ifdef LIBXML_SAX1_ENABLED if (ret->sax->initialized == XML_SAX2_MAGIC) {#endif /* LIBXML_SAX1_ENABLED */ ret->startElementNs = ret->sax->startElementNs; ret->sax->startElementNs = xmlTextReaderStartElementNs; ret->endElementNs = ret->sax->endElementNs; ret->sax->endElementNs = xmlTextReaderEndElementNs;#ifdef LIBXML_SAX1_ENABLED } else { ret->startElementNs = NULL; ret->endElementNs = NULL; }#endif /* LIBXML_SAX1_ENABLED */ ret->characters = ret->sax->characters; ret->sax->characters = xmlTextReaderCharacters; ret->sax->ignorableWhitespace = xmlTextReaderCharacters; ret->cdataBlock = ret->sax->cdataBlock; ret->sax->cdataBlock = xmlTextReaderCDataBlock;
ret->mode = XML_TEXTREADER_MODE_INITIAL; ret->node = NULL; ret->curnode = NULL; if (xmlBufUse(ret->input->buffer) < 4) { xmlParserInputBufferRead(input, 4); } if (xmlBufUse(ret->input->buffer) >= 4) { ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, (const char *) xmlBufContent(ret->input->buffer), 4, URI); ret->base = 0; ret->cur = 4; } else { ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI); ret->base = 0; ret->cur = 0; }
if (ret->ctxt == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); xmlBufFree(ret->buffer); xmlFree(ret->sax); xmlFree(ret); return(NULL); } ret->ctxt->parseMode = XML_PARSE_READER; ret->ctxt->_private = ret; ret->ctxt->linenumbers = 1; ret->ctxt->dictNames = 1; ret->allocs = XML_TEXTREADER_CTXT; /* * use the parser dictionary to allocate all elements and attributes names */ ret->ctxt->docdict = 1; ret->dict = ret->ctxt->dict;#ifdef LIBXML_XINCLUDE_ENABLED ret->xinclude = 0;#endif#ifdef LIBXML_PATTERN_ENABLED ret->patternMax = 0; ret->patternTab = NULL;#endif return(ret);}
/** * xmlNewTextReaderFilename: * @URI: the URI of the resource to process * * Create an xmlTextReader structure fed with the resource at @URI * * Returns the new xmlTextReaderPtr or NULL in case of error */xmlTextReaderPtrxmlNewTextReaderFilename(const char *URI) { xmlParserInputBufferPtr input; xmlTextReaderPtr ret; char *directory = NULL;
input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE); if (input == NULL) return(NULL); ret = xmlNewTextReader(input, URI); if (ret == NULL) { xmlFreeParserInputBuffer(input); return(NULL); } ret->allocs |= XML_TEXTREADER_INPUT; if (ret->ctxt->directory == NULL) directory = xmlParserGetDirectory(URI); if ((ret->ctxt->directory == NULL) && (directory != NULL)) ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); if (directory != NULL) xmlFree(directory); return(ret);}
/** * xmlFreeTextReader: * @reader: the xmlTextReaderPtr * * Deallocate all the resources associated to the reader */voidxmlFreeTextReader(xmlTextReaderPtr reader) { if (reader == NULL) return;#ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngSchemas != NULL) { xmlRelaxNGFree(reader->rngSchemas); reader->rngSchemas = NULL; } if (reader->rngValidCtxt != NULL) { if (! reader->rngPreserveCtxt) xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } if (reader->xsdPlug != NULL) { xmlSchemaSAXUnplug(reader->xsdPlug); reader->xsdPlug = NULL; } if (reader->xsdValidCtxt != NULL) { if (! reader->xsdPreserveCtxt) xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); reader->xsdValidCtxt = NULL; } if (reader->xsdSchemas != NULL) { xmlSchemaFree(reader->xsdSchemas); reader->xsdSchemas = NULL; }#endif#ifdef LIBXML_XINCLUDE_ENABLED if (reader->xincctxt != NULL) xmlXIncludeFreeContext(reader->xincctxt);#endif#ifdef LIBXML_PATTERN_ENABLED if (reader->patternTab != NULL) { int i; for (i = 0;i < reader->patternNr;i++) { if (reader->patternTab[i] != NULL) xmlFreePattern(reader->patternTab[i]); } xmlFree(reader->patternTab); }#endif if (reader->mode != XML_TEXTREADER_MODE_CLOSED) xmlTextReaderClose(reader); if (reader->ctxt != NULL) { if (reader->dict == reader->ctxt->dict) reader->dict = NULL; if (reader->allocs & XML_TEXTREADER_CTXT) xmlFreeParserCtxt(reader->ctxt); } if (reader->sax != NULL) xmlFree(reader->sax); if (reader->buffer != NULL) xmlBufFree(reader->buffer); if (reader->entTab != NULL) xmlFree(reader->entTab); if (reader->dict != NULL) xmlDictFree(reader->dict); xmlFree(reader);}
/************************************************************************ * * * Methods for XmlTextReader * * * ************************************************************************//** * xmlTextReaderClose: * @reader: the xmlTextReaderPtr used * * This method releases any resources allocated by the current instance * changes the state to Closed and close any underlying input. * * Returns 0 or -1 in case of error */intxmlTextReaderClose(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); reader->node = NULL; reader->curnode = NULL; reader->mode = XML_TEXTREADER_MODE_CLOSED; if (reader->faketext != NULL) { xmlFreeNode(reader->faketext); reader->faketext = NULL; } if (reader->ctxt != NULL) {#ifdef LIBXML_VALID_ENABLED if ((reader->ctxt->vctxt.vstateTab != NULL) && (reader->ctxt->vctxt.vstateMax > 0)){#ifdef LIBXML_REGEXP_ENABLED while (reader->ctxt->vctxt.vstateNr > 0) xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);#endif /* LIBXML_REGEXP_ENABLED */ xmlFree(reader->ctxt->vctxt.vstateTab); reader->ctxt->vctxt.vstateTab = NULL; reader->ctxt->vctxt.vstateMax = 0; }#endif /* LIBXML_VALID_ENABLED */ xmlStopParser(reader->ctxt); if (reader->ctxt->myDoc != NULL) { if (reader->preserve == 0) xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); reader->ctxt->myDoc = NULL; } } if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) { xmlFreeParserInputBuffer(reader->input); reader->allocs -= XML_TEXTREADER_INPUT; } return(0);}
/** * xmlTextReaderGetAttributeNo: * @reader: the xmlTextReaderPtr used * @no: the zero-based index of the attribute relative to the containing element * * Provides the value of the attribute with the specified index relative * to the containing element. * * Returns a string containing the value of the specified attribute, or NULL * in case of error. The string must be deallocated by the caller. */xmlChar *xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) { xmlChar *ret; int i; xmlAttrPtr cur; xmlNsPtr ns;
if (reader == NULL) return(NULL); if (reader->node == NULL) return(NULL); if (reader->curnode != NULL) return(NULL); /* TODO: handle the xmlDecl */ if (reader->node->type != XML_ELEMENT_NODE) return(NULL);
ns = reader->node->nsDef; for (i = 0;(i < no) && (ns != NULL);i++) { ns = ns->next; } if (ns != NULL) return(xmlStrdup(ns->href));
cur = reader->node->properties; if (cur == NULL) return(NULL); for (;i < no;i++) { cur = cur->next; if (cur == NULL) return(NULL); } /* TODO walk the DTD if present */
ret = xmlNodeListGetString(reader->node->doc, cur->children, 1); if (ret == NULL) return(xmlStrdup((xmlChar *)"")); return(ret);}
/** * xmlTextReaderGetAttribute: * @reader: the xmlTextReaderPtr used * @name: the qualified name of the attribute. * * Provides the value of the attribute with the specified qualified name. * * Returns a string containing the value of the specified attribute, or NULL * in case of error. The string must be deallocated by the caller. */xmlChar *xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) { xmlChar *prefix = NULL; xmlChar *localname; xmlNsPtr ns; xmlChar *ret = NULL;
if ((reader == NULL) || (name == NULL)) return(NULL); if (reader->node == NULL) return(NULL); if (reader->curnode != NULL) return(NULL);
/* TODO: handle the xmlDecl */ if (reader->node->type != XML_ELEMENT_NODE) return(NULL);
localname = xmlSplitQName2(name, &prefix); if (localname == NULL) { /* * Namespace default decl */ if (xmlStrEqual(name, BAD_CAST "xmlns")) { ns = reader->node->nsDef; while (ns != NULL) { if (ns->prefix == NULL) { return(xmlStrdup(ns->href)); } ns = ns->next; } return NULL; } return(xmlGetNoNsProp(reader->node, name)); }
/* * Namespace default decl */ if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { ns = reader->node->nsDef; while (ns != NULL) { if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { ret = xmlStrdup(ns->href); break; } ns = ns->next; } } else { ns = xmlSearchNs(reader->node->doc, reader->node, prefix); if (ns != NULL) ret = xmlGetNsProp(reader->node, localname, ns->href); }
xmlFree(localname); if (prefix != NULL) xmlFree(prefix); return(ret);}
/** * xmlTextReaderGetAttributeNs: * @reader: the xmlTextReaderPtr used * @localName: the local name of the attribute. * @namespaceURI: the namespace URI of the attribute. * * Provides the value of the specified attribute * * Returns a string containing the value of the specified attribute, or NULL * in case of error. The string must be deallocated by the caller. */xmlChar *xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName, const xmlChar *namespaceURI) { xmlChar *prefix = NULL; xmlNsPtr ns;
if ((reader == NULL) || (localName == NULL)) return(NULL); if (reader->node == NULL) return(NULL); if (reader->curnode != NULL) return(NULL);
/* TODO: handle the xmlDecl */ if (reader->node->type != XML_ELEMENT_NODE) return(NULL);
if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) { if (! xmlStrEqual(localName, BAD_CAST "xmlns")) { prefix = BAD_CAST localName; } ns = reader->node->nsDef; while (ns != NULL) { if ((prefix == NULL && ns->prefix == NULL) || ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) { return xmlStrdup(ns->href); } ns = ns->next; } return NULL; }
return(xmlGetNsProp(reader->node, localName, namespaceURI));}
/** * xmlTextReaderGetRemainder: * @reader: the xmlTextReaderPtr used * * Method to get the remainder of the buffered XML. this method stops the * parser, set its state to End Of File and return the input stream with * what is left that the parser did not use. * * The implementation is not good, the parser certainly progressed past * what's left in reader->input, and there is an allocation problem. Best * would be to rewrite it differently. * * Returns the xmlParserInputBufferPtr attached to the XML or NULL * in case of error. */xmlParserInputBufferPtrxmlTextReaderGetRemainder(xmlTextReaderPtr reader) { xmlParserInputBufferPtr ret = NULL;
if (reader == NULL) return(NULL); if (reader->node == NULL) return(NULL);
reader->node = NULL; reader->curnode = NULL; reader->mode = XML_TEXTREADER_MODE_EOF; if (reader->ctxt != NULL) { xmlStopParser(reader->ctxt); if (reader->ctxt->myDoc != NULL) { if (reader->preserve == 0) xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); reader->ctxt->myDoc = NULL; } } if (reader->allocs & XML_TEXTREADER_INPUT) { ret = reader->input; reader->input = NULL; reader->allocs -= XML_TEXTREADER_INPUT; } else { /* * Hum, one may need to duplicate the data structure because * without reference counting the input may be freed twice: * - by the layer which allocated it. * - by the layer to which would have been returned to. */ TODO return(NULL); } return(ret);}
/** * xmlTextReaderLookupNamespace: * @reader: the xmlTextReaderPtr used * @prefix: the prefix whose namespace URI is to be resolved. To return * the default namespace, specify NULL * * Resolves a namespace prefix in the scope of the current element. * * Returns a string containing the namespace URI to which the prefix maps * or NULL in case of error. The string must be deallocated by the caller. */xmlChar *xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) { xmlNsPtr ns;
if (reader == NULL) return(NULL); if (reader->node == NULL) return(NULL);
ns = xmlSearchNs(reader->node->doc, reader->node, prefix); if (ns == NULL) return(NULL); return(xmlStrdup(ns->href));}
/** * xmlTextReaderMoveToAttributeNo: * @reader: the xmlTextReaderPtr used * @no: the zero-based index of the attribute relative to the containing * element. * * Moves the position of the current instance to the attribute with * the specified index relative to the containing element. * * Returns 1 in case of success, -1 in case of error, 0 if not found */intxmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) { int i; xmlAttrPtr cur; xmlNsPtr ns;
if (reader == NULL) return(-1); if (reader->node == NULL) return(-1); /* TODO: handle the xmlDecl */ if (reader->node->type != XML_ELEMENT_NODE) return(-1);
reader->curnode = NULL;
ns = reader->node->nsDef; for (i = 0;(i < no) && (ns != NULL);i++) { ns = ns->next; } if (ns != NULL) { reader->curnode = (xmlNodePtr) ns; return(1); }
cur = reader->node->properties; if (cur == NULL) return(0); for (;i < no;i++) { cur = cur->next; if (cur == NULL) return(0); } /* TODO walk the DTD if present */
reader->curnode = (xmlNodePtr) cur; return(1);}
/** * xmlTextReaderMoveToAttribute: * @reader: the xmlTextReaderPtr used * @name: the qualified name of the attribute. * * Moves the position of the current instance to the attribute with * the specified qualified name. * * Returns 1 in case of success, -1 in case of error, 0 if not found */intxmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) { xmlChar *prefix = NULL; xmlChar *localname; xmlNsPtr ns; xmlAttrPtr prop;
if ((reader == NULL) || (name == NULL)) return(-1); if (reader->node == NULL) return(-1);
/* TODO: handle the xmlDecl */ if (reader->node->type != XML_ELEMENT_NODE) return(0);
localname = xmlSplitQName2(name, &prefix); if (localname == NULL) { /* * Namespace default decl */ if (xmlStrEqual(name, BAD_CAST "xmlns")) { ns = reader->node->nsDef; while (ns != NULL) { if (ns->prefix == NULL) { reader->curnode = (xmlNodePtr) ns; return(1); } ns = ns->next; } return(0); }
prop = reader->node->properties; while (prop != NULL) { /* * One need to have * - same attribute names * - and the attribute carrying that namespace */ if ((xmlStrEqual(prop->name, name)) && ((prop->ns == NULL) || (prop->ns->prefix == NULL))) { reader->curnode = (xmlNodePtr) prop; return(1); } prop = prop->next; } return(0); }
/* * Namespace default decl */ if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { ns = reader->node->nsDef; while (ns != NULL) { if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { reader->curnode = (xmlNodePtr) ns; goto found; } ns = ns->next; } goto not_found; } prop = reader->node->properties; while (prop != NULL) { /* * One need to have * - same attribute names * - and the attribute carrying that namespace */ if ((xmlStrEqual(prop->name, localname)) && (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) { reader->curnode = (xmlNodePtr) prop; goto found; } prop = prop->next; }not_found: if (localname != NULL) xmlFree(localname); if (prefix != NULL) xmlFree(prefix); return(0);
found: if (localname != NULL) xmlFree(localname); if (prefix != NULL) xmlFree(prefix); return(1);}
/** * xmlTextReaderMoveToAttributeNs: * @reader: the xmlTextReaderPtr used * @localName: the local name of the attribute. * @namespaceURI: the namespace URI of the attribute. * * Moves the position of the current instance to the attribute with the * specified local name and namespace URI. * * Returns 1 in case of success, -1 in case of error, 0 if not found */intxmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName, const xmlChar *namespaceURI) { xmlAttrPtr prop; xmlNodePtr node; xmlNsPtr ns; xmlChar *prefix = NULL;
if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL)) return(-1); if (reader->node == NULL) return(-1); if (reader->node->type != XML_ELEMENT_NODE) return(0); node = reader->node;
if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) { if (! xmlStrEqual(localName, BAD_CAST "xmlns")) { prefix = BAD_CAST localName; } ns = reader->node->nsDef; while (ns != NULL) { if ((prefix == NULL && ns->prefix == NULL) || ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) { reader->curnode = (xmlNodePtr) ns; return(1); } ns = ns->next; } return(0); }
prop = node->properties; while (prop != NULL) { /* * One need to have * - same attribute names * - and the attribute carrying that namespace */ if (xmlStrEqual(prop->name, localName) && ((prop->ns != NULL) && (xmlStrEqual(prop->ns->href, namespaceURI)))) { reader->curnode = (xmlNodePtr) prop; return(1); } prop = prop->next; } return(0);}
/** * xmlTextReaderMoveToFirstAttribute: * @reader: the xmlTextReaderPtr used * * Moves the position of the current instance to the first attribute * associated with the current node. * * Returns 1 in case of success, -1 in case of error, 0 if not found */intxmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); if (reader->node == NULL) return(-1); if (reader->node->type != XML_ELEMENT_NODE) return(0);
if (reader->node->nsDef != NULL) { reader->curnode = (xmlNodePtr) reader->node->nsDef; return(1); } if (reader->node->properties != NULL) { reader->curnode = (xmlNodePtr) reader->node->properties; return(1); } return(0);}
/** * xmlTextReaderMoveToNextAttribute: * @reader: the xmlTextReaderPtr used * * Moves the position of the current instance to the next attribute * associated with the current node. * * Returns 1 in case of success, -1 in case of error, 0 if not found */intxmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); if (reader->node == NULL) return(-1); if (reader->node->type != XML_ELEMENT_NODE) return(0); if (reader->curnode == NULL) return(xmlTextReaderMoveToFirstAttribute(reader));
if (reader->curnode->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) reader->curnode; if (ns->next != NULL) { reader->curnode = (xmlNodePtr) ns->next; return(1); } if (reader->node->properties != NULL) { reader->curnode = (xmlNodePtr) reader->node->properties; return(1); } return(0); } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) && (reader->curnode->next != NULL)) { reader->curnode = reader->curnode->next; return(1); } return(0);}
/** * xmlTextReaderMoveToElement: * @reader: the xmlTextReaderPtr used * * Moves the position of the current instance to the node that * contains the current Attribute node. * * Returns 1 in case of success, -1 in case of error, 0 if not moved */intxmlTextReaderMoveToElement(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); if (reader->node == NULL) return(-1); if (reader->node->type != XML_ELEMENT_NODE) return(0); if (reader->curnode != NULL) { reader->curnode = NULL; return(1); } return(0);}
/** * xmlTextReaderReadAttributeValue: * @reader: the xmlTextReaderPtr used * * Parses an attribute value into one or more Text and EntityReference nodes. * * Returns 1 in case of success, 0 if the reader was not positioned on an * attribute node or all the attribute values have been read, or -1 * in case of error. */intxmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); if (reader->node == NULL) return(-1); if (reader->curnode == NULL) return(0); if (reader->curnode->type == XML_ATTRIBUTE_NODE) { if (reader->curnode->children == NULL) return(0); reader->curnode = reader->curnode->children; } else if (reader->curnode->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) reader->curnode;
if (reader->faketext == NULL) { reader->faketext = xmlNewDocText(reader->node->doc, ns->href); } else { if ((reader->faketext->content != NULL) && (reader->faketext->content != (xmlChar *) &(reader->faketext->properties))) xmlFree(reader->faketext->content); reader->faketext->content = xmlStrdup(ns->href); } reader->curnode = reader->faketext; } else { if (reader->curnode->next == NULL) return(0); reader->curnode = reader->curnode->next; } return(1);}
/** * xmlTextReaderConstEncoding: * @reader: the xmlTextReaderPtr used * * Determine the encoding of the document being read. * * Returns a string containing the encoding of the document or NULL in * case of error. The string is deallocated with the reader. */const xmlChar *xmlTextReaderConstEncoding(xmlTextReaderPtr reader) { const xmlChar *encoding = NULL;
if (reader == NULL) return(NULL);
if (reader->ctxt != NULL) encoding = xmlGetActualEncoding(reader->ctxt); else if (reader->doc != NULL) encoding = reader->doc->encoding;
return(CONSTSTR(encoding));}
/************************************************************************ * * * Access API to the current node * * * ************************************************************************//** * xmlTextReaderAttributeCount: * @reader: the xmlTextReaderPtr used * * Provides the number of attributes of the current node * * Returns 0 i no attributes, -1 in case of error or the attribute count */intxmlTextReaderAttributeCount(xmlTextReaderPtr reader) { int ret; xmlAttrPtr attr; xmlNsPtr ns; xmlNodePtr node;
if (reader == NULL) return(-1); if (reader->node == NULL) return(0);
if (reader->curnode != NULL) node = reader->curnode; else node = reader->node;
if (node->type != XML_ELEMENT_NODE) return(0); if ((reader->state == XML_TEXTREADER_END) || (reader->state == XML_TEXTREADER_BACKTRACK)) return(0); ret = 0; attr = node->properties; while (attr != NULL) { ret++; attr = attr->next; } ns = node->nsDef; while (ns != NULL) { ret++; ns = ns->next; } return(ret);}
/** * xmlTextReaderNodeType: * @reader: the xmlTextReaderPtr used * * Get the node type of the current node * Reference: * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html * * Returns the xmlReaderTypes of the current node or -1 in case of error */intxmlTextReaderNodeType(xmlTextReaderPtr reader) { xmlNodePtr node;
if (reader == NULL) return(-1); if (reader->node == NULL) return(XML_READER_TYPE_NONE); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node; switch (node->type) { case XML_ELEMENT_NODE: if ((reader->state == XML_TEXTREADER_END) || (reader->state == XML_TEXTREADER_BACKTRACK)) return(XML_READER_TYPE_END_ELEMENT); return(XML_READER_TYPE_ELEMENT); case XML_NAMESPACE_DECL: case XML_ATTRIBUTE_NODE: return(XML_READER_TYPE_ATTRIBUTE); case XML_TEXT_NODE: if (xmlIsBlankNode(reader->node)) { if (xmlNodeGetSpacePreserve(reader->node)) return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE); else return(XML_READER_TYPE_WHITESPACE); } else { return(XML_READER_TYPE_TEXT); } case XML_CDATA_SECTION_NODE: return(XML_READER_TYPE_CDATA); case XML_ENTITY_REF_NODE: return(XML_READER_TYPE_ENTITY_REFERENCE); case XML_ENTITY_NODE: return(XML_READER_TYPE_ENTITY); case XML_PI_NODE: return(XML_READER_TYPE_PROCESSING_INSTRUCTION); case XML_COMMENT_NODE: return(XML_READER_TYPE_COMMENT); case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: return(XML_READER_TYPE_DOCUMENT); case XML_DOCUMENT_FRAG_NODE: return(XML_READER_TYPE_DOCUMENT_FRAGMENT); case XML_NOTATION_NODE: return(XML_READER_TYPE_NOTATION); case XML_DOCUMENT_TYPE_NODE: case XML_DTD_NODE: return(XML_READER_TYPE_DOCUMENT_TYPE);
case XML_ELEMENT_DECL: case XML_ATTRIBUTE_DECL: case XML_ENTITY_DECL: case XML_XINCLUDE_START: case XML_XINCLUDE_END: return(XML_READER_TYPE_NONE); } return(-1);}
/** * xmlTextReaderIsEmptyElement: * @reader: the xmlTextReaderPtr used * * Check if the current node is empty * * Returns 1 if empty, 0 if not and -1 in case of error */intxmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) { if ((reader == NULL) || (reader->node == NULL)) return(-1); if (reader->node->type != XML_ELEMENT_NODE) return(0); if (reader->curnode != NULL) return(0); if (reader->node->children != NULL) return(0); if (reader->state == XML_TEXTREADER_END) return(0); if (reader->doc != NULL) return(1);#ifdef LIBXML_XINCLUDE_ENABLED if (reader->in_xinclude > 0) return(1);#endif return((reader->node->extra & NODE_IS_EMPTY) != 0);}
/** * xmlTextReaderLocalName: * @reader: the xmlTextReaderPtr used * * The local name of the node. * * Returns the local name or NULL if not available, * if non NULL it need to be freed by the caller. */xmlChar *xmlTextReaderLocalName(xmlTextReaderPtr reader) { xmlNodePtr node; if ((reader == NULL) || (reader->node == NULL)) return(NULL); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node; if (node->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) return(xmlStrdup(BAD_CAST "xmlns")); else return(xmlStrdup(ns->prefix)); } if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(xmlTextReaderName(reader)); return(xmlStrdup(node->name));}
/** * xmlTextReaderConstLocalName: * @reader: the xmlTextReaderPtr used * * The local name of the node. * * Returns the local name or NULL if not available, the * string will be deallocated with the reader. */const xmlChar *xmlTextReaderConstLocalName(xmlTextReaderPtr reader) { xmlNodePtr node; if ((reader == NULL) || (reader->node == NULL)) return(NULL); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node; if (node->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) return(CONSTSTR(BAD_CAST "xmlns")); else return(ns->prefix); } if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(xmlTextReaderConstName(reader)); return(node->name);}
/** * xmlTextReaderName: * @reader: the xmlTextReaderPtr used * * The qualified name of the node, equal to Prefix :LocalName. * * Returns the local name or NULL if not available, * if non NULL it need to be freed by the caller. */xmlChar *xmlTextReaderName(xmlTextReaderPtr reader) { xmlNodePtr node; xmlChar *ret;
if ((reader == NULL) || (reader->node == NULL)) return(NULL); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node; switch (node->type) { case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: if ((node->ns == NULL) || (node->ns->prefix == NULL)) return(xmlStrdup(node->name));
ret = xmlStrdup(node->ns->prefix); ret = xmlStrcat(ret, BAD_CAST ":"); ret = xmlStrcat(ret, node->name); return(ret); case XML_TEXT_NODE: return(xmlStrdup(BAD_CAST "#text")); case XML_CDATA_SECTION_NODE: return(xmlStrdup(BAD_CAST "#cdata-section")); case XML_ENTITY_NODE: case XML_ENTITY_REF_NODE: return(xmlStrdup(node->name)); case XML_PI_NODE: return(xmlStrdup(node->name)); case XML_COMMENT_NODE: return(xmlStrdup(BAD_CAST "#comment")); case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: return(xmlStrdup(BAD_CAST "#document")); case XML_DOCUMENT_FRAG_NODE: return(xmlStrdup(BAD_CAST "#document-fragment")); case XML_NOTATION_NODE: return(xmlStrdup(node->name)); case XML_DOCUMENT_TYPE_NODE: case XML_DTD_NODE: return(xmlStrdup(node->name)); case XML_NAMESPACE_DECL: { xmlNsPtr ns = (xmlNsPtr) node;
ret = xmlStrdup(BAD_CAST "xmlns"); if (ns->prefix == NULL) return(ret); ret = xmlStrcat(ret, BAD_CAST ":"); ret = xmlStrcat(ret, ns->prefix); return(ret); }
case XML_ELEMENT_DECL: case XML_ATTRIBUTE_DECL: case XML_ENTITY_DECL: case XML_XINCLUDE_START: case XML_XINCLUDE_END: return(NULL); } return(NULL);}
/** * xmlTextReaderConstName: * @reader: the xmlTextReaderPtr used * * The qualified name of the node, equal to Prefix :LocalName. * * Returns the local name or NULL if not available, the string is * deallocated with the reader. */const xmlChar *xmlTextReaderConstName(xmlTextReaderPtr reader) { xmlNodePtr node;
if ((reader == NULL) || (reader->node == NULL)) return(NULL); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node; switch (node->type) { case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: if ((node->ns == NULL) || (node->ns->prefix == NULL)) return(node->name); return(CONSTQSTR(node->ns->prefix, node->name)); case XML_TEXT_NODE: return(CONSTSTR(BAD_CAST "#text")); case XML_CDATA_SECTION_NODE: return(CONSTSTR(BAD_CAST "#cdata-section")); case XML_ENTITY_NODE: case XML_ENTITY_REF_NODE: return(CONSTSTR(node->name)); case XML_PI_NODE: return(CONSTSTR(node->name)); case XML_COMMENT_NODE: return(CONSTSTR(BAD_CAST "#comment")); case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: return(CONSTSTR(BAD_CAST "#document")); case XML_DOCUMENT_FRAG_NODE: return(CONSTSTR(BAD_CAST "#document-fragment")); case XML_NOTATION_NODE: return(CONSTSTR(node->name)); case XML_DOCUMENT_TYPE_NODE: case XML_DTD_NODE: return(CONSTSTR(node->name)); case XML_NAMESPACE_DECL: { xmlNsPtr ns = (xmlNsPtr) node;
if (ns->prefix == NULL) return(CONSTSTR(BAD_CAST "xmlns")); return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix)); }
case XML_ELEMENT_DECL: case XML_ATTRIBUTE_DECL: case XML_ENTITY_DECL: case XML_XINCLUDE_START: case XML_XINCLUDE_END: return(NULL); } return(NULL);}
/** * xmlTextReaderPrefix: * @reader: the xmlTextReaderPtr used * * A shorthand reference to the namespace associated with the node. * * Returns the prefix or NULL if not available, * if non NULL it need to be freed by the caller. */xmlChar *xmlTextReaderPrefix(xmlTextReaderPtr reader) { xmlNodePtr node; if ((reader == NULL) || (reader->node == NULL)) return(NULL); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node; if (node->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) return(NULL); return(xmlStrdup(BAD_CAST "xmlns")); } if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(NULL); if ((node->ns != NULL) && (node->ns->prefix != NULL)) return(xmlStrdup(node->ns->prefix)); return(NULL);}
/** * xmlTextReaderConstPrefix: * @reader: the xmlTextReaderPtr used * * A shorthand reference to the namespace associated with the node. * * Returns the prefix or NULL if not available, the string is deallocated * with the reader. */const xmlChar *xmlTextReaderConstPrefix(xmlTextReaderPtr reader) { xmlNodePtr node; if ((reader == NULL) || (reader->node == NULL)) return(NULL); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node; if (node->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) return(NULL); return(CONSTSTR(BAD_CAST "xmlns")); } if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(NULL); if ((node->ns != NULL) && (node->ns->prefix != NULL)) return(CONSTSTR(node->ns->prefix)); return(NULL);}
/** * xmlTextReaderNamespaceUri: * @reader: the xmlTextReaderPtr used * * The URI defining the namespace associated with the node. * * Returns the namespace URI or NULL if not available, * if non NULL it need to be freed by the caller. */xmlChar *xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) { xmlNodePtr node; if ((reader == NULL) || (reader->node == NULL)) return(NULL); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node; if (node->type == XML_NAMESPACE_DECL) return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/")); if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(NULL); if (node->ns != NULL) return(xmlStrdup(node->ns->href)); return(NULL);}
/** * xmlTextReaderConstNamespaceUri: * @reader: the xmlTextReaderPtr used * * The URI defining the namespace associated with the node. * * Returns the namespace URI or NULL if not available, the string * will be deallocated with the reader */const xmlChar *xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) { xmlNodePtr node; if ((reader == NULL) || (reader->node == NULL)) return(NULL); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node; if (node->type == XML_NAMESPACE_DECL) return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/")); if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(NULL); if (node->ns != NULL) return(CONSTSTR(node->ns->href)); return(NULL);}
/** * xmlTextReaderBaseUri: * @reader: the xmlTextReaderPtr used * * The base URI of the node. * * Returns the base URI or NULL if not available, * if non NULL it need to be freed by the caller. */xmlChar *xmlTextReaderBaseUri(xmlTextReaderPtr reader) { if ((reader == NULL) || (reader->node == NULL)) return(NULL); return(xmlNodeGetBase(NULL, reader->node));}
/** * xmlTextReaderConstBaseUri: * @reader: the xmlTextReaderPtr used * * The base URI of the node. * * Returns the base URI or NULL if not available, the string * will be deallocated with the reader */const xmlChar *xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) { xmlChar *tmp; const xmlChar *ret;
if ((reader == NULL) || (reader->node == NULL)) return(NULL); tmp = xmlNodeGetBase(NULL, reader->node); if (tmp == NULL) return(NULL); ret = CONSTSTR(tmp); xmlFree(tmp); return(ret);}
/** * xmlTextReaderDepth: * @reader: the xmlTextReaderPtr used * * The depth of the node in the tree. * * Returns the depth or -1 in case of error */intxmlTextReaderDepth(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); if (reader->node == NULL) return(0);
if (reader->curnode != NULL) { if ((reader->curnode->type == XML_ATTRIBUTE_NODE) || (reader->curnode->type == XML_NAMESPACE_DECL)) return(reader->depth + 1); return(reader->depth + 2); } return(reader->depth);}
/** * xmlTextReaderHasAttributes: * @reader: the xmlTextReaderPtr used * * Whether the node has attributes. * * Returns 1 if true, 0 if false, and -1 in case or error */intxmlTextReaderHasAttributes(xmlTextReaderPtr reader) { xmlNodePtr node; if (reader == NULL) return(-1); if (reader->node == NULL) return(0); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node;
if ((node->type == XML_ELEMENT_NODE) && ((node->properties != NULL) || (node->nsDef != NULL))) return(1); /* TODO: handle the xmlDecl */ return(0);}
/** * xmlTextReaderHasValue: * @reader: the xmlTextReaderPtr used * * Whether the node can have a text value. * * Returns 1 if true, 0 if false, and -1 in case or error */intxmlTextReaderHasValue(xmlTextReaderPtr reader) { xmlNodePtr node; if (reader == NULL) return(-1); if (reader->node == NULL) return(0); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node;
switch (node->type) { case XML_ATTRIBUTE_NODE: case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: case XML_NAMESPACE_DECL: return(1); default: break; } return(0);}
/** * xmlTextReaderValue: * @reader: the xmlTextReaderPtr used * * Provides the text value of the node if present * * Returns the string or NULL if not available. The result must be deallocated * with xmlFree() */xmlChar *xmlTextReaderValue(xmlTextReaderPtr reader) { xmlNodePtr node; if (reader == NULL) return(NULL); if (reader->node == NULL) return(NULL); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node;
switch (node->type) { case XML_NAMESPACE_DECL: return(xmlStrdup(((xmlNsPtr) node)->href)); case XML_ATTRIBUTE_NODE:{ xmlAttrPtr attr = (xmlAttrPtr) node;
if (attr->parent != NULL) return (xmlNodeListGetString (attr->parent->doc, attr->children, 1)); else return (xmlNodeListGetString(NULL, attr->children, 1)); break; } case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: if (node->content != NULL) return (xmlStrdup(node->content)); default: break; } return(NULL);}
/** * xmlTextReaderConstValue: * @reader: the xmlTextReaderPtr used * * Provides the text value of the node if present * * Returns the string or NULL if not available. The result will be * deallocated on the next Read() operation. */const xmlChar *xmlTextReaderConstValue(xmlTextReaderPtr reader) { xmlNodePtr node; if (reader == NULL) return(NULL); if (reader->node == NULL) return(NULL); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node;
switch (node->type) { case XML_NAMESPACE_DECL: return(((xmlNsPtr) node)->href); case XML_ATTRIBUTE_NODE:{ xmlAttrPtr attr = (xmlAttrPtr) node; const xmlChar *ret;
if ((attr->children != NULL) && (attr->children->type == XML_TEXT_NODE) && (attr->children->next == NULL)) return(attr->children->content); else { if (reader->buffer == NULL) { reader->buffer = xmlBufCreateSize(100); if (reader->buffer == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlTextReaderSetup : malloc failed\n"); return (NULL); } xmlBufSetAllocationScheme(reader->buffer, XML_BUFFER_ALLOC_DOUBLEIT); } else xmlBufEmpty(reader->buffer); xmlBufGetNodeContent(reader->buffer, node); ret = xmlBufContent(reader->buffer); if (ret == NULL) { /* error on the buffer best to reallocate */ xmlBufFree(reader->buffer); reader->buffer = xmlBufCreateSize(100); xmlBufSetAllocationScheme(reader->buffer, XML_BUFFER_ALLOC_DOUBLEIT); ret = BAD_CAST ""; } return(ret); } break; } case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: return(node->content); default: break; } return(NULL);}
/** * xmlTextReaderIsDefault: * @reader: the xmlTextReaderPtr used * * Whether an Attribute node was generated from the default value * defined in the DTD or schema. * * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error */intxmlTextReaderIsDefault(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); return(0);}
/** * xmlTextReaderQuoteChar: * @reader: the xmlTextReaderPtr used * * The quotation mark character used to enclose the value of an attribute. * * Returns " or ' and -1 in case of error */intxmlTextReaderQuoteChar(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); /* TODO maybe lookup the attribute value for " first */ return('"');}
/** * xmlTextReaderXmlLang: * @reader: the xmlTextReaderPtr used * * The xml:lang scope within which the node resides. * * Returns the xml:lang value or NULL if none exists., * if non NULL it need to be freed by the caller. */xmlChar *xmlTextReaderXmlLang(xmlTextReaderPtr reader) { if (reader == NULL) return(NULL); if (reader->node == NULL) return(NULL); return(xmlNodeGetLang(reader->node));}
/** * xmlTextReaderConstXmlLang: * @reader: the xmlTextReaderPtr used * * The xml:lang scope within which the node resides. * * Returns the xml:lang value or NULL if none exists. */const xmlChar *xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) { xmlChar *tmp; const xmlChar *ret;
if (reader == NULL) return(NULL); if (reader->node == NULL) return(NULL); tmp = xmlNodeGetLang(reader->node); if (tmp == NULL) return(NULL); ret = CONSTSTR(tmp); xmlFree(tmp); return(ret);}
/** * xmlTextReaderConstString: * @reader: the xmlTextReaderPtr used * @str: the string to intern. * * Get an interned string from the reader, allows for example to * speedup string name comparisons * * Returns an interned copy of the string or NULL in case of error. The * string will be deallocated with the reader. */const xmlChar *xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) { if (reader == NULL) return(NULL); return(CONSTSTR(str));}
/** * xmlTextReaderNormalization: * @reader: the xmlTextReaderPtr used * * The value indicating whether to normalize white space and attribute values. * Since attribute value and end of line normalizations are a MUST in the XML * specification only the value true is accepted. The broken behaviour of * accepting out of range character entities like � is of course not * supported either. * * Returns 1 or -1 in case of error. */intxmlTextReaderNormalization(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); return(1);}
/************************************************************************ * * * Extensions to the base APIs * * * ************************************************************************/
/** * xmlTextReaderSetParserProp: * @reader: the xmlTextReaderPtr used * @prop: the xmlParserProperties to set * @value: usually 0 or 1 to (de)activate it * * Change the parser processing behaviour by changing some of its internal * properties. Note that some properties can only be changed before any * read has been done. * * Returns 0 if the call was successful, or -1 in case of error */intxmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) { xmlParserProperties p = (xmlParserProperties) prop; xmlParserCtxtPtr ctxt;
if ((reader == NULL) || (reader->ctxt == NULL)) return(-1); ctxt = reader->ctxt;
switch (p) { case XML_PARSER_LOADDTD: if (value != 0) { if (ctxt->loadsubset == 0) { if (reader->mode != XML_TEXTREADER_MODE_INITIAL) return(-1); ctxt->loadsubset = XML_DETECT_IDS; } } else { ctxt->loadsubset = 0; } return(0); case XML_PARSER_DEFAULTATTRS: if (value != 0) { ctxt->loadsubset |= XML_COMPLETE_ATTRS; } else { if (ctxt->loadsubset & XML_COMPLETE_ATTRS) ctxt->loadsubset -= XML_COMPLETE_ATTRS; } return(0); case XML_PARSER_VALIDATE: if (value != 0) { ctxt->options |= XML_PARSE_DTDVALID; ctxt->validate = 1; reader->validate = XML_TEXTREADER_VALIDATE_DTD; } else { ctxt->options &= ~XML_PARSE_DTDVALID; ctxt->validate = 0; } return(0); case XML_PARSER_SUBST_ENTITIES: if (value != 0) { ctxt->options |= XML_PARSE_NOENT; ctxt->replaceEntities = 1; } else { ctxt->options &= ~XML_PARSE_NOENT; ctxt->replaceEntities = 0; } return(0); } return(-1);}
/** * xmlTextReaderGetParserProp: * @reader: the xmlTextReaderPtr used * @prop: the xmlParserProperties to get * * Read the parser internal property. * * Returns the value, usually 0 or 1, or -1 in case of error. */intxmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) { xmlParserProperties p = (xmlParserProperties) prop; xmlParserCtxtPtr ctxt;
if ((reader == NULL) || (reader->ctxt == NULL)) return(-1); ctxt = reader->ctxt;
switch (p) { case XML_PARSER_LOADDTD: if ((ctxt->loadsubset != 0) || (ctxt->validate != 0)) return(1); return(0); case XML_PARSER_DEFAULTATTRS: if (ctxt->loadsubset & XML_COMPLETE_ATTRS) return(1); return(0); case XML_PARSER_VALIDATE: return(reader->validate); case XML_PARSER_SUBST_ENTITIES: return(ctxt->replaceEntities); } return(-1);}
/** * xmlTextReaderGetParserLineNumber: * @reader: the user data (XML reader context) * * Provide the line number of the current parsing point. * * Returns an int or 0 if not available */intxmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader){ if ((reader == NULL) || (reader->ctxt == NULL) || (reader->ctxt->input == NULL)) { return (0); } return (reader->ctxt->input->line);}
/** * xmlTextReaderGetParserColumnNumber: * @reader: the user data (XML reader context) * * Provide the column number of the current parsing point. * * Returns an int or 0 if not available */intxmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader){ if ((reader == NULL) || (reader->ctxt == NULL) || (reader->ctxt->input == NULL)) { return (0); } return (reader->ctxt->input->col);}
/** * xmlTextReaderCurrentNode: * @reader: the xmlTextReaderPtr used * * Hacking interface allowing to get the xmlNodePtr corresponding to the * current node being accessed by the xmlTextReader. This is dangerous * because the underlying node may be destroyed on the next Reads. * * Returns the xmlNodePtr or NULL in case of error. */xmlNodePtrxmlTextReaderCurrentNode(xmlTextReaderPtr reader) { if (reader == NULL) return(NULL);
if (reader->curnode != NULL) return(reader->curnode); return(reader->node);}
/** * xmlTextReaderPreserve: * @reader: the xmlTextReaderPtr used * * This tells the XML Reader to preserve the current node. * The caller must also use xmlTextReaderCurrentDoc() to * keep an handle on the resulting document once parsing has finished * * Returns the xmlNodePtr or NULL in case of error. */xmlNodePtrxmlTextReaderPreserve(xmlTextReaderPtr reader) { xmlNodePtr cur, parent;
if (reader == NULL) return(NULL);
if (reader->curnode != NULL) cur = reader->curnode; else cur = reader->node; if (cur == NULL) return(NULL);
if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) { cur->extra |= NODE_IS_PRESERVED; cur->extra |= NODE_IS_SPRESERVED; } reader->preserves++;
parent = cur->parent; while (parent != NULL) { if (parent->type == XML_ELEMENT_NODE) parent->extra |= NODE_IS_PRESERVED; parent = parent->parent; } return(cur);}
#ifdef LIBXML_PATTERN_ENABLED/** * xmlTextReaderPreservePattern: * @reader: the xmlTextReaderPtr used * @pattern: an XPath subset pattern * @namespaces: the prefix definitions, array of [URI, prefix] or NULL * * This tells the XML Reader to preserve all nodes matched by the * pattern. The caller must also use xmlTextReaderCurrentDoc() to * keep an handle on the resulting document once parsing has finished * * Returns a non-negative number in case of success and -1 in case of error */intxmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern, const xmlChar **namespaces){ xmlPatternPtr comp;
if ((reader == NULL) || (pattern == NULL)) return(-1);
comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces); if (comp == NULL) return(-1);
if (reader->patternMax <= 0) { reader->patternMax = 4; reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax * sizeof(reader->patternTab[0])); if (reader->patternTab == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); return (-1); } } if (reader->patternNr >= reader->patternMax) { xmlPatternPtr *tmp; reader->patternMax *= 2; tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab, reader->patternMax * sizeof(reader->patternTab[0])); if (tmp == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); reader->patternMax /= 2; return (-1); } reader->patternTab = tmp; } reader->patternTab[reader->patternNr] = comp; return(reader->patternNr++);}#endif
/** * xmlTextReaderCurrentDoc: * @reader: the xmlTextReaderPtr used * * Hacking interface allowing to get the xmlDocPtr corresponding to the * current document being accessed by the xmlTextReader. * NOTE: as a result of this call, the reader will not destroy the * associated XML document and calling xmlFreeDoc() on the result * is needed once the reader parsing has finished. * * Returns the xmlDocPtr or NULL in case of error. */xmlDocPtrxmlTextReaderCurrentDoc(xmlTextReaderPtr reader) { if (reader == NULL) return(NULL); if (reader->doc != NULL) return(reader->doc); if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL)) return(NULL);
reader->preserve = 1; return(reader->ctxt->myDoc);}
#ifdef LIBXML_SCHEMAS_ENABLEDstatic char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
static voidxmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
static voidxmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
static voidxmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
static voidxmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
static voidxmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...){ xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
char *str;
va_list ap;
va_start(ap, msg); str = xmlTextReaderBuildMessage(msg, ap); if (!reader->errorFunc) { xmlTextReaderValidityError(ctx, "%s", str); } else { reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */ ); } if (str != NULL) xmlFree(str); va_end(ap);}
static voidxmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...){ xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
char *str;
va_list ap;
va_start(ap, msg); str = xmlTextReaderBuildMessage(msg, ap); if (!reader->errorFunc) { xmlTextReaderValidityWarning(ctx, "%s", str); } else { reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */ ); } if (str != NULL) xmlFree(str); va_end(ap);}
static voidxmlTextReaderStructuredError(void *ctxt, const xmlError *error);
static voidxmlTextReaderValidityStructuredRelay(void *userData, const xmlError *error){ xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
if (reader->sErrorFunc) { reader->sErrorFunc(reader->errorFuncArg, error); } else { xmlTextReaderStructuredError(reader, error); }}/** * xmlTextReaderRelaxNGSetSchema: * @reader: the xmlTextReaderPtr used * @schema: a precompiled RelaxNG schema * * Use RelaxNG to validate the document as it is processed. * Activation is only possible before the first Read(). * if @schema is NULL, then RelaxNG validation is deactivated. @ The @schema should not be freed until the reader is deallocated * or its use has been deactivated. * * Returns 0 in case the RelaxNG validation could be (de)activated and * -1 in case of error. */intxmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) { if (reader == NULL) return(-1); if (schema == NULL) { if (reader->rngSchemas != NULL) { xmlRelaxNGFree(reader->rngSchemas); reader->rngSchemas = NULL; } if (reader->rngValidCtxt != NULL) { if (! reader->rngPreserveCtxt) xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } reader->rngPreserveCtxt = 0; return(0); } if (reader->mode != XML_TEXTREADER_MODE_INITIAL) return(-1); if (reader->rngSchemas != NULL) { xmlRelaxNGFree(reader->rngSchemas); reader->rngSchemas = NULL; } if (reader->rngValidCtxt != NULL) { if (! reader->rngPreserveCtxt) xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } reader->rngPreserveCtxt = 0; reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema); if (reader->rngValidCtxt == NULL) return(-1); if (reader->errorFunc != NULL) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } if (reader->sErrorFunc != NULL) { xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } reader->rngValidErrors = 0; reader->rngFullNode = NULL; reader->validate = XML_TEXTREADER_VALIDATE_RNG; return(0);}
/** * xmlTextReaderLocator: * @ctx: the xmlTextReaderPtr used * @file: returned file information * @line: returned line information * * Internal locator function for the readers * * Returns 0 in case the Schema validation could be (de)activated and * -1 in case of error. */static intxmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) { xmlTextReaderPtr reader;
if ((ctx == NULL) || ((file == NULL) && (line == NULL))) return(-1);
if (file != NULL) *file = NULL; if (line != NULL) *line = 0;
reader = (xmlTextReaderPtr) ctx; if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) { if (file != NULL) *file = reader->ctxt->input->filename; if (line != NULL) *line = reader->ctxt->input->line; return(0); } if (reader->node != NULL) { long res; int ret = 0;
if (line != NULL) { res = xmlGetLineNo(reader->node); if (res > 0) *line = (unsigned long) res; else ret = -1; } if (file != NULL) { xmlDocPtr doc = reader->node->doc; if ((doc != NULL) && (doc->URL != NULL)) *file = (const char *) doc->URL; else ret = -1; } return(ret); } return(-1);}
/** * xmlTextReaderSetSchema: * @reader: the xmlTextReaderPtr used * @schema: a precompiled Schema schema * * Use XSD Schema to validate the document as it is processed. * Activation is only possible before the first Read(). * if @schema is NULL, then Schema validation is deactivated. * The @schema should not be freed until the reader is deallocated * or its use has been deactivated. * * Returns 0 in case the Schema validation could be (de)activated and * -1 in case of error. */intxmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) { if (reader == NULL) return(-1); if (schema == NULL) { if (reader->xsdPlug != NULL) { xmlSchemaSAXUnplug(reader->xsdPlug); reader->xsdPlug = NULL; } if (reader->xsdValidCtxt != NULL) { if (! reader->xsdPreserveCtxt) xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); reader->xsdValidCtxt = NULL; } reader->xsdPreserveCtxt = 0; if (reader->xsdSchemas != NULL) { xmlSchemaFree(reader->xsdSchemas); reader->xsdSchemas = NULL; } return(0); } if (reader->mode != XML_TEXTREADER_MODE_INITIAL) return(-1); if (reader->xsdPlug != NULL) { xmlSchemaSAXUnplug(reader->xsdPlug); reader->xsdPlug = NULL; } if (reader->xsdValidCtxt != NULL) { if (! reader->xsdPreserveCtxt) xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); reader->xsdValidCtxt = NULL; } reader->xsdPreserveCtxt = 0; if (reader->xsdSchemas != NULL) { xmlSchemaFree(reader->xsdSchemas); reader->xsdSchemas = NULL; } reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema); if (reader->xsdValidCtxt == NULL) { xmlSchemaFree(reader->xsdSchemas); reader->xsdSchemas = NULL; return(-1); } reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, &(reader->ctxt->sax), &(reader->ctxt->userData)); if (reader->xsdPlug == NULL) { xmlSchemaFree(reader->xsdSchemas); reader->xsdSchemas = NULL; xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); reader->xsdValidCtxt = NULL; return(-1); } xmlSchemaValidateSetLocator(reader->xsdValidCtxt, xmlTextReaderLocator, (void *) reader);
if (reader->errorFunc != NULL) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } if (reader->sErrorFunc != NULL) { xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } reader->xsdValidErrors = 0; reader->validate = XML_TEXTREADER_VALIDATE_XSD; return(0);}
/** * xmlTextReaderRelaxNGValidateInternal: * @reader: the xmlTextReaderPtr used * @rng: the path to a RelaxNG schema or NULL * @ctxt: the RelaxNG schema validation context or NULL * @options: options (not yet used) * * Use RelaxNG to validate the document as it is processed. * Activation is only possible before the first Read(). * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated. * * Returns 0 in case the RelaxNG validation could be (de)activated and * -1 in case of error. */static intxmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader, const char *rng, xmlRelaxNGValidCtxtPtr ctxt, int options ATTRIBUTE_UNUSED){ if (reader == NULL) return(-1);
if ((rng != NULL) && (ctxt != NULL)) return (-1);
if (((rng != NULL) || (ctxt != NULL)) && ((reader->mode != XML_TEXTREADER_MODE_INITIAL) || (reader->ctxt == NULL))) return(-1);
/* Cleanup previous validation stuff. */ if (reader->rngValidCtxt != NULL) { if ( !reader->rngPreserveCtxt) xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } reader->rngPreserveCtxt = 0; if (reader->rngSchemas != NULL) { xmlRelaxNGFree(reader->rngSchemas); reader->rngSchemas = NULL; }
if ((rng == NULL) && (ctxt == NULL)) { /* We just want to deactivate the validation, so get out. */ return(0); }
if (rng != NULL) { xmlRelaxNGParserCtxtPtr pctxt; /* Parse the schema and create validation environment. */
pctxt = xmlRelaxNGNewParserCtxt(rng); if (reader->errorFunc != NULL) { xmlRelaxNGSetParserErrors(pctxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } if (reader->sErrorFunc != NULL) { xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } reader->rngSchemas = xmlRelaxNGParse(pctxt); xmlRelaxNGFreeParserCtxt(pctxt); if (reader->rngSchemas == NULL) return(-1); reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas); if (reader->rngValidCtxt == NULL) { xmlRelaxNGFree(reader->rngSchemas); reader->rngSchemas = NULL; return(-1); } } else { /* Use the given validation context. */ reader->rngValidCtxt = ctxt; reader->rngPreserveCtxt = 1; } /* * Redirect the validation context's error channels to use * the reader channels. * TODO: In case the user provides the validation context we * could make this redirection optional. */ if (reader->errorFunc != NULL) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } if (reader->sErrorFunc != NULL) { xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } reader->rngValidErrors = 0; reader->rngFullNode = NULL; reader->validate = XML_TEXTREADER_VALIDATE_RNG; return(0);}
/** * xmlTextReaderSchemaValidateInternal: * @reader: the xmlTextReaderPtr used * @xsd: the path to a W3C XSD schema or NULL * @ctxt: the XML Schema validation context or NULL * @options: options (not used yet) * * Validate the document as it is processed using XML Schema. * Activation is only possible before the first Read(). * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated. * * Returns 0 in case the schemas validation could be (de)activated and * -1 in case of error. */static intxmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader, const char *xsd, xmlSchemaValidCtxtPtr ctxt, int options ATTRIBUTE_UNUSED){ if (reader == NULL) return(-1);
if ((xsd != NULL) && (ctxt != NULL)) return(-1);
if (((xsd != NULL) || (ctxt != NULL)) && ((reader->mode != XML_TEXTREADER_MODE_INITIAL) || (reader->ctxt == NULL))) return(-1);
/* Cleanup previous validation stuff. */ if (reader->xsdPlug != NULL) { xmlSchemaSAXUnplug(reader->xsdPlug); reader->xsdPlug = NULL; } if (reader->xsdValidCtxt != NULL) { if (! reader->xsdPreserveCtxt) xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); reader->xsdValidCtxt = NULL; } reader->xsdPreserveCtxt = 0; if (reader->xsdSchemas != NULL) { xmlSchemaFree(reader->xsdSchemas); reader->xsdSchemas = NULL; }
if ((xsd == NULL) && (ctxt == NULL)) { /* We just want to deactivate the validation, so get out. */ return(0); }
if (xsd != NULL) { xmlSchemaParserCtxtPtr pctxt; /* Parse the schema and create validation environment. */ pctxt = xmlSchemaNewParserCtxt(xsd); if (reader->errorFunc != NULL) { xmlSchemaSetParserErrors(pctxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } reader->xsdSchemas = xmlSchemaParse(pctxt); xmlSchemaFreeParserCtxt(pctxt); if (reader->xsdSchemas == NULL) return(-1); reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas); if (reader->xsdValidCtxt == NULL) { xmlSchemaFree(reader->xsdSchemas); reader->xsdSchemas = NULL; return(-1); } reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, &(reader->ctxt->sax), &(reader->ctxt->userData)); if (reader->xsdPlug == NULL) { xmlSchemaFree(reader->xsdSchemas); reader->xsdSchemas = NULL; xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); reader->xsdValidCtxt = NULL; return(-1); } } else { /* Use the given validation context. */ reader->xsdValidCtxt = ctxt; reader->xsdPreserveCtxt = 1; reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, &(reader->ctxt->sax), &(reader->ctxt->userData)); if (reader->xsdPlug == NULL) { reader->xsdValidCtxt = NULL; reader->xsdPreserveCtxt = 0; return(-1); } } xmlSchemaValidateSetLocator(reader->xsdValidCtxt, xmlTextReaderLocator, (void *) reader); /* * Redirect the validation context's error channels to use * the reader channels. * TODO: In case the user provides the validation context we * could make this redirection optional. */ if (reader->errorFunc != NULL) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); } if (reader->sErrorFunc != NULL) { xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } reader->xsdValidErrors = 0; reader->validate = XML_TEXTREADER_VALIDATE_XSD; return(0);}
/** * xmlTextReaderSchemaValidateCtxt: * @reader: the xmlTextReaderPtr used * @ctxt: the XML Schema validation context or NULL * @options: options (not used yet) * * Use W3C XSD schema context to validate the document as it is processed. * Activation is only possible before the first Read(). * If @ctxt is NULL, then XML Schema validation is deactivated. * * Returns 0 in case the schemas validation could be (de)activated and * -1 in case of error. */intxmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader, xmlSchemaValidCtxtPtr ctxt, int options){ return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));}
/** * xmlTextReaderSchemaValidate: * @reader: the xmlTextReaderPtr used * @xsd: the path to a W3C XSD schema or NULL * * Use W3C XSD schema to validate the document as it is processed. * Activation is only possible before the first Read(). * If @xsd is NULL, then XML Schema validation is deactivated. * * Returns 0 in case the schemas validation could be (de)activated and * -1 in case of error. */intxmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd){ return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));}
/** * xmlTextReaderRelaxNGValidateCtxt: * @reader: the xmlTextReaderPtr used * @ctxt: the RelaxNG schema validation context or NULL * @options: options (not used yet) * * Use RelaxNG schema context to validate the document as it is processed. * Activation is only possible before the first Read(). * If @ctxt is NULL, then RelaxNG schema validation is deactivated. * * Returns 0 in case the schemas validation could be (de)activated and * -1 in case of error. */intxmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader, xmlRelaxNGValidCtxtPtr ctxt, int options){ return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));}
/** * xmlTextReaderRelaxNGValidate: * @reader: the xmlTextReaderPtr used * @rng: the path to a RelaxNG schema or NULL * * Use RelaxNG schema to validate the document as it is processed. * Activation is only possible before the first Read(). * If @rng is NULL, then RelaxNG schema validation is deactivated. * * Returns 0 in case the schemas validation could be (de)activated and * -1 in case of error. */intxmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng){ return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));}
#endif
/** * xmlTextReaderIsNamespaceDecl: * @reader: the xmlTextReaderPtr used * * Determine whether the current node is a namespace declaration * rather than a regular attribute. * * Returns 1 if the current node is a namespace declaration, 0 if it * is a regular attribute or other type of node, or -1 in case of * error. */intxmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) { xmlNodePtr node; if (reader == NULL) return(-1); if (reader->node == NULL) return(-1); if (reader->curnode != NULL) node = reader->curnode; else node = reader->node;
if (XML_NAMESPACE_DECL == node->type) return(1); else return(0);}
/** * xmlTextReaderConstXmlVersion: * @reader: the xmlTextReaderPtr used * * Determine the XML version of the document being read. * * Returns a string containing the XML version of the document or NULL * in case of error. The string is deallocated with the reader. */const xmlChar *xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) { xmlDocPtr doc = NULL; if (reader == NULL) return(NULL); if (reader->doc != NULL) doc = reader->doc; else if (reader->ctxt != NULL) doc = reader->ctxt->myDoc; if (doc == NULL) return(NULL);
if (doc->version == NULL) return(NULL); else return(CONSTSTR(doc->version));}
/** * xmlTextReaderStandalone: * @reader: the xmlTextReaderPtr used * * Determine the standalone status of the document being read. * * Returns 1 if the document was declared to be standalone, 0 if it * was declared to be not standalone, or -1 if the document did not * specify its standalone status or in case of error. */intxmlTextReaderStandalone(xmlTextReaderPtr reader) { xmlDocPtr doc = NULL; if (reader == NULL) return(-1); if (reader->doc != NULL) doc = reader->doc; else if (reader->ctxt != NULL) doc = reader->ctxt->myDoc; if (doc == NULL) return(-1);
return(doc->standalone);}
/************************************************************************ * * * Error Handling Extensions * * * ************************************************************************/
/* helper to build a xmlMalloc'ed string from a format and va_list */static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) { int size = 0; int chars; char *larger; char *str = NULL; va_list aq;
while (1) { VA_COPY(aq, ap); chars = vsnprintf(str, size, msg, aq); va_end(aq); if (chars < 0) { xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n"); if (str) xmlFree(str); return NULL; } if ((chars < size) || (size == MAX_ERR_MSG_SIZE)) break; if (chars < MAX_ERR_MSG_SIZE) size = chars + 1; else size = MAX_ERR_MSG_SIZE; if ((larger = (char *) xmlRealloc(str, size)) == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); if (str) xmlFree(str); return NULL; } str = larger; }
return str;}
/** * xmlTextReaderLocatorLineNumber: * @locator: the xmlTextReaderLocatorPtr used * * Obtain the line number for the given locator. * * Returns the line number or -1 in case of error. */intxmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) { /* we know that locator is a xmlParserCtxtPtr */ xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator; int ret = -1;
if (locator == NULL) return(-1); if (ctx->node != NULL) { ret = xmlGetLineNo(ctx->node); } else { /* inspired from error.c */ xmlParserInputPtr input; input = ctx->input; if ((input->filename == NULL) && (ctx->inputNr > 1)) input = ctx->inputTab[ctx->inputNr - 2]; if (input != NULL) { ret = input->line; } else { ret = -1; } }
return ret;}
/** * xmlTextReaderLocatorBaseURI: * @locator: the xmlTextReaderLocatorPtr used * * Obtain the base URI for the given locator. * * Returns the base URI or NULL in case of error, * if non NULL it need to be freed by the caller. */xmlChar *xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) { /* we know that locator is a xmlParserCtxtPtr */ xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator; xmlChar *ret = NULL;
if (locator == NULL) return(NULL); if (ctx->node != NULL) { ret = xmlNodeGetBase(NULL,ctx->node); } else { /* inspired from error.c */ xmlParserInputPtr input; input = ctx->input; if ((input->filename == NULL) && (ctx->inputNr > 1)) input = ctx->inputTab[ctx->inputNr - 2]; if (input != NULL) { ret = xmlStrdup(BAD_CAST input->filename); } else { ret = NULL; } }
return ret;}
static voidxmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str){ xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
if (str != NULL) { if (reader->errorFunc) reader->errorFunc(reader->errorFuncArg, str, severity, (xmlTextReaderLocatorPtr) ctx); xmlFree(str); }}
static voidxmlTextReaderStructuredError(void *ctxt, const xmlError *error){ xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
if (error && reader->sErrorFunc) { reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error); }}
static void LIBXML_ATTR_FORMAT(2,3)xmlTextReaderError(void *ctxt, const char *msg, ...){ va_list ap;
va_start(ap, msg); xmlTextReaderGenericError(ctxt, XML_PARSER_SEVERITY_ERROR, xmlTextReaderBuildMessage(msg, ap)); va_end(ap);
}
static void LIBXML_ATTR_FORMAT(2,3)xmlTextReaderWarning(void *ctxt, const char *msg, ...){ va_list ap;
va_start(ap, msg); xmlTextReaderGenericError(ctxt, XML_PARSER_SEVERITY_WARNING, xmlTextReaderBuildMessage(msg, ap)); va_end(ap);}
static voidxmlTextReaderValidityError(void *ctxt, const char *msg, ...){ va_list ap;
int len = xmlStrlen((const xmlChar *) msg);
if ((len > 1) && (msg[len - 2] != ':')) { /* * some callbacks only report locator information: * skip them (mimicking behaviour in error.c) */ va_start(ap, msg); xmlTextReaderGenericError(ctxt, XML_PARSER_SEVERITY_VALIDITY_ERROR, xmlTextReaderBuildMessage(msg, ap)); va_end(ap); }}
static voidxmlTextReaderValidityWarning(void *ctxt, const char *msg, ...){ va_list ap;
int len = xmlStrlen((const xmlChar *) msg);
if ((len != 0) && (msg[len - 1] != ':')) { /* * some callbacks only report locator information: * skip them (mimicking behaviour in error.c) */ va_start(ap, msg); xmlTextReaderGenericError(ctxt, XML_PARSER_SEVERITY_VALIDITY_WARNING, xmlTextReaderBuildMessage(msg, ap)); va_end(ap); }}
/** * xmlTextReaderSetErrorHandler: * @reader: the xmlTextReaderPtr used * @f: the callback function to call on error and warnings * @arg: a user argument to pass to the callback function * * Register a callback function that will be called on error and warnings. * * If @f is NULL, the default error and warning handlers are restored. */voidxmlTextReaderSetErrorHandler(xmlTextReaderPtr reader, xmlTextReaderErrorFunc f, void *arg){ if (f != NULL) { reader->ctxt->sax->error = xmlTextReaderError; reader->ctxt->sax->serror = NULL; reader->ctxt->vctxt.error = xmlTextReaderValidityError; reader->ctxt->sax->warning = xmlTextReaderWarning; reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; reader->errorFunc = f; reader->sErrorFunc = NULL; reader->errorFuncArg = arg;#ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader); } if (reader->xsdValidCtxt) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, xmlTextReaderValidityErrorRelay, xmlTextReaderValidityWarningRelay, reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader); }#endif } else { /* restore defaults */ reader->ctxt->sax->error = xmlParserError; reader->ctxt->vctxt.error = xmlParserValidityError; reader->ctxt->sax->warning = xmlParserWarning; reader->ctxt->vctxt.warning = xmlParserValidityWarning; reader->errorFunc = NULL; reader->sErrorFunc = NULL; reader->errorFuncArg = NULL;#ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader); } if (reader->xsdValidCtxt) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader); }#endif }}
/*** xmlTextReaderSetStructuredErrorHandler: * @reader: the xmlTextReaderPtr used * @f: the callback function to call on error and warnings * @arg: a user argument to pass to the callback function * * Register a callback function that will be called on error and warnings. * * If @f is NULL, the default error and warning handlers are restored. */voidxmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader, xmlStructuredErrorFunc f, void *arg){ if (f != NULL) { reader->ctxt->sax->error = NULL; reader->ctxt->sax->serror = xmlTextReaderStructuredError; reader->ctxt->vctxt.error = xmlTextReaderValidityError; reader->ctxt->sax->warning = xmlTextReaderWarning; reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; reader->sErrorFunc = f; reader->errorFunc = NULL; reader->errorFuncArg = arg;#ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, xmlTextReaderValidityStructuredRelay, reader); } if (reader->xsdValidCtxt) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, xmlTextReaderValidityStructuredRelay, reader); }#endif } else { /* restore defaults */ reader->ctxt->sax->error = xmlParserError; reader->ctxt->sax->serror = NULL; reader->ctxt->vctxt.error = xmlParserValidityError; reader->ctxt->sax->warning = xmlParserWarning; reader->ctxt->vctxt.warning = xmlParserValidityWarning; reader->errorFunc = NULL; reader->sErrorFunc = NULL; reader->errorFuncArg = NULL;#ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader); } if (reader->xsdValidCtxt) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader); }#endif }}
/** * xmlTextReaderIsValid: * @reader: the xmlTextReaderPtr used * * Retrieve the validity status from the parser context * * Returns the flag value 1 if valid, 0 if no, and -1 in case of error */intxmlTextReaderIsValid(xmlTextReaderPtr reader){ if (reader == NULL) return (-1);#ifdef LIBXML_SCHEMAS_ENABLED if (reader->validate == XML_TEXTREADER_VALIDATE_RNG) return (reader->rngValidErrors == 0); if (reader->validate == XML_TEXTREADER_VALIDATE_XSD) return (reader->xsdValidErrors == 0);#endif if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1)) return (reader->ctxt->valid); return (0);}
/** * xmlTextReaderGetErrorHandler: * @reader: the xmlTextReaderPtr used * @f: the callback function or NULL is no callback has been registered * @arg: a user argument * * Retrieve the error callback function and user argument. */voidxmlTextReaderGetErrorHandler(xmlTextReaderPtr reader, xmlTextReaderErrorFunc * f, void **arg){ if (f != NULL) *f = reader->errorFunc; if (arg != NULL) *arg = reader->errorFuncArg;}/************************************************************************ * * * New set (2.6.0) of simpler and more flexible APIs * * * ************************************************************************/
/** * xmlTextReaderSetup: * @reader: an XML reader * @input: xmlParserInputBufferPtr used to feed the reader, will * be destroyed with it. * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * Setup an XML reader with new options * * Returns 0 in case of success and -1 in case of error. */intxmlTextReaderSetup(xmlTextReaderPtr reader, xmlParserInputBufferPtr input, const char *URL, const char *encoding, int options){ if (reader == NULL) { if (input != NULL) xmlFreeParserInputBuffer(input); return (-1); }
/* * we force the generation of compact text nodes on the reader * since usr applications should never modify the tree */ options |= XML_PARSE_COMPACT;
reader->doc = NULL; reader->entNr = 0; reader->parserFlags = options; reader->validate = XML_TEXTREADER_NOT_VALIDATE; if ((input != NULL) && (reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) { xmlFreeParserInputBuffer(reader->input); reader->input = NULL; reader->allocs -= XML_TEXTREADER_INPUT; } if (input != NULL) { reader->input = input; reader->allocs |= XML_TEXTREADER_INPUT; } if (reader->buffer == NULL) reader->buffer = xmlBufCreateSize(100); if (reader->buffer == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlTextReaderSetup : malloc failed\n"); return (-1); } /* no operation on a reader should require a huge buffer */ xmlBufSetAllocationScheme(reader->buffer, XML_BUFFER_ALLOC_DOUBLEIT); if (reader->sax == NULL) reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); if (reader->sax == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlTextReaderSetup : malloc failed\n"); return (-1); } xmlSAXVersion(reader->sax, 2); reader->startElement = reader->sax->startElement; reader->sax->startElement = xmlTextReaderStartElement; reader->endElement = reader->sax->endElement; reader->sax->endElement = xmlTextReaderEndElement;#ifdef LIBXML_SAX1_ENABLED if (reader->sax->initialized == XML_SAX2_MAGIC) {#endif /* LIBXML_SAX1_ENABLED */ reader->startElementNs = reader->sax->startElementNs; reader->sax->startElementNs = xmlTextReaderStartElementNs; reader->endElementNs = reader->sax->endElementNs; reader->sax->endElementNs = xmlTextReaderEndElementNs;#ifdef LIBXML_SAX1_ENABLED } else { reader->startElementNs = NULL; reader->endElementNs = NULL; }#endif /* LIBXML_SAX1_ENABLED */ reader->characters = reader->sax->characters; reader->sax->characters = xmlTextReaderCharacters; reader->sax->ignorableWhitespace = xmlTextReaderCharacters; reader->cdataBlock = reader->sax->cdataBlock; reader->sax->cdataBlock = xmlTextReaderCDataBlock;
reader->mode = XML_TEXTREADER_MODE_INITIAL; reader->node = NULL; reader->curnode = NULL; if (input != NULL) { if (xmlBufUse(reader->input->buffer) < 4) { xmlParserInputBufferRead(input, 4); } if (reader->ctxt == NULL) { if (xmlBufUse(reader->input->buffer) >= 4) { reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, (const char *) xmlBufContent(reader->input->buffer), 4, URL); reader->base = 0; reader->cur = 4; } else { reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL); reader->base = 0; reader->cur = 0; } } else { xmlParserInputPtr inputStream; xmlParserInputBufferPtr buf; xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
xmlCtxtReset(reader->ctxt); buf = xmlAllocParserInputBuffer(enc); if (buf == NULL) return(-1); inputStream = xmlNewInputStream(reader->ctxt); if (inputStream == NULL) { xmlFreeParserInputBuffer(buf); return(-1); }
if (URL == NULL) inputStream->filename = NULL; else inputStream->filename = (char *) xmlCanonicPath((const xmlChar *) URL); inputStream->buf = buf; xmlBufResetInput(buf->buffer, inputStream);
inputPush(reader->ctxt, inputStream); reader->cur = 0; } if (reader->ctxt == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlTextReaderSetup : malloc failed\n"); return (-1); } } if (reader->dict != NULL) { if (reader->ctxt->dict != NULL) { if (reader->dict != reader->ctxt->dict) { xmlDictFree(reader->dict); reader->dict = reader->ctxt->dict; } } else { reader->ctxt->dict = reader->dict; } } else { if (reader->ctxt->dict == NULL) reader->ctxt->dict = xmlDictCreate(); reader->dict = reader->ctxt->dict; } reader->ctxt->_private = reader; reader->ctxt->linenumbers = 1; reader->ctxt->dictNames = 1; /* * use the parser dictionary to allocate all elements and attributes names */ reader->ctxt->docdict = 1; reader->ctxt->parseMode = XML_PARSE_READER;
#ifdef LIBXML_XINCLUDE_ENABLED if (reader->xincctxt != NULL) { xmlXIncludeFreeContext(reader->xincctxt); reader->xincctxt = NULL; } if (options & XML_PARSE_XINCLUDE) { reader->xinclude = 1; reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1); options -= XML_PARSE_XINCLUDE; } else reader->xinclude = 0; reader->in_xinclude = 0;#endif#ifdef LIBXML_PATTERN_ENABLED if (reader->patternTab == NULL) { reader->patternNr = 0; reader->patternMax = 0; } while (reader->patternNr > 0) { reader->patternNr--; if (reader->patternTab[reader->patternNr] != NULL) { xmlFreePattern(reader->patternTab[reader->patternNr]); reader->patternTab[reader->patternNr] = NULL; } }#endif
if (options & XML_PARSE_DTDVALID) reader->validate = XML_TEXTREADER_VALIDATE_DTD;
xmlCtxtUseOptions(reader->ctxt, options); if (encoding != NULL) { xmlCharEncodingHandlerPtr hdlr;
hdlr = xmlFindCharEncodingHandler(encoding); if (hdlr != NULL) xmlSwitchToEncoding(reader->ctxt, hdlr); } if ((URL != NULL) && (reader->ctxt->input != NULL) && (reader->ctxt->input->filename == NULL)) reader->ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
reader->doc = NULL;
return (0);}
/** * xmlTextReaderSetMaxAmplification: * @reader: an XML reader * @maxAmpl: maximum amplification factor * * Set the maximum amplification factor. See xmlCtxtSetMaxAmplification. */voidxmlTextReaderSetMaxAmplification(xmlTextReaderPtr reader, unsigned maxAmpl){ xmlCtxtSetMaxAmplification(reader->ctxt, maxAmpl);}
/** * xmlTextReaderByteConsumed: * @reader: an XML reader * * This function provides the current index of the parser used * by the reader, relative to the start of the current entity. * This function actually just wraps a call to xmlBytesConsumed() * for the parser context associated with the reader. * See xmlBytesConsumed() for more information. * * Returns the index in bytes from the beginning of the entity or -1 * in case the index could not be computed. */longxmlTextReaderByteConsumed(xmlTextReaderPtr reader) { if ((reader == NULL) || (reader->ctxt == NULL)) return(-1); return(xmlByteConsumed(reader->ctxt));}
/** * xmlReaderWalker: * @doc: a preparsed document * * Create an xmltextReader for a preparsed document. * * Returns the new reader or NULL in case of error. */xmlTextReaderPtrxmlReaderWalker(xmlDocPtr doc){ xmlTextReaderPtr ret;
if (doc == NULL) return(NULL);
ret = xmlMalloc(sizeof(xmlTextReader)); if (ret == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); return(NULL); } memset(ret, 0, sizeof(xmlTextReader)); ret->entNr = 0; ret->input = NULL; ret->mode = XML_TEXTREADER_MODE_INITIAL; ret->node = NULL; ret->curnode = NULL; ret->base = 0; ret->cur = 0; ret->allocs = XML_TEXTREADER_CTXT; ret->doc = doc; ret->state = XML_TEXTREADER_START; ret->dict = xmlDictCreate(); return(ret);}
/** * xmlReaderForDoc: * @cur: a pointer to a zero terminated string * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * Create an xmltextReader for an XML in-memory document. * The parsing flags @options are a combination of xmlParserOption. * * Returns the new reader or NULL in case of error. */xmlTextReaderPtrxmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding, int options){ int len;
if (cur == NULL) return (NULL); len = xmlStrlen(cur);
return (xmlReaderForMemory ((const char *) cur, len, URL, encoding, options));}
/** * xmlReaderForFile: * @filename: a file or URL * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * parse an XML file from the filesystem or the network. * The parsing flags @options are a combination of xmlParserOption. * * Returns the new reader or NULL in case of error. */xmlTextReaderPtrxmlReaderForFile(const char *filename, const char *encoding, int options){ xmlTextReaderPtr reader;
reader = xmlNewTextReaderFilename(filename); if (reader == NULL) return (NULL); xmlTextReaderSetup(reader, NULL, NULL, encoding, options); return (reader);}
/** * xmlReaderForMemory: * @buffer: a pointer to a char array * @size: the size of the array * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * Create an xmltextReader for an XML in-memory document. * The parsing flags @options are a combination of xmlParserOption. * * Returns the new reader or NULL in case of error. */xmlTextReaderPtrxmlReaderForMemory(const char *buffer, int size, const char *URL, const char *encoding, int options){ xmlTextReaderPtr reader; xmlParserInputBufferPtr buf;
buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); if (buf == NULL) { return (NULL); } reader = xmlNewTextReader(buf, URL); if (reader == NULL) { xmlFreeParserInputBuffer(buf); return (NULL); } reader->allocs |= XML_TEXTREADER_INPUT; xmlTextReaderSetup(reader, NULL, URL, encoding, options); return (reader);}
/** * xmlReaderForFd: * @fd: an open file descriptor * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * Create an xmltextReader for an XML from a file descriptor. * The parsing flags @options are a combination of xmlParserOption. * NOTE that the file descriptor will not be closed when the * reader is closed or reset. * * Returns the new reader or NULL in case of error. */xmlTextReaderPtrxmlReaderForFd(int fd, const char *URL, const char *encoding, int options){ xmlTextReaderPtr reader; xmlParserInputBufferPtr input;
if (fd < 0) return (NULL);
input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); if (input == NULL) return (NULL); input->closecallback = NULL; reader = xmlNewTextReader(input, URL); if (reader == NULL) { xmlFreeParserInputBuffer(input); return (NULL); } reader->allocs |= XML_TEXTREADER_INPUT; xmlTextReaderSetup(reader, NULL, URL, encoding, options); return (reader);}
/** * xmlReaderForIO: * @ioread: an I/O read function * @ioclose: an I/O close function * @ioctx: an I/O handler * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * Create an xmltextReader for an XML document from I/O functions and source. * The parsing flags @options are a combination of xmlParserOption. * * Returns the new reader or NULL in case of error. */xmlTextReaderPtrxmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, const char *URL, const char *encoding, int options){ xmlTextReaderPtr reader; xmlParserInputBufferPtr input;
if (ioread == NULL) return (NULL);
input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, XML_CHAR_ENCODING_NONE); if (input == NULL) { if (ioclose != NULL) ioclose(ioctx); return (NULL); } reader = xmlNewTextReader(input, URL); if (reader == NULL) { xmlFreeParserInputBuffer(input); return (NULL); } reader->allocs |= XML_TEXTREADER_INPUT; xmlTextReaderSetup(reader, NULL, URL, encoding, options); return (reader);}
/** * xmlReaderNewWalker: * @reader: an XML reader * @doc: a preparsed document * * Setup an xmltextReader to parse a preparsed XML document. * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error */intxmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc){ if (doc == NULL) return (-1); if (reader == NULL) return (-1);
if (reader->input != NULL) { xmlFreeParserInputBuffer(reader->input); } if (reader->ctxt != NULL) { xmlCtxtReset(reader->ctxt); }
reader->entNr = 0; reader->input = NULL; reader->mode = XML_TEXTREADER_MODE_INITIAL; reader->node = NULL; reader->curnode = NULL; reader->base = 0; reader->cur = 0; reader->allocs = XML_TEXTREADER_CTXT; reader->doc = doc; reader->state = XML_TEXTREADER_START; if (reader->dict == NULL) { if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL)) reader->dict = reader->ctxt->dict; else reader->dict = xmlDictCreate(); } return(0);}
/** * xmlReaderNewDoc: * @reader: an XML reader * @cur: a pointer to a zero terminated string * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * Setup an xmltextReader to parse an XML in-memory document. * The parsing flags @options are a combination of xmlParserOption. * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error */intxmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur, const char *URL, const char *encoding, int options){
int len;
if (cur == NULL) return (-1); if (reader == NULL) return (-1);
len = xmlStrlen(cur); return (xmlReaderNewMemory(reader, (const char *)cur, len, URL, encoding, options));}
/** * xmlReaderNewFile: * @reader: an XML reader * @filename: a file or URL * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * parse an XML file from the filesystem or the network. * The parsing flags @options are a combination of xmlParserOption. * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error */intxmlReaderNewFile(xmlTextReaderPtr reader, const char *filename, const char *encoding, int options){ xmlParserInputBufferPtr input;
if (filename == NULL) return (-1); if (reader == NULL) return (-1);
input = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE); if (input == NULL) return (-1); return (xmlTextReaderSetup(reader, input, filename, encoding, options));}
/** * xmlReaderNewMemory: * @reader: an XML reader * @buffer: a pointer to a char array * @size: the size of the array * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * Setup an xmltextReader to parse an XML in-memory document. * The parsing flags @options are a combination of xmlParserOption. * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error */intxmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size, const char *URL, const char *encoding, int options){ xmlParserInputBufferPtr input;
if (reader == NULL) return (-1); if (buffer == NULL) return (-1);
input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); if (input == NULL) { return (-1); } return (xmlTextReaderSetup(reader, input, URL, encoding, options));}
/** * xmlReaderNewFd: * @reader: an XML reader * @fd: an open file descriptor * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * Setup an xmltextReader to parse an XML from a file descriptor. * NOTE that the file descriptor will not be closed when the * reader is closed or reset. * The parsing flags @options are a combination of xmlParserOption. * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error */intxmlReaderNewFd(xmlTextReaderPtr reader, int fd, const char *URL, const char *encoding, int options){ xmlParserInputBufferPtr input;
if (fd < 0) return (-1); if (reader == NULL) return (-1);
input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); if (input == NULL) return (-1); input->closecallback = NULL; return (xmlTextReaderSetup(reader, input, URL, encoding, options));}
/** * xmlReaderNewIO: * @reader: an XML reader * @ioread: an I/O read function * @ioclose: an I/O close function * @ioctx: an I/O handler * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption * * Setup an xmltextReader to parse an XML document from I/O functions * and source. * The parsing flags @options are a combination of xmlParserOption. * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error */intxmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, const char *URL, const char *encoding, int options){ xmlParserInputBufferPtr input;
if (ioread == NULL) return (-1); if (reader == NULL) return (-1);
input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, XML_CHAR_ENCODING_NONE); if (input == NULL) { if (ioclose != NULL) ioclose(ioctx); return (-1); } return (xmlTextReaderSetup(reader, input, URL, encoding, options));}
/************************************************************************ * * * Utilities * * * ************************************************************************/#ifdef NOT_USED_YET
/** * xmlBase64Decode: * @in: the input buffer * @inlen: the size of the input (in), the size read from it (out) * @to: the output buffer * @tolen: the size of the output (in), the size written to (out) * * Base64 decoder, reads from @in and save in @to * TODO: tell jody when this is actually exported * * Returns 0 if all the input was consumer, 1 if the Base64 end was reached, * 2 if there wasn't enough space on the output or -1 in case of error. */static intxmlBase64Decode(const unsigned char *in, unsigned long *inlen, unsigned char *to, unsigned long *tolen){ unsigned long incur; /* current index in in[] */
unsigned long inblk; /* last block index in in[] */
unsigned long outcur; /* current index in out[] */
unsigned long inmax; /* size of in[] */
unsigned long outmax; /* size of out[] */
unsigned char cur; /* the current value read from in[] */
unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
int nbintmp; /* number of byte in intmp[] */
int is_ignore; /* cur should be ignored */
int is_end = 0; /* the end of the base64 was found */
int retval = 1;
int i;
if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL)) return (-1);
incur = 0; inblk = 0; outcur = 0; inmax = *inlen; outmax = *tolen; nbintmp = 0;
while (1) { if (incur >= inmax) break; cur = in[incur++]; is_ignore = 0; if ((cur >= 'A') && (cur <= 'Z')) cur = cur - 'A'; else if ((cur >= 'a') && (cur <= 'z')) cur = cur - 'a' + 26; else if ((cur >= '0') && (cur <= '9')) cur = cur - '0' + 52; else if (cur == '+') cur = 62; else if (cur == '/') cur = 63; else if (cur == '.') cur = 0; else if (cur == '=') /*no op , end of the base64 stream */ is_end = 1; else { is_ignore = 1; if (nbintmp == 0) inblk = incur; }
if (!is_ignore) { int nbouttmp = 3;
int is_break = 0;
if (is_end) { if (nbintmp == 0) break; if ((nbintmp == 1) || (nbintmp == 2)) nbouttmp = 1; else nbouttmp = 2; nbintmp = 3; is_break = 1; } intmp[nbintmp++] = cur; /* * if intmp is full, push the 4byte sequence as a 3 byte * sequence out */ if (nbintmp == 4) { nbintmp = 0; outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4); outtmp[1] = ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2); outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F); if (outcur + 3 >= outmax) { retval = 2; break; }
for (i = 0; i < nbouttmp; i++) to[outcur++] = outtmp[i]; inblk = incur; }
if (is_break) { retval = 0; break; } } }
*tolen = outcur; *inlen = inblk; return (retval);}
/* * Test routine for the xmlBase64Decode function */#if 0intmain(int argc, char **argv){ char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
char output[100];
char output2[100];
char output3[100];
unsigned long inlen = strlen(input);
unsigned long outlen = 100;
int ret;
unsigned long cons, tmp, tmp2, prod;
/* * Direct */ ret = xmlBase64Decode(input, &inlen, output, &outlen);
output[outlen] = 0; printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output)indent: Standard input:179: Error:Unmatched #endif;
/* * output chunking */ cons = 0; prod = 0; while (cons < inlen) { tmp = 5; tmp2 = inlen - cons;
printf("%ld %ld\n", cons, prod); ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp); cons += tmp2; prod += tmp; printf("%ld %ld\n", cons, prod); } output2[outlen] = 0; printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
/* * input chunking */ cons = 0; prod = 0; while (cons < inlen) { tmp = 100 - prod; tmp2 = inlen - cons; if (tmp2 > 5) tmp2 = 5;
printf("%ld %ld\n", cons, prod); ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp); cons += tmp2; prod += tmp; printf("%ld %ld\n", cons, prod); } output3[outlen] = 0; printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3); return (0);
}#endif#endif /* NOT_USED_YET */
#endif /* LIBXML_READER_ENABLED */