tree.c 256 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148
  1. /*
  2. * tree.c : implementation of access function for an XML tree.
  3. *
  4. * References:
  5. * XHTML 1.0 W3C REC: http://www.w3.org/TR/2002/REC-xhtml1-20020801/
  6. *
  7. * See Copyright for the status of this software.
  8. *
  9. * daniel@veillard.com
  10. *
  11. */
  12. /* To avoid EBCDIC trouble when parsing on zOS */
  13. #if defined(__MVS__)
  14. #pragma convert("ISO8859-1")
  15. #endif
  16. #define IN_LIBXML
  17. #include "libxml.h"
  18. #include <string.h> /* for memset() only ! */
  19. #include <stddef.h>
  20. #include <limits.h>
  21. #ifdef HAVE_CTYPE_H
  22. #include <ctype.h>
  23. #endif
  24. #ifdef HAVE_STDLIB_H
  25. #include <stdlib.h>
  26. #endif
  27. #ifdef LIBXML_ZLIB_ENABLED
  28. #include <zlib.h>
  29. #endif
  30. #include <libxml/xmlmemory.h>
  31. #include <libxml/tree.h>
  32. #include <libxml/parser.h>
  33. #include <libxml/uri.h>
  34. #include <libxml/entities.h>
  35. #include <libxml/valid.h>
  36. #include <libxml/xmlerror.h>
  37. #include <libxml/parserInternals.h>
  38. #include <libxml/globals.h>
  39. #ifdef LIBXML_HTML_ENABLED
  40. #include <libxml/HTMLtree.h>
  41. #endif
  42. #ifdef LIBXML_DEBUG_ENABLED
  43. #include <libxml/debugXML.h>
  44. #endif
  45. #include "buf.h"
  46. #include "save.h"
  47. int __xmlRegisterCallbacks = 0;
  48. /************************************************************************
  49. * *
  50. * Forward declarations *
  51. * *
  52. ************************************************************************/
  53. static xmlNsPtr
  54. xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns);
  55. static xmlChar* xmlGetPropNodeValueInternal(const xmlAttr *prop);
  56. /************************************************************************
  57. * *
  58. * Tree memory error handler *
  59. * *
  60. ************************************************************************/
  61. /**
  62. * xmlTreeErrMemory:
  63. * @extra: extra informations
  64. *
  65. * Handle an out of memory condition
  66. */
  67. static void
  68. xmlTreeErrMemory(const char *extra)
  69. {
  70. __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra);
  71. }
  72. /**
  73. * xmlTreeErr:
  74. * @code: the error number
  75. * @extra: extra informations
  76. *
  77. * Handle an out of memory condition
  78. */
  79. static void
  80. xmlTreeErr(int code, xmlNodePtr node, const char *extra)
  81. {
  82. const char *msg = NULL;
  83. switch(code) {
  84. case XML_TREE_INVALID_HEX:
  85. msg = "invalid hexadecimal character value\n";
  86. break;
  87. case XML_TREE_INVALID_DEC:
  88. msg = "invalid decimal character value\n";
  89. break;
  90. case XML_TREE_UNTERMINATED_ENTITY:
  91. msg = "unterminated entity reference %15s\n";
  92. break;
  93. case XML_TREE_NOT_UTF8:
  94. msg = "string is not in UTF-8\n";
  95. break;
  96. default:
  97. msg = "unexpected error number\n";
  98. }
  99. __xmlSimpleError(XML_FROM_TREE, code, node, msg, extra);
  100. }
  101. /************************************************************************
  102. * *
  103. * A few static variables and macros *
  104. * *
  105. ************************************************************************/
  106. /* #undef xmlStringText */
  107. const xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
  108. /* #undef xmlStringTextNoenc */
  109. const xmlChar xmlStringTextNoenc[] =
  110. { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
  111. /* #undef xmlStringComment */
  112. const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
  113. static int xmlCompressMode = 0;
  114. static int xmlCheckDTD = 1;
  115. #define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \
  116. xmlNodePtr ulccur = (n)->children; \
  117. if (ulccur == NULL) { \
  118. (n)->last = NULL; \
  119. } else { \
  120. while (ulccur->next != NULL) { \
  121. ulccur->parent = (n); \
  122. ulccur = ulccur->next; \
  123. } \
  124. ulccur->parent = (n); \
  125. (n)->last = ulccur; \
  126. }}
  127. #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
  128. (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
  129. /* #define DEBUG_BUFFER */
  130. /* #define DEBUG_TREE */
  131. /************************************************************************
  132. * *
  133. * Functions to move to entities.c once the *
  134. * API freeze is smoothen and they can be made public. *
  135. * *
  136. ************************************************************************/
  137. #include <libxml/hash.h>
  138. #ifdef LIBXML_TREE_ENABLED
  139. /**
  140. * xmlGetEntityFromDtd:
  141. * @dtd: A pointer to the DTD to search
  142. * @name: The entity name
  143. *
  144. * Do an entity lookup in the DTD entity hash table and
  145. * return the corresponding entity, if found.
  146. *
  147. * Returns A pointer to the entity structure or NULL if not found.
  148. */
  149. static xmlEntityPtr
  150. xmlGetEntityFromDtd(const xmlDtd *dtd, const xmlChar *name) {
  151. xmlEntitiesTablePtr table;
  152. if((dtd != NULL) && (dtd->entities != NULL)) {
  153. table = (xmlEntitiesTablePtr) dtd->entities;
  154. return((xmlEntityPtr) xmlHashLookup(table, name));
  155. /* return(xmlGetEntityFromTable(table, name)); */
  156. }
  157. return(NULL);
  158. }
  159. /**
  160. * xmlGetParameterEntityFromDtd:
  161. * @dtd: A pointer to the DTD to search
  162. * @name: The entity name
  163. *
  164. * Do an entity lookup in the DTD parameter entity hash table and
  165. * return the corresponding entity, if found.
  166. *
  167. * Returns A pointer to the entity structure or NULL if not found.
  168. */
  169. static xmlEntityPtr
  170. xmlGetParameterEntityFromDtd(const xmlDtd *dtd, const xmlChar *name) {
  171. xmlEntitiesTablePtr table;
  172. if ((dtd != NULL) && (dtd->pentities != NULL)) {
  173. table = (xmlEntitiesTablePtr) dtd->pentities;
  174. return((xmlEntityPtr) xmlHashLookup(table, name));
  175. /* return(xmlGetEntityFromTable(table, name)); */
  176. }
  177. return(NULL);
  178. }
  179. #endif /* LIBXML_TREE_ENABLED */
  180. /************************************************************************
  181. * *
  182. * QName handling helper *
  183. * *
  184. ************************************************************************/
  185. /**
  186. * xmlBuildQName:
  187. * @ncname: the Name
  188. * @prefix: the prefix
  189. * @memory: preallocated memory
  190. * @len: preallocated memory length
  191. *
  192. * Builds the QName @prefix:@ncname in @memory if there is enough space
  193. * and prefix is not NULL nor empty, otherwise allocate a new string.
  194. * If prefix is NULL or empty it returns ncname.
  195. *
  196. * Returns the new string which must be freed by the caller if different from
  197. * @memory and @ncname or NULL in case of error
  198. */
  199. xmlChar *
  200. xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix,
  201. xmlChar *memory, int len) {
  202. int lenn, lenp;
  203. xmlChar *ret;
  204. if (ncname == NULL) return(NULL);
  205. if (prefix == NULL) return((xmlChar *) ncname);
  206. lenn = strlen((char *) ncname);
  207. lenp = strlen((char *) prefix);
  208. if ((memory == NULL) || (len < lenn + lenp + 2)) {
  209. ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
  210. if (ret == NULL) {
  211. xmlTreeErrMemory("building QName");
  212. return(NULL);
  213. }
  214. } else {
  215. ret = memory;
  216. }
  217. memcpy(&ret[0], prefix, lenp);
  218. ret[lenp] = ':';
  219. memcpy(&ret[lenp + 1], ncname, lenn);
  220. ret[lenn + lenp + 1] = 0;
  221. return(ret);
  222. }
  223. /**
  224. * xmlSplitQName2:
  225. * @name: the full QName
  226. * @prefix: a xmlChar **
  227. *
  228. * parse an XML qualified name string
  229. *
  230. * [NS 5] QName ::= (Prefix ':')? LocalPart
  231. *
  232. * [NS 6] Prefix ::= NCName
  233. *
  234. * [NS 7] LocalPart ::= NCName
  235. *
  236. * Returns NULL if the name doesn't have a prefix. Otherwise, returns the
  237. * local part, and prefix is updated to get the Prefix. Both the return value
  238. * and the prefix must be freed by the caller.
  239. */
  240. xmlChar *
  241. xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
  242. int len = 0;
  243. xmlChar *ret = NULL;
  244. if (prefix == NULL) return(NULL);
  245. *prefix = NULL;
  246. if (name == NULL) return(NULL);
  247. #ifndef XML_XML_NAMESPACE
  248. /* xml: prefix is not really a namespace */
  249. if ((name[0] == 'x') && (name[1] == 'm') &&
  250. (name[2] == 'l') && (name[3] == ':'))
  251. return(NULL);
  252. #endif
  253. /* nasty but valid */
  254. if (name[0] == ':')
  255. return(NULL);
  256. /*
  257. * we are not trying to validate but just to cut, and yes it will
  258. * work even if this is as set of UTF-8 encoded chars
  259. */
  260. while ((name[len] != 0) && (name[len] != ':'))
  261. len++;
  262. if (name[len] == 0)
  263. return(NULL);
  264. *prefix = xmlStrndup(name, len);
  265. if (*prefix == NULL) {
  266. xmlTreeErrMemory("QName split");
  267. return(NULL);
  268. }
  269. ret = xmlStrdup(&name[len + 1]);
  270. if (ret == NULL) {
  271. xmlTreeErrMemory("QName split");
  272. if (*prefix != NULL) {
  273. xmlFree(*prefix);
  274. *prefix = NULL;
  275. }
  276. return(NULL);
  277. }
  278. return(ret);
  279. }
  280. /**
  281. * xmlSplitQName3:
  282. * @name: the full QName
  283. * @len: an int *
  284. *
  285. * parse an XML qualified name string,i
  286. *
  287. * returns NULL if it is not a Qualified Name, otherwise, update len
  288. * with the length in byte of the prefix and return a pointer
  289. * to the start of the name without the prefix
  290. */
  291. const xmlChar *
  292. xmlSplitQName3(const xmlChar *name, int *len) {
  293. int l = 0;
  294. if (name == NULL) return(NULL);
  295. if (len == NULL) return(NULL);
  296. /* nasty but valid */
  297. if (name[0] == ':')
  298. return(NULL);
  299. /*
  300. * we are not trying to validate but just to cut, and yes it will
  301. * work even if this is as set of UTF-8 encoded chars
  302. */
  303. while ((name[l] != 0) && (name[l] != ':'))
  304. l++;
  305. if (name[l] == 0)
  306. return(NULL);
  307. *len = l;
  308. return(&name[l+1]);
  309. }
  310. /************************************************************************
  311. * *
  312. * Check Name, NCName and QName strings *
  313. * *
  314. ************************************************************************/
  315. #define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
  316. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
  317. /**
  318. * xmlValidateNCName:
  319. * @value: the value to check
  320. * @space: allow spaces in front and end of the string
  321. *
  322. * Check that a value conforms to the lexical space of NCName
  323. *
  324. * Returns 0 if this validates, a positive error code number otherwise
  325. * and -1 in case of internal or API error.
  326. */
  327. int
  328. xmlValidateNCName(const xmlChar *value, int space) {
  329. const xmlChar *cur = value;
  330. int c,l;
  331. if (value == NULL)
  332. return(-1);
  333. /*
  334. * First quick algorithm for ASCII range
  335. */
  336. if (space)
  337. while (IS_BLANK_CH(*cur)) cur++;
  338. if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
  339. (*cur == '_'))
  340. cur++;
  341. else
  342. goto try_complex;
  343. while (((*cur >= 'a') && (*cur <= 'z')) ||
  344. ((*cur >= 'A') && (*cur <= 'Z')) ||
  345. ((*cur >= '0') && (*cur <= '9')) ||
  346. (*cur == '_') || (*cur == '-') || (*cur == '.'))
  347. cur++;
  348. if (space)
  349. while (IS_BLANK_CH(*cur)) cur++;
  350. if (*cur == 0)
  351. return(0);
  352. try_complex:
  353. /*
  354. * Second check for chars outside the ASCII range
  355. */
  356. cur = value;
  357. c = CUR_SCHAR(cur, l);
  358. if (space) {
  359. while (IS_BLANK(c)) {
  360. cur += l;
  361. c = CUR_SCHAR(cur, l);
  362. }
  363. }
  364. if ((!IS_LETTER(c)) && (c != '_'))
  365. return(1);
  366. cur += l;
  367. c = CUR_SCHAR(cur, l);
  368. while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
  369. (c == '-') || (c == '_') || IS_COMBINING(c) ||
  370. IS_EXTENDER(c)) {
  371. cur += l;
  372. c = CUR_SCHAR(cur, l);
  373. }
  374. if (space) {
  375. while (IS_BLANK(c)) {
  376. cur += l;
  377. c = CUR_SCHAR(cur, l);
  378. }
  379. }
  380. if (c != 0)
  381. return(1);
  382. return(0);
  383. }
  384. #endif
  385. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
  386. /**
  387. * xmlValidateQName:
  388. * @value: the value to check
  389. * @space: allow spaces in front and end of the string
  390. *
  391. * Check that a value conforms to the lexical space of QName
  392. *
  393. * Returns 0 if this validates, a positive error code number otherwise
  394. * and -1 in case of internal or API error.
  395. */
  396. int
  397. xmlValidateQName(const xmlChar *value, int space) {
  398. const xmlChar *cur = value;
  399. int c,l;
  400. if (value == NULL)
  401. return(-1);
  402. /*
  403. * First quick algorithm for ASCII range
  404. */
  405. if (space)
  406. while (IS_BLANK_CH(*cur)) cur++;
  407. if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
  408. (*cur == '_'))
  409. cur++;
  410. else
  411. goto try_complex;
  412. while (((*cur >= 'a') && (*cur <= 'z')) ||
  413. ((*cur >= 'A') && (*cur <= 'Z')) ||
  414. ((*cur >= '0') && (*cur <= '9')) ||
  415. (*cur == '_') || (*cur == '-') || (*cur == '.'))
  416. cur++;
  417. if (*cur == ':') {
  418. cur++;
  419. if (((*cur >= 'a') && (*cur <= 'z')) ||
  420. ((*cur >= 'A') && (*cur <= 'Z')) ||
  421. (*cur == '_'))
  422. cur++;
  423. else
  424. goto try_complex;
  425. while (((*cur >= 'a') && (*cur <= 'z')) ||
  426. ((*cur >= 'A') && (*cur <= 'Z')) ||
  427. ((*cur >= '0') && (*cur <= '9')) ||
  428. (*cur == '_') || (*cur == '-') || (*cur == '.'))
  429. cur++;
  430. }
  431. if (space)
  432. while (IS_BLANK_CH(*cur)) cur++;
  433. if (*cur == 0)
  434. return(0);
  435. try_complex:
  436. /*
  437. * Second check for chars outside the ASCII range
  438. */
  439. cur = value;
  440. c = CUR_SCHAR(cur, l);
  441. if (space) {
  442. while (IS_BLANK(c)) {
  443. cur += l;
  444. c = CUR_SCHAR(cur, l);
  445. }
  446. }
  447. if ((!IS_LETTER(c)) && (c != '_'))
  448. return(1);
  449. cur += l;
  450. c = CUR_SCHAR(cur, l);
  451. while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
  452. (c == '-') || (c == '_') || IS_COMBINING(c) ||
  453. IS_EXTENDER(c)) {
  454. cur += l;
  455. c = CUR_SCHAR(cur, l);
  456. }
  457. if (c == ':') {
  458. cur += l;
  459. c = CUR_SCHAR(cur, l);
  460. if ((!IS_LETTER(c)) && (c != '_'))
  461. return(1);
  462. cur += l;
  463. c = CUR_SCHAR(cur, l);
  464. while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
  465. (c == '-') || (c == '_') || IS_COMBINING(c) ||
  466. IS_EXTENDER(c)) {
  467. cur += l;
  468. c = CUR_SCHAR(cur, l);
  469. }
  470. }
  471. if (space) {
  472. while (IS_BLANK(c)) {
  473. cur += l;
  474. c = CUR_SCHAR(cur, l);
  475. }
  476. }
  477. if (c != 0)
  478. return(1);
  479. return(0);
  480. }
  481. /**
  482. * xmlValidateName:
  483. * @value: the value to check
  484. * @space: allow spaces in front and end of the string
  485. *
  486. * Check that a value conforms to the lexical space of Name
  487. *
  488. * Returns 0 if this validates, a positive error code number otherwise
  489. * and -1 in case of internal or API error.
  490. */
  491. int
  492. xmlValidateName(const xmlChar *value, int space) {
  493. const xmlChar *cur = value;
  494. int c,l;
  495. if (value == NULL)
  496. return(-1);
  497. /*
  498. * First quick algorithm for ASCII range
  499. */
  500. if (space)
  501. while (IS_BLANK_CH(*cur)) cur++;
  502. if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
  503. (*cur == '_') || (*cur == ':'))
  504. cur++;
  505. else
  506. goto try_complex;
  507. while (((*cur >= 'a') && (*cur <= 'z')) ||
  508. ((*cur >= 'A') && (*cur <= 'Z')) ||
  509. ((*cur >= '0') && (*cur <= '9')) ||
  510. (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
  511. cur++;
  512. if (space)
  513. while (IS_BLANK_CH(*cur)) cur++;
  514. if (*cur == 0)
  515. return(0);
  516. try_complex:
  517. /*
  518. * Second check for chars outside the ASCII range
  519. */
  520. cur = value;
  521. c = CUR_SCHAR(cur, l);
  522. if (space) {
  523. while (IS_BLANK(c)) {
  524. cur += l;
  525. c = CUR_SCHAR(cur, l);
  526. }
  527. }
  528. if ((!IS_LETTER(c)) && (c != '_') && (c != ':'))
  529. return(1);
  530. cur += l;
  531. c = CUR_SCHAR(cur, l);
  532. while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
  533. (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) {
  534. cur += l;
  535. c = CUR_SCHAR(cur, l);
  536. }
  537. if (space) {
  538. while (IS_BLANK(c)) {
  539. cur += l;
  540. c = CUR_SCHAR(cur, l);
  541. }
  542. }
  543. if (c != 0)
  544. return(1);
  545. return(0);
  546. }
  547. /**
  548. * xmlValidateNMToken:
  549. * @value: the value to check
  550. * @space: allow spaces in front and end of the string
  551. *
  552. * Check that a value conforms to the lexical space of NMToken
  553. *
  554. * Returns 0 if this validates, a positive error code number otherwise
  555. * and -1 in case of internal or API error.
  556. */
  557. int
  558. xmlValidateNMToken(const xmlChar *value, int space) {
  559. const xmlChar *cur = value;
  560. int c,l;
  561. if (value == NULL)
  562. return(-1);
  563. /*
  564. * First quick algorithm for ASCII range
  565. */
  566. if (space)
  567. while (IS_BLANK_CH(*cur)) cur++;
  568. if (((*cur >= 'a') && (*cur <= 'z')) ||
  569. ((*cur >= 'A') && (*cur <= 'Z')) ||
  570. ((*cur >= '0') && (*cur <= '9')) ||
  571. (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
  572. cur++;
  573. else
  574. goto try_complex;
  575. while (((*cur >= 'a') && (*cur <= 'z')) ||
  576. ((*cur >= 'A') && (*cur <= 'Z')) ||
  577. ((*cur >= '0') && (*cur <= '9')) ||
  578. (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
  579. cur++;
  580. if (space)
  581. while (IS_BLANK_CH(*cur)) cur++;
  582. if (*cur == 0)
  583. return(0);
  584. try_complex:
  585. /*
  586. * Second check for chars outside the ASCII range
  587. */
  588. cur = value;
  589. c = CUR_SCHAR(cur, l);
  590. if (space) {
  591. while (IS_BLANK(c)) {
  592. cur += l;
  593. c = CUR_SCHAR(cur, l);
  594. }
  595. }
  596. if (!(IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
  597. (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)))
  598. return(1);
  599. cur += l;
  600. c = CUR_SCHAR(cur, l);
  601. while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
  602. (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) {
  603. cur += l;
  604. c = CUR_SCHAR(cur, l);
  605. }
  606. if (space) {
  607. while (IS_BLANK(c)) {
  608. cur += l;
  609. c = CUR_SCHAR(cur, l);
  610. }
  611. }
  612. if (c != 0)
  613. return(1);
  614. return(0);
  615. }
  616. #endif /* LIBXML_TREE_ENABLED */
  617. /************************************************************************
  618. * *
  619. * Allocation and deallocation of basic structures *
  620. * *
  621. ************************************************************************/
  622. /**
  623. * xmlSetBufferAllocationScheme:
  624. * @scheme: allocation method to use
  625. *
  626. * Set the buffer allocation method. Types are
  627. * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
  628. * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
  629. * improves performance
  630. */
  631. void
  632. xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
  633. if ((scheme == XML_BUFFER_ALLOC_EXACT) ||
  634. (scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
  635. (scheme == XML_BUFFER_ALLOC_HYBRID))
  636. xmlBufferAllocScheme = scheme;
  637. }
  638. /**
  639. * xmlGetBufferAllocationScheme:
  640. *
  641. * Types are
  642. * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
  643. * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
  644. * improves performance
  645. * XML_BUFFER_ALLOC_HYBRID - use exact sizes on small strings to keep memory usage tight
  646. * in normal usage, and doubleit on large strings to avoid
  647. * pathological performance.
  648. *
  649. * Returns the current allocation scheme
  650. */
  651. xmlBufferAllocationScheme
  652. xmlGetBufferAllocationScheme(void) {
  653. return(xmlBufferAllocScheme);
  654. }
  655. /**
  656. * xmlNewNs:
  657. * @node: the element carrying the namespace
  658. * @href: the URI associated
  659. * @prefix: the prefix for the namespace
  660. *
  661. * Creation of a new Namespace. This function will refuse to create
  662. * a namespace with a similar prefix than an existing one present on this
  663. * node.
  664. * Note that for a default namespace, @prefix should be NULL.
  665. *
  666. * We use href==NULL in the case of an element creation where the namespace
  667. * was not defined.
  668. *
  669. * Returns a new namespace pointer or NULL
  670. */
  671. xmlNsPtr
  672. xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
  673. xmlNsPtr cur;
  674. if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
  675. return(NULL);
  676. if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
  677. /* xml namespace is predefined, no need to add it */
  678. if (xmlStrEqual(href, XML_XML_NAMESPACE))
  679. return(NULL);
  680. /*
  681. * Problem, this is an attempt to bind xml prefix to a wrong
  682. * namespace, which breaks
  683. * Namespace constraint: Reserved Prefixes and Namespace Names
  684. * from XML namespace. But documents authors may not care in
  685. * their context so let's proceed.
  686. */
  687. }
  688. /*
  689. * Allocate a new Namespace and fill the fields.
  690. */
  691. cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
  692. if (cur == NULL) {
  693. xmlTreeErrMemory("building namespace");
  694. return(NULL);
  695. }
  696. memset(cur, 0, sizeof(xmlNs));
  697. cur->type = XML_LOCAL_NAMESPACE;
  698. if (href != NULL)
  699. cur->href = xmlStrdup(href);
  700. if (prefix != NULL)
  701. cur->prefix = xmlStrdup(prefix);
  702. /*
  703. * Add it at the end to preserve parsing order ...
  704. * and checks for existing use of the prefix
  705. */
  706. if (node != NULL) {
  707. if (node->nsDef == NULL) {
  708. node->nsDef = cur;
  709. } else {
  710. xmlNsPtr prev = node->nsDef;
  711. if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
  712. (xmlStrEqual(prev->prefix, cur->prefix))) {
  713. xmlFreeNs(cur);
  714. return(NULL);
  715. }
  716. while (prev->next != NULL) {
  717. prev = prev->next;
  718. if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
  719. (xmlStrEqual(prev->prefix, cur->prefix))) {
  720. xmlFreeNs(cur);
  721. return(NULL);
  722. }
  723. }
  724. prev->next = cur;
  725. }
  726. }
  727. return(cur);
  728. }
  729. /**
  730. * xmlSetNs:
  731. * @node: a node in the document
  732. * @ns: a namespace pointer
  733. *
  734. * Associate a namespace to a node, a posteriori.
  735. */
  736. void
  737. xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
  738. if (node == NULL) {
  739. #ifdef DEBUG_TREE
  740. xmlGenericError(xmlGenericErrorContext,
  741. "xmlSetNs: node == NULL\n");
  742. #endif
  743. return;
  744. }
  745. if ((node->type == XML_ELEMENT_NODE) ||
  746. (node->type == XML_ATTRIBUTE_NODE))
  747. node->ns = ns;
  748. }
  749. /**
  750. * xmlFreeNs:
  751. * @cur: the namespace pointer
  752. *
  753. * Free up the structures associated to a namespace
  754. */
  755. void
  756. xmlFreeNs(xmlNsPtr cur) {
  757. if (cur == NULL) {
  758. #ifdef DEBUG_TREE
  759. xmlGenericError(xmlGenericErrorContext,
  760. "xmlFreeNs : ns == NULL\n");
  761. #endif
  762. return;
  763. }
  764. if (cur->href != NULL) xmlFree((char *) cur->href);
  765. if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
  766. xmlFree(cur);
  767. }
  768. /**
  769. * xmlFreeNsList:
  770. * @cur: the first namespace pointer
  771. *
  772. * Free up all the structures associated to the chained namespaces.
  773. */
  774. void
  775. xmlFreeNsList(xmlNsPtr cur) {
  776. xmlNsPtr next;
  777. if (cur == NULL) {
  778. #ifdef DEBUG_TREE
  779. xmlGenericError(xmlGenericErrorContext,
  780. "xmlFreeNsList : ns == NULL\n");
  781. #endif
  782. return;
  783. }
  784. while (cur != NULL) {
  785. next = cur->next;
  786. xmlFreeNs(cur);
  787. cur = next;
  788. }
  789. }
  790. /**
  791. * xmlNewDtd:
  792. * @doc: the document pointer
  793. * @name: the DTD name
  794. * @ExternalID: the external ID
  795. * @SystemID: the system ID
  796. *
  797. * Creation of a new DTD for the external subset. To create an
  798. * internal subset, use xmlCreateIntSubset().
  799. *
  800. * Returns a pointer to the new DTD structure
  801. */
  802. xmlDtdPtr
  803. xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
  804. const xmlChar *ExternalID, const xmlChar *SystemID) {
  805. xmlDtdPtr cur;
  806. if ((doc != NULL) && (doc->extSubset != NULL)) {
  807. #ifdef DEBUG_TREE
  808. xmlGenericError(xmlGenericErrorContext,
  809. "xmlNewDtd(%s): document %s already have a DTD %s\n",
  810. /* !!! */ (char *) name, doc->name,
  811. /* !!! */ (char *)doc->extSubset->name);
  812. #endif
  813. return(NULL);
  814. }
  815. /*
  816. * Allocate a new DTD and fill the fields.
  817. */
  818. cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
  819. if (cur == NULL) {
  820. xmlTreeErrMemory("building DTD");
  821. return(NULL);
  822. }
  823. memset(cur, 0 , sizeof(xmlDtd));
  824. cur->type = XML_DTD_NODE;
  825. if (name != NULL)
  826. cur->name = xmlStrdup(name);
  827. if (ExternalID != NULL)
  828. cur->ExternalID = xmlStrdup(ExternalID);
  829. if (SystemID != NULL)
  830. cur->SystemID = xmlStrdup(SystemID);
  831. if (doc != NULL)
  832. doc->extSubset = cur;
  833. cur->doc = doc;
  834. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  835. xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
  836. return(cur);
  837. }
  838. /**
  839. * xmlGetIntSubset:
  840. * @doc: the document pointer
  841. *
  842. * Get the internal subset of a document
  843. * Returns a pointer to the DTD structure or NULL if not found
  844. */
  845. xmlDtdPtr
  846. xmlGetIntSubset(const xmlDoc *doc) {
  847. xmlNodePtr cur;
  848. if (doc == NULL)
  849. return(NULL);
  850. cur = doc->children;
  851. while (cur != NULL) {
  852. if (cur->type == XML_DTD_NODE)
  853. return((xmlDtdPtr) cur);
  854. cur = cur->next;
  855. }
  856. return((xmlDtdPtr) doc->intSubset);
  857. }
  858. /**
  859. * xmlCreateIntSubset:
  860. * @doc: the document pointer
  861. * @name: the DTD name
  862. * @ExternalID: the external (PUBLIC) ID
  863. * @SystemID: the system ID
  864. *
  865. * Create the internal subset of a document
  866. * Returns a pointer to the new DTD structure
  867. */
  868. xmlDtdPtr
  869. xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
  870. const xmlChar *ExternalID, const xmlChar *SystemID) {
  871. xmlDtdPtr cur;
  872. if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
  873. #ifdef DEBUG_TREE
  874. xmlGenericError(xmlGenericErrorContext,
  875. "xmlCreateIntSubset(): document %s already have an internal subset\n",
  876. doc->name);
  877. #endif
  878. return(NULL);
  879. }
  880. /*
  881. * Allocate a new DTD and fill the fields.
  882. */
  883. cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
  884. if (cur == NULL) {
  885. xmlTreeErrMemory("building internal subset");
  886. return(NULL);
  887. }
  888. memset(cur, 0, sizeof(xmlDtd));
  889. cur->type = XML_DTD_NODE;
  890. if (name != NULL) {
  891. cur->name = xmlStrdup(name);
  892. if (cur->name == NULL) {
  893. xmlTreeErrMemory("building internal subset");
  894. xmlFree(cur);
  895. return(NULL);
  896. }
  897. }
  898. if (ExternalID != NULL) {
  899. cur->ExternalID = xmlStrdup(ExternalID);
  900. if (cur->ExternalID == NULL) {
  901. xmlTreeErrMemory("building internal subset");
  902. if (cur->name != NULL)
  903. xmlFree((char *)cur->name);
  904. xmlFree(cur);
  905. return(NULL);
  906. }
  907. }
  908. if (SystemID != NULL) {
  909. cur->SystemID = xmlStrdup(SystemID);
  910. if (cur->SystemID == NULL) {
  911. xmlTreeErrMemory("building internal subset");
  912. if (cur->name != NULL)
  913. xmlFree((char *)cur->name);
  914. if (cur->ExternalID != NULL)
  915. xmlFree((char *)cur->ExternalID);
  916. xmlFree(cur);
  917. return(NULL);
  918. }
  919. }
  920. if (doc != NULL) {
  921. doc->intSubset = cur;
  922. cur->parent = doc;
  923. cur->doc = doc;
  924. if (doc->children == NULL) {
  925. doc->children = (xmlNodePtr) cur;
  926. doc->last = (xmlNodePtr) cur;
  927. } else {
  928. if (doc->type == XML_HTML_DOCUMENT_NODE) {
  929. xmlNodePtr prev;
  930. prev = doc->children;
  931. prev->prev = (xmlNodePtr) cur;
  932. cur->next = prev;
  933. doc->children = (xmlNodePtr) cur;
  934. } else {
  935. xmlNodePtr next;
  936. next = doc->children;
  937. while ((next != NULL) && (next->type != XML_ELEMENT_NODE))
  938. next = next->next;
  939. if (next == NULL) {
  940. cur->prev = doc->last;
  941. cur->prev->next = (xmlNodePtr) cur;
  942. cur->next = NULL;
  943. doc->last = (xmlNodePtr) cur;
  944. } else {
  945. cur->next = next;
  946. cur->prev = next->prev;
  947. if (cur->prev == NULL)
  948. doc->children = (xmlNodePtr) cur;
  949. else
  950. cur->prev->next = (xmlNodePtr) cur;
  951. next->prev = (xmlNodePtr) cur;
  952. }
  953. }
  954. }
  955. }
  956. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  957. xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
  958. return(cur);
  959. }
  960. /**
  961. * DICT_FREE:
  962. * @str: a string
  963. *
  964. * Free a string if it is not owned by the "dict" dictionary in the
  965. * current scope
  966. */
  967. #define DICT_FREE(str) \
  968. if ((str) && ((!dict) || \
  969. (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
  970. xmlFree((char *)(str));
  971. /**
  972. * DICT_COPY:
  973. * @str: a string
  974. *
  975. * Copy a string using a "dict" dictionary in the current scope,
  976. * if availabe.
  977. */
  978. #define DICT_COPY(str, cpy) \
  979. if (str) { \
  980. if (dict) { \
  981. if (xmlDictOwns(dict, (const xmlChar *)(str))) \
  982. cpy = (xmlChar *) (str); \
  983. else \
  984. cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
  985. } else \
  986. cpy = xmlStrdup((const xmlChar *)(str)); }
  987. /**
  988. * DICT_CONST_COPY:
  989. * @str: a string
  990. *
  991. * Copy a string using a "dict" dictionary in the current scope,
  992. * if availabe.
  993. */
  994. #define DICT_CONST_COPY(str, cpy) \
  995. if (str) { \
  996. if (dict) { \
  997. if (xmlDictOwns(dict, (const xmlChar *)(str))) \
  998. cpy = (const xmlChar *) (str); \
  999. else \
  1000. cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
  1001. } else \
  1002. cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
  1003. /**
  1004. * xmlFreeDtd:
  1005. * @cur: the DTD structure to free up
  1006. *
  1007. * Free a DTD structure.
  1008. */
  1009. void
  1010. xmlFreeDtd(xmlDtdPtr cur) {
  1011. xmlDictPtr dict = NULL;
  1012. if (cur == NULL) {
  1013. return;
  1014. }
  1015. if (cur->doc != NULL) dict = cur->doc->dict;
  1016. if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
  1017. xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
  1018. if (cur->children != NULL) {
  1019. xmlNodePtr next, c = cur->children;
  1020. /*
  1021. * Cleanup all nodes which are not part of the specific lists
  1022. * of notations, elements, attributes and entities.
  1023. */
  1024. while (c != NULL) {
  1025. next = c->next;
  1026. if ((c->type != XML_NOTATION_NODE) &&
  1027. (c->type != XML_ELEMENT_DECL) &&
  1028. (c->type != XML_ATTRIBUTE_DECL) &&
  1029. (c->type != XML_ENTITY_DECL)) {
  1030. xmlUnlinkNode(c);
  1031. xmlFreeNode(c);
  1032. }
  1033. c = next;
  1034. }
  1035. }
  1036. DICT_FREE(cur->name)
  1037. DICT_FREE(cur->SystemID)
  1038. DICT_FREE(cur->ExternalID)
  1039. /* TODO !!! */
  1040. if (cur->notations != NULL)
  1041. xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
  1042. if (cur->elements != NULL)
  1043. xmlFreeElementTable((xmlElementTablePtr) cur->elements);
  1044. if (cur->attributes != NULL)
  1045. xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
  1046. if (cur->entities != NULL)
  1047. xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
  1048. if (cur->pentities != NULL)
  1049. xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities);
  1050. xmlFree(cur);
  1051. }
  1052. /**
  1053. * xmlNewDoc:
  1054. * @version: xmlChar string giving the version of XML "1.0"
  1055. *
  1056. * Creates a new XML document
  1057. *
  1058. * Returns a new document
  1059. */
  1060. xmlDocPtr
  1061. xmlNewDoc(const xmlChar *version) {
  1062. xmlDocPtr cur;
  1063. if (version == NULL)
  1064. version = (const xmlChar *) "1.0";
  1065. /*
  1066. * Allocate a new document and fill the fields.
  1067. */
  1068. cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
  1069. if (cur == NULL) {
  1070. xmlTreeErrMemory("building doc");
  1071. return(NULL);
  1072. }
  1073. memset(cur, 0, sizeof(xmlDoc));
  1074. cur->type = XML_DOCUMENT_NODE;
  1075. cur->version = xmlStrdup(version);
  1076. if (cur->version == NULL) {
  1077. xmlTreeErrMemory("building doc");
  1078. xmlFree(cur);
  1079. return(NULL);
  1080. }
  1081. cur->standalone = -1;
  1082. cur->compression = -1; /* not initialized */
  1083. cur->doc = cur;
  1084. cur->parseFlags = 0;
  1085. cur->properties = XML_DOC_USERBUILT;
  1086. /*
  1087. * The in memory encoding is always UTF8
  1088. * This field will never change and would
  1089. * be obsolete if not for binary compatibility.
  1090. */
  1091. cur->charset = XML_CHAR_ENCODING_UTF8;
  1092. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  1093. xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
  1094. return(cur);
  1095. }
  1096. /**
  1097. * xmlFreeDoc:
  1098. * @cur: pointer to the document
  1099. *
  1100. * Free up all the structures used by a document, tree included.
  1101. */
  1102. void
  1103. xmlFreeDoc(xmlDocPtr cur) {
  1104. xmlDtdPtr extSubset, intSubset;
  1105. xmlDictPtr dict = NULL;
  1106. if (cur == NULL) {
  1107. #ifdef DEBUG_TREE
  1108. xmlGenericError(xmlGenericErrorContext,
  1109. "xmlFreeDoc : document == NULL\n");
  1110. #endif
  1111. return;
  1112. }
  1113. #ifdef LIBXML_DEBUG_RUNTIME
  1114. #ifdef LIBXML_DEBUG_ENABLED
  1115. xmlDebugCheckDocument(stderr, cur);
  1116. #endif
  1117. #endif
  1118. if (cur != NULL) dict = cur->dict;
  1119. if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
  1120. xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
  1121. /*
  1122. * Do this before freeing the children list to avoid ID lookups
  1123. */
  1124. if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
  1125. cur->ids = NULL;
  1126. if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
  1127. cur->refs = NULL;
  1128. extSubset = cur->extSubset;
  1129. intSubset = cur->intSubset;
  1130. if (intSubset == extSubset)
  1131. extSubset = NULL;
  1132. if (extSubset != NULL) {
  1133. xmlUnlinkNode((xmlNodePtr) cur->extSubset);
  1134. cur->extSubset = NULL;
  1135. xmlFreeDtd(extSubset);
  1136. }
  1137. if (intSubset != NULL) {
  1138. xmlUnlinkNode((xmlNodePtr) cur->intSubset);
  1139. cur->intSubset = NULL;
  1140. xmlFreeDtd(intSubset);
  1141. }
  1142. if (cur->children != NULL) xmlFreeNodeList(cur->children);
  1143. if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
  1144. DICT_FREE(cur->version)
  1145. DICT_FREE(cur->name)
  1146. DICT_FREE(cur->encoding)
  1147. DICT_FREE(cur->URL)
  1148. xmlFree(cur);
  1149. if (dict) xmlDictFree(dict);
  1150. }
  1151. /**
  1152. * xmlStringLenGetNodeList:
  1153. * @doc: the document
  1154. * @value: the value of the text
  1155. * @len: the length of the string value
  1156. *
  1157. * Parse the value string and build the node list associated. Should
  1158. * produce a flat tree with only TEXTs and ENTITY_REFs.
  1159. * Returns a pointer to the first child
  1160. */
  1161. xmlNodePtr
  1162. xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
  1163. xmlNodePtr ret = NULL, last = NULL;
  1164. xmlNodePtr node;
  1165. xmlChar *val;
  1166. const xmlChar *cur = value, *end = cur + len;
  1167. const xmlChar *q;
  1168. xmlEntityPtr ent;
  1169. xmlBufPtr buf;
  1170. if (value == NULL) return(NULL);
  1171. buf = xmlBufCreateSize(0);
  1172. if (buf == NULL) return(NULL);
  1173. xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_HYBRID);
  1174. q = cur;
  1175. while ((cur < end) && (*cur != 0)) {
  1176. if (cur[0] == '&') {
  1177. int charval = 0;
  1178. xmlChar tmp;
  1179. /*
  1180. * Save the current text.
  1181. */
  1182. if (cur != q) {
  1183. if (xmlBufAdd(buf, q, cur - q))
  1184. goto out;
  1185. }
  1186. q = cur;
  1187. if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) {
  1188. cur += 3;
  1189. if (cur < end)
  1190. tmp = *cur;
  1191. else
  1192. tmp = 0;
  1193. while (tmp != ';') { /* Non input consuming loop */
  1194. if ((tmp >= '0') && (tmp <= '9'))
  1195. charval = charval * 16 + (tmp - '0');
  1196. else if ((tmp >= 'a') && (tmp <= 'f'))
  1197. charval = charval * 16 + (tmp - 'a') + 10;
  1198. else if ((tmp >= 'A') && (tmp <= 'F'))
  1199. charval = charval * 16 + (tmp - 'A') + 10;
  1200. else {
  1201. xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
  1202. NULL);
  1203. charval = 0;
  1204. break;
  1205. }
  1206. cur++;
  1207. if (cur < end)
  1208. tmp = *cur;
  1209. else
  1210. tmp = 0;
  1211. }
  1212. if (tmp == ';')
  1213. cur++;
  1214. q = cur;
  1215. } else if ((cur + 1 < end) && (cur[1] == '#')) {
  1216. cur += 2;
  1217. if (cur < end)
  1218. tmp = *cur;
  1219. else
  1220. tmp = 0;
  1221. while (tmp != ';') { /* Non input consuming loops */
  1222. if ((tmp >= '0') && (tmp <= '9'))
  1223. charval = charval * 10 + (tmp - '0');
  1224. else {
  1225. xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
  1226. NULL);
  1227. charval = 0;
  1228. break;
  1229. }
  1230. cur++;
  1231. if (cur < end)
  1232. tmp = *cur;
  1233. else
  1234. tmp = 0;
  1235. }
  1236. if (tmp == ';')
  1237. cur++;
  1238. q = cur;
  1239. } else {
  1240. /*
  1241. * Read the entity string
  1242. */
  1243. cur++;
  1244. q = cur;
  1245. while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++;
  1246. if ((cur >= end) || (*cur == 0)) {
  1247. xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc,
  1248. (const char *) q);
  1249. goto out;
  1250. }
  1251. if (cur != q) {
  1252. /*
  1253. * Predefined entities don't generate nodes
  1254. */
  1255. val = xmlStrndup(q, cur - q);
  1256. ent = xmlGetDocEntity(doc, val);
  1257. if ((ent != NULL) &&
  1258. (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
  1259. if (xmlBufCat(buf, ent->content))
  1260. goto out;
  1261. } else {
  1262. /*
  1263. * Flush buffer so far
  1264. */
  1265. if (!xmlBufIsEmpty(buf)) {
  1266. node = xmlNewDocText(doc, NULL);
  1267. if (node == NULL) {
  1268. if (val != NULL) xmlFree(val);
  1269. goto out;
  1270. }
  1271. node->content = xmlBufDetach(buf);
  1272. if (last == NULL) {
  1273. last = ret = node;
  1274. } else {
  1275. last = xmlAddNextSibling(last, node);
  1276. }
  1277. }
  1278. /*
  1279. * Create a new REFERENCE_REF node
  1280. */
  1281. node = xmlNewReference(doc, val);
  1282. if (node == NULL) {
  1283. if (val != NULL) xmlFree(val);
  1284. goto out;
  1285. }
  1286. else if ((ent != NULL) && (ent->children == NULL)) {
  1287. xmlNodePtr temp;
  1288. /* Set to non-NULL value to avoid recursion. */
  1289. ent->children = (xmlNodePtr) -1;
  1290. ent->children = xmlStringGetNodeList(doc,
  1291. (const xmlChar*)node->content);
  1292. ent->owner = 1;
  1293. temp = ent->children;
  1294. while (temp) {
  1295. temp->parent = (xmlNodePtr)ent;
  1296. ent->last = temp;
  1297. temp = temp->next;
  1298. }
  1299. }
  1300. if (last == NULL) {
  1301. last = ret = node;
  1302. } else {
  1303. last = xmlAddNextSibling(last, node);
  1304. }
  1305. }
  1306. xmlFree(val);
  1307. }
  1308. cur++;
  1309. q = cur;
  1310. }
  1311. if (charval != 0) {
  1312. xmlChar buffer[10];
  1313. int l;
  1314. l = xmlCopyCharMultiByte(buffer, charval);
  1315. buffer[l] = 0;
  1316. if (xmlBufCat(buf, buffer))
  1317. goto out;
  1318. charval = 0;
  1319. }
  1320. } else
  1321. cur++;
  1322. }
  1323. if (cur != q) {
  1324. /*
  1325. * Handle the last piece of text.
  1326. */
  1327. if (xmlBufAdd(buf, q, cur - q))
  1328. goto out;
  1329. }
  1330. if (!xmlBufIsEmpty(buf)) {
  1331. node = xmlNewDocText(doc, NULL);
  1332. if (node == NULL) goto out;
  1333. node->content = xmlBufDetach(buf);
  1334. if (last == NULL) {
  1335. ret = node;
  1336. } else {
  1337. xmlAddNextSibling(last, node);
  1338. }
  1339. } else if (ret == NULL) {
  1340. ret = xmlNewDocText(doc, BAD_CAST "");
  1341. }
  1342. out:
  1343. xmlBufFree(buf);
  1344. return(ret);
  1345. }
  1346. /**
  1347. * xmlStringGetNodeList:
  1348. * @doc: the document
  1349. * @value: the value of the attribute
  1350. *
  1351. * Parse the value string and build the node list associated. Should
  1352. * produce a flat tree with only TEXTs and ENTITY_REFs.
  1353. * Returns a pointer to the first child
  1354. */
  1355. xmlNodePtr
  1356. xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
  1357. xmlNodePtr ret = NULL, last = NULL;
  1358. xmlNodePtr node;
  1359. xmlChar *val;
  1360. const xmlChar *cur = value;
  1361. const xmlChar *q;
  1362. xmlEntityPtr ent;
  1363. xmlBufPtr buf;
  1364. if (value == NULL) return(NULL);
  1365. buf = xmlBufCreateSize(0);
  1366. if (buf == NULL) return(NULL);
  1367. xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_HYBRID);
  1368. q = cur;
  1369. while (*cur != 0) {
  1370. if (cur[0] == '&') {
  1371. int charval = 0;
  1372. xmlChar tmp;
  1373. /*
  1374. * Save the current text.
  1375. */
  1376. if (cur != q) {
  1377. if (xmlBufAdd(buf, q, cur - q))
  1378. goto out;
  1379. }
  1380. q = cur;
  1381. if ((cur[1] == '#') && (cur[2] == 'x')) {
  1382. cur += 3;
  1383. tmp = *cur;
  1384. while (tmp != ';') { /* Non input consuming loop */
  1385. if ((tmp >= '0') && (tmp <= '9'))
  1386. charval = charval * 16 + (tmp - '0');
  1387. else if ((tmp >= 'a') && (tmp <= 'f'))
  1388. charval = charval * 16 + (tmp - 'a') + 10;
  1389. else if ((tmp >= 'A') && (tmp <= 'F'))
  1390. charval = charval * 16 + (tmp - 'A') + 10;
  1391. else {
  1392. xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
  1393. NULL);
  1394. charval = 0;
  1395. break;
  1396. }
  1397. cur++;
  1398. tmp = *cur;
  1399. }
  1400. if (tmp == ';')
  1401. cur++;
  1402. q = cur;
  1403. } else if (cur[1] == '#') {
  1404. cur += 2;
  1405. tmp = *cur;
  1406. while (tmp != ';') { /* Non input consuming loops */
  1407. if ((tmp >= '0') && (tmp <= '9'))
  1408. charval = charval * 10 + (tmp - '0');
  1409. else {
  1410. xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
  1411. NULL);
  1412. charval = 0;
  1413. break;
  1414. }
  1415. cur++;
  1416. tmp = *cur;
  1417. }
  1418. if (tmp == ';')
  1419. cur++;
  1420. q = cur;
  1421. } else {
  1422. /*
  1423. * Read the entity string
  1424. */
  1425. cur++;
  1426. q = cur;
  1427. while ((*cur != 0) && (*cur != ';')) cur++;
  1428. if (*cur == 0) {
  1429. xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY,
  1430. (xmlNodePtr) doc, (const char *) q);
  1431. goto out;
  1432. }
  1433. if (cur != q) {
  1434. /*
  1435. * Predefined entities don't generate nodes
  1436. */
  1437. val = xmlStrndup(q, cur - q);
  1438. ent = xmlGetDocEntity(doc, val);
  1439. if ((ent != NULL) &&
  1440. (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
  1441. if (xmlBufCat(buf, ent->content))
  1442. goto out;
  1443. } else {
  1444. /*
  1445. * Flush buffer so far
  1446. */
  1447. if (!xmlBufIsEmpty(buf)) {
  1448. node = xmlNewDocText(doc, NULL);
  1449. node->content = xmlBufDetach(buf);
  1450. if (last == NULL) {
  1451. last = ret = node;
  1452. } else {
  1453. last = xmlAddNextSibling(last, node);
  1454. }
  1455. }
  1456. /*
  1457. * Create a new REFERENCE_REF node
  1458. */
  1459. node = xmlNewReference(doc, val);
  1460. if (node == NULL) {
  1461. if (val != NULL) xmlFree(val);
  1462. goto out;
  1463. }
  1464. else if ((ent != NULL) && (ent->children == NULL)) {
  1465. xmlNodePtr temp;
  1466. /* Set to non-NULL value to avoid recursion. */
  1467. ent->children = (xmlNodePtr) -1;
  1468. ent->children = xmlStringGetNodeList(doc,
  1469. (const xmlChar*)node->content);
  1470. ent->owner = 1;
  1471. temp = ent->children;
  1472. while (temp) {
  1473. temp->parent = (xmlNodePtr)ent;
  1474. ent->last = temp;
  1475. temp = temp->next;
  1476. }
  1477. }
  1478. if (last == NULL) {
  1479. last = ret = node;
  1480. } else {
  1481. last = xmlAddNextSibling(last, node);
  1482. }
  1483. }
  1484. xmlFree(val);
  1485. }
  1486. cur++;
  1487. q = cur;
  1488. }
  1489. if (charval != 0) {
  1490. xmlChar buffer[10];
  1491. int len;
  1492. len = xmlCopyCharMultiByte(buffer, charval);
  1493. buffer[len] = 0;
  1494. if (xmlBufCat(buf, buffer))
  1495. goto out;
  1496. charval = 0;
  1497. }
  1498. } else
  1499. cur++;
  1500. }
  1501. if ((cur != q) || (ret == NULL)) {
  1502. /*
  1503. * Handle the last piece of text.
  1504. */
  1505. xmlBufAdd(buf, q, cur - q);
  1506. }
  1507. if (!xmlBufIsEmpty(buf)) {
  1508. node = xmlNewDocText(doc, NULL);
  1509. node->content = xmlBufDetach(buf);
  1510. if (last == NULL) {
  1511. ret = node;
  1512. } else {
  1513. xmlAddNextSibling(last, node);
  1514. }
  1515. }
  1516. out:
  1517. xmlBufFree(buf);
  1518. return(ret);
  1519. }
  1520. /**
  1521. * xmlNodeListGetString:
  1522. * @doc: the document
  1523. * @list: a Node list
  1524. * @inLine: should we replace entity contents or show their external form
  1525. *
  1526. * Build the string equivalent to the text contained in the Node list
  1527. * made of TEXTs and ENTITY_REFs
  1528. *
  1529. * Returns a pointer to the string copy, the caller must free it with xmlFree().
  1530. */
  1531. xmlChar *
  1532. xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine)
  1533. {
  1534. const xmlNode *node = list;
  1535. xmlChar *ret = NULL;
  1536. xmlEntityPtr ent;
  1537. int attr;
  1538. if (list == NULL)
  1539. return (NULL);
  1540. if ((list->parent != NULL) && (list->parent->type == XML_ATTRIBUTE_NODE))
  1541. attr = 1;
  1542. else
  1543. attr = 0;
  1544. while (node != NULL) {
  1545. if ((node->type == XML_TEXT_NODE) ||
  1546. (node->type == XML_CDATA_SECTION_NODE)) {
  1547. if (inLine) {
  1548. ret = xmlStrcat(ret, node->content);
  1549. } else {
  1550. xmlChar *buffer;
  1551. if (attr)
  1552. buffer = xmlEncodeAttributeEntities(doc, node->content);
  1553. else
  1554. buffer = xmlEncodeEntitiesReentrant(doc, node->content);
  1555. if (buffer != NULL) {
  1556. ret = xmlStrcat(ret, buffer);
  1557. xmlFree(buffer);
  1558. }
  1559. }
  1560. } else if (node->type == XML_ENTITY_REF_NODE) {
  1561. if (inLine) {
  1562. ent = xmlGetDocEntity(doc, node->name);
  1563. if (ent != NULL) {
  1564. xmlChar *buffer;
  1565. /* an entity content can be any "well balanced chunk",
  1566. * i.e. the result of the content [43] production:
  1567. * http://www.w3.org/TR/REC-xml#NT-content.
  1568. * So it can contain text, CDATA section or nested
  1569. * entity reference nodes (among others).
  1570. * -> we recursive call xmlNodeListGetString()
  1571. * which handles these types */
  1572. buffer = xmlNodeListGetString(doc, ent->children, 1);
  1573. if (buffer != NULL) {
  1574. ret = xmlStrcat(ret, buffer);
  1575. xmlFree(buffer);
  1576. }
  1577. } else {
  1578. ret = xmlStrcat(ret, node->content);
  1579. }
  1580. } else {
  1581. xmlChar buf[2];
  1582. buf[0] = '&';
  1583. buf[1] = 0;
  1584. ret = xmlStrncat(ret, buf, 1);
  1585. ret = xmlStrcat(ret, node->name);
  1586. buf[0] = ';';
  1587. buf[1] = 0;
  1588. ret = xmlStrncat(ret, buf, 1);
  1589. }
  1590. }
  1591. #if 0
  1592. else {
  1593. xmlGenericError(xmlGenericErrorContext,
  1594. "xmlGetNodeListString : invalid node type %d\n",
  1595. node->type);
  1596. }
  1597. #endif
  1598. node = node->next;
  1599. }
  1600. return (ret);
  1601. }
  1602. #ifdef LIBXML_TREE_ENABLED
  1603. /**
  1604. * xmlNodeListGetRawString:
  1605. * @doc: the document
  1606. * @list: a Node list
  1607. * @inLine: should we replace entity contents or show their external form
  1608. *
  1609. * Builds the string equivalent to the text contained in the Node list
  1610. * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
  1611. * this function doesn't do any character encoding handling.
  1612. *
  1613. * Returns a pointer to the string copy, the caller must free it with xmlFree().
  1614. */
  1615. xmlChar *
  1616. xmlNodeListGetRawString(const xmlDoc *doc, const xmlNode *list, int inLine)
  1617. {
  1618. const xmlNode *node = list;
  1619. xmlChar *ret = NULL;
  1620. xmlEntityPtr ent;
  1621. if (list == NULL)
  1622. return (NULL);
  1623. while (node != NULL) {
  1624. if ((node->type == XML_TEXT_NODE) ||
  1625. (node->type == XML_CDATA_SECTION_NODE)) {
  1626. if (inLine) {
  1627. ret = xmlStrcat(ret, node->content);
  1628. } else {
  1629. xmlChar *buffer;
  1630. buffer = xmlEncodeSpecialChars(doc, node->content);
  1631. if (buffer != NULL) {
  1632. ret = xmlStrcat(ret, buffer);
  1633. xmlFree(buffer);
  1634. }
  1635. }
  1636. } else if (node->type == XML_ENTITY_REF_NODE) {
  1637. if (inLine) {
  1638. ent = xmlGetDocEntity(doc, node->name);
  1639. if (ent != NULL) {
  1640. xmlChar *buffer;
  1641. /* an entity content can be any "well balanced chunk",
  1642. * i.e. the result of the content [43] production:
  1643. * http://www.w3.org/TR/REC-xml#NT-content.
  1644. * So it can contain text, CDATA section or nested
  1645. * entity reference nodes (among others).
  1646. * -> we recursive call xmlNodeListGetRawString()
  1647. * which handles these types */
  1648. buffer =
  1649. xmlNodeListGetRawString(doc, ent->children, 1);
  1650. if (buffer != NULL) {
  1651. ret = xmlStrcat(ret, buffer);
  1652. xmlFree(buffer);
  1653. }
  1654. } else {
  1655. ret = xmlStrcat(ret, node->content);
  1656. }
  1657. } else {
  1658. xmlChar buf[2];
  1659. buf[0] = '&';
  1660. buf[1] = 0;
  1661. ret = xmlStrncat(ret, buf, 1);
  1662. ret = xmlStrcat(ret, node->name);
  1663. buf[0] = ';';
  1664. buf[1] = 0;
  1665. ret = xmlStrncat(ret, buf, 1);
  1666. }
  1667. }
  1668. #if 0
  1669. else {
  1670. xmlGenericError(xmlGenericErrorContext,
  1671. "xmlGetNodeListString : invalid node type %d\n",
  1672. node->type);
  1673. }
  1674. #endif
  1675. node = node->next;
  1676. }
  1677. return (ret);
  1678. }
  1679. #endif /* LIBXML_TREE_ENABLED */
  1680. static xmlAttrPtr
  1681. xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
  1682. const xmlChar * name, const xmlChar * value,
  1683. int eatname)
  1684. {
  1685. xmlAttrPtr cur;
  1686. xmlDocPtr doc = NULL;
  1687. if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) {
  1688. if ((eatname == 1) &&
  1689. ((node->doc == NULL) ||
  1690. (!(xmlDictOwns(node->doc->dict, name)))))
  1691. xmlFree((xmlChar *) name);
  1692. return (NULL);
  1693. }
  1694. /*
  1695. * Allocate a new property and fill the fields.
  1696. */
  1697. cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
  1698. if (cur == NULL) {
  1699. if ((eatname == 1) &&
  1700. ((node == NULL) || (node->doc == NULL) ||
  1701. (!(xmlDictOwns(node->doc->dict, name)))))
  1702. xmlFree((xmlChar *) name);
  1703. xmlTreeErrMemory("building attribute");
  1704. return (NULL);
  1705. }
  1706. memset(cur, 0, sizeof(xmlAttr));
  1707. cur->type = XML_ATTRIBUTE_NODE;
  1708. cur->parent = node;
  1709. if (node != NULL) {
  1710. doc = node->doc;
  1711. cur->doc = doc;
  1712. }
  1713. cur->ns = ns;
  1714. if (eatname == 0) {
  1715. if ((doc != NULL) && (doc->dict != NULL))
  1716. cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
  1717. else
  1718. cur->name = xmlStrdup(name);
  1719. } else
  1720. cur->name = name;
  1721. if (value != NULL) {
  1722. xmlNodePtr tmp;
  1723. if(!xmlCheckUTF8(value)) {
  1724. xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) doc,
  1725. NULL);
  1726. if (doc != NULL)
  1727. doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
  1728. }
  1729. cur->children = xmlNewDocText(doc, value);
  1730. cur->last = NULL;
  1731. tmp = cur->children;
  1732. while (tmp != NULL) {
  1733. tmp->parent = (xmlNodePtr) cur;
  1734. if (tmp->next == NULL)
  1735. cur->last = tmp;
  1736. tmp = tmp->next;
  1737. }
  1738. }
  1739. /*
  1740. * Add it at the end to preserve parsing order ...
  1741. */
  1742. if (node != NULL) {
  1743. if (node->properties == NULL) {
  1744. node->properties = cur;
  1745. } else {
  1746. xmlAttrPtr prev = node->properties;
  1747. while (prev->next != NULL)
  1748. prev = prev->next;
  1749. prev->next = cur;
  1750. cur->prev = prev;
  1751. }
  1752. }
  1753. if ((value != NULL) && (node != NULL) &&
  1754. (xmlIsID(node->doc, node, cur) == 1))
  1755. xmlAddID(NULL, node->doc, value, cur);
  1756. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  1757. xmlRegisterNodeDefaultValue((xmlNodePtr) cur);
  1758. return (cur);
  1759. }
  1760. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
  1761. defined(LIBXML_SCHEMAS_ENABLED)
  1762. /**
  1763. * xmlNewProp:
  1764. * @node: the holding node
  1765. * @name: the name of the attribute
  1766. * @value: the value of the attribute
  1767. *
  1768. * Create a new property carried by a node.
  1769. * Returns a pointer to the attribute
  1770. */
  1771. xmlAttrPtr
  1772. xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
  1773. if (name == NULL) {
  1774. #ifdef DEBUG_TREE
  1775. xmlGenericError(xmlGenericErrorContext,
  1776. "xmlNewProp : name == NULL\n");
  1777. #endif
  1778. return(NULL);
  1779. }
  1780. return xmlNewPropInternal(node, NULL, name, value, 0);
  1781. }
  1782. #endif /* LIBXML_TREE_ENABLED */
  1783. /**
  1784. * xmlNewNsProp:
  1785. * @node: the holding node
  1786. * @ns: the namespace
  1787. * @name: the name of the attribute
  1788. * @value: the value of the attribute
  1789. *
  1790. * Create a new property tagged with a namespace and carried by a node.
  1791. * Returns a pointer to the attribute
  1792. */
  1793. xmlAttrPtr
  1794. xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
  1795. const xmlChar *value) {
  1796. if (name == NULL) {
  1797. #ifdef DEBUG_TREE
  1798. xmlGenericError(xmlGenericErrorContext,
  1799. "xmlNewNsProp : name == NULL\n");
  1800. #endif
  1801. return(NULL);
  1802. }
  1803. return xmlNewPropInternal(node, ns, name, value, 0);
  1804. }
  1805. /**
  1806. * xmlNewNsPropEatName:
  1807. * @node: the holding node
  1808. * @ns: the namespace
  1809. * @name: the name of the attribute
  1810. * @value: the value of the attribute
  1811. *
  1812. * Create a new property tagged with a namespace and carried by a node.
  1813. * Returns a pointer to the attribute
  1814. */
  1815. xmlAttrPtr
  1816. xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
  1817. const xmlChar *value) {
  1818. if (name == NULL) {
  1819. #ifdef DEBUG_TREE
  1820. xmlGenericError(xmlGenericErrorContext,
  1821. "xmlNewNsPropEatName : name == NULL\n");
  1822. #endif
  1823. return(NULL);
  1824. }
  1825. return xmlNewPropInternal(node, ns, name, value, 1);
  1826. }
  1827. /**
  1828. * xmlNewDocProp:
  1829. * @doc: the document
  1830. * @name: the name of the attribute
  1831. * @value: the value of the attribute
  1832. *
  1833. * Create a new property carried by a document.
  1834. * Returns a pointer to the attribute
  1835. */
  1836. xmlAttrPtr
  1837. xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
  1838. xmlAttrPtr cur;
  1839. if (name == NULL) {
  1840. #ifdef DEBUG_TREE
  1841. xmlGenericError(xmlGenericErrorContext,
  1842. "xmlNewDocProp : name == NULL\n");
  1843. #endif
  1844. return(NULL);
  1845. }
  1846. /*
  1847. * Allocate a new property and fill the fields.
  1848. */
  1849. cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
  1850. if (cur == NULL) {
  1851. xmlTreeErrMemory("building attribute");
  1852. return(NULL);
  1853. }
  1854. memset(cur, 0, sizeof(xmlAttr));
  1855. cur->type = XML_ATTRIBUTE_NODE;
  1856. if ((doc != NULL) && (doc->dict != NULL))
  1857. cur->name = xmlDictLookup(doc->dict, name, -1);
  1858. else
  1859. cur->name = xmlStrdup(name);
  1860. cur->doc = doc;
  1861. if (value != NULL) {
  1862. xmlNodePtr tmp;
  1863. cur->children = xmlStringGetNodeList(doc, value);
  1864. cur->last = NULL;
  1865. tmp = cur->children;
  1866. while (tmp != NULL) {
  1867. tmp->parent = (xmlNodePtr) cur;
  1868. if (tmp->next == NULL)
  1869. cur->last = tmp;
  1870. tmp = tmp->next;
  1871. }
  1872. }
  1873. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  1874. xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
  1875. return(cur);
  1876. }
  1877. /**
  1878. * xmlFreePropList:
  1879. * @cur: the first property in the list
  1880. *
  1881. * Free a property and all its siblings, all the children are freed too.
  1882. */
  1883. void
  1884. xmlFreePropList(xmlAttrPtr cur) {
  1885. xmlAttrPtr next;
  1886. if (cur == NULL) return;
  1887. while (cur != NULL) {
  1888. next = cur->next;
  1889. xmlFreeProp(cur);
  1890. cur = next;
  1891. }
  1892. }
  1893. /**
  1894. * xmlFreeProp:
  1895. * @cur: an attribute
  1896. *
  1897. * Free one attribute, all the content is freed too
  1898. */
  1899. void
  1900. xmlFreeProp(xmlAttrPtr cur) {
  1901. xmlDictPtr dict = NULL;
  1902. if (cur == NULL) return;
  1903. if (cur->doc != NULL) dict = cur->doc->dict;
  1904. if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
  1905. xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
  1906. /* Check for ID removal -> leading to invalid references ! */
  1907. if ((cur->doc != NULL) && (cur->atype == XML_ATTRIBUTE_ID)) {
  1908. xmlRemoveID(cur->doc, cur);
  1909. }
  1910. if (cur->children != NULL) xmlFreeNodeList(cur->children);
  1911. DICT_FREE(cur->name)
  1912. xmlFree(cur);
  1913. }
  1914. /**
  1915. * xmlRemoveProp:
  1916. * @cur: an attribute
  1917. *
  1918. * Unlink and free one attribute, all the content is freed too
  1919. * Note this doesn't work for namespace definition attributes
  1920. *
  1921. * Returns 0 if success and -1 in case of error.
  1922. */
  1923. int
  1924. xmlRemoveProp(xmlAttrPtr cur) {
  1925. xmlAttrPtr tmp;
  1926. if (cur == NULL) {
  1927. #ifdef DEBUG_TREE
  1928. xmlGenericError(xmlGenericErrorContext,
  1929. "xmlRemoveProp : cur == NULL\n");
  1930. #endif
  1931. return(-1);
  1932. }
  1933. if (cur->parent == NULL) {
  1934. #ifdef DEBUG_TREE
  1935. xmlGenericError(xmlGenericErrorContext,
  1936. "xmlRemoveProp : cur->parent == NULL\n");
  1937. #endif
  1938. return(-1);
  1939. }
  1940. tmp = cur->parent->properties;
  1941. if (tmp == cur) {
  1942. cur->parent->properties = cur->next;
  1943. if (cur->next != NULL)
  1944. cur->next->prev = NULL;
  1945. xmlFreeProp(cur);
  1946. return(0);
  1947. }
  1948. while (tmp != NULL) {
  1949. if (tmp->next == cur) {
  1950. tmp->next = cur->next;
  1951. if (tmp->next != NULL)
  1952. tmp->next->prev = tmp;
  1953. xmlFreeProp(cur);
  1954. return(0);
  1955. }
  1956. tmp = tmp->next;
  1957. }
  1958. #ifdef DEBUG_TREE
  1959. xmlGenericError(xmlGenericErrorContext,
  1960. "xmlRemoveProp : attribute not owned by its node\n");
  1961. #endif
  1962. return(-1);
  1963. }
  1964. /**
  1965. * xmlNewDocPI:
  1966. * @doc: the target document
  1967. * @name: the processing instruction name
  1968. * @content: the PI content
  1969. *
  1970. * Creation of a processing instruction element.
  1971. * Returns a pointer to the new node object.
  1972. */
  1973. xmlNodePtr
  1974. xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) {
  1975. xmlNodePtr cur;
  1976. if (name == NULL) {
  1977. #ifdef DEBUG_TREE
  1978. xmlGenericError(xmlGenericErrorContext,
  1979. "xmlNewPI : name == NULL\n");
  1980. #endif
  1981. return(NULL);
  1982. }
  1983. /*
  1984. * Allocate a new node and fill the fields.
  1985. */
  1986. cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  1987. if (cur == NULL) {
  1988. xmlTreeErrMemory("building PI");
  1989. return(NULL);
  1990. }
  1991. memset(cur, 0, sizeof(xmlNode));
  1992. cur->type = XML_PI_NODE;
  1993. if ((doc != NULL) && (doc->dict != NULL))
  1994. cur->name = xmlDictLookup(doc->dict, name, -1);
  1995. else
  1996. cur->name = xmlStrdup(name);
  1997. if (content != NULL) {
  1998. cur->content = xmlStrdup(content);
  1999. }
  2000. cur->doc = doc;
  2001. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  2002. xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
  2003. return(cur);
  2004. }
  2005. /**
  2006. * xmlNewPI:
  2007. * @name: the processing instruction name
  2008. * @content: the PI content
  2009. *
  2010. * Creation of a processing instruction element.
  2011. * Use xmlDocNewPI preferably to get string interning
  2012. *
  2013. * Returns a pointer to the new node object.
  2014. */
  2015. xmlNodePtr
  2016. xmlNewPI(const xmlChar *name, const xmlChar *content) {
  2017. return(xmlNewDocPI(NULL, name, content));
  2018. }
  2019. /**
  2020. * xmlNewNode:
  2021. * @ns: namespace if any
  2022. * @name: the node name
  2023. *
  2024. * Creation of a new node element. @ns is optional (NULL).
  2025. *
  2026. * Returns a pointer to the new node object. Uses xmlStrdup() to make
  2027. * copy of @name.
  2028. */
  2029. xmlNodePtr
  2030. xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
  2031. xmlNodePtr cur;
  2032. if (name == NULL) {
  2033. #ifdef DEBUG_TREE
  2034. xmlGenericError(xmlGenericErrorContext,
  2035. "xmlNewNode : name == NULL\n");
  2036. #endif
  2037. return(NULL);
  2038. }
  2039. /*
  2040. * Allocate a new node and fill the fields.
  2041. */
  2042. cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  2043. if (cur == NULL) {
  2044. xmlTreeErrMemory("building node");
  2045. return(NULL);
  2046. }
  2047. memset(cur, 0, sizeof(xmlNode));
  2048. cur->type = XML_ELEMENT_NODE;
  2049. cur->name = xmlStrdup(name);
  2050. cur->ns = ns;
  2051. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  2052. xmlRegisterNodeDefaultValue(cur);
  2053. return(cur);
  2054. }
  2055. /**
  2056. * xmlNewNodeEatName:
  2057. * @ns: namespace if any
  2058. * @name: the node name
  2059. *
  2060. * Creation of a new node element. @ns is optional (NULL).
  2061. *
  2062. * Returns a pointer to the new node object, with pointer @name as
  2063. * new node's name. Use xmlNewNode() if a copy of @name string is
  2064. * is needed as new node's name.
  2065. */
  2066. xmlNodePtr
  2067. xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) {
  2068. xmlNodePtr cur;
  2069. if (name == NULL) {
  2070. #ifdef DEBUG_TREE
  2071. xmlGenericError(xmlGenericErrorContext,
  2072. "xmlNewNode : name == NULL\n");
  2073. #endif
  2074. return(NULL);
  2075. }
  2076. /*
  2077. * Allocate a new node and fill the fields.
  2078. */
  2079. cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  2080. if (cur == NULL) {
  2081. xmlTreeErrMemory("building node");
  2082. /* we can't check here that name comes from the doc dictionary */
  2083. return(NULL);
  2084. }
  2085. memset(cur, 0, sizeof(xmlNode));
  2086. cur->type = XML_ELEMENT_NODE;
  2087. cur->name = name;
  2088. cur->ns = ns;
  2089. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  2090. xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
  2091. return(cur);
  2092. }
  2093. /**
  2094. * xmlNewDocNode:
  2095. * @doc: the document
  2096. * @ns: namespace if any
  2097. * @name: the node name
  2098. * @content: the XML text content if any
  2099. *
  2100. * Creation of a new node element within a document. @ns and @content
  2101. * are optional (NULL).
  2102. * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
  2103. * references, but XML special chars need to be escaped first by using
  2104. * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
  2105. * need entities support.
  2106. *
  2107. * Returns a pointer to the new node object.
  2108. */
  2109. xmlNodePtr
  2110. xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
  2111. const xmlChar *name, const xmlChar *content) {
  2112. xmlNodePtr cur;
  2113. if ((doc != NULL) && (doc->dict != NULL))
  2114. cur = xmlNewNodeEatName(ns, (xmlChar *)
  2115. xmlDictLookup(doc->dict, name, -1));
  2116. else
  2117. cur = xmlNewNode(ns, name);
  2118. if (cur != NULL) {
  2119. cur->doc = doc;
  2120. if (content != NULL) {
  2121. cur->children = xmlStringGetNodeList(doc, content);
  2122. UPDATE_LAST_CHILD_AND_PARENT(cur)
  2123. }
  2124. }
  2125. return(cur);
  2126. }
  2127. /**
  2128. * xmlNewDocNodeEatName:
  2129. * @doc: the document
  2130. * @ns: namespace if any
  2131. * @name: the node name
  2132. * @content: the XML text content if any
  2133. *
  2134. * Creation of a new node element within a document. @ns and @content
  2135. * are optional (NULL).
  2136. * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
  2137. * references, but XML special chars need to be escaped first by using
  2138. * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
  2139. * need entities support.
  2140. *
  2141. * Returns a pointer to the new node object.
  2142. */
  2143. xmlNodePtr
  2144. xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns,
  2145. xmlChar *name, const xmlChar *content) {
  2146. xmlNodePtr cur;
  2147. cur = xmlNewNodeEatName(ns, name);
  2148. if (cur != NULL) {
  2149. cur->doc = doc;
  2150. if (content != NULL) {
  2151. cur->children = xmlStringGetNodeList(doc, content);
  2152. UPDATE_LAST_CHILD_AND_PARENT(cur)
  2153. }
  2154. } else {
  2155. /* if name don't come from the doc dictionary free it here */
  2156. if ((name != NULL) && (doc != NULL) &&
  2157. (!(xmlDictOwns(doc->dict, name))))
  2158. xmlFree(name);
  2159. }
  2160. return(cur);
  2161. }
  2162. #ifdef LIBXML_TREE_ENABLED
  2163. /**
  2164. * xmlNewDocRawNode:
  2165. * @doc: the document
  2166. * @ns: namespace if any
  2167. * @name: the node name
  2168. * @content: the text content if any
  2169. *
  2170. * Creation of a new node element within a document. @ns and @content
  2171. * are optional (NULL).
  2172. *
  2173. * Returns a pointer to the new node object.
  2174. */
  2175. xmlNodePtr
  2176. xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
  2177. const xmlChar *name, const xmlChar *content) {
  2178. xmlNodePtr cur;
  2179. cur = xmlNewDocNode(doc, ns, name, NULL);
  2180. if (cur != NULL) {
  2181. cur->doc = doc;
  2182. if (content != NULL) {
  2183. cur->children = xmlNewDocText(doc, content);
  2184. UPDATE_LAST_CHILD_AND_PARENT(cur)
  2185. }
  2186. }
  2187. return(cur);
  2188. }
  2189. /**
  2190. * xmlNewDocFragment:
  2191. * @doc: the document owning the fragment
  2192. *
  2193. * Creation of a new Fragment node.
  2194. * Returns a pointer to the new node object.
  2195. */
  2196. xmlNodePtr
  2197. xmlNewDocFragment(xmlDocPtr doc) {
  2198. xmlNodePtr cur;
  2199. /*
  2200. * Allocate a new DocumentFragment node and fill the fields.
  2201. */
  2202. cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  2203. if (cur == NULL) {
  2204. xmlTreeErrMemory("building fragment");
  2205. return(NULL);
  2206. }
  2207. memset(cur, 0, sizeof(xmlNode));
  2208. cur->type = XML_DOCUMENT_FRAG_NODE;
  2209. cur->doc = doc;
  2210. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  2211. xmlRegisterNodeDefaultValue(cur);
  2212. return(cur);
  2213. }
  2214. #endif /* LIBXML_TREE_ENABLED */
  2215. /**
  2216. * xmlNewText:
  2217. * @content: the text content
  2218. *
  2219. * Creation of a new text node.
  2220. * Returns a pointer to the new node object.
  2221. */
  2222. xmlNodePtr
  2223. xmlNewText(const xmlChar *content) {
  2224. xmlNodePtr cur;
  2225. /*
  2226. * Allocate a new node and fill the fields.
  2227. */
  2228. cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  2229. if (cur == NULL) {
  2230. xmlTreeErrMemory("building text");
  2231. return(NULL);
  2232. }
  2233. memset(cur, 0, sizeof(xmlNode));
  2234. cur->type = XML_TEXT_NODE;
  2235. cur->name = xmlStringText;
  2236. if (content != NULL) {
  2237. cur->content = xmlStrdup(content);
  2238. }
  2239. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  2240. xmlRegisterNodeDefaultValue(cur);
  2241. return(cur);
  2242. }
  2243. #ifdef LIBXML_TREE_ENABLED
  2244. /**
  2245. * xmlNewTextChild:
  2246. * @parent: the parent node
  2247. * @ns: a namespace if any
  2248. * @name: the name of the child
  2249. * @content: the text content of the child if any.
  2250. *
  2251. * Creation of a new child element, added at the end of @parent children list.
  2252. * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
  2253. * created element inherits the namespace of @parent. If @content is non NULL,
  2254. * a child TEXT node will be created containing the string @content.
  2255. * NOTE: Use xmlNewChild() if @content will contain entities that need to be
  2256. * preserved. Use this function, xmlNewTextChild(), if you need to ensure that
  2257. * reserved XML chars that might appear in @content, such as the ampersand,
  2258. * greater-than or less-than signs, are automatically replaced by their XML
  2259. * escaped entity representations.
  2260. *
  2261. * Returns a pointer to the new node object.
  2262. */
  2263. xmlNodePtr
  2264. xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
  2265. const xmlChar *name, const xmlChar *content) {
  2266. xmlNodePtr cur, prev;
  2267. if (parent == NULL) {
  2268. #ifdef DEBUG_TREE
  2269. xmlGenericError(xmlGenericErrorContext,
  2270. "xmlNewTextChild : parent == NULL\n");
  2271. #endif
  2272. return(NULL);
  2273. }
  2274. if (name == NULL) {
  2275. #ifdef DEBUG_TREE
  2276. xmlGenericError(xmlGenericErrorContext,
  2277. "xmlNewTextChild : name == NULL\n");
  2278. #endif
  2279. return(NULL);
  2280. }
  2281. /*
  2282. * Allocate a new node
  2283. */
  2284. if (parent->type == XML_ELEMENT_NODE) {
  2285. if (ns == NULL)
  2286. cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
  2287. else
  2288. cur = xmlNewDocRawNode(parent->doc, ns, name, content);
  2289. } else if ((parent->type == XML_DOCUMENT_NODE) ||
  2290. (parent->type == XML_HTML_DOCUMENT_NODE)) {
  2291. if (ns == NULL)
  2292. cur = xmlNewDocRawNode((xmlDocPtr) parent, NULL, name, content);
  2293. else
  2294. cur = xmlNewDocRawNode((xmlDocPtr) parent, ns, name, content);
  2295. } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
  2296. cur = xmlNewDocRawNode( parent->doc, ns, name, content);
  2297. } else {
  2298. return(NULL);
  2299. }
  2300. if (cur == NULL) return(NULL);
  2301. /*
  2302. * add the new element at the end of the children list.
  2303. */
  2304. cur->type = XML_ELEMENT_NODE;
  2305. cur->parent = parent;
  2306. cur->doc = parent->doc;
  2307. if (parent->children == NULL) {
  2308. parent->children = cur;
  2309. parent->last = cur;
  2310. } else {
  2311. prev = parent->last;
  2312. prev->next = cur;
  2313. cur->prev = prev;
  2314. parent->last = cur;
  2315. }
  2316. return(cur);
  2317. }
  2318. #endif /* LIBXML_TREE_ENABLED */
  2319. /**
  2320. * xmlNewCharRef:
  2321. * @doc: the document
  2322. * @name: the char ref string, starting with # or "&# ... ;"
  2323. *
  2324. * Creation of a new character reference node.
  2325. * Returns a pointer to the new node object.
  2326. */
  2327. xmlNodePtr
  2328. xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
  2329. xmlNodePtr cur;
  2330. if (name == NULL)
  2331. return(NULL);
  2332. /*
  2333. * Allocate a new node and fill the fields.
  2334. */
  2335. cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  2336. if (cur == NULL) {
  2337. xmlTreeErrMemory("building character reference");
  2338. return(NULL);
  2339. }
  2340. memset(cur, 0, sizeof(xmlNode));
  2341. cur->type = XML_ENTITY_REF_NODE;
  2342. cur->doc = doc;
  2343. if (name[0] == '&') {
  2344. int len;
  2345. name++;
  2346. len = xmlStrlen(name);
  2347. if (name[len - 1] == ';')
  2348. cur->name = xmlStrndup(name, len - 1);
  2349. else
  2350. cur->name = xmlStrndup(name, len);
  2351. } else
  2352. cur->name = xmlStrdup(name);
  2353. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  2354. xmlRegisterNodeDefaultValue(cur);
  2355. return(cur);
  2356. }
  2357. /**
  2358. * xmlNewReference:
  2359. * @doc: the document
  2360. * @name: the reference name, or the reference string with & and ;
  2361. *
  2362. * Creation of a new reference node.
  2363. * Returns a pointer to the new node object.
  2364. */
  2365. xmlNodePtr
  2366. xmlNewReference(const xmlDoc *doc, const xmlChar *name) {
  2367. xmlNodePtr cur;
  2368. xmlEntityPtr ent;
  2369. if (name == NULL)
  2370. return(NULL);
  2371. /*
  2372. * Allocate a new node and fill the fields.
  2373. */
  2374. cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  2375. if (cur == NULL) {
  2376. xmlTreeErrMemory("building reference");
  2377. return(NULL);
  2378. }
  2379. memset(cur, 0, sizeof(xmlNode));
  2380. cur->type = XML_ENTITY_REF_NODE;
  2381. cur->doc = (xmlDoc *)doc;
  2382. if (name[0] == '&') {
  2383. int len;
  2384. name++;
  2385. len = xmlStrlen(name);
  2386. if (name[len - 1] == ';')
  2387. cur->name = xmlStrndup(name, len - 1);
  2388. else
  2389. cur->name = xmlStrndup(name, len);
  2390. } else
  2391. cur->name = xmlStrdup(name);
  2392. ent = xmlGetDocEntity(doc, cur->name);
  2393. if (ent != NULL) {
  2394. cur->content = ent->content;
  2395. /*
  2396. * The parent pointer in entity is a DTD pointer and thus is NOT
  2397. * updated. Not sure if this is 100% correct.
  2398. * -George
  2399. */
  2400. cur->children = (xmlNodePtr) ent;
  2401. cur->last = (xmlNodePtr) ent;
  2402. }
  2403. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  2404. xmlRegisterNodeDefaultValue(cur);
  2405. return(cur);
  2406. }
  2407. /**
  2408. * xmlNewDocText:
  2409. * @doc: the document
  2410. * @content: the text content
  2411. *
  2412. * Creation of a new text node within a document.
  2413. * Returns a pointer to the new node object.
  2414. */
  2415. xmlNodePtr
  2416. xmlNewDocText(const xmlDoc *doc, const xmlChar *content) {
  2417. xmlNodePtr cur;
  2418. cur = xmlNewText(content);
  2419. if (cur != NULL) cur->doc = (xmlDoc *)doc;
  2420. return(cur);
  2421. }
  2422. /**
  2423. * xmlNewTextLen:
  2424. * @content: the text content
  2425. * @len: the text len.
  2426. *
  2427. * Creation of a new text node with an extra parameter for the content's length
  2428. * Returns a pointer to the new node object.
  2429. */
  2430. xmlNodePtr
  2431. xmlNewTextLen(const xmlChar *content, int len) {
  2432. xmlNodePtr cur;
  2433. /*
  2434. * Allocate a new node and fill the fields.
  2435. */
  2436. cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  2437. if (cur == NULL) {
  2438. xmlTreeErrMemory("building text");
  2439. return(NULL);
  2440. }
  2441. memset(cur, 0, sizeof(xmlNode));
  2442. cur->type = XML_TEXT_NODE;
  2443. cur->name = xmlStringText;
  2444. if (content != NULL) {
  2445. cur->content = xmlStrndup(content, len);
  2446. }
  2447. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  2448. xmlRegisterNodeDefaultValue(cur);
  2449. return(cur);
  2450. }
  2451. /**
  2452. * xmlNewDocTextLen:
  2453. * @doc: the document
  2454. * @content: the text content
  2455. * @len: the text len.
  2456. *
  2457. * Creation of a new text node with an extra content length parameter. The
  2458. * text node pertain to a given document.
  2459. * Returns a pointer to the new node object.
  2460. */
  2461. xmlNodePtr
  2462. xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
  2463. xmlNodePtr cur;
  2464. cur = xmlNewTextLen(content, len);
  2465. if (cur != NULL) cur->doc = doc;
  2466. return(cur);
  2467. }
  2468. /**
  2469. * xmlNewComment:
  2470. * @content: the comment content
  2471. *
  2472. * Creation of a new node containing a comment.
  2473. * Returns a pointer to the new node object.
  2474. */
  2475. xmlNodePtr
  2476. xmlNewComment(const xmlChar *content) {
  2477. xmlNodePtr cur;
  2478. /*
  2479. * Allocate a new node and fill the fields.
  2480. */
  2481. cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  2482. if (cur == NULL) {
  2483. xmlTreeErrMemory("building comment");
  2484. return(NULL);
  2485. }
  2486. memset(cur, 0, sizeof(xmlNode));
  2487. cur->type = XML_COMMENT_NODE;
  2488. cur->name = xmlStringComment;
  2489. if (content != NULL) {
  2490. cur->content = xmlStrdup(content);
  2491. }
  2492. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  2493. xmlRegisterNodeDefaultValue(cur);
  2494. return(cur);
  2495. }
  2496. /**
  2497. * xmlNewCDataBlock:
  2498. * @doc: the document
  2499. * @content: the CDATA block content content
  2500. * @len: the length of the block
  2501. *
  2502. * Creation of a new node containing a CDATA block.
  2503. * Returns a pointer to the new node object.
  2504. */
  2505. xmlNodePtr
  2506. xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
  2507. xmlNodePtr cur;
  2508. /*
  2509. * Allocate a new node and fill the fields.
  2510. */
  2511. cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  2512. if (cur == NULL) {
  2513. xmlTreeErrMemory("building CDATA");
  2514. return(NULL);
  2515. }
  2516. memset(cur, 0, sizeof(xmlNode));
  2517. cur->type = XML_CDATA_SECTION_NODE;
  2518. cur->doc = doc;
  2519. if (content != NULL) {
  2520. cur->content = xmlStrndup(content, len);
  2521. }
  2522. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  2523. xmlRegisterNodeDefaultValue(cur);
  2524. return(cur);
  2525. }
  2526. /**
  2527. * xmlNewDocComment:
  2528. * @doc: the document
  2529. * @content: the comment content
  2530. *
  2531. * Creation of a new node containing a comment within a document.
  2532. * Returns a pointer to the new node object.
  2533. */
  2534. xmlNodePtr
  2535. xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
  2536. xmlNodePtr cur;
  2537. cur = xmlNewComment(content);
  2538. if (cur != NULL) cur->doc = doc;
  2539. return(cur);
  2540. }
  2541. /**
  2542. * xmlSetTreeDoc:
  2543. * @tree: the top element
  2544. * @doc: the document
  2545. *
  2546. * update all nodes under the tree to point to the right document
  2547. */
  2548. void
  2549. xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
  2550. xmlAttrPtr prop;
  2551. if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
  2552. return;
  2553. if (tree->doc != doc) {
  2554. if(tree->type == XML_ELEMENT_NODE) {
  2555. prop = tree->properties;
  2556. while (prop != NULL) {
  2557. if (prop->atype == XML_ATTRIBUTE_ID) {
  2558. xmlRemoveID(tree->doc, prop);
  2559. }
  2560. prop->doc = doc;
  2561. xmlSetListDoc(prop->children, doc);
  2562. /*
  2563. * TODO: ID attributes should be also added to the new
  2564. * document, but this breaks things like xmlReplaceNode.
  2565. * The underlying problem is that xmlRemoveID is only called
  2566. * if a node is destroyed, not if it's unlinked.
  2567. */
  2568. #if 0
  2569. if (xmlIsID(doc, tree, prop)) {
  2570. xmlChar *idVal = xmlNodeListGetString(doc, prop->children,
  2571. 1);
  2572. xmlAddID(NULL, doc, idVal, prop);
  2573. }
  2574. #endif
  2575. prop = prop->next;
  2576. }
  2577. }
  2578. if (tree->children != NULL)
  2579. xmlSetListDoc(tree->children, doc);
  2580. tree->doc = doc;
  2581. }
  2582. }
  2583. /**
  2584. * xmlSetListDoc:
  2585. * @list: the first element
  2586. * @doc: the document
  2587. *
  2588. * update all nodes in the list to point to the right document
  2589. */
  2590. void
  2591. xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) {
  2592. xmlNodePtr cur;
  2593. if ((list == NULL) || (list->type == XML_NAMESPACE_DECL))
  2594. return;
  2595. cur = list;
  2596. while (cur != NULL) {
  2597. if (cur->doc != doc)
  2598. xmlSetTreeDoc(cur, doc);
  2599. cur = cur->next;
  2600. }
  2601. }
  2602. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
  2603. /**
  2604. * xmlNewChild:
  2605. * @parent: the parent node
  2606. * @ns: a namespace if any
  2607. * @name: the name of the child
  2608. * @content: the XML content of the child if any.
  2609. *
  2610. * Creation of a new child element, added at the end of @parent children list.
  2611. * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
  2612. * created element inherits the namespace of @parent. If @content is non NULL,
  2613. * a child list containing the TEXTs and ENTITY_REFs node will be created.
  2614. * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
  2615. * references. XML special chars must be escaped first by using
  2616. * xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.
  2617. *
  2618. * Returns a pointer to the new node object.
  2619. */
  2620. xmlNodePtr
  2621. xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
  2622. const xmlChar *name, const xmlChar *content) {
  2623. xmlNodePtr cur, prev;
  2624. if (parent == NULL) {
  2625. #ifdef DEBUG_TREE
  2626. xmlGenericError(xmlGenericErrorContext,
  2627. "xmlNewChild : parent == NULL\n");
  2628. #endif
  2629. return(NULL);
  2630. }
  2631. if (name == NULL) {
  2632. #ifdef DEBUG_TREE
  2633. xmlGenericError(xmlGenericErrorContext,
  2634. "xmlNewChild : name == NULL\n");
  2635. #endif
  2636. return(NULL);
  2637. }
  2638. /*
  2639. * Allocate a new node
  2640. */
  2641. if (parent->type == XML_ELEMENT_NODE) {
  2642. if (ns == NULL)
  2643. cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
  2644. else
  2645. cur = xmlNewDocNode(parent->doc, ns, name, content);
  2646. } else if ((parent->type == XML_DOCUMENT_NODE) ||
  2647. (parent->type == XML_HTML_DOCUMENT_NODE)) {
  2648. if (ns == NULL)
  2649. cur = xmlNewDocNode((xmlDocPtr) parent, NULL, name, content);
  2650. else
  2651. cur = xmlNewDocNode((xmlDocPtr) parent, ns, name, content);
  2652. } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
  2653. cur = xmlNewDocNode( parent->doc, ns, name, content);
  2654. } else {
  2655. return(NULL);
  2656. }
  2657. if (cur == NULL) return(NULL);
  2658. /*
  2659. * add the new element at the end of the children list.
  2660. */
  2661. cur->type = XML_ELEMENT_NODE;
  2662. cur->parent = parent;
  2663. cur->doc = parent->doc;
  2664. if (parent->children == NULL) {
  2665. parent->children = cur;
  2666. parent->last = cur;
  2667. } else {
  2668. prev = parent->last;
  2669. prev->next = cur;
  2670. cur->prev = prev;
  2671. parent->last = cur;
  2672. }
  2673. return(cur);
  2674. }
  2675. #endif /* LIBXML_TREE_ENABLED */
  2676. /**
  2677. * xmlAddPropSibling:
  2678. * @prev: the attribute to which @prop is added after
  2679. * @cur: the base attribute passed to calling function
  2680. * @prop: the new attribute
  2681. *
  2682. * Add a new attribute after @prev using @cur as base attribute.
  2683. * When inserting before @cur, @prev is passed as @cur->prev.
  2684. * When inserting after @cur, @prev is passed as @cur.
  2685. * If an existing attribute is found it is destroyed prior to adding @prop.
  2686. *
  2687. * Returns the attribute being inserted or NULL in case of error.
  2688. */
  2689. static xmlNodePtr
  2690. xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) {
  2691. xmlAttrPtr attr;
  2692. if ((cur == NULL) || (cur->type != XML_ATTRIBUTE_NODE) ||
  2693. (prop == NULL) || (prop->type != XML_ATTRIBUTE_NODE) ||
  2694. ((prev != NULL) && (prev->type != XML_ATTRIBUTE_NODE)))
  2695. return(NULL);
  2696. /* check if an attribute with the same name exists */
  2697. if (prop->ns == NULL)
  2698. attr = xmlHasNsProp(cur->parent, prop->name, NULL);
  2699. else
  2700. attr = xmlHasNsProp(cur->parent, prop->name, prop->ns->href);
  2701. if (prop->doc != cur->doc) {
  2702. xmlSetTreeDoc(prop, cur->doc);
  2703. }
  2704. prop->parent = cur->parent;
  2705. prop->prev = prev;
  2706. if (prev != NULL) {
  2707. prop->next = prev->next;
  2708. prev->next = prop;
  2709. if (prop->next)
  2710. prop->next->prev = prop;
  2711. } else {
  2712. prop->next = cur;
  2713. cur->prev = prop;
  2714. }
  2715. if (prop->prev == NULL && prop->parent != NULL)
  2716. prop->parent->properties = (xmlAttrPtr) prop;
  2717. if ((attr != NULL) && (attr->type != XML_ATTRIBUTE_DECL)) {
  2718. /* different instance, destroy it (attributes must be unique) */
  2719. xmlRemoveProp((xmlAttrPtr) attr);
  2720. }
  2721. return prop;
  2722. }
  2723. /**
  2724. * xmlAddNextSibling:
  2725. * @cur: the child node
  2726. * @elem: the new node
  2727. *
  2728. * Add a new node @elem as the next sibling of @cur
  2729. * If the new node was already inserted in a document it is
  2730. * first unlinked from its existing context.
  2731. * As a result of text merging @elem may be freed.
  2732. * If the new node is ATTRIBUTE, it is added into properties instead of children.
  2733. * If there is an attribute with equal name, it is first destroyed.
  2734. *
  2735. * Returns the new node or NULL in case of error.
  2736. */
  2737. xmlNodePtr
  2738. xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
  2739. if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
  2740. #ifdef DEBUG_TREE
  2741. xmlGenericError(xmlGenericErrorContext,
  2742. "xmlAddNextSibling : cur == NULL\n");
  2743. #endif
  2744. return(NULL);
  2745. }
  2746. if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
  2747. #ifdef DEBUG_TREE
  2748. xmlGenericError(xmlGenericErrorContext,
  2749. "xmlAddNextSibling : elem == NULL\n");
  2750. #endif
  2751. return(NULL);
  2752. }
  2753. if (cur == elem) {
  2754. #ifdef DEBUG_TREE
  2755. xmlGenericError(xmlGenericErrorContext,
  2756. "xmlAddNextSibling : cur == elem\n");
  2757. #endif
  2758. return(NULL);
  2759. }
  2760. xmlUnlinkNode(elem);
  2761. if (elem->type == XML_TEXT_NODE) {
  2762. if (cur->type == XML_TEXT_NODE) {
  2763. xmlNodeAddContent(cur, elem->content);
  2764. xmlFreeNode(elem);
  2765. return(cur);
  2766. }
  2767. if ((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE) &&
  2768. (cur->name == cur->next->name)) {
  2769. xmlChar *tmp;
  2770. tmp = xmlStrdup(elem->content);
  2771. tmp = xmlStrcat(tmp, cur->next->content);
  2772. xmlNodeSetContent(cur->next, tmp);
  2773. xmlFree(tmp);
  2774. xmlFreeNode(elem);
  2775. return(cur->next);
  2776. }
  2777. } else if (elem->type == XML_ATTRIBUTE_NODE) {
  2778. return xmlAddPropSibling(cur, cur, elem);
  2779. }
  2780. if (elem->doc != cur->doc) {
  2781. xmlSetTreeDoc(elem, cur->doc);
  2782. }
  2783. elem->parent = cur->parent;
  2784. elem->prev = cur;
  2785. elem->next = cur->next;
  2786. cur->next = elem;
  2787. if (elem->next != NULL)
  2788. elem->next->prev = elem;
  2789. if ((elem->parent != NULL) && (elem->parent->last == cur))
  2790. elem->parent->last = elem;
  2791. return(elem);
  2792. }
  2793. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
  2794. defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
  2795. /**
  2796. * xmlAddPrevSibling:
  2797. * @cur: the child node
  2798. * @elem: the new node
  2799. *
  2800. * Add a new node @elem as the previous sibling of @cur
  2801. * merging adjacent TEXT nodes (@elem may be freed)
  2802. * If the new node was already inserted in a document it is
  2803. * first unlinked from its existing context.
  2804. * If the new node is ATTRIBUTE, it is added into properties instead of children.
  2805. * If there is an attribute with equal name, it is first destroyed.
  2806. *
  2807. * Returns the new node or NULL in case of error.
  2808. */
  2809. xmlNodePtr
  2810. xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
  2811. if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
  2812. #ifdef DEBUG_TREE
  2813. xmlGenericError(xmlGenericErrorContext,
  2814. "xmlAddPrevSibling : cur == NULL\n");
  2815. #endif
  2816. return(NULL);
  2817. }
  2818. if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
  2819. #ifdef DEBUG_TREE
  2820. xmlGenericError(xmlGenericErrorContext,
  2821. "xmlAddPrevSibling : elem == NULL\n");
  2822. #endif
  2823. return(NULL);
  2824. }
  2825. if (cur == elem) {
  2826. #ifdef DEBUG_TREE
  2827. xmlGenericError(xmlGenericErrorContext,
  2828. "xmlAddPrevSibling : cur == elem\n");
  2829. #endif
  2830. return(NULL);
  2831. }
  2832. xmlUnlinkNode(elem);
  2833. if (elem->type == XML_TEXT_NODE) {
  2834. if (cur->type == XML_TEXT_NODE) {
  2835. xmlChar *tmp;
  2836. tmp = xmlStrdup(elem->content);
  2837. tmp = xmlStrcat(tmp, cur->content);
  2838. xmlNodeSetContent(cur, tmp);
  2839. xmlFree(tmp);
  2840. xmlFreeNode(elem);
  2841. return(cur);
  2842. }
  2843. if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE) &&
  2844. (cur->name == cur->prev->name)) {
  2845. xmlNodeAddContent(cur->prev, elem->content);
  2846. xmlFreeNode(elem);
  2847. return(cur->prev);
  2848. }
  2849. } else if (elem->type == XML_ATTRIBUTE_NODE) {
  2850. return xmlAddPropSibling(cur->prev, cur, elem);
  2851. }
  2852. if (elem->doc != cur->doc) {
  2853. xmlSetTreeDoc(elem, cur->doc);
  2854. }
  2855. elem->parent = cur->parent;
  2856. elem->next = cur;
  2857. elem->prev = cur->prev;
  2858. cur->prev = elem;
  2859. if (elem->prev != NULL)
  2860. elem->prev->next = elem;
  2861. if ((elem->parent != NULL) && (elem->parent->children == cur)) {
  2862. elem->parent->children = elem;
  2863. }
  2864. return(elem);
  2865. }
  2866. #endif /* LIBXML_TREE_ENABLED */
  2867. /**
  2868. * xmlAddSibling:
  2869. * @cur: the child node
  2870. * @elem: the new node
  2871. *
  2872. * Add a new element @elem to the list of siblings of @cur
  2873. * merging adjacent TEXT nodes (@elem may be freed)
  2874. * If the new element was already inserted in a document it is
  2875. * first unlinked from its existing context.
  2876. *
  2877. * Returns the new element or NULL in case of error.
  2878. */
  2879. xmlNodePtr
  2880. xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
  2881. xmlNodePtr parent;
  2882. if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
  2883. #ifdef DEBUG_TREE
  2884. xmlGenericError(xmlGenericErrorContext,
  2885. "xmlAddSibling : cur == NULL\n");
  2886. #endif
  2887. return(NULL);
  2888. }
  2889. if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
  2890. #ifdef DEBUG_TREE
  2891. xmlGenericError(xmlGenericErrorContext,
  2892. "xmlAddSibling : elem == NULL\n");
  2893. #endif
  2894. return(NULL);
  2895. }
  2896. if (cur == elem) {
  2897. #ifdef DEBUG_TREE
  2898. xmlGenericError(xmlGenericErrorContext,
  2899. "xmlAddSibling : cur == elem\n");
  2900. #endif
  2901. return(NULL);
  2902. }
  2903. /*
  2904. * Constant time is we can rely on the ->parent->last to find
  2905. * the last sibling.
  2906. */
  2907. if ((cur->type != XML_ATTRIBUTE_NODE) && (cur->parent != NULL) &&
  2908. (cur->parent->children != NULL) &&
  2909. (cur->parent->last != NULL) &&
  2910. (cur->parent->last->next == NULL)) {
  2911. cur = cur->parent->last;
  2912. } else {
  2913. while (cur->next != NULL) cur = cur->next;
  2914. }
  2915. xmlUnlinkNode(elem);
  2916. if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE) &&
  2917. (cur->name == elem->name)) {
  2918. xmlNodeAddContent(cur, elem->content);
  2919. xmlFreeNode(elem);
  2920. return(cur);
  2921. } else if (elem->type == XML_ATTRIBUTE_NODE) {
  2922. return xmlAddPropSibling(cur, cur, elem);
  2923. }
  2924. if (elem->doc != cur->doc) {
  2925. xmlSetTreeDoc(elem, cur->doc);
  2926. }
  2927. parent = cur->parent;
  2928. elem->prev = cur;
  2929. elem->next = NULL;
  2930. elem->parent = parent;
  2931. cur->next = elem;
  2932. if (parent != NULL)
  2933. parent->last = elem;
  2934. return(elem);
  2935. }
  2936. /**
  2937. * xmlAddChildList:
  2938. * @parent: the parent node
  2939. * @cur: the first node in the list
  2940. *
  2941. * Add a list of node at the end of the child list of the parent
  2942. * merging adjacent TEXT nodes (@cur may be freed)
  2943. *
  2944. * Returns the last child or NULL in case of error.
  2945. */
  2946. xmlNodePtr
  2947. xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
  2948. xmlNodePtr prev;
  2949. if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
  2950. #ifdef DEBUG_TREE
  2951. xmlGenericError(xmlGenericErrorContext,
  2952. "xmlAddChildList : parent == NULL\n");
  2953. #endif
  2954. return(NULL);
  2955. }
  2956. if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
  2957. #ifdef DEBUG_TREE
  2958. xmlGenericError(xmlGenericErrorContext,
  2959. "xmlAddChildList : child == NULL\n");
  2960. #endif
  2961. return(NULL);
  2962. }
  2963. if ((cur->doc != NULL) && (parent->doc != NULL) &&
  2964. (cur->doc != parent->doc)) {
  2965. #ifdef DEBUG_TREE
  2966. xmlGenericError(xmlGenericErrorContext,
  2967. "Elements moved to a different document\n");
  2968. #endif
  2969. }
  2970. /*
  2971. * add the first element at the end of the children list.
  2972. */
  2973. if (parent->children == NULL) {
  2974. parent->children = cur;
  2975. } else {
  2976. /*
  2977. * If cur and parent->last both are TEXT nodes, then merge them.
  2978. */
  2979. if ((cur->type == XML_TEXT_NODE) &&
  2980. (parent->last->type == XML_TEXT_NODE) &&
  2981. (cur->name == parent->last->name)) {
  2982. xmlNodeAddContent(parent->last, cur->content);
  2983. /*
  2984. * if it's the only child, nothing more to be done.
  2985. */
  2986. if (cur->next == NULL) {
  2987. xmlFreeNode(cur);
  2988. return(parent->last);
  2989. }
  2990. prev = cur;
  2991. cur = cur->next;
  2992. xmlFreeNode(prev);
  2993. }
  2994. prev = parent->last;
  2995. prev->next = cur;
  2996. cur->prev = prev;
  2997. }
  2998. while (cur->next != NULL) {
  2999. cur->parent = parent;
  3000. if (cur->doc != parent->doc) {
  3001. xmlSetTreeDoc(cur, parent->doc);
  3002. }
  3003. cur = cur->next;
  3004. }
  3005. cur->parent = parent;
  3006. /* the parent may not be linked to a doc ! */
  3007. if (cur->doc != parent->doc) {
  3008. xmlSetTreeDoc(cur, parent->doc);
  3009. }
  3010. parent->last = cur;
  3011. return(cur);
  3012. }
  3013. /**
  3014. * xmlAddChild:
  3015. * @parent: the parent node
  3016. * @cur: the child node
  3017. *
  3018. * Add a new node to @parent, at the end of the child (or property) list
  3019. * merging adjacent TEXT nodes (in which case @cur is freed)
  3020. * If the new node is ATTRIBUTE, it is added into properties instead of children.
  3021. * If there is an attribute with equal name, it is first destroyed.
  3022. *
  3023. * Returns the child or NULL in case of error.
  3024. */
  3025. xmlNodePtr
  3026. xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
  3027. xmlNodePtr prev;
  3028. if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
  3029. #ifdef DEBUG_TREE
  3030. xmlGenericError(xmlGenericErrorContext,
  3031. "xmlAddChild : parent == NULL\n");
  3032. #endif
  3033. return(NULL);
  3034. }
  3035. if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
  3036. #ifdef DEBUG_TREE
  3037. xmlGenericError(xmlGenericErrorContext,
  3038. "xmlAddChild : child == NULL\n");
  3039. #endif
  3040. return(NULL);
  3041. }
  3042. if (parent == cur) {
  3043. #ifdef DEBUG_TREE
  3044. xmlGenericError(xmlGenericErrorContext,
  3045. "xmlAddChild : parent == cur\n");
  3046. #endif
  3047. return(NULL);
  3048. }
  3049. /*
  3050. * If cur is a TEXT node, merge its content with adjacent TEXT nodes
  3051. * cur is then freed.
  3052. */
  3053. if (cur->type == XML_TEXT_NODE) {
  3054. if ((parent->type == XML_TEXT_NODE) &&
  3055. (parent->content != NULL) &&
  3056. (parent->name == cur->name)) {
  3057. xmlNodeAddContent(parent, cur->content);
  3058. xmlFreeNode(cur);
  3059. return(parent);
  3060. }
  3061. if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) &&
  3062. (parent->last->name == cur->name) &&
  3063. (parent->last != cur)) {
  3064. xmlNodeAddContent(parent->last, cur->content);
  3065. xmlFreeNode(cur);
  3066. return(parent->last);
  3067. }
  3068. }
  3069. /*
  3070. * add the new element at the end of the children list.
  3071. */
  3072. prev = cur->parent;
  3073. cur->parent = parent;
  3074. if (cur->doc != parent->doc) {
  3075. xmlSetTreeDoc(cur, parent->doc);
  3076. }
  3077. /* this check prevents a loop on tree-traversions if a developer
  3078. * tries to add a node to its parent multiple times
  3079. */
  3080. if (prev == parent)
  3081. return(cur);
  3082. /*
  3083. * Coalescing
  3084. */
  3085. if ((parent->type == XML_TEXT_NODE) &&
  3086. (parent->content != NULL) &&
  3087. (parent != cur)) {
  3088. xmlNodeAddContent(parent, cur->content);
  3089. xmlFreeNode(cur);
  3090. return(parent);
  3091. }
  3092. if (cur->type == XML_ATTRIBUTE_NODE) {
  3093. if (parent->type != XML_ELEMENT_NODE)
  3094. return(NULL);
  3095. if (parent->properties != NULL) {
  3096. /* check if an attribute with the same name exists */
  3097. xmlAttrPtr lastattr;
  3098. if (cur->ns == NULL)
  3099. lastattr = xmlHasNsProp(parent, cur->name, NULL);
  3100. else
  3101. lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href);
  3102. if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur) && (lastattr->type != XML_ATTRIBUTE_DECL)) {
  3103. /* different instance, destroy it (attributes must be unique) */
  3104. xmlUnlinkNode((xmlNodePtr) lastattr);
  3105. xmlFreeProp(lastattr);
  3106. }
  3107. if (lastattr == (xmlAttrPtr) cur)
  3108. return(cur);
  3109. }
  3110. if (parent->properties == NULL) {
  3111. parent->properties = (xmlAttrPtr) cur;
  3112. } else {
  3113. /* find the end */
  3114. xmlAttrPtr lastattr = parent->properties;
  3115. while (lastattr->next != NULL) {
  3116. lastattr = lastattr->next;
  3117. }
  3118. lastattr->next = (xmlAttrPtr) cur;
  3119. ((xmlAttrPtr) cur)->prev = lastattr;
  3120. }
  3121. } else {
  3122. if (parent->children == NULL) {
  3123. parent->children = cur;
  3124. parent->last = cur;
  3125. } else {
  3126. prev = parent->last;
  3127. prev->next = cur;
  3128. cur->prev = prev;
  3129. parent->last = cur;
  3130. }
  3131. }
  3132. return(cur);
  3133. }
  3134. /**
  3135. * xmlGetLastChild:
  3136. * @parent: the parent node
  3137. *
  3138. * Search the last child of a node.
  3139. * Returns the last child or NULL if none.
  3140. */
  3141. xmlNodePtr
  3142. xmlGetLastChild(const xmlNode *parent) {
  3143. if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
  3144. #ifdef DEBUG_TREE
  3145. xmlGenericError(xmlGenericErrorContext,
  3146. "xmlGetLastChild : parent == NULL\n");
  3147. #endif
  3148. return(NULL);
  3149. }
  3150. return(parent->last);
  3151. }
  3152. #ifdef LIBXML_TREE_ENABLED
  3153. /*
  3154. * 5 interfaces from DOM ElementTraversal
  3155. */
  3156. /**
  3157. * xmlChildElementCount:
  3158. * @parent: the parent node
  3159. *
  3160. * Finds the current number of child nodes of that element which are
  3161. * element nodes.
  3162. * Note the handling of entities references is different than in
  3163. * the W3C DOM element traversal spec since we don't have back reference
  3164. * from entities content to entities references.
  3165. *
  3166. * Returns the count of element child or 0 if not available
  3167. */
  3168. unsigned long
  3169. xmlChildElementCount(xmlNodePtr parent) {
  3170. unsigned long ret = 0;
  3171. xmlNodePtr cur = NULL;
  3172. if (parent == NULL)
  3173. return(0);
  3174. switch (parent->type) {
  3175. case XML_ELEMENT_NODE:
  3176. case XML_ENTITY_NODE:
  3177. case XML_DOCUMENT_NODE:
  3178. case XML_DOCUMENT_FRAG_NODE:
  3179. case XML_HTML_DOCUMENT_NODE:
  3180. cur = parent->children;
  3181. break;
  3182. default:
  3183. return(0);
  3184. }
  3185. while (cur != NULL) {
  3186. if (cur->type == XML_ELEMENT_NODE)
  3187. ret++;
  3188. cur = cur->next;
  3189. }
  3190. return(ret);
  3191. }
  3192. /**
  3193. * xmlFirstElementChild:
  3194. * @parent: the parent node
  3195. *
  3196. * Finds the first child node of that element which is a Element node
  3197. * Note the handling of entities references is different than in
  3198. * the W3C DOM element traversal spec since we don't have back reference
  3199. * from entities content to entities references.
  3200. *
  3201. * Returns the first element child or NULL if not available
  3202. */
  3203. xmlNodePtr
  3204. xmlFirstElementChild(xmlNodePtr parent) {
  3205. xmlNodePtr cur = NULL;
  3206. if (parent == NULL)
  3207. return(NULL);
  3208. switch (parent->type) {
  3209. case XML_ELEMENT_NODE:
  3210. case XML_ENTITY_NODE:
  3211. case XML_DOCUMENT_NODE:
  3212. case XML_DOCUMENT_FRAG_NODE:
  3213. case XML_HTML_DOCUMENT_NODE:
  3214. cur = parent->children;
  3215. break;
  3216. default:
  3217. return(NULL);
  3218. }
  3219. while (cur != NULL) {
  3220. if (cur->type == XML_ELEMENT_NODE)
  3221. return(cur);
  3222. cur = cur->next;
  3223. }
  3224. return(NULL);
  3225. }
  3226. /**
  3227. * xmlLastElementChild:
  3228. * @parent: the parent node
  3229. *
  3230. * Finds the last child node of that element which is a Element node
  3231. * Note the handling of entities references is different than in
  3232. * the W3C DOM element traversal spec since we don't have back reference
  3233. * from entities content to entities references.
  3234. *
  3235. * Returns the last element child or NULL if not available
  3236. */
  3237. xmlNodePtr
  3238. xmlLastElementChild(xmlNodePtr parent) {
  3239. xmlNodePtr cur = NULL;
  3240. if (parent == NULL)
  3241. return(NULL);
  3242. switch (parent->type) {
  3243. case XML_ELEMENT_NODE:
  3244. case XML_ENTITY_NODE:
  3245. case XML_DOCUMENT_NODE:
  3246. case XML_DOCUMENT_FRAG_NODE:
  3247. case XML_HTML_DOCUMENT_NODE:
  3248. cur = parent->last;
  3249. break;
  3250. default:
  3251. return(NULL);
  3252. }
  3253. while (cur != NULL) {
  3254. if (cur->type == XML_ELEMENT_NODE)
  3255. return(cur);
  3256. cur = cur->prev;
  3257. }
  3258. return(NULL);
  3259. }
  3260. /**
  3261. * xmlPreviousElementSibling:
  3262. * @node: the current node
  3263. *
  3264. * Finds the first closest previous sibling of the node which is an
  3265. * element node.
  3266. * Note the handling of entities references is different than in
  3267. * the W3C DOM element traversal spec since we don't have back reference
  3268. * from entities content to entities references.
  3269. *
  3270. * Returns the previous element sibling or NULL if not available
  3271. */
  3272. xmlNodePtr
  3273. xmlPreviousElementSibling(xmlNodePtr node) {
  3274. if (node == NULL)
  3275. return(NULL);
  3276. switch (node->type) {
  3277. case XML_ELEMENT_NODE:
  3278. case XML_TEXT_NODE:
  3279. case XML_CDATA_SECTION_NODE:
  3280. case XML_ENTITY_REF_NODE:
  3281. case XML_ENTITY_NODE:
  3282. case XML_PI_NODE:
  3283. case XML_COMMENT_NODE:
  3284. case XML_XINCLUDE_START:
  3285. case XML_XINCLUDE_END:
  3286. node = node->prev;
  3287. break;
  3288. default:
  3289. return(NULL);
  3290. }
  3291. while (node != NULL) {
  3292. if (node->type == XML_ELEMENT_NODE)
  3293. return(node);
  3294. node = node->prev;
  3295. }
  3296. return(NULL);
  3297. }
  3298. /**
  3299. * xmlNextElementSibling:
  3300. * @node: the current node
  3301. *
  3302. * Finds the first closest next sibling of the node which is an
  3303. * element node.
  3304. * Note the handling of entities references is different than in
  3305. * the W3C DOM element traversal spec since we don't have back reference
  3306. * from entities content to entities references.
  3307. *
  3308. * Returns the next element sibling or NULL if not available
  3309. */
  3310. xmlNodePtr
  3311. xmlNextElementSibling(xmlNodePtr node) {
  3312. if (node == NULL)
  3313. return(NULL);
  3314. switch (node->type) {
  3315. case XML_ELEMENT_NODE:
  3316. case XML_TEXT_NODE:
  3317. case XML_CDATA_SECTION_NODE:
  3318. case XML_ENTITY_REF_NODE:
  3319. case XML_ENTITY_NODE:
  3320. case XML_PI_NODE:
  3321. case XML_COMMENT_NODE:
  3322. case XML_DTD_NODE:
  3323. case XML_XINCLUDE_START:
  3324. case XML_XINCLUDE_END:
  3325. node = node->next;
  3326. break;
  3327. default:
  3328. return(NULL);
  3329. }
  3330. while (node != NULL) {
  3331. if (node->type == XML_ELEMENT_NODE)
  3332. return(node);
  3333. node = node->next;
  3334. }
  3335. return(NULL);
  3336. }
  3337. #endif /* LIBXML_TREE_ENABLED */
  3338. /**
  3339. * xmlFreeNodeList:
  3340. * @cur: the first node in the list
  3341. *
  3342. * Free a node and all its siblings, this is a recursive behaviour, all
  3343. * the children are freed too.
  3344. */
  3345. void
  3346. xmlFreeNodeList(xmlNodePtr cur) {
  3347. xmlNodePtr next;
  3348. xmlNodePtr parent;
  3349. xmlDictPtr dict = NULL;
  3350. size_t depth = 0;
  3351. if (cur == NULL) return;
  3352. if (cur->type == XML_NAMESPACE_DECL) {
  3353. xmlFreeNsList((xmlNsPtr) cur);
  3354. return;
  3355. }
  3356. if ((cur->type == XML_DOCUMENT_NODE) ||
  3357. #ifdef LIBXML_DOCB_ENABLED
  3358. (cur->type == XML_DOCB_DOCUMENT_NODE) ||
  3359. #endif
  3360. (cur->type == XML_HTML_DOCUMENT_NODE)) {
  3361. xmlFreeDoc((xmlDocPtr) cur);
  3362. return;
  3363. }
  3364. if (cur->doc != NULL) dict = cur->doc->dict;
  3365. while (1) {
  3366. while ((cur->children != NULL) &&
  3367. (cur->type != XML_DTD_NODE) &&
  3368. (cur->type != XML_ENTITY_REF_NODE)) {
  3369. cur = cur->children;
  3370. depth += 1;
  3371. }
  3372. next = cur->next;
  3373. parent = cur->parent;
  3374. if (cur->type != XML_DTD_NODE) {
  3375. if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
  3376. xmlDeregisterNodeDefaultValue(cur);
  3377. if (((cur->type == XML_ELEMENT_NODE) ||
  3378. (cur->type == XML_XINCLUDE_START) ||
  3379. (cur->type == XML_XINCLUDE_END)) &&
  3380. (cur->properties != NULL))
  3381. xmlFreePropList(cur->properties);
  3382. if ((cur->type != XML_ELEMENT_NODE) &&
  3383. (cur->type != XML_XINCLUDE_START) &&
  3384. (cur->type != XML_XINCLUDE_END) &&
  3385. (cur->type != XML_ENTITY_REF_NODE) &&
  3386. (cur->content != (xmlChar *) &(cur->properties))) {
  3387. DICT_FREE(cur->content)
  3388. }
  3389. if (((cur->type == XML_ELEMENT_NODE) ||
  3390. (cur->type == XML_XINCLUDE_START) ||
  3391. (cur->type == XML_XINCLUDE_END)) &&
  3392. (cur->nsDef != NULL))
  3393. xmlFreeNsList(cur->nsDef);
  3394. /*
  3395. * When a node is a text node or a comment, it uses a global static
  3396. * variable for the name of the node.
  3397. * Otherwise the node name might come from the document's
  3398. * dictionary
  3399. */
  3400. if ((cur->name != NULL) &&
  3401. (cur->type != XML_TEXT_NODE) &&
  3402. (cur->type != XML_COMMENT_NODE))
  3403. DICT_FREE(cur->name)
  3404. xmlFree(cur);
  3405. }
  3406. if (next != NULL) {
  3407. cur = next;
  3408. } else {
  3409. if ((depth == 0) || (parent == NULL))
  3410. break;
  3411. depth -= 1;
  3412. cur = parent;
  3413. cur->children = NULL;
  3414. }
  3415. }
  3416. }
  3417. /**
  3418. * xmlFreeNode:
  3419. * @cur: the node
  3420. *
  3421. * Free a node, this is a recursive behaviour, all the children are freed too.
  3422. * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
  3423. */
  3424. void
  3425. xmlFreeNode(xmlNodePtr cur) {
  3426. xmlDictPtr dict = NULL;
  3427. if (cur == NULL) return;
  3428. /* use xmlFreeDtd for DTD nodes */
  3429. if (cur->type == XML_DTD_NODE) {
  3430. xmlFreeDtd((xmlDtdPtr) cur);
  3431. return;
  3432. }
  3433. if (cur->type == XML_NAMESPACE_DECL) {
  3434. xmlFreeNs((xmlNsPtr) cur);
  3435. return;
  3436. }
  3437. if (cur->type == XML_ATTRIBUTE_NODE) {
  3438. xmlFreeProp((xmlAttrPtr) cur);
  3439. return;
  3440. }
  3441. if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
  3442. xmlDeregisterNodeDefaultValue(cur);
  3443. if (cur->doc != NULL) dict = cur->doc->dict;
  3444. if (cur->type == XML_ENTITY_DECL) {
  3445. xmlEntityPtr ent = (xmlEntityPtr) cur;
  3446. DICT_FREE(ent->SystemID);
  3447. DICT_FREE(ent->ExternalID);
  3448. }
  3449. if ((cur->children != NULL) &&
  3450. (cur->type != XML_ENTITY_REF_NODE))
  3451. xmlFreeNodeList(cur->children);
  3452. if (((cur->type == XML_ELEMENT_NODE) ||
  3453. (cur->type == XML_XINCLUDE_START) ||
  3454. (cur->type == XML_XINCLUDE_END)) &&
  3455. (cur->properties != NULL))
  3456. xmlFreePropList(cur->properties);
  3457. if ((cur->type != XML_ELEMENT_NODE) &&
  3458. (cur->content != NULL) &&
  3459. (cur->type != XML_ENTITY_REF_NODE) &&
  3460. (cur->type != XML_XINCLUDE_END) &&
  3461. (cur->type != XML_XINCLUDE_START) &&
  3462. (cur->content != (xmlChar *) &(cur->properties))) {
  3463. DICT_FREE(cur->content)
  3464. }
  3465. /*
  3466. * When a node is a text node or a comment, it uses a global static
  3467. * variable for the name of the node.
  3468. * Otherwise the node name might come from the document's dictionary
  3469. */
  3470. if ((cur->name != NULL) &&
  3471. (cur->type != XML_TEXT_NODE) &&
  3472. (cur->type != XML_COMMENT_NODE))
  3473. DICT_FREE(cur->name)
  3474. if (((cur->type == XML_ELEMENT_NODE) ||
  3475. (cur->type == XML_XINCLUDE_START) ||
  3476. (cur->type == XML_XINCLUDE_END)) &&
  3477. (cur->nsDef != NULL))
  3478. xmlFreeNsList(cur->nsDef);
  3479. xmlFree(cur);
  3480. }
  3481. /**
  3482. * xmlUnlinkNode:
  3483. * @cur: the node
  3484. *
  3485. * Unlink a node from it's current context, the node is not freed
  3486. * If one need to free the node, use xmlFreeNode() routine after the
  3487. * unlink to discard it.
  3488. * Note that namespace nodes can't be unlinked as they do not have
  3489. * pointer to their parent.
  3490. */
  3491. void
  3492. xmlUnlinkNode(xmlNodePtr cur) {
  3493. if (cur == NULL) {
  3494. #ifdef DEBUG_TREE
  3495. xmlGenericError(xmlGenericErrorContext,
  3496. "xmlUnlinkNode : node == NULL\n");
  3497. #endif
  3498. return;
  3499. }
  3500. if (cur->type == XML_NAMESPACE_DECL)
  3501. return;
  3502. if (cur->type == XML_DTD_NODE) {
  3503. xmlDocPtr doc;
  3504. doc = cur->doc;
  3505. if (doc != NULL) {
  3506. if (doc->intSubset == (xmlDtdPtr) cur)
  3507. doc->intSubset = NULL;
  3508. if (doc->extSubset == (xmlDtdPtr) cur)
  3509. doc->extSubset = NULL;
  3510. }
  3511. }
  3512. if (cur->type == XML_ENTITY_DECL) {
  3513. xmlDocPtr doc;
  3514. doc = cur->doc;
  3515. if (doc != NULL) {
  3516. if (doc->intSubset != NULL) {
  3517. if (xmlHashLookup(doc->intSubset->entities, cur->name) == cur)
  3518. xmlHashRemoveEntry(doc->intSubset->entities, cur->name,
  3519. NULL);
  3520. if (xmlHashLookup(doc->intSubset->pentities, cur->name) == cur)
  3521. xmlHashRemoveEntry(doc->intSubset->pentities, cur->name,
  3522. NULL);
  3523. }
  3524. if (doc->extSubset != NULL) {
  3525. if (xmlHashLookup(doc->extSubset->entities, cur->name) == cur)
  3526. xmlHashRemoveEntry(doc->extSubset->entities, cur->name,
  3527. NULL);
  3528. if (xmlHashLookup(doc->extSubset->pentities, cur->name) == cur)
  3529. xmlHashRemoveEntry(doc->extSubset->pentities, cur->name,
  3530. NULL);
  3531. }
  3532. }
  3533. }
  3534. if (cur->parent != NULL) {
  3535. xmlNodePtr parent;
  3536. parent = cur->parent;
  3537. if (cur->type == XML_ATTRIBUTE_NODE) {
  3538. if (parent->properties == (xmlAttrPtr) cur)
  3539. parent->properties = ((xmlAttrPtr) cur)->next;
  3540. } else {
  3541. if (parent->children == cur)
  3542. parent->children = cur->next;
  3543. if (parent->last == cur)
  3544. parent->last = cur->prev;
  3545. }
  3546. cur->parent = NULL;
  3547. }
  3548. if (cur->next != NULL)
  3549. cur->next->prev = cur->prev;
  3550. if (cur->prev != NULL)
  3551. cur->prev->next = cur->next;
  3552. cur->next = cur->prev = NULL;
  3553. }
  3554. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
  3555. /**
  3556. * xmlReplaceNode:
  3557. * @old: the old node
  3558. * @cur: the node
  3559. *
  3560. * Unlink the old node from its current context, prune the new one
  3561. * at the same place. If @cur was already inserted in a document it is
  3562. * first unlinked from its existing context.
  3563. *
  3564. * Returns the @old node
  3565. */
  3566. xmlNodePtr
  3567. xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
  3568. if (old == cur) return(NULL);
  3569. if ((old == NULL) || (old->type == XML_NAMESPACE_DECL) ||
  3570. (old->parent == NULL)) {
  3571. #ifdef DEBUG_TREE
  3572. xmlGenericError(xmlGenericErrorContext,
  3573. "xmlReplaceNode : old == NULL or without parent\n");
  3574. #endif
  3575. return(NULL);
  3576. }
  3577. if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
  3578. xmlUnlinkNode(old);
  3579. return(old);
  3580. }
  3581. if (cur == old) {
  3582. return(old);
  3583. }
  3584. if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) {
  3585. #ifdef DEBUG_TREE
  3586. xmlGenericError(xmlGenericErrorContext,
  3587. "xmlReplaceNode : Trying to replace attribute node with other node type\n");
  3588. #endif
  3589. return(old);
  3590. }
  3591. if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) {
  3592. #ifdef DEBUG_TREE
  3593. xmlGenericError(xmlGenericErrorContext,
  3594. "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
  3595. #endif
  3596. return(old);
  3597. }
  3598. xmlUnlinkNode(cur);
  3599. xmlSetTreeDoc(cur, old->doc);
  3600. cur->parent = old->parent;
  3601. cur->next = old->next;
  3602. if (cur->next != NULL)
  3603. cur->next->prev = cur;
  3604. cur->prev = old->prev;
  3605. if (cur->prev != NULL)
  3606. cur->prev->next = cur;
  3607. if (cur->parent != NULL) {
  3608. if (cur->type == XML_ATTRIBUTE_NODE) {
  3609. if (cur->parent->properties == (xmlAttrPtr)old)
  3610. cur->parent->properties = ((xmlAttrPtr) cur);
  3611. } else {
  3612. if (cur->parent->children == old)
  3613. cur->parent->children = cur;
  3614. if (cur->parent->last == old)
  3615. cur->parent->last = cur;
  3616. }
  3617. }
  3618. old->next = old->prev = NULL;
  3619. old->parent = NULL;
  3620. return(old);
  3621. }
  3622. #endif /* LIBXML_TREE_ENABLED */
  3623. /************************************************************************
  3624. * *
  3625. * Copy operations *
  3626. * *
  3627. ************************************************************************/
  3628. /**
  3629. * xmlCopyNamespace:
  3630. * @cur: the namespace
  3631. *
  3632. * Do a copy of the namespace.
  3633. *
  3634. * Returns: a new #xmlNsPtr, or NULL in case of error.
  3635. */
  3636. xmlNsPtr
  3637. xmlCopyNamespace(xmlNsPtr cur) {
  3638. xmlNsPtr ret;
  3639. if (cur == NULL) return(NULL);
  3640. switch (cur->type) {
  3641. case XML_LOCAL_NAMESPACE:
  3642. ret = xmlNewNs(NULL, cur->href, cur->prefix);
  3643. break;
  3644. default:
  3645. #ifdef DEBUG_TREE
  3646. xmlGenericError(xmlGenericErrorContext,
  3647. "xmlCopyNamespace: invalid type %d\n", cur->type);
  3648. #endif
  3649. return(NULL);
  3650. }
  3651. return(ret);
  3652. }
  3653. /**
  3654. * xmlCopyNamespaceList:
  3655. * @cur: the first namespace
  3656. *
  3657. * Do a copy of an namespace list.
  3658. *
  3659. * Returns: a new #xmlNsPtr, or NULL in case of error.
  3660. */
  3661. xmlNsPtr
  3662. xmlCopyNamespaceList(xmlNsPtr cur) {
  3663. xmlNsPtr ret = NULL;
  3664. xmlNsPtr p = NULL,q;
  3665. while (cur != NULL) {
  3666. q = xmlCopyNamespace(cur);
  3667. if (p == NULL) {
  3668. ret = p = q;
  3669. } else {
  3670. p->next = q;
  3671. p = q;
  3672. }
  3673. cur = cur->next;
  3674. }
  3675. return(ret);
  3676. }
  3677. static xmlNodePtr
  3678. xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
  3679. static xmlAttrPtr
  3680. xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
  3681. xmlAttrPtr ret;
  3682. if (cur == NULL) return(NULL);
  3683. if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
  3684. return(NULL);
  3685. if (target != NULL)
  3686. ret = xmlNewDocProp(target->doc, cur->name, NULL);
  3687. else if (doc != NULL)
  3688. ret = xmlNewDocProp(doc, cur->name, NULL);
  3689. else if (cur->parent != NULL)
  3690. ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);
  3691. else if (cur->children != NULL)
  3692. ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);
  3693. else
  3694. ret = xmlNewDocProp(NULL, cur->name, NULL);
  3695. if (ret == NULL) return(NULL);
  3696. ret->parent = target;
  3697. if ((cur->ns != NULL) && (target != NULL)) {
  3698. xmlNsPtr ns;
  3699. ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
  3700. if (ns == NULL) {
  3701. /*
  3702. * Humm, we are copying an element whose namespace is defined
  3703. * out of the new tree scope. Search it in the original tree
  3704. * and add it at the top of the new tree
  3705. */
  3706. ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix);
  3707. if (ns != NULL) {
  3708. xmlNodePtr root = target;
  3709. xmlNodePtr pred = NULL;
  3710. while (root->parent != NULL) {
  3711. pred = root;
  3712. root = root->parent;
  3713. }
  3714. if (root == (xmlNodePtr) target->doc) {
  3715. /* correct possibly cycling above the document elt */
  3716. root = pred;
  3717. }
  3718. ret->ns = xmlNewNs(root, ns->href, ns->prefix);
  3719. }
  3720. } else {
  3721. /*
  3722. * we have to find something appropriate here since
  3723. * we cant be sure, that the namespace we found is identified
  3724. * by the prefix
  3725. */
  3726. if (xmlStrEqual(ns->href, cur->ns->href)) {
  3727. /* this is the nice case */
  3728. ret->ns = ns;
  3729. } else {
  3730. /*
  3731. * we are in trouble: we need a new reconciled namespace.
  3732. * This is expensive
  3733. */
  3734. ret->ns = xmlNewReconciledNs(target->doc, target, cur->ns);
  3735. }
  3736. }
  3737. } else
  3738. ret->ns = NULL;
  3739. if (cur->children != NULL) {
  3740. xmlNodePtr tmp;
  3741. ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret);
  3742. ret->last = NULL;
  3743. tmp = ret->children;
  3744. while (tmp != NULL) {
  3745. /* tmp->parent = (xmlNodePtr)ret; */
  3746. if (tmp->next == NULL)
  3747. ret->last = tmp;
  3748. tmp = tmp->next;
  3749. }
  3750. }
  3751. /*
  3752. * Try to handle IDs
  3753. */
  3754. if ((target!= NULL) && (cur!= NULL) &&
  3755. (target->doc != NULL) && (cur->doc != NULL) &&
  3756. (cur->doc->ids != NULL) && (cur->parent != NULL)) {
  3757. if (xmlIsID(cur->doc, cur->parent, cur)) {
  3758. xmlChar *id;
  3759. id = xmlNodeListGetString(cur->doc, cur->children, 1);
  3760. if (id != NULL) {
  3761. xmlAddID(NULL, target->doc, id, ret);
  3762. xmlFree(id);
  3763. }
  3764. }
  3765. }
  3766. return(ret);
  3767. }
  3768. /**
  3769. * xmlCopyProp:
  3770. * @target: the element where the attribute will be grafted
  3771. * @cur: the attribute
  3772. *
  3773. * Do a copy of the attribute.
  3774. *
  3775. * Returns: a new #xmlAttrPtr, or NULL in case of error.
  3776. */
  3777. xmlAttrPtr
  3778. xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
  3779. return xmlCopyPropInternal(NULL, target, cur);
  3780. }
  3781. /**
  3782. * xmlCopyPropList:
  3783. * @target: the element where the attributes will be grafted
  3784. * @cur: the first attribute
  3785. *
  3786. * Do a copy of an attribute list.
  3787. *
  3788. * Returns: a new #xmlAttrPtr, or NULL in case of error.
  3789. */
  3790. xmlAttrPtr
  3791. xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
  3792. xmlAttrPtr ret = NULL;
  3793. xmlAttrPtr p = NULL,q;
  3794. if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
  3795. return(NULL);
  3796. while (cur != NULL) {
  3797. q = xmlCopyProp(target, cur);
  3798. if (q == NULL)
  3799. return(NULL);
  3800. if (p == NULL) {
  3801. ret = p = q;
  3802. } else {
  3803. p->next = q;
  3804. q->prev = p;
  3805. p = q;
  3806. }
  3807. cur = cur->next;
  3808. }
  3809. return(ret);
  3810. }
  3811. /*
  3812. * NOTE about the CopyNode operations !
  3813. *
  3814. * They are split into external and internal parts for one
  3815. * tricky reason: namespaces. Doing a direct copy of a node
  3816. * say RPM:Copyright without changing the namespace pointer to
  3817. * something else can produce stale links. One way to do it is
  3818. * to keep a reference counter but this doesn't work as soon
  3819. * as one moves the element or the subtree out of the scope of
  3820. * the existing namespace. The actual solution seems to be to add
  3821. * a copy of the namespace at the top of the copied tree if
  3822. * not available in the subtree.
  3823. * Hence two functions, the public front-end call the inner ones
  3824. * The argument "recursive" normally indicates a recursive copy
  3825. * of the node with values 0 (no) and 1 (yes). For XInclude,
  3826. * however, we allow a value of 2 to indicate copy properties and
  3827. * namespace info, but don't recurse on children.
  3828. */
  3829. static xmlNodePtr
  3830. xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
  3831. int extended) {
  3832. xmlNodePtr ret;
  3833. if (node == NULL) return(NULL);
  3834. switch (node->type) {
  3835. case XML_TEXT_NODE:
  3836. case XML_CDATA_SECTION_NODE:
  3837. case XML_ELEMENT_NODE:
  3838. case XML_DOCUMENT_FRAG_NODE:
  3839. case XML_ENTITY_REF_NODE:
  3840. case XML_ENTITY_NODE:
  3841. case XML_PI_NODE:
  3842. case XML_COMMENT_NODE:
  3843. case XML_XINCLUDE_START:
  3844. case XML_XINCLUDE_END:
  3845. break;
  3846. case XML_ATTRIBUTE_NODE:
  3847. return((xmlNodePtr) xmlCopyPropInternal(doc, parent, (xmlAttrPtr) node));
  3848. case XML_NAMESPACE_DECL:
  3849. return((xmlNodePtr) xmlCopyNamespaceList((xmlNsPtr) node));
  3850. case XML_DOCUMENT_NODE:
  3851. case XML_HTML_DOCUMENT_NODE:
  3852. #ifdef LIBXML_DOCB_ENABLED
  3853. case XML_DOCB_DOCUMENT_NODE:
  3854. #endif
  3855. #ifdef LIBXML_TREE_ENABLED
  3856. return((xmlNodePtr) xmlCopyDoc((xmlDocPtr) node, extended));
  3857. #endif /* LIBXML_TREE_ENABLED */
  3858. case XML_DOCUMENT_TYPE_NODE:
  3859. case XML_NOTATION_NODE:
  3860. case XML_DTD_NODE:
  3861. case XML_ELEMENT_DECL:
  3862. case XML_ATTRIBUTE_DECL:
  3863. case XML_ENTITY_DECL:
  3864. return(NULL);
  3865. }
  3866. /*
  3867. * Allocate a new node and fill the fields.
  3868. */
  3869. ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  3870. if (ret == NULL) {
  3871. xmlTreeErrMemory("copying node");
  3872. return(NULL);
  3873. }
  3874. memset(ret, 0, sizeof(xmlNode));
  3875. ret->type = node->type;
  3876. ret->doc = doc;
  3877. ret->parent = parent;
  3878. if (node->name == xmlStringText)
  3879. ret->name = xmlStringText;
  3880. else if (node->name == xmlStringTextNoenc)
  3881. ret->name = xmlStringTextNoenc;
  3882. else if (node->name == xmlStringComment)
  3883. ret->name = xmlStringComment;
  3884. else if (node->name != NULL) {
  3885. if ((doc != NULL) && (doc->dict != NULL))
  3886. ret->name = xmlDictLookup(doc->dict, node->name, -1);
  3887. else
  3888. ret->name = xmlStrdup(node->name);
  3889. }
  3890. if ((node->type != XML_ELEMENT_NODE) &&
  3891. (node->content != NULL) &&
  3892. (node->type != XML_ENTITY_REF_NODE) &&
  3893. (node->type != XML_XINCLUDE_END) &&
  3894. (node->type != XML_XINCLUDE_START)) {
  3895. ret->content = xmlStrdup(node->content);
  3896. }else{
  3897. if (node->type == XML_ELEMENT_NODE)
  3898. ret->line = node->line;
  3899. }
  3900. if (parent != NULL) {
  3901. xmlNodePtr tmp;
  3902. /*
  3903. * this is a tricky part for the node register thing:
  3904. * in case ret does get coalesced in xmlAddChild
  3905. * the deregister-node callback is called; so we register ret now already
  3906. */
  3907. if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
  3908. xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
  3909. tmp = xmlAddChild(parent, ret);
  3910. /* node could have coalesced */
  3911. if (tmp != ret)
  3912. return(tmp);
  3913. }
  3914. if (!extended)
  3915. goto out;
  3916. if (((node->type == XML_ELEMENT_NODE) ||
  3917. (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL))
  3918. ret->nsDef = xmlCopyNamespaceList(node->nsDef);
  3919. if (node->ns != NULL) {
  3920. xmlNsPtr ns;
  3921. ns = xmlSearchNs(doc, ret, node->ns->prefix);
  3922. if (ns == NULL) {
  3923. /*
  3924. * Humm, we are copying an element whose namespace is defined
  3925. * out of the new tree scope. Search it in the original tree
  3926. * and add it at the top of the new tree
  3927. */
  3928. ns = xmlSearchNs(node->doc, node, node->ns->prefix);
  3929. if (ns != NULL) {
  3930. xmlNodePtr root = ret;
  3931. while (root->parent != NULL) root = root->parent;
  3932. ret->ns = xmlNewNs(root, ns->href, ns->prefix);
  3933. } else {
  3934. ret->ns = xmlNewReconciledNs(doc, ret, node->ns);
  3935. }
  3936. } else {
  3937. /*
  3938. * reference the existing namespace definition in our own tree.
  3939. */
  3940. ret->ns = ns;
  3941. }
  3942. }
  3943. if (((node->type == XML_ELEMENT_NODE) ||
  3944. (node->type == XML_XINCLUDE_START)) && (node->properties != NULL))
  3945. ret->properties = xmlCopyPropList(ret, node->properties);
  3946. if (node->type == XML_ENTITY_REF_NODE) {
  3947. if ((doc == NULL) || (node->doc != doc)) {
  3948. /*
  3949. * The copied node will go into a separate document, so
  3950. * to avoid dangling references to the ENTITY_DECL node
  3951. * we cannot keep the reference. Try to find it in the
  3952. * target document.
  3953. */
  3954. ret->children = (xmlNodePtr) xmlGetDocEntity(doc, ret->name);
  3955. } else {
  3956. ret->children = node->children;
  3957. }
  3958. ret->last = ret->children;
  3959. } else if ((node->children != NULL) && (extended != 2)) {
  3960. ret->children = xmlStaticCopyNodeList(node->children, doc, ret);
  3961. UPDATE_LAST_CHILD_AND_PARENT(ret)
  3962. }
  3963. out:
  3964. /* if parent != NULL we already registered the node above */
  3965. if ((parent == NULL) &&
  3966. ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)))
  3967. xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
  3968. return(ret);
  3969. }
  3970. static xmlNodePtr
  3971. xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
  3972. xmlNodePtr ret = NULL;
  3973. xmlNodePtr p = NULL,q;
  3974. while (node != NULL) {
  3975. #ifdef LIBXML_TREE_ENABLED
  3976. if (node->type == XML_DTD_NODE ) {
  3977. if (doc == NULL) {
  3978. node = node->next;
  3979. continue;
  3980. }
  3981. if (doc->intSubset == NULL) {
  3982. q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
  3983. if (q == NULL) return(NULL);
  3984. q->doc = doc;
  3985. q->parent = parent;
  3986. doc->intSubset = (xmlDtdPtr) q;
  3987. xmlAddChild(parent, q);
  3988. } else {
  3989. q = (xmlNodePtr) doc->intSubset;
  3990. xmlAddChild(parent, q);
  3991. }
  3992. } else
  3993. #endif /* LIBXML_TREE_ENABLED */
  3994. q = xmlStaticCopyNode(node, doc, parent, 1);
  3995. if (q == NULL) return(NULL);
  3996. if (ret == NULL) {
  3997. q->prev = NULL;
  3998. ret = p = q;
  3999. } else if (p != q) {
  4000. /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
  4001. p->next = q;
  4002. q->prev = p;
  4003. p = q;
  4004. }
  4005. node = node->next;
  4006. }
  4007. return(ret);
  4008. }
  4009. /**
  4010. * xmlCopyNode:
  4011. * @node: the node
  4012. * @extended: if 1 do a recursive copy (properties, namespaces and children
  4013. * when applicable)
  4014. * if 2 copy properties and namespaces (when applicable)
  4015. *
  4016. * Do a copy of the node.
  4017. *
  4018. * Returns: a new #xmlNodePtr, or NULL in case of error.
  4019. */
  4020. xmlNodePtr
  4021. xmlCopyNode(xmlNodePtr node, int extended) {
  4022. xmlNodePtr ret;
  4023. ret = xmlStaticCopyNode(node, NULL, NULL, extended);
  4024. return(ret);
  4025. }
  4026. /**
  4027. * xmlDocCopyNode:
  4028. * @node: the node
  4029. * @doc: the document
  4030. * @extended: if 1 do a recursive copy (properties, namespaces and children
  4031. * when applicable)
  4032. * if 2 copy properties and namespaces (when applicable)
  4033. *
  4034. * Do a copy of the node to a given document.
  4035. *
  4036. * Returns: a new #xmlNodePtr, or NULL in case of error.
  4037. */
  4038. xmlNodePtr
  4039. xmlDocCopyNode(xmlNodePtr node, xmlDocPtr doc, int extended) {
  4040. xmlNodePtr ret;
  4041. ret = xmlStaticCopyNode(node, doc, NULL, extended);
  4042. return(ret);
  4043. }
  4044. /**
  4045. * xmlDocCopyNodeList:
  4046. * @doc: the target document
  4047. * @node: the first node in the list.
  4048. *
  4049. * Do a recursive copy of the node list.
  4050. *
  4051. * Returns: a new #xmlNodePtr, or NULL in case of error.
  4052. */
  4053. xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, xmlNodePtr node) {
  4054. xmlNodePtr ret = xmlStaticCopyNodeList(node, doc, NULL);
  4055. return(ret);
  4056. }
  4057. /**
  4058. * xmlCopyNodeList:
  4059. * @node: the first node in the list.
  4060. *
  4061. * Do a recursive copy of the node list.
  4062. * Use xmlDocCopyNodeList() if possible to ensure string interning.
  4063. *
  4064. * Returns: a new #xmlNodePtr, or NULL in case of error.
  4065. */
  4066. xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
  4067. xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
  4068. return(ret);
  4069. }
  4070. #if defined(LIBXML_TREE_ENABLED)
  4071. /**
  4072. * xmlCopyDtd:
  4073. * @dtd: the dtd
  4074. *
  4075. * Do a copy of the dtd.
  4076. *
  4077. * Returns: a new #xmlDtdPtr, or NULL in case of error.
  4078. */
  4079. xmlDtdPtr
  4080. xmlCopyDtd(xmlDtdPtr dtd) {
  4081. xmlDtdPtr ret;
  4082. xmlNodePtr cur, p = NULL, q;
  4083. if (dtd == NULL) return(NULL);
  4084. ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
  4085. if (ret == NULL) return(NULL);
  4086. if (dtd->entities != NULL)
  4087. ret->entities = (void *) xmlCopyEntitiesTable(
  4088. (xmlEntitiesTablePtr) dtd->entities);
  4089. if (dtd->notations != NULL)
  4090. ret->notations = (void *) xmlCopyNotationTable(
  4091. (xmlNotationTablePtr) dtd->notations);
  4092. if (dtd->elements != NULL)
  4093. ret->elements = (void *) xmlCopyElementTable(
  4094. (xmlElementTablePtr) dtd->elements);
  4095. if (dtd->attributes != NULL)
  4096. ret->attributes = (void *) xmlCopyAttributeTable(
  4097. (xmlAttributeTablePtr) dtd->attributes);
  4098. if (dtd->pentities != NULL)
  4099. ret->pentities = (void *) xmlCopyEntitiesTable(
  4100. (xmlEntitiesTablePtr) dtd->pentities);
  4101. cur = dtd->children;
  4102. while (cur != NULL) {
  4103. q = NULL;
  4104. if (cur->type == XML_ENTITY_DECL) {
  4105. xmlEntityPtr tmp = (xmlEntityPtr) cur;
  4106. switch (tmp->etype) {
  4107. case XML_INTERNAL_GENERAL_ENTITY:
  4108. case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
  4109. case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
  4110. q = (xmlNodePtr) xmlGetEntityFromDtd(ret, tmp->name);
  4111. break;
  4112. case XML_INTERNAL_PARAMETER_ENTITY:
  4113. case XML_EXTERNAL_PARAMETER_ENTITY:
  4114. q = (xmlNodePtr)
  4115. xmlGetParameterEntityFromDtd(ret, tmp->name);
  4116. break;
  4117. case XML_INTERNAL_PREDEFINED_ENTITY:
  4118. break;
  4119. }
  4120. } else if (cur->type == XML_ELEMENT_DECL) {
  4121. xmlElementPtr tmp = (xmlElementPtr) cur;
  4122. q = (xmlNodePtr)
  4123. xmlGetDtdQElementDesc(ret, tmp->name, tmp->prefix);
  4124. } else if (cur->type == XML_ATTRIBUTE_DECL) {
  4125. xmlAttributePtr tmp = (xmlAttributePtr) cur;
  4126. q = (xmlNodePtr)
  4127. xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix);
  4128. } else if (cur->type == XML_COMMENT_NODE) {
  4129. q = xmlCopyNode(cur, 0);
  4130. }
  4131. if (q == NULL) {
  4132. cur = cur->next;
  4133. continue;
  4134. }
  4135. if (p == NULL)
  4136. ret->children = q;
  4137. else
  4138. p->next = q;
  4139. q->prev = p;
  4140. q->parent = (xmlNodePtr) ret;
  4141. q->next = NULL;
  4142. ret->last = q;
  4143. p = q;
  4144. cur = cur->next;
  4145. }
  4146. return(ret);
  4147. }
  4148. #endif
  4149. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
  4150. /**
  4151. * xmlCopyDoc:
  4152. * @doc: the document
  4153. * @recursive: if not zero do a recursive copy.
  4154. *
  4155. * Do a copy of the document info. If recursive, the content tree will
  4156. * be copied too as well as DTD, namespaces and entities.
  4157. *
  4158. * Returns: a new #xmlDocPtr, or NULL in case of error.
  4159. */
  4160. xmlDocPtr
  4161. xmlCopyDoc(xmlDocPtr doc, int recursive) {
  4162. xmlDocPtr ret;
  4163. if (doc == NULL) return(NULL);
  4164. ret = xmlNewDoc(doc->version);
  4165. if (ret == NULL) return(NULL);
  4166. if (doc->name != NULL)
  4167. ret->name = xmlMemStrdup(doc->name);
  4168. if (doc->encoding != NULL)
  4169. ret->encoding = xmlStrdup(doc->encoding);
  4170. if (doc->URL != NULL)
  4171. ret->URL = xmlStrdup(doc->URL);
  4172. ret->charset = doc->charset;
  4173. ret->compression = doc->compression;
  4174. ret->standalone = doc->standalone;
  4175. if (!recursive) return(ret);
  4176. ret->last = NULL;
  4177. ret->children = NULL;
  4178. #ifdef LIBXML_TREE_ENABLED
  4179. if (doc->intSubset != NULL) {
  4180. ret->intSubset = xmlCopyDtd(doc->intSubset);
  4181. if (ret->intSubset == NULL) {
  4182. xmlFreeDoc(ret);
  4183. return(NULL);
  4184. }
  4185. xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret);
  4186. ret->intSubset->parent = ret;
  4187. }
  4188. #endif
  4189. if (doc->oldNs != NULL)
  4190. ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
  4191. if (doc->children != NULL) {
  4192. xmlNodePtr tmp;
  4193. ret->children = xmlStaticCopyNodeList(doc->children, ret,
  4194. (xmlNodePtr)ret);
  4195. ret->last = NULL;
  4196. tmp = ret->children;
  4197. while (tmp != NULL) {
  4198. if (tmp->next == NULL)
  4199. ret->last = tmp;
  4200. tmp = tmp->next;
  4201. }
  4202. }
  4203. return(ret);
  4204. }
  4205. #endif /* LIBXML_TREE_ENABLED */
  4206. /************************************************************************
  4207. * *
  4208. * Content access functions *
  4209. * *
  4210. ************************************************************************/
  4211. /**
  4212. * xmlGetLineNoInternal:
  4213. * @node: valid node
  4214. * @depth: used to limit any risk of recursion
  4215. *
  4216. * Get line number of @node.
  4217. * Try to override the limitation of lines being store in 16 bits ints
  4218. *
  4219. * Returns the line number if successful, -1 otherwise
  4220. */
  4221. static long
  4222. xmlGetLineNoInternal(const xmlNode *node, int depth)
  4223. {
  4224. long result = -1;
  4225. if (depth >= 5)
  4226. return(-1);
  4227. if (!node)
  4228. return result;
  4229. if ((node->type == XML_ELEMENT_NODE) ||
  4230. (node->type == XML_TEXT_NODE) ||
  4231. (node->type == XML_COMMENT_NODE) ||
  4232. (node->type == XML_PI_NODE)) {
  4233. if (node->line == 65535) {
  4234. if ((node->type == XML_TEXT_NODE) && (node->psvi != NULL))
  4235. result = (long) (ptrdiff_t) node->psvi;
  4236. else if ((node->type == XML_ELEMENT_NODE) &&
  4237. (node->children != NULL))
  4238. result = xmlGetLineNoInternal(node->children, depth + 1);
  4239. else if (node->next != NULL)
  4240. result = xmlGetLineNoInternal(node->next, depth + 1);
  4241. else if (node->prev != NULL)
  4242. result = xmlGetLineNoInternal(node->prev, depth + 1);
  4243. }
  4244. if ((result == -1) || (result == 65535))
  4245. result = (long) node->line;
  4246. } else if ((node->prev != NULL) &&
  4247. ((node->prev->type == XML_ELEMENT_NODE) ||
  4248. (node->prev->type == XML_TEXT_NODE) ||
  4249. (node->prev->type == XML_COMMENT_NODE) ||
  4250. (node->prev->type == XML_PI_NODE)))
  4251. result = xmlGetLineNoInternal(node->prev, depth + 1);
  4252. else if ((node->parent != NULL) &&
  4253. (node->parent->type == XML_ELEMENT_NODE))
  4254. result = xmlGetLineNoInternal(node->parent, depth + 1);
  4255. return result;
  4256. }
  4257. /**
  4258. * xmlGetLineNo:
  4259. * @node: valid node
  4260. *
  4261. * Get line number of @node.
  4262. * Try to override the limitation of lines being store in 16 bits ints
  4263. * if XML_PARSE_BIG_LINES parser option was used
  4264. *
  4265. * Returns the line number if successful, -1 otherwise
  4266. */
  4267. long
  4268. xmlGetLineNo(const xmlNode *node)
  4269. {
  4270. return(xmlGetLineNoInternal(node, 0));
  4271. }
  4272. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
  4273. /**
  4274. * xmlGetNodePath:
  4275. * @node: a node
  4276. *
  4277. * Build a structure based Path for the given node
  4278. *
  4279. * Returns the new path or NULL in case of error. The caller must free
  4280. * the returned string
  4281. */
  4282. xmlChar *
  4283. xmlGetNodePath(const xmlNode *node)
  4284. {
  4285. const xmlNode *cur, *tmp, *next;
  4286. xmlChar *buffer = NULL, *temp;
  4287. size_t buf_len;
  4288. xmlChar *buf;
  4289. const char *sep;
  4290. const char *name;
  4291. char nametemp[100];
  4292. int occur = 0, generic;
  4293. if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
  4294. return (NULL);
  4295. buf_len = 500;
  4296. buffer = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar));
  4297. if (buffer == NULL) {
  4298. xmlTreeErrMemory("getting node path");
  4299. return (NULL);
  4300. }
  4301. buf = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar));
  4302. if (buf == NULL) {
  4303. xmlTreeErrMemory("getting node path");
  4304. xmlFree(buffer);
  4305. return (NULL);
  4306. }
  4307. buffer[0] = 0;
  4308. cur = node;
  4309. do {
  4310. name = "";
  4311. sep = "?";
  4312. occur = 0;
  4313. if ((cur->type == XML_DOCUMENT_NODE) ||
  4314. (cur->type == XML_HTML_DOCUMENT_NODE)) {
  4315. if (buffer[0] == '/')
  4316. break;
  4317. sep = "/";
  4318. next = NULL;
  4319. } else if (cur->type == XML_ELEMENT_NODE) {
  4320. generic = 0;
  4321. sep = "/";
  4322. name = (const char *) cur->name;
  4323. if (cur->ns) {
  4324. if (cur->ns->prefix != NULL) {
  4325. snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
  4326. (char *)cur->ns->prefix, (char *)cur->name);
  4327. nametemp[sizeof(nametemp) - 1] = 0;
  4328. name = nametemp;
  4329. } else {
  4330. /*
  4331. * We cannot express named elements in the default
  4332. * namespace, so use "*".
  4333. */
  4334. generic = 1;
  4335. name = "*";
  4336. }
  4337. }
  4338. next = cur->parent;
  4339. /*
  4340. * Thumbler index computation
  4341. * TODO: the occurrence test seems bogus for namespaced names
  4342. */
  4343. tmp = cur->prev;
  4344. while (tmp != NULL) {
  4345. if ((tmp->type == XML_ELEMENT_NODE) &&
  4346. (generic ||
  4347. (xmlStrEqual(cur->name, tmp->name) &&
  4348. ((tmp->ns == cur->ns) ||
  4349. ((tmp->ns != NULL) && (cur->ns != NULL) &&
  4350. (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
  4351. occur++;
  4352. tmp = tmp->prev;
  4353. }
  4354. if (occur == 0) {
  4355. tmp = cur->next;
  4356. while (tmp != NULL && occur == 0) {
  4357. if ((tmp->type == XML_ELEMENT_NODE) &&
  4358. (generic ||
  4359. (xmlStrEqual(cur->name, tmp->name) &&
  4360. ((tmp->ns == cur->ns) ||
  4361. ((tmp->ns != NULL) && (cur->ns != NULL) &&
  4362. (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
  4363. occur++;
  4364. tmp = tmp->next;
  4365. }
  4366. if (occur != 0)
  4367. occur = 1;
  4368. } else
  4369. occur++;
  4370. } else if (cur->type == XML_COMMENT_NODE) {
  4371. sep = "/";
  4372. name = "comment()";
  4373. next = cur->parent;
  4374. /*
  4375. * Thumbler index computation
  4376. */
  4377. tmp = cur->prev;
  4378. while (tmp != NULL) {
  4379. if (tmp->type == XML_COMMENT_NODE)
  4380. occur++;
  4381. tmp = tmp->prev;
  4382. }
  4383. if (occur == 0) {
  4384. tmp = cur->next;
  4385. while (tmp != NULL && occur == 0) {
  4386. if (tmp->type == XML_COMMENT_NODE)
  4387. occur++;
  4388. tmp = tmp->next;
  4389. }
  4390. if (occur != 0)
  4391. occur = 1;
  4392. } else
  4393. occur++;
  4394. } else if ((cur->type == XML_TEXT_NODE) ||
  4395. (cur->type == XML_CDATA_SECTION_NODE)) {
  4396. sep = "/";
  4397. name = "text()";
  4398. next = cur->parent;
  4399. /*
  4400. * Thumbler index computation
  4401. */
  4402. tmp = cur->prev;
  4403. while (tmp != NULL) {
  4404. if ((tmp->type == XML_TEXT_NODE) ||
  4405. (tmp->type == XML_CDATA_SECTION_NODE))
  4406. occur++;
  4407. tmp = tmp->prev;
  4408. }
  4409. /*
  4410. * Evaluate if this is the only text- or CDATA-section-node;
  4411. * if yes, then we'll get "text()", otherwise "text()[1]".
  4412. */
  4413. if (occur == 0) {
  4414. tmp = cur->next;
  4415. while (tmp != NULL) {
  4416. if ((tmp->type == XML_TEXT_NODE) ||
  4417. (tmp->type == XML_CDATA_SECTION_NODE))
  4418. {
  4419. occur = 1;
  4420. break;
  4421. }
  4422. tmp = tmp->next;
  4423. }
  4424. } else
  4425. occur++;
  4426. } else if (cur->type == XML_PI_NODE) {
  4427. sep = "/";
  4428. snprintf(nametemp, sizeof(nametemp) - 1,
  4429. "processing-instruction('%s')", (char *)cur->name);
  4430. nametemp[sizeof(nametemp) - 1] = 0;
  4431. name = nametemp;
  4432. next = cur->parent;
  4433. /*
  4434. * Thumbler index computation
  4435. */
  4436. tmp = cur->prev;
  4437. while (tmp != NULL) {
  4438. if ((tmp->type == XML_PI_NODE) &&
  4439. (xmlStrEqual(cur->name, tmp->name)))
  4440. occur++;
  4441. tmp = tmp->prev;
  4442. }
  4443. if (occur == 0) {
  4444. tmp = cur->next;
  4445. while (tmp != NULL && occur == 0) {
  4446. if ((tmp->type == XML_PI_NODE) &&
  4447. (xmlStrEqual(cur->name, tmp->name)))
  4448. occur++;
  4449. tmp = tmp->next;
  4450. }
  4451. if (occur != 0)
  4452. occur = 1;
  4453. } else
  4454. occur++;
  4455. } else if (cur->type == XML_ATTRIBUTE_NODE) {
  4456. sep = "/@";
  4457. name = (const char *) (((xmlAttrPtr) cur)->name);
  4458. if (cur->ns) {
  4459. if (cur->ns->prefix != NULL)
  4460. snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
  4461. (char *)cur->ns->prefix, (char *)cur->name);
  4462. else
  4463. snprintf(nametemp, sizeof(nametemp) - 1, "%s",
  4464. (char *)cur->name);
  4465. nametemp[sizeof(nametemp) - 1] = 0;
  4466. name = nametemp;
  4467. }
  4468. next = ((xmlAttrPtr) cur)->parent;
  4469. } else {
  4470. next = cur->parent;
  4471. }
  4472. /*
  4473. * Make sure there is enough room
  4474. */
  4475. if (xmlStrlen(buffer) + sizeof(nametemp) + 20 > buf_len) {
  4476. buf_len =
  4477. 2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20;
  4478. temp = (xmlChar *) xmlRealloc(buffer, buf_len);
  4479. if (temp == NULL) {
  4480. xmlTreeErrMemory("getting node path");
  4481. xmlFree(buf);
  4482. xmlFree(buffer);
  4483. return (NULL);
  4484. }
  4485. buffer = temp;
  4486. temp = (xmlChar *) xmlRealloc(buf, buf_len);
  4487. if (temp == NULL) {
  4488. xmlTreeErrMemory("getting node path");
  4489. xmlFree(buf);
  4490. xmlFree(buffer);
  4491. return (NULL);
  4492. }
  4493. buf = temp;
  4494. }
  4495. if (occur == 0)
  4496. snprintf((char *) buf, buf_len, "%s%s%s",
  4497. sep, name, (char *) buffer);
  4498. else
  4499. snprintf((char *) buf, buf_len, "%s%s[%d]%s",
  4500. sep, name, occur, (char *) buffer);
  4501. snprintf((char *) buffer, buf_len, "%s", (char *)buf);
  4502. cur = next;
  4503. } while (cur != NULL);
  4504. xmlFree(buf);
  4505. return (buffer);
  4506. }
  4507. #endif /* LIBXML_TREE_ENABLED */
  4508. /**
  4509. * xmlDocGetRootElement:
  4510. * @doc: the document
  4511. *
  4512. * Get the root element of the document (doc->children is a list
  4513. * containing possibly comments, PIs, etc ...).
  4514. *
  4515. * Returns the #xmlNodePtr for the root or NULL
  4516. */
  4517. xmlNodePtr
  4518. xmlDocGetRootElement(const xmlDoc *doc) {
  4519. xmlNodePtr ret;
  4520. if (doc == NULL) return(NULL);
  4521. ret = doc->children;
  4522. while (ret != NULL) {
  4523. if (ret->type == XML_ELEMENT_NODE)
  4524. return(ret);
  4525. ret = ret->next;
  4526. }
  4527. return(ret);
  4528. }
  4529. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
  4530. /**
  4531. * xmlDocSetRootElement:
  4532. * @doc: the document
  4533. * @root: the new document root element, if root is NULL no action is taken,
  4534. * to remove a node from a document use xmlUnlinkNode(root) instead.
  4535. *
  4536. * Set the root element of the document (doc->children is a list
  4537. * containing possibly comments, PIs, etc ...).
  4538. *
  4539. * Returns the old root element if any was found, NULL if root was NULL
  4540. */
  4541. xmlNodePtr
  4542. xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
  4543. xmlNodePtr old = NULL;
  4544. if (doc == NULL) return(NULL);
  4545. if ((root == NULL) || (root->type == XML_NAMESPACE_DECL))
  4546. return(NULL);
  4547. xmlUnlinkNode(root);
  4548. xmlSetTreeDoc(root, doc);
  4549. root->parent = (xmlNodePtr) doc;
  4550. old = doc->children;
  4551. while (old != NULL) {
  4552. if (old->type == XML_ELEMENT_NODE)
  4553. break;
  4554. old = old->next;
  4555. }
  4556. if (old == NULL) {
  4557. if (doc->children == NULL) {
  4558. doc->children = root;
  4559. doc->last = root;
  4560. } else {
  4561. xmlAddSibling(doc->children, root);
  4562. }
  4563. } else {
  4564. xmlReplaceNode(old, root);
  4565. }
  4566. return(old);
  4567. }
  4568. #endif
  4569. #if defined(LIBXML_TREE_ENABLED)
  4570. /**
  4571. * xmlNodeSetLang:
  4572. * @cur: the node being changed
  4573. * @lang: the language description
  4574. *
  4575. * Set the language of a node, i.e. the values of the xml:lang
  4576. * attribute.
  4577. */
  4578. void
  4579. xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
  4580. xmlNsPtr ns;
  4581. if (cur == NULL) return;
  4582. switch(cur->type) {
  4583. case XML_TEXT_NODE:
  4584. case XML_CDATA_SECTION_NODE:
  4585. case XML_COMMENT_NODE:
  4586. case XML_DOCUMENT_NODE:
  4587. case XML_DOCUMENT_TYPE_NODE:
  4588. case XML_DOCUMENT_FRAG_NODE:
  4589. case XML_NOTATION_NODE:
  4590. case XML_HTML_DOCUMENT_NODE:
  4591. case XML_DTD_NODE:
  4592. case XML_ELEMENT_DECL:
  4593. case XML_ATTRIBUTE_DECL:
  4594. case XML_ENTITY_DECL:
  4595. case XML_PI_NODE:
  4596. case XML_ENTITY_REF_NODE:
  4597. case XML_ENTITY_NODE:
  4598. case XML_NAMESPACE_DECL:
  4599. #ifdef LIBXML_DOCB_ENABLED
  4600. case XML_DOCB_DOCUMENT_NODE:
  4601. #endif
  4602. case XML_XINCLUDE_START:
  4603. case XML_XINCLUDE_END:
  4604. return;
  4605. case XML_ELEMENT_NODE:
  4606. case XML_ATTRIBUTE_NODE:
  4607. break;
  4608. }
  4609. ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
  4610. if (ns == NULL)
  4611. return;
  4612. xmlSetNsProp(cur, ns, BAD_CAST "lang", lang);
  4613. }
  4614. #endif /* LIBXML_TREE_ENABLED */
  4615. /**
  4616. * xmlNodeGetLang:
  4617. * @cur: the node being checked
  4618. *
  4619. * Searches the language of a node, i.e. the values of the xml:lang
  4620. * attribute or the one carried by the nearest ancestor.
  4621. *
  4622. * Returns a pointer to the lang value, or NULL if not found
  4623. * It's up to the caller to free the memory with xmlFree().
  4624. */
  4625. xmlChar *
  4626. xmlNodeGetLang(const xmlNode *cur) {
  4627. xmlChar *lang;
  4628. if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
  4629. return(NULL);
  4630. while (cur != NULL) {
  4631. lang = xmlGetNsProp(cur, BAD_CAST "lang", XML_XML_NAMESPACE);
  4632. if (lang != NULL)
  4633. return(lang);
  4634. cur = cur->parent;
  4635. }
  4636. return(NULL);
  4637. }
  4638. #ifdef LIBXML_TREE_ENABLED
  4639. /**
  4640. * xmlNodeSetSpacePreserve:
  4641. * @cur: the node being changed
  4642. * @val: the xml:space value ("0": default, 1: "preserve")
  4643. *
  4644. * Set (or reset) the space preserving behaviour of a node, i.e. the
  4645. * value of the xml:space attribute.
  4646. */
  4647. void
  4648. xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) {
  4649. xmlNsPtr ns;
  4650. if (cur == NULL) return;
  4651. switch(cur->type) {
  4652. case XML_TEXT_NODE:
  4653. case XML_CDATA_SECTION_NODE:
  4654. case XML_COMMENT_NODE:
  4655. case XML_DOCUMENT_NODE:
  4656. case XML_DOCUMENT_TYPE_NODE:
  4657. case XML_DOCUMENT_FRAG_NODE:
  4658. case XML_NOTATION_NODE:
  4659. case XML_HTML_DOCUMENT_NODE:
  4660. case XML_DTD_NODE:
  4661. case XML_ELEMENT_DECL:
  4662. case XML_ATTRIBUTE_DECL:
  4663. case XML_ENTITY_DECL:
  4664. case XML_PI_NODE:
  4665. case XML_ENTITY_REF_NODE:
  4666. case XML_ENTITY_NODE:
  4667. case XML_NAMESPACE_DECL:
  4668. case XML_XINCLUDE_START:
  4669. case XML_XINCLUDE_END:
  4670. #ifdef LIBXML_DOCB_ENABLED
  4671. case XML_DOCB_DOCUMENT_NODE:
  4672. #endif
  4673. return;
  4674. case XML_ELEMENT_NODE:
  4675. case XML_ATTRIBUTE_NODE:
  4676. break;
  4677. }
  4678. ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
  4679. if (ns == NULL)
  4680. return;
  4681. switch (val) {
  4682. case 0:
  4683. xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "default");
  4684. break;
  4685. case 1:
  4686. xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "preserve");
  4687. break;
  4688. }
  4689. }
  4690. #endif /* LIBXML_TREE_ENABLED */
  4691. /**
  4692. * xmlNodeGetSpacePreserve:
  4693. * @cur: the node being checked
  4694. *
  4695. * Searches the space preserving behaviour of a node, i.e. the values
  4696. * of the xml:space attribute or the one carried by the nearest
  4697. * ancestor.
  4698. *
  4699. * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve"
  4700. */
  4701. int
  4702. xmlNodeGetSpacePreserve(const xmlNode *cur) {
  4703. xmlChar *space;
  4704. if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
  4705. return(-1);
  4706. while (cur != NULL) {
  4707. space = xmlGetNsProp(cur, BAD_CAST "space", XML_XML_NAMESPACE);
  4708. if (space != NULL) {
  4709. if (xmlStrEqual(space, BAD_CAST "preserve")) {
  4710. xmlFree(space);
  4711. return(1);
  4712. }
  4713. if (xmlStrEqual(space, BAD_CAST "default")) {
  4714. xmlFree(space);
  4715. return(0);
  4716. }
  4717. xmlFree(space);
  4718. }
  4719. cur = cur->parent;
  4720. }
  4721. return(-1);
  4722. }
  4723. #ifdef LIBXML_TREE_ENABLED
  4724. /**
  4725. * xmlNodeSetName:
  4726. * @cur: the node being changed
  4727. * @name: the new tag name
  4728. *
  4729. * Set (or reset) the name of a node.
  4730. */
  4731. void
  4732. xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
  4733. xmlDocPtr doc;
  4734. xmlDictPtr dict;
  4735. const xmlChar *freeme = NULL;
  4736. if (cur == NULL) return;
  4737. if (name == NULL) return;
  4738. switch(cur->type) {
  4739. case XML_TEXT_NODE:
  4740. case XML_CDATA_SECTION_NODE:
  4741. case XML_COMMENT_NODE:
  4742. case XML_DOCUMENT_TYPE_NODE:
  4743. case XML_DOCUMENT_FRAG_NODE:
  4744. case XML_NOTATION_NODE:
  4745. case XML_HTML_DOCUMENT_NODE:
  4746. case XML_NAMESPACE_DECL:
  4747. case XML_XINCLUDE_START:
  4748. case XML_XINCLUDE_END:
  4749. #ifdef LIBXML_DOCB_ENABLED
  4750. case XML_DOCB_DOCUMENT_NODE:
  4751. #endif
  4752. return;
  4753. case XML_ELEMENT_NODE:
  4754. case XML_ATTRIBUTE_NODE:
  4755. case XML_PI_NODE:
  4756. case XML_ENTITY_REF_NODE:
  4757. case XML_ENTITY_NODE:
  4758. case XML_DTD_NODE:
  4759. case XML_DOCUMENT_NODE:
  4760. case XML_ELEMENT_DECL:
  4761. case XML_ATTRIBUTE_DECL:
  4762. case XML_ENTITY_DECL:
  4763. break;
  4764. }
  4765. doc = cur->doc;
  4766. if (doc != NULL)
  4767. dict = doc->dict;
  4768. else
  4769. dict = NULL;
  4770. if (dict != NULL) {
  4771. if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))
  4772. freeme = cur->name;
  4773. cur->name = xmlDictLookup(dict, name, -1);
  4774. } else {
  4775. if (cur->name != NULL)
  4776. freeme = cur->name;
  4777. cur->name = xmlStrdup(name);
  4778. }
  4779. if (freeme)
  4780. xmlFree((xmlChar *) freeme);
  4781. }
  4782. #endif
  4783. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
  4784. /**
  4785. * xmlNodeSetBase:
  4786. * @cur: the node being changed
  4787. * @uri: the new base URI
  4788. *
  4789. * Set (or reset) the base URI of a node, i.e. the value of the
  4790. * xml:base attribute.
  4791. */
  4792. void
  4793. xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) {
  4794. xmlNsPtr ns;
  4795. xmlChar* fixed;
  4796. if (cur == NULL) return;
  4797. switch(cur->type) {
  4798. case XML_TEXT_NODE:
  4799. case XML_CDATA_SECTION_NODE:
  4800. case XML_COMMENT_NODE:
  4801. case XML_DOCUMENT_TYPE_NODE:
  4802. case XML_DOCUMENT_FRAG_NODE:
  4803. case XML_NOTATION_NODE:
  4804. case XML_DTD_NODE:
  4805. case XML_ELEMENT_DECL:
  4806. case XML_ATTRIBUTE_DECL:
  4807. case XML_ENTITY_DECL:
  4808. case XML_PI_NODE:
  4809. case XML_ENTITY_REF_NODE:
  4810. case XML_ENTITY_NODE:
  4811. case XML_NAMESPACE_DECL:
  4812. case XML_XINCLUDE_START:
  4813. case XML_XINCLUDE_END:
  4814. return;
  4815. case XML_ELEMENT_NODE:
  4816. case XML_ATTRIBUTE_NODE:
  4817. break;
  4818. case XML_DOCUMENT_NODE:
  4819. #ifdef LIBXML_DOCB_ENABLED
  4820. case XML_DOCB_DOCUMENT_NODE:
  4821. #endif
  4822. case XML_HTML_DOCUMENT_NODE: {
  4823. xmlDocPtr doc = (xmlDocPtr) cur;
  4824. if (doc->URL != NULL)
  4825. xmlFree((xmlChar *) doc->URL);
  4826. if (uri == NULL)
  4827. doc->URL = NULL;
  4828. else
  4829. doc->URL = xmlPathToURI(uri);
  4830. return;
  4831. }
  4832. }
  4833. ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
  4834. if (ns == NULL)
  4835. return;
  4836. fixed = xmlPathToURI(uri);
  4837. if (fixed != NULL) {
  4838. xmlSetNsProp(cur, ns, BAD_CAST "base", fixed);
  4839. xmlFree(fixed);
  4840. } else {
  4841. xmlSetNsProp(cur, ns, BAD_CAST "base", uri);
  4842. }
  4843. }
  4844. #endif /* LIBXML_TREE_ENABLED */
  4845. /**
  4846. * xmlNodeGetBase:
  4847. * @doc: the document the node pertains to
  4848. * @cur: the node being checked
  4849. *
  4850. * Searches for the BASE URL. The code should work on both XML
  4851. * and HTML document even if base mechanisms are completely different.
  4852. * It returns the base as defined in RFC 2396 sections
  4853. * 5.1.1. Base URI within Document Content
  4854. * and
  4855. * 5.1.2. Base URI from the Encapsulating Entity
  4856. * However it does not return the document base (5.1.3), use
  4857. * doc->URL in this case
  4858. *
  4859. * Returns a pointer to the base URL, or NULL if not found
  4860. * It's up to the caller to free the memory with xmlFree().
  4861. */
  4862. xmlChar *
  4863. xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) {
  4864. xmlChar *oldbase = NULL;
  4865. xmlChar *base, *newbase;
  4866. if ((cur == NULL) && (doc == NULL))
  4867. return(NULL);
  4868. if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
  4869. return(NULL);
  4870. if (doc == NULL) doc = cur->doc;
  4871. if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
  4872. cur = doc->children;
  4873. while ((cur != NULL) && (cur->name != NULL)) {
  4874. if (cur->type != XML_ELEMENT_NODE) {
  4875. cur = cur->next;
  4876. continue;
  4877. }
  4878. if (!xmlStrcasecmp(cur->name, BAD_CAST "html")) {
  4879. cur = cur->children;
  4880. continue;
  4881. }
  4882. if (!xmlStrcasecmp(cur->name, BAD_CAST "head")) {
  4883. cur = cur->children;
  4884. continue;
  4885. }
  4886. if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) {
  4887. return(xmlGetProp(cur, BAD_CAST "href"));
  4888. }
  4889. cur = cur->next;
  4890. }
  4891. return(NULL);
  4892. }
  4893. while (cur != NULL) {
  4894. if (cur->type == XML_ENTITY_DECL) {
  4895. xmlEntityPtr ent = (xmlEntityPtr) cur;
  4896. return(xmlStrdup(ent->URI));
  4897. }
  4898. if (cur->type == XML_ELEMENT_NODE) {
  4899. base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
  4900. if (base != NULL) {
  4901. if (oldbase != NULL) {
  4902. newbase = xmlBuildURI(oldbase, base);
  4903. if (newbase != NULL) {
  4904. xmlFree(oldbase);
  4905. xmlFree(base);
  4906. oldbase = newbase;
  4907. } else {
  4908. xmlFree(oldbase);
  4909. xmlFree(base);
  4910. return(NULL);
  4911. }
  4912. } else {
  4913. oldbase = base;
  4914. }
  4915. if ((!xmlStrncmp(oldbase, BAD_CAST "http://", 7)) ||
  4916. (!xmlStrncmp(oldbase, BAD_CAST "ftp://", 6)) ||
  4917. (!xmlStrncmp(oldbase, BAD_CAST "urn:", 4)))
  4918. return(oldbase);
  4919. }
  4920. }
  4921. cur = cur->parent;
  4922. }
  4923. if ((doc != NULL) && (doc->URL != NULL)) {
  4924. if (oldbase == NULL)
  4925. return(xmlStrdup(doc->URL));
  4926. newbase = xmlBuildURI(oldbase, doc->URL);
  4927. xmlFree(oldbase);
  4928. return(newbase);
  4929. }
  4930. return(oldbase);
  4931. }
  4932. /**
  4933. * xmlNodeBufGetContent:
  4934. * @buffer: a buffer
  4935. * @cur: the node being read
  4936. *
  4937. * Read the value of a node @cur, this can be either the text carried
  4938. * directly by this node if it's a TEXT node or the aggregate string
  4939. * of the values carried by this node child's (TEXT and ENTITY_REF).
  4940. * Entity references are substituted.
  4941. * Fills up the buffer @buffer with this value
  4942. *
  4943. * Returns 0 in case of success and -1 in case of error.
  4944. */
  4945. int
  4946. xmlNodeBufGetContent(xmlBufferPtr buffer, const xmlNode *cur)
  4947. {
  4948. xmlBufPtr buf;
  4949. int ret;
  4950. if ((cur == NULL) || (buffer == NULL)) return(-1);
  4951. buf = xmlBufFromBuffer(buffer);
  4952. ret = xmlBufGetNodeContent(buf, cur);
  4953. buffer = xmlBufBackToBuffer(buf);
  4954. if ((ret < 0) || (buffer == NULL))
  4955. return(-1);
  4956. return(0);
  4957. }
  4958. /**
  4959. * xmlBufGetNodeContent:
  4960. * @buf: a buffer xmlBufPtr
  4961. * @cur: the node being read
  4962. *
  4963. * Read the value of a node @cur, this can be either the text carried
  4964. * directly by this node if it's a TEXT node or the aggregate string
  4965. * of the values carried by this node child's (TEXT and ENTITY_REF).
  4966. * Entity references are substituted.
  4967. * Fills up the buffer @buf with this value
  4968. *
  4969. * Returns 0 in case of success and -1 in case of error.
  4970. */
  4971. int
  4972. xmlBufGetNodeContent(xmlBufPtr buf, const xmlNode *cur)
  4973. {
  4974. if ((cur == NULL) || (buf == NULL)) return(-1);
  4975. switch (cur->type) {
  4976. case XML_CDATA_SECTION_NODE:
  4977. case XML_TEXT_NODE:
  4978. xmlBufCat(buf, cur->content);
  4979. break;
  4980. case XML_DOCUMENT_FRAG_NODE:
  4981. case XML_ELEMENT_NODE:{
  4982. const xmlNode *tmp = cur;
  4983. while (tmp != NULL) {
  4984. switch (tmp->type) {
  4985. case XML_CDATA_SECTION_NODE:
  4986. case XML_TEXT_NODE:
  4987. if (tmp->content != NULL)
  4988. xmlBufCat(buf, tmp->content);
  4989. break;
  4990. case XML_ENTITY_REF_NODE:
  4991. xmlBufGetNodeContent(buf, tmp);
  4992. break;
  4993. default:
  4994. break;
  4995. }
  4996. /*
  4997. * Skip to next node
  4998. */
  4999. if (tmp->children != NULL) {
  5000. if (tmp->children->type != XML_ENTITY_DECL) {
  5001. tmp = tmp->children;
  5002. continue;
  5003. }
  5004. }
  5005. if (tmp == cur)
  5006. break;
  5007. if (tmp->next != NULL) {
  5008. tmp = tmp->next;
  5009. continue;
  5010. }
  5011. do {
  5012. tmp = tmp->parent;
  5013. if (tmp == NULL)
  5014. break;
  5015. if (tmp == cur) {
  5016. tmp = NULL;
  5017. break;
  5018. }
  5019. if (tmp->next != NULL) {
  5020. tmp = tmp->next;
  5021. break;
  5022. }
  5023. } while (tmp != NULL);
  5024. }
  5025. break;
  5026. }
  5027. case XML_ATTRIBUTE_NODE:{
  5028. xmlAttrPtr attr = (xmlAttrPtr) cur;
  5029. xmlNodePtr tmp = attr->children;
  5030. while (tmp != NULL) {
  5031. if (tmp->type == XML_TEXT_NODE)
  5032. xmlBufCat(buf, tmp->content);
  5033. else
  5034. xmlBufGetNodeContent(buf, tmp);
  5035. tmp = tmp->next;
  5036. }
  5037. break;
  5038. }
  5039. case XML_COMMENT_NODE:
  5040. case XML_PI_NODE:
  5041. xmlBufCat(buf, cur->content);
  5042. break;
  5043. case XML_ENTITY_REF_NODE:{
  5044. xmlEntityPtr ent;
  5045. xmlNodePtr tmp;
  5046. /* lookup entity declaration */
  5047. ent = xmlGetDocEntity(cur->doc, cur->name);
  5048. if (ent == NULL)
  5049. return(-1);
  5050. /* an entity content can be any "well balanced chunk",
  5051. * i.e. the result of the content [43] production:
  5052. * http://www.w3.org/TR/REC-xml#NT-content
  5053. * -> we iterate through child nodes and recursive call
  5054. * xmlNodeGetContent() which handles all possible node types */
  5055. tmp = ent->children;
  5056. while (tmp) {
  5057. xmlBufGetNodeContent(buf, tmp);
  5058. tmp = tmp->next;
  5059. }
  5060. break;
  5061. }
  5062. case XML_ENTITY_NODE:
  5063. case XML_DOCUMENT_TYPE_NODE:
  5064. case XML_NOTATION_NODE:
  5065. case XML_DTD_NODE:
  5066. case XML_XINCLUDE_START:
  5067. case XML_XINCLUDE_END:
  5068. break;
  5069. case XML_DOCUMENT_NODE:
  5070. #ifdef LIBXML_DOCB_ENABLED
  5071. case XML_DOCB_DOCUMENT_NODE:
  5072. #endif
  5073. case XML_HTML_DOCUMENT_NODE:
  5074. cur = cur->children;
  5075. while (cur!= NULL) {
  5076. if ((cur->type == XML_ELEMENT_NODE) ||
  5077. (cur->type == XML_TEXT_NODE) ||
  5078. (cur->type == XML_CDATA_SECTION_NODE)) {
  5079. xmlBufGetNodeContent(buf, cur);
  5080. }
  5081. cur = cur->next;
  5082. }
  5083. break;
  5084. case XML_NAMESPACE_DECL:
  5085. xmlBufCat(buf, ((xmlNsPtr) cur)->href);
  5086. break;
  5087. case XML_ELEMENT_DECL:
  5088. case XML_ATTRIBUTE_DECL:
  5089. case XML_ENTITY_DECL:
  5090. break;
  5091. }
  5092. return(0);
  5093. }
  5094. /**
  5095. * xmlNodeGetContent:
  5096. * @cur: the node being read
  5097. *
  5098. * Read the value of a node, this can be either the text carried
  5099. * directly by this node if it's a TEXT node or the aggregate string
  5100. * of the values carried by this node child's (TEXT and ENTITY_REF).
  5101. * Entity references are substituted.
  5102. * Returns a new #xmlChar * or NULL if no content is available.
  5103. * It's up to the caller to free the memory with xmlFree().
  5104. */
  5105. xmlChar *
  5106. xmlNodeGetContent(const xmlNode *cur)
  5107. {
  5108. if (cur == NULL)
  5109. return (NULL);
  5110. switch (cur->type) {
  5111. case XML_DOCUMENT_FRAG_NODE:
  5112. case XML_ELEMENT_NODE:{
  5113. xmlBufPtr buf;
  5114. xmlChar *ret;
  5115. buf = xmlBufCreateSize(64);
  5116. if (buf == NULL)
  5117. return (NULL);
  5118. xmlBufGetNodeContent(buf, cur);
  5119. ret = xmlBufDetach(buf);
  5120. xmlBufFree(buf);
  5121. return (ret);
  5122. }
  5123. case XML_ATTRIBUTE_NODE:
  5124. return(xmlGetPropNodeValueInternal((xmlAttrPtr) cur));
  5125. case XML_COMMENT_NODE:
  5126. case XML_PI_NODE:
  5127. if (cur->content != NULL)
  5128. return (xmlStrdup(cur->content));
  5129. return (NULL);
  5130. case XML_ENTITY_REF_NODE:{
  5131. xmlEntityPtr ent;
  5132. xmlBufPtr buf;
  5133. xmlChar *ret;
  5134. /* lookup entity declaration */
  5135. ent = xmlGetDocEntity(cur->doc, cur->name);
  5136. if (ent == NULL)
  5137. return (NULL);
  5138. buf = xmlBufCreate();
  5139. if (buf == NULL)
  5140. return (NULL);
  5141. xmlBufGetNodeContent(buf, cur);
  5142. ret = xmlBufDetach(buf);
  5143. xmlBufFree(buf);
  5144. return (ret);
  5145. }
  5146. case XML_ENTITY_NODE:
  5147. case XML_DOCUMENT_TYPE_NODE:
  5148. case XML_NOTATION_NODE:
  5149. case XML_DTD_NODE:
  5150. case XML_XINCLUDE_START:
  5151. case XML_XINCLUDE_END:
  5152. return (NULL);
  5153. case XML_DOCUMENT_NODE:
  5154. #ifdef LIBXML_DOCB_ENABLED
  5155. case XML_DOCB_DOCUMENT_NODE:
  5156. #endif
  5157. case XML_HTML_DOCUMENT_NODE: {
  5158. xmlBufPtr buf;
  5159. xmlChar *ret;
  5160. buf = xmlBufCreate();
  5161. if (buf == NULL)
  5162. return (NULL);
  5163. xmlBufGetNodeContent(buf, (xmlNodePtr) cur);
  5164. ret = xmlBufDetach(buf);
  5165. xmlBufFree(buf);
  5166. return (ret);
  5167. }
  5168. case XML_NAMESPACE_DECL: {
  5169. xmlChar *tmp;
  5170. tmp = xmlStrdup(((xmlNsPtr) cur)->href);
  5171. return (tmp);
  5172. }
  5173. case XML_ELEMENT_DECL:
  5174. /* TODO !!! */
  5175. return (NULL);
  5176. case XML_ATTRIBUTE_DECL:
  5177. /* TODO !!! */
  5178. return (NULL);
  5179. case XML_ENTITY_DECL:
  5180. /* TODO !!! */
  5181. return (NULL);
  5182. case XML_CDATA_SECTION_NODE:
  5183. case XML_TEXT_NODE:
  5184. if (cur->content != NULL)
  5185. return (xmlStrdup(cur->content));
  5186. return (NULL);
  5187. }
  5188. return (NULL);
  5189. }
  5190. /**
  5191. * xmlNodeSetContent:
  5192. * @cur: the node being modified
  5193. * @content: the new value of the content
  5194. *
  5195. * Replace the content of a node.
  5196. * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
  5197. * references, but XML special chars need to be escaped first by using
  5198. * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
  5199. */
  5200. void
  5201. xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
  5202. if (cur == NULL) {
  5203. #ifdef DEBUG_TREE
  5204. xmlGenericError(xmlGenericErrorContext,
  5205. "xmlNodeSetContent : node == NULL\n");
  5206. #endif
  5207. return;
  5208. }
  5209. switch (cur->type) {
  5210. case XML_DOCUMENT_FRAG_NODE:
  5211. case XML_ELEMENT_NODE:
  5212. case XML_ATTRIBUTE_NODE:
  5213. if (cur->children != NULL) xmlFreeNodeList(cur->children);
  5214. cur->children = xmlStringGetNodeList(cur->doc, content);
  5215. UPDATE_LAST_CHILD_AND_PARENT(cur)
  5216. break;
  5217. case XML_TEXT_NODE:
  5218. case XML_CDATA_SECTION_NODE:
  5219. case XML_ENTITY_REF_NODE:
  5220. case XML_ENTITY_NODE:
  5221. case XML_PI_NODE:
  5222. case XML_COMMENT_NODE:
  5223. if ((cur->content != NULL) &&
  5224. (cur->content != (xmlChar *) &(cur->properties))) {
  5225. if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
  5226. (xmlDictOwns(cur->doc->dict, cur->content))))
  5227. xmlFree(cur->content);
  5228. }
  5229. if (cur->children != NULL) xmlFreeNodeList(cur->children);
  5230. cur->last = cur->children = NULL;
  5231. if (content != NULL) {
  5232. cur->content = xmlStrdup(content);
  5233. } else
  5234. cur->content = NULL;
  5235. cur->properties = NULL;
  5236. cur->nsDef = NULL;
  5237. break;
  5238. case XML_DOCUMENT_NODE:
  5239. case XML_HTML_DOCUMENT_NODE:
  5240. case XML_DOCUMENT_TYPE_NODE:
  5241. case XML_XINCLUDE_START:
  5242. case XML_XINCLUDE_END:
  5243. #ifdef LIBXML_DOCB_ENABLED
  5244. case XML_DOCB_DOCUMENT_NODE:
  5245. #endif
  5246. break;
  5247. case XML_NOTATION_NODE:
  5248. break;
  5249. case XML_DTD_NODE:
  5250. break;
  5251. case XML_NAMESPACE_DECL:
  5252. break;
  5253. case XML_ELEMENT_DECL:
  5254. /* TODO !!! */
  5255. break;
  5256. case XML_ATTRIBUTE_DECL:
  5257. /* TODO !!! */
  5258. break;
  5259. case XML_ENTITY_DECL:
  5260. /* TODO !!! */
  5261. break;
  5262. }
  5263. }
  5264. #ifdef LIBXML_TREE_ENABLED
  5265. /**
  5266. * xmlNodeSetContentLen:
  5267. * @cur: the node being modified
  5268. * @content: the new value of the content
  5269. * @len: the size of @content
  5270. *
  5271. * Replace the content of a node.
  5272. * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
  5273. * references, but XML special chars need to be escaped first by using
  5274. * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
  5275. */
  5276. void
  5277. xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
  5278. if (cur == NULL) {
  5279. #ifdef DEBUG_TREE
  5280. xmlGenericError(xmlGenericErrorContext,
  5281. "xmlNodeSetContentLen : node == NULL\n");
  5282. #endif
  5283. return;
  5284. }
  5285. switch (cur->type) {
  5286. case XML_DOCUMENT_FRAG_NODE:
  5287. case XML_ELEMENT_NODE:
  5288. case XML_ATTRIBUTE_NODE:
  5289. if (cur->children != NULL) xmlFreeNodeList(cur->children);
  5290. cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
  5291. UPDATE_LAST_CHILD_AND_PARENT(cur)
  5292. break;
  5293. case XML_TEXT_NODE:
  5294. case XML_CDATA_SECTION_NODE:
  5295. case XML_ENTITY_REF_NODE:
  5296. case XML_ENTITY_NODE:
  5297. case XML_PI_NODE:
  5298. case XML_COMMENT_NODE:
  5299. case XML_NOTATION_NODE:
  5300. if ((cur->content != NULL) &&
  5301. (cur->content != (xmlChar *) &(cur->properties))) {
  5302. if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
  5303. (xmlDictOwns(cur->doc->dict, cur->content))))
  5304. xmlFree(cur->content);
  5305. }
  5306. if (cur->children != NULL) xmlFreeNodeList(cur->children);
  5307. cur->children = cur->last = NULL;
  5308. if (content != NULL) {
  5309. cur->content = xmlStrndup(content, len);
  5310. } else
  5311. cur->content = NULL;
  5312. cur->properties = NULL;
  5313. cur->nsDef = NULL;
  5314. break;
  5315. case XML_DOCUMENT_NODE:
  5316. case XML_DTD_NODE:
  5317. case XML_HTML_DOCUMENT_NODE:
  5318. case XML_DOCUMENT_TYPE_NODE:
  5319. case XML_NAMESPACE_DECL:
  5320. case XML_XINCLUDE_START:
  5321. case XML_XINCLUDE_END:
  5322. #ifdef LIBXML_DOCB_ENABLED
  5323. case XML_DOCB_DOCUMENT_NODE:
  5324. #endif
  5325. break;
  5326. case XML_ELEMENT_DECL:
  5327. /* TODO !!! */
  5328. break;
  5329. case XML_ATTRIBUTE_DECL:
  5330. /* TODO !!! */
  5331. break;
  5332. case XML_ENTITY_DECL:
  5333. /* TODO !!! */
  5334. break;
  5335. }
  5336. }
  5337. #endif /* LIBXML_TREE_ENABLED */
  5338. /**
  5339. * xmlNodeAddContentLen:
  5340. * @cur: the node being modified
  5341. * @content: extra content
  5342. * @len: the size of @content
  5343. *
  5344. * Append the extra substring to the node content.
  5345. * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be
  5346. * raw text, so unescaped XML special chars are allowed, entity
  5347. * references are not supported.
  5348. */
  5349. void
  5350. xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
  5351. if (cur == NULL) {
  5352. #ifdef DEBUG_TREE
  5353. xmlGenericError(xmlGenericErrorContext,
  5354. "xmlNodeAddContentLen : node == NULL\n");
  5355. #endif
  5356. return;
  5357. }
  5358. if (len <= 0) return;
  5359. switch (cur->type) {
  5360. case XML_DOCUMENT_FRAG_NODE:
  5361. case XML_ELEMENT_NODE: {
  5362. xmlNodePtr last, newNode, tmp;
  5363. last = cur->last;
  5364. newNode = xmlNewTextLen(content, len);
  5365. if (newNode != NULL) {
  5366. tmp = xmlAddChild(cur, newNode);
  5367. if (tmp != newNode)
  5368. return;
  5369. if ((last != NULL) && (last->next == newNode)) {
  5370. xmlTextMerge(last, newNode);
  5371. }
  5372. }
  5373. break;
  5374. }
  5375. case XML_ATTRIBUTE_NODE:
  5376. break;
  5377. case XML_TEXT_NODE:
  5378. case XML_CDATA_SECTION_NODE:
  5379. case XML_ENTITY_REF_NODE:
  5380. case XML_ENTITY_NODE:
  5381. case XML_PI_NODE:
  5382. case XML_COMMENT_NODE:
  5383. case XML_NOTATION_NODE:
  5384. if (content != NULL) {
  5385. if ((cur->content == (xmlChar *) &(cur->properties)) ||
  5386. ((cur->doc != NULL) && (cur->doc->dict != NULL) &&
  5387. xmlDictOwns(cur->doc->dict, cur->content))) {
  5388. cur->content = xmlStrncatNew(cur->content, content, len);
  5389. cur->properties = NULL;
  5390. cur->nsDef = NULL;
  5391. break;
  5392. }
  5393. cur->content = xmlStrncat(cur->content, content, len);
  5394. }
  5395. case XML_DOCUMENT_NODE:
  5396. case XML_DTD_NODE:
  5397. case XML_HTML_DOCUMENT_NODE:
  5398. case XML_DOCUMENT_TYPE_NODE:
  5399. case XML_NAMESPACE_DECL:
  5400. case XML_XINCLUDE_START:
  5401. case XML_XINCLUDE_END:
  5402. #ifdef LIBXML_DOCB_ENABLED
  5403. case XML_DOCB_DOCUMENT_NODE:
  5404. #endif
  5405. break;
  5406. case XML_ELEMENT_DECL:
  5407. case XML_ATTRIBUTE_DECL:
  5408. case XML_ENTITY_DECL:
  5409. break;
  5410. }
  5411. }
  5412. /**
  5413. * xmlNodeAddContent:
  5414. * @cur: the node being modified
  5415. * @content: extra content
  5416. *
  5417. * Append the extra substring to the node content.
  5418. * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be
  5419. * raw text, so unescaped XML special chars are allowed, entity
  5420. * references are not supported.
  5421. */
  5422. void
  5423. xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
  5424. int len;
  5425. if (cur == NULL) {
  5426. #ifdef DEBUG_TREE
  5427. xmlGenericError(xmlGenericErrorContext,
  5428. "xmlNodeAddContent : node == NULL\n");
  5429. #endif
  5430. return;
  5431. }
  5432. if (content == NULL) return;
  5433. len = xmlStrlen(content);
  5434. xmlNodeAddContentLen(cur, content, len);
  5435. }
  5436. /**
  5437. * xmlTextMerge:
  5438. * @first: the first text node
  5439. * @second: the second text node being merged
  5440. *
  5441. * Merge two text nodes into one
  5442. * Returns the first text node augmented
  5443. */
  5444. xmlNodePtr
  5445. xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
  5446. if (first == NULL) return(second);
  5447. if (second == NULL) return(first);
  5448. if (first->type != XML_TEXT_NODE) return(first);
  5449. if (second->type != XML_TEXT_NODE) return(first);
  5450. if (second->name != first->name)
  5451. return(first);
  5452. xmlNodeAddContent(first, second->content);
  5453. xmlUnlinkNode(second);
  5454. xmlFreeNode(second);
  5455. return(first);
  5456. }
  5457. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
  5458. /**
  5459. * xmlGetNsList:
  5460. * @doc: the document
  5461. * @node: the current node
  5462. *
  5463. * Search all the namespace applying to a given element.
  5464. * Returns an NULL terminated array of all the #xmlNsPtr found
  5465. * that need to be freed by the caller or NULL if no
  5466. * namespace if defined
  5467. */
  5468. xmlNsPtr *
  5469. xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node)
  5470. {
  5471. xmlNsPtr cur;
  5472. xmlNsPtr *ret = NULL;
  5473. int nbns = 0;
  5474. int maxns = 10;
  5475. int i;
  5476. if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
  5477. return(NULL);
  5478. while (node != NULL) {
  5479. if (node->type == XML_ELEMENT_NODE) {
  5480. cur = node->nsDef;
  5481. while (cur != NULL) {
  5482. if (ret == NULL) {
  5483. ret =
  5484. (xmlNsPtr *) xmlMalloc((maxns + 1) *
  5485. sizeof(xmlNsPtr));
  5486. if (ret == NULL) {
  5487. xmlTreeErrMemory("getting namespace list");
  5488. return (NULL);
  5489. }
  5490. ret[nbns] = NULL;
  5491. }
  5492. for (i = 0; i < nbns; i++) {
  5493. if ((cur->prefix == ret[i]->prefix) ||
  5494. (xmlStrEqual(cur->prefix, ret[i]->prefix)))
  5495. break;
  5496. }
  5497. if (i >= nbns) {
  5498. if (nbns >= maxns) {
  5499. maxns *= 2;
  5500. ret = (xmlNsPtr *) xmlRealloc(ret,
  5501. (maxns +
  5502. 1) *
  5503. sizeof(xmlNsPtr));
  5504. if (ret == NULL) {
  5505. xmlTreeErrMemory("getting namespace list");
  5506. return (NULL);
  5507. }
  5508. }
  5509. ret[nbns++] = cur;
  5510. ret[nbns] = NULL;
  5511. }
  5512. cur = cur->next;
  5513. }
  5514. }
  5515. node = node->parent;
  5516. }
  5517. return (ret);
  5518. }
  5519. #endif /* LIBXML_TREE_ENABLED */
  5520. /*
  5521. * xmlTreeEnsureXMLDecl:
  5522. * @doc: the doc
  5523. *
  5524. * Ensures that there is an XML namespace declaration on the doc.
  5525. *
  5526. * Returns the XML ns-struct or NULL on API and internal errors.
  5527. */
  5528. static xmlNsPtr
  5529. xmlTreeEnsureXMLDecl(xmlDocPtr doc)
  5530. {
  5531. if (doc == NULL)
  5532. return (NULL);
  5533. if (doc->oldNs != NULL)
  5534. return (doc->oldNs);
  5535. {
  5536. xmlNsPtr ns;
  5537. ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
  5538. if (ns == NULL) {
  5539. xmlTreeErrMemory(
  5540. "allocating the XML namespace");
  5541. return (NULL);
  5542. }
  5543. memset(ns, 0, sizeof(xmlNs));
  5544. ns->type = XML_LOCAL_NAMESPACE;
  5545. ns->href = xmlStrdup(XML_XML_NAMESPACE);
  5546. ns->prefix = xmlStrdup((const xmlChar *)"xml");
  5547. doc->oldNs = ns;
  5548. return (ns);
  5549. }
  5550. }
  5551. /**
  5552. * xmlSearchNs:
  5553. * @doc: the document
  5554. * @node: the current node
  5555. * @nameSpace: the namespace prefix
  5556. *
  5557. * Search a Ns registered under a given name space for a document.
  5558. * recurse on the parents until it finds the defined namespace
  5559. * or return NULL otherwise.
  5560. * @nameSpace can be NULL, this is a search for the default namespace.
  5561. * We don't allow to cross entities boundaries. If you don't declare
  5562. * the namespace within those you will be in troubles !!! A warning
  5563. * is generated to cover this case.
  5564. *
  5565. * Returns the namespace pointer or NULL.
  5566. */
  5567. xmlNsPtr
  5568. xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
  5569. xmlNsPtr cur;
  5570. const xmlNode *orig = node;
  5571. if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) return(NULL);
  5572. if ((nameSpace != NULL) &&
  5573. (xmlStrEqual(nameSpace, (const xmlChar *)"xml"))) {
  5574. if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
  5575. /*
  5576. * The XML-1.0 namespace is normally held on the root
  5577. * element. In this case exceptionally create it on the
  5578. * node element.
  5579. */
  5580. cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
  5581. if (cur == NULL) {
  5582. xmlTreeErrMemory("searching namespace");
  5583. return(NULL);
  5584. }
  5585. memset(cur, 0, sizeof(xmlNs));
  5586. cur->type = XML_LOCAL_NAMESPACE;
  5587. cur->href = xmlStrdup(XML_XML_NAMESPACE);
  5588. cur->prefix = xmlStrdup((const xmlChar *)"xml");
  5589. cur->next = node->nsDef;
  5590. node->nsDef = cur;
  5591. return(cur);
  5592. }
  5593. if (doc == NULL) {
  5594. doc = node->doc;
  5595. if (doc == NULL)
  5596. return(NULL);
  5597. }
  5598. /*
  5599. * Return the XML namespace declaration held by the doc.
  5600. */
  5601. if (doc->oldNs == NULL)
  5602. return(xmlTreeEnsureXMLDecl(doc));
  5603. else
  5604. return(doc->oldNs);
  5605. }
  5606. while (node != NULL) {
  5607. if ((node->type == XML_ENTITY_REF_NODE) ||
  5608. (node->type == XML_ENTITY_NODE) ||
  5609. (node->type == XML_ENTITY_DECL))
  5610. return(NULL);
  5611. if (node->type == XML_ELEMENT_NODE) {
  5612. cur = node->nsDef;
  5613. while (cur != NULL) {
  5614. if ((cur->prefix == NULL) && (nameSpace == NULL) &&
  5615. (cur->href != NULL))
  5616. return(cur);
  5617. if ((cur->prefix != NULL) && (nameSpace != NULL) &&
  5618. (cur->href != NULL) &&
  5619. (xmlStrEqual(cur->prefix, nameSpace)))
  5620. return(cur);
  5621. cur = cur->next;
  5622. }
  5623. if (orig != node) {
  5624. cur = node->ns;
  5625. if (cur != NULL) {
  5626. if ((cur->prefix == NULL) && (nameSpace == NULL) &&
  5627. (cur->href != NULL))
  5628. return(cur);
  5629. if ((cur->prefix != NULL) && (nameSpace != NULL) &&
  5630. (cur->href != NULL) &&
  5631. (xmlStrEqual(cur->prefix, nameSpace)))
  5632. return(cur);
  5633. }
  5634. }
  5635. }
  5636. node = node->parent;
  5637. }
  5638. return(NULL);
  5639. }
  5640. /**
  5641. * xmlNsInScope:
  5642. * @doc: the document
  5643. * @node: the current node
  5644. * @ancestor: the ancestor carrying the namespace
  5645. * @prefix: the namespace prefix
  5646. *
  5647. * Verify that the given namespace held on @ancestor is still in scope
  5648. * on node.
  5649. *
  5650. * Returns 1 if true, 0 if false and -1 in case of error.
  5651. */
  5652. static int
  5653. xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node,
  5654. xmlNodePtr ancestor, const xmlChar * prefix)
  5655. {
  5656. xmlNsPtr tst;
  5657. while ((node != NULL) && (node != ancestor)) {
  5658. if ((node->type == XML_ENTITY_REF_NODE) ||
  5659. (node->type == XML_ENTITY_NODE) ||
  5660. (node->type == XML_ENTITY_DECL))
  5661. return (-1);
  5662. if (node->type == XML_ELEMENT_NODE) {
  5663. tst = node->nsDef;
  5664. while (tst != NULL) {
  5665. if ((tst->prefix == NULL)
  5666. && (prefix == NULL))
  5667. return (0);
  5668. if ((tst->prefix != NULL)
  5669. && (prefix != NULL)
  5670. && (xmlStrEqual(tst->prefix, prefix)))
  5671. return (0);
  5672. tst = tst->next;
  5673. }
  5674. }
  5675. node = node->parent;
  5676. }
  5677. if (node != ancestor)
  5678. return (-1);
  5679. return (1);
  5680. }
  5681. /**
  5682. * xmlSearchNsByHref:
  5683. * @doc: the document
  5684. * @node: the current node
  5685. * @href: the namespace value
  5686. *
  5687. * Search a Ns aliasing a given URI. Recurse on the parents until it finds
  5688. * the defined namespace or return NULL otherwise.
  5689. * Returns the namespace pointer or NULL.
  5690. */
  5691. xmlNsPtr
  5692. xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
  5693. {
  5694. xmlNsPtr cur;
  5695. xmlNodePtr orig = node;
  5696. int is_attr;
  5697. if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) || (href == NULL))
  5698. return (NULL);
  5699. if (xmlStrEqual(href, XML_XML_NAMESPACE)) {
  5700. /*
  5701. * Only the document can hold the XML spec namespace.
  5702. */
  5703. if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
  5704. /*
  5705. * The XML-1.0 namespace is normally held on the root
  5706. * element. In this case exceptionally create it on the
  5707. * node element.
  5708. */
  5709. cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
  5710. if (cur == NULL) {
  5711. xmlTreeErrMemory("searching namespace");
  5712. return (NULL);
  5713. }
  5714. memset(cur, 0, sizeof(xmlNs));
  5715. cur->type = XML_LOCAL_NAMESPACE;
  5716. cur->href = xmlStrdup(XML_XML_NAMESPACE);
  5717. cur->prefix = xmlStrdup((const xmlChar *) "xml");
  5718. cur->next = node->nsDef;
  5719. node->nsDef = cur;
  5720. return (cur);
  5721. }
  5722. if (doc == NULL) {
  5723. doc = node->doc;
  5724. if (doc == NULL)
  5725. return(NULL);
  5726. }
  5727. /*
  5728. * Return the XML namespace declaration held by the doc.
  5729. */
  5730. if (doc->oldNs == NULL)
  5731. return(xmlTreeEnsureXMLDecl(doc));
  5732. else
  5733. return(doc->oldNs);
  5734. }
  5735. is_attr = (node->type == XML_ATTRIBUTE_NODE);
  5736. while (node != NULL) {
  5737. if ((node->type == XML_ENTITY_REF_NODE) ||
  5738. (node->type == XML_ENTITY_NODE) ||
  5739. (node->type == XML_ENTITY_DECL))
  5740. return (NULL);
  5741. if (node->type == XML_ELEMENT_NODE) {
  5742. cur = node->nsDef;
  5743. while (cur != NULL) {
  5744. if ((cur->href != NULL) && (href != NULL) &&
  5745. (xmlStrEqual(cur->href, href))) {
  5746. if (((!is_attr) || (cur->prefix != NULL)) &&
  5747. (xmlNsInScope(doc, orig, node, cur->prefix) == 1))
  5748. return (cur);
  5749. }
  5750. cur = cur->next;
  5751. }
  5752. if (orig != node) {
  5753. cur = node->ns;
  5754. if (cur != NULL) {
  5755. if ((cur->href != NULL) && (href != NULL) &&
  5756. (xmlStrEqual(cur->href, href))) {
  5757. if (((!is_attr) || (cur->prefix != NULL)) &&
  5758. (xmlNsInScope(doc, orig, node, cur->prefix) == 1))
  5759. return (cur);
  5760. }
  5761. }
  5762. }
  5763. }
  5764. node = node->parent;
  5765. }
  5766. return (NULL);
  5767. }
  5768. /**
  5769. * xmlNewReconciledNs:
  5770. * @doc: the document
  5771. * @tree: a node expected to hold the new namespace
  5772. * @ns: the original namespace
  5773. *
  5774. * This function tries to locate a namespace definition in a tree
  5775. * ancestors, or create a new namespace definition node similar to
  5776. * @ns trying to reuse the same prefix. However if the given prefix is
  5777. * null (default namespace) or reused within the subtree defined by
  5778. * @tree or on one of its ancestors then a new prefix is generated.
  5779. * Returns the (new) namespace definition or NULL in case of error
  5780. */
  5781. static xmlNsPtr
  5782. xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
  5783. xmlNsPtr def;
  5784. xmlChar prefix[50];
  5785. int counter = 1;
  5786. if ((tree == NULL) || (tree->type != XML_ELEMENT_NODE)) {
  5787. #ifdef DEBUG_TREE
  5788. xmlGenericError(xmlGenericErrorContext,
  5789. "xmlNewReconciledNs : tree == NULL\n");
  5790. #endif
  5791. return(NULL);
  5792. }
  5793. if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) {
  5794. #ifdef DEBUG_TREE
  5795. xmlGenericError(xmlGenericErrorContext,
  5796. "xmlNewReconciledNs : ns == NULL\n");
  5797. #endif
  5798. return(NULL);
  5799. }
  5800. /*
  5801. * Search an existing namespace definition inherited.
  5802. */
  5803. def = xmlSearchNsByHref(doc, tree, ns->href);
  5804. if (def != NULL)
  5805. return(def);
  5806. /*
  5807. * Find a close prefix which is not already in use.
  5808. * Let's strip namespace prefixes longer than 20 chars !
  5809. */
  5810. if (ns->prefix == NULL)
  5811. snprintf((char *) prefix, sizeof(prefix), "default");
  5812. else
  5813. snprintf((char *) prefix, sizeof(prefix), "%.20s", (char *)ns->prefix);
  5814. def = xmlSearchNs(doc, tree, prefix);
  5815. while (def != NULL) {
  5816. if (counter > 1000) return(NULL);
  5817. if (ns->prefix == NULL)
  5818. snprintf((char *) prefix, sizeof(prefix), "default%d", counter++);
  5819. else
  5820. snprintf((char *) prefix, sizeof(prefix), "%.20s%d",
  5821. (char *)ns->prefix, counter++);
  5822. def = xmlSearchNs(doc, tree, prefix);
  5823. }
  5824. /*
  5825. * OK, now we are ready to create a new one.
  5826. */
  5827. def = xmlNewNs(tree, ns->href, prefix);
  5828. return(def);
  5829. }
  5830. #ifdef LIBXML_TREE_ENABLED
  5831. /**
  5832. * xmlReconciliateNs:
  5833. * @doc: the document
  5834. * @tree: a node defining the subtree to reconciliate
  5835. *
  5836. * This function checks that all the namespaces declared within the given
  5837. * tree are properly declared. This is needed for example after Copy or Cut
  5838. * and then paste operations. The subtree may still hold pointers to
  5839. * namespace declarations outside the subtree or invalid/masked. As much
  5840. * as possible the function try to reuse the existing namespaces found in
  5841. * the new environment. If not possible the new namespaces are redeclared
  5842. * on @tree at the top of the given subtree.
  5843. * Returns the number of namespace declarations created or -1 in case of error.
  5844. */
  5845. int
  5846. xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
  5847. xmlNsPtr *oldNs = NULL;
  5848. xmlNsPtr *newNs = NULL;
  5849. int sizeCache = 0;
  5850. int nbCache = 0;
  5851. xmlNsPtr n;
  5852. xmlNodePtr node = tree;
  5853. xmlAttrPtr attr;
  5854. int ret = 0, i;
  5855. if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) return(-1);
  5856. if ((doc == NULL) || (doc->type != XML_DOCUMENT_NODE)) return(-1);
  5857. if (node->doc != doc) return(-1);
  5858. while (node != NULL) {
  5859. /*
  5860. * Reconciliate the node namespace
  5861. */
  5862. if (node->ns != NULL) {
  5863. /*
  5864. * initialize the cache if needed
  5865. */
  5866. if (sizeCache == 0) {
  5867. sizeCache = 10;
  5868. oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
  5869. sizeof(xmlNsPtr));
  5870. if (oldNs == NULL) {
  5871. xmlTreeErrMemory("fixing namespaces");
  5872. return(-1);
  5873. }
  5874. newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
  5875. sizeof(xmlNsPtr));
  5876. if (newNs == NULL) {
  5877. xmlTreeErrMemory("fixing namespaces");
  5878. xmlFree(oldNs);
  5879. return(-1);
  5880. }
  5881. }
  5882. for (i = 0;i < nbCache;i++) {
  5883. if (oldNs[i] == node->ns) {
  5884. node->ns = newNs[i];
  5885. break;
  5886. }
  5887. }
  5888. if (i == nbCache) {
  5889. /*
  5890. * OK we need to recreate a new namespace definition
  5891. */
  5892. n = xmlNewReconciledNs(doc, tree, node->ns);
  5893. if (n != NULL) { /* :-( what if else ??? */
  5894. /*
  5895. * check if we need to grow the cache buffers.
  5896. */
  5897. if (sizeCache <= nbCache) {
  5898. sizeCache *= 2;
  5899. oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
  5900. sizeof(xmlNsPtr));
  5901. if (oldNs == NULL) {
  5902. xmlTreeErrMemory("fixing namespaces");
  5903. xmlFree(newNs);
  5904. return(-1);
  5905. }
  5906. newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
  5907. sizeof(xmlNsPtr));
  5908. if (newNs == NULL) {
  5909. xmlTreeErrMemory("fixing namespaces");
  5910. xmlFree(oldNs);
  5911. return(-1);
  5912. }
  5913. }
  5914. newNs[nbCache] = n;
  5915. oldNs[nbCache++] = node->ns;
  5916. node->ns = n;
  5917. }
  5918. }
  5919. }
  5920. /*
  5921. * now check for namespace held by attributes on the node.
  5922. */
  5923. if (node->type == XML_ELEMENT_NODE) {
  5924. attr = node->properties;
  5925. while (attr != NULL) {
  5926. if (attr->ns != NULL) {
  5927. /*
  5928. * initialize the cache if needed
  5929. */
  5930. if (sizeCache == 0) {
  5931. sizeCache = 10;
  5932. oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
  5933. sizeof(xmlNsPtr));
  5934. if (oldNs == NULL) {
  5935. xmlTreeErrMemory("fixing namespaces");
  5936. return(-1);
  5937. }
  5938. newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
  5939. sizeof(xmlNsPtr));
  5940. if (newNs == NULL) {
  5941. xmlTreeErrMemory("fixing namespaces");
  5942. xmlFree(oldNs);
  5943. return(-1);
  5944. }
  5945. }
  5946. for (i = 0;i < nbCache;i++) {
  5947. if (oldNs[i] == attr->ns) {
  5948. attr->ns = newNs[i];
  5949. break;
  5950. }
  5951. }
  5952. if (i == nbCache) {
  5953. /*
  5954. * OK we need to recreate a new namespace definition
  5955. */
  5956. n = xmlNewReconciledNs(doc, tree, attr->ns);
  5957. if (n != NULL) { /* :-( what if else ??? */
  5958. /*
  5959. * check if we need to grow the cache buffers.
  5960. */
  5961. if (sizeCache <= nbCache) {
  5962. sizeCache *= 2;
  5963. oldNs = (xmlNsPtr *) xmlRealloc(oldNs,
  5964. sizeCache * sizeof(xmlNsPtr));
  5965. if (oldNs == NULL) {
  5966. xmlTreeErrMemory("fixing namespaces");
  5967. xmlFree(newNs);
  5968. return(-1);
  5969. }
  5970. newNs = (xmlNsPtr *) xmlRealloc(newNs,
  5971. sizeCache * sizeof(xmlNsPtr));
  5972. if (newNs == NULL) {
  5973. xmlTreeErrMemory("fixing namespaces");
  5974. xmlFree(oldNs);
  5975. return(-1);
  5976. }
  5977. }
  5978. newNs[nbCache] = n;
  5979. oldNs[nbCache++] = attr->ns;
  5980. attr->ns = n;
  5981. }
  5982. }
  5983. }
  5984. attr = attr->next;
  5985. }
  5986. }
  5987. /*
  5988. * Browse the full subtree, deep first
  5989. */
  5990. if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
  5991. /* deep first */
  5992. node = node->children;
  5993. } else if ((node != tree) && (node->next != NULL)) {
  5994. /* then siblings */
  5995. node = node->next;
  5996. } else if (node != tree) {
  5997. /* go up to parents->next if needed */
  5998. while (node != tree) {
  5999. if (node->parent != NULL)
  6000. node = node->parent;
  6001. if ((node != tree) && (node->next != NULL)) {
  6002. node = node->next;
  6003. break;
  6004. }
  6005. if (node->parent == NULL) {
  6006. node = NULL;
  6007. break;
  6008. }
  6009. }
  6010. /* exit condition */
  6011. if (node == tree)
  6012. node = NULL;
  6013. } else
  6014. break;
  6015. }
  6016. if (oldNs != NULL)
  6017. xmlFree(oldNs);
  6018. if (newNs != NULL)
  6019. xmlFree(newNs);
  6020. return(ret);
  6021. }
  6022. #endif /* LIBXML_TREE_ENABLED */
  6023. static xmlAttrPtr
  6024. xmlGetPropNodeInternal(const xmlNode *node, const xmlChar *name,
  6025. const xmlChar *nsName, int useDTD)
  6026. {
  6027. xmlAttrPtr prop;
  6028. if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
  6029. return(NULL);
  6030. if (node->properties != NULL) {
  6031. prop = node->properties;
  6032. if (nsName == NULL) {
  6033. /*
  6034. * We want the attr to be in no namespace.
  6035. */
  6036. do {
  6037. if ((prop->ns == NULL) && xmlStrEqual(prop->name, name)) {
  6038. return(prop);
  6039. }
  6040. prop = prop->next;
  6041. } while (prop != NULL);
  6042. } else {
  6043. /*
  6044. * We want the attr to be in the specified namespace.
  6045. */
  6046. do {
  6047. if ((prop->ns != NULL) && xmlStrEqual(prop->name, name) &&
  6048. ((prop->ns->href == nsName) ||
  6049. xmlStrEqual(prop->ns->href, nsName)))
  6050. {
  6051. return(prop);
  6052. }
  6053. prop = prop->next;
  6054. } while (prop != NULL);
  6055. }
  6056. }
  6057. #ifdef LIBXML_TREE_ENABLED
  6058. if (! useDTD)
  6059. return(NULL);
  6060. /*
  6061. * Check if there is a default/fixed attribute declaration in
  6062. * the internal or external subset.
  6063. */
  6064. if ((node->doc != NULL) && (node->doc->intSubset != NULL)) {
  6065. xmlDocPtr doc = node->doc;
  6066. xmlAttributePtr attrDecl = NULL;
  6067. xmlChar *elemQName, *tmpstr = NULL;
  6068. /*
  6069. * We need the QName of the element for the DTD-lookup.
  6070. */
  6071. if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
  6072. tmpstr = xmlStrdup(node->ns->prefix);
  6073. tmpstr = xmlStrcat(tmpstr, BAD_CAST ":");
  6074. tmpstr = xmlStrcat(tmpstr, node->name);
  6075. if (tmpstr == NULL)
  6076. return(NULL);
  6077. elemQName = tmpstr;
  6078. } else
  6079. elemQName = (xmlChar *) node->name;
  6080. if (nsName == NULL) {
  6081. /*
  6082. * The common and nice case: Attr in no namespace.
  6083. */
  6084. attrDecl = xmlGetDtdQAttrDesc(doc->intSubset,
  6085. elemQName, name, NULL);
  6086. if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
  6087. attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,
  6088. elemQName, name, NULL);
  6089. }
  6090. } else {
  6091. xmlNsPtr *nsList, *cur;
  6092. /*
  6093. * The ugly case: Search using the prefixes of in-scope
  6094. * ns-decls corresponding to @nsName.
  6095. */
  6096. nsList = xmlGetNsList(node->doc, node);
  6097. if (nsList == NULL) {
  6098. if (tmpstr != NULL)
  6099. xmlFree(tmpstr);
  6100. return(NULL);
  6101. }
  6102. cur = nsList;
  6103. while (*cur != NULL) {
  6104. if (xmlStrEqual((*cur)->href, nsName)) {
  6105. attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elemQName,
  6106. name, (*cur)->prefix);
  6107. if (attrDecl)
  6108. break;
  6109. if (doc->extSubset != NULL) {
  6110. attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elemQName,
  6111. name, (*cur)->prefix);
  6112. if (attrDecl)
  6113. break;
  6114. }
  6115. }
  6116. cur++;
  6117. }
  6118. xmlFree(nsList);
  6119. }
  6120. if (tmpstr != NULL)
  6121. xmlFree(tmpstr);
  6122. /*
  6123. * Only default/fixed attrs are relevant.
  6124. */
  6125. if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL))
  6126. return((xmlAttrPtr) attrDecl);
  6127. }
  6128. #endif /* LIBXML_TREE_ENABLED */
  6129. return(NULL);
  6130. }
  6131. static xmlChar*
  6132. xmlGetPropNodeValueInternal(const xmlAttr *prop)
  6133. {
  6134. if (prop == NULL)
  6135. return(NULL);
  6136. if (prop->type == XML_ATTRIBUTE_NODE) {
  6137. /*
  6138. * Note that we return at least the empty string.
  6139. * TODO: Do we really always want that?
  6140. */
  6141. if (prop->children != NULL) {
  6142. if ((prop->children->next == NULL) &&
  6143. ((prop->children->type == XML_TEXT_NODE) ||
  6144. (prop->children->type == XML_CDATA_SECTION_NODE)))
  6145. {
  6146. /*
  6147. * Optimization for the common case: only 1 text node.
  6148. */
  6149. return(xmlStrdup(prop->children->content));
  6150. } else {
  6151. xmlChar *ret;
  6152. ret = xmlNodeListGetString(prop->doc, prop->children, 1);
  6153. if (ret != NULL)
  6154. return(ret);
  6155. }
  6156. }
  6157. return(xmlStrdup((xmlChar *)""));
  6158. } else if (prop->type == XML_ATTRIBUTE_DECL) {
  6159. return(xmlStrdup(((xmlAttributePtr)prop)->defaultValue));
  6160. }
  6161. return(NULL);
  6162. }
  6163. /**
  6164. * xmlHasProp:
  6165. * @node: the node
  6166. * @name: the attribute name
  6167. *
  6168. * Search an attribute associated to a node
  6169. * This function also looks in DTD attribute declaration for #FIXED or
  6170. * default declaration values unless DTD use has been turned off.
  6171. *
  6172. * Returns the attribute or the attribute declaration or NULL if
  6173. * neither was found.
  6174. */
  6175. xmlAttrPtr
  6176. xmlHasProp(const xmlNode *node, const xmlChar *name) {
  6177. xmlAttrPtr prop;
  6178. xmlDocPtr doc;
  6179. if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
  6180. return(NULL);
  6181. /*
  6182. * Check on the properties attached to the node
  6183. */
  6184. prop = node->properties;
  6185. while (prop != NULL) {
  6186. if (xmlStrEqual(prop->name, name)) {
  6187. return(prop);
  6188. }
  6189. prop = prop->next;
  6190. }
  6191. if (!xmlCheckDTD) return(NULL);
  6192. /*
  6193. * Check if there is a default declaration in the internal
  6194. * or external subsets
  6195. */
  6196. doc = node->doc;
  6197. if (doc != NULL) {
  6198. xmlAttributePtr attrDecl;
  6199. if (doc->intSubset != NULL) {
  6200. attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
  6201. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  6202. attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
  6203. if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL))
  6204. /* return attribute declaration only if a default value is given
  6205. (that includes #FIXED declarations) */
  6206. return((xmlAttrPtr) attrDecl);
  6207. }
  6208. }
  6209. return(NULL);
  6210. }
  6211. /**
  6212. * xmlHasNsProp:
  6213. * @node: the node
  6214. * @name: the attribute name
  6215. * @nameSpace: the URI of the namespace
  6216. *
  6217. * Search for an attribute associated to a node
  6218. * This attribute has to be anchored in the namespace specified.
  6219. * This does the entity substitution.
  6220. * This function looks in DTD attribute declaration for #FIXED or
  6221. * default declaration values unless DTD use has been turned off.
  6222. * Note that a namespace of NULL indicates to use the default namespace.
  6223. *
  6224. * Returns the attribute or the attribute declaration or NULL
  6225. * if neither was found.
  6226. */
  6227. xmlAttrPtr
  6228. xmlHasNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) {
  6229. return(xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD));
  6230. }
  6231. /**
  6232. * xmlGetProp:
  6233. * @node: the node
  6234. * @name: the attribute name
  6235. *
  6236. * Search and get the value of an attribute associated to a node
  6237. * This does the entity substitution.
  6238. * This function looks in DTD attribute declaration for #FIXED or
  6239. * default declaration values unless DTD use has been turned off.
  6240. * NOTE: this function acts independently of namespaces associated
  6241. * to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp()
  6242. * for namespace aware processing.
  6243. *
  6244. * Returns the attribute value or NULL if not found.
  6245. * It's up to the caller to free the memory with xmlFree().
  6246. */
  6247. xmlChar *
  6248. xmlGetProp(const xmlNode *node, const xmlChar *name) {
  6249. xmlAttrPtr prop;
  6250. prop = xmlHasProp(node, name);
  6251. if (prop == NULL)
  6252. return(NULL);
  6253. return(xmlGetPropNodeValueInternal(prop));
  6254. }
  6255. /**
  6256. * xmlGetNoNsProp:
  6257. * @node: the node
  6258. * @name: the attribute name
  6259. *
  6260. * Search and get the value of an attribute associated to a node
  6261. * This does the entity substitution.
  6262. * This function looks in DTD attribute declaration for #FIXED or
  6263. * default declaration values unless DTD use has been turned off.
  6264. * This function is similar to xmlGetProp except it will accept only
  6265. * an attribute in no namespace.
  6266. *
  6267. * Returns the attribute value or NULL if not found.
  6268. * It's up to the caller to free the memory with xmlFree().
  6269. */
  6270. xmlChar *
  6271. xmlGetNoNsProp(const xmlNode *node, const xmlChar *name) {
  6272. xmlAttrPtr prop;
  6273. prop = xmlGetPropNodeInternal(node, name, NULL, xmlCheckDTD);
  6274. if (prop == NULL)
  6275. return(NULL);
  6276. return(xmlGetPropNodeValueInternal(prop));
  6277. }
  6278. /**
  6279. * xmlGetNsProp:
  6280. * @node: the node
  6281. * @name: the attribute name
  6282. * @nameSpace: the URI of the namespace
  6283. *
  6284. * Search and get the value of an attribute associated to a node
  6285. * This attribute has to be anchored in the namespace specified.
  6286. * This does the entity substitution.
  6287. * This function looks in DTD attribute declaration for #FIXED or
  6288. * default declaration values unless DTD use has been turned off.
  6289. *
  6290. * Returns the attribute value or NULL if not found.
  6291. * It's up to the caller to free the memory with xmlFree().
  6292. */
  6293. xmlChar *
  6294. xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) {
  6295. xmlAttrPtr prop;
  6296. prop = xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD);
  6297. if (prop == NULL)
  6298. return(NULL);
  6299. return(xmlGetPropNodeValueInternal(prop));
  6300. }
  6301. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
  6302. /**
  6303. * xmlUnsetProp:
  6304. * @node: the node
  6305. * @name: the attribute name
  6306. *
  6307. * Remove an attribute carried by a node.
  6308. * This handles only attributes in no namespace.
  6309. * Returns 0 if successful, -1 if not found
  6310. */
  6311. int
  6312. xmlUnsetProp(xmlNodePtr node, const xmlChar *name) {
  6313. xmlAttrPtr prop;
  6314. prop = xmlGetPropNodeInternal(node, name, NULL, 0);
  6315. if (prop == NULL)
  6316. return(-1);
  6317. xmlUnlinkNode((xmlNodePtr) prop);
  6318. xmlFreeProp(prop);
  6319. return(0);
  6320. }
  6321. /**
  6322. * xmlUnsetNsProp:
  6323. * @node: the node
  6324. * @ns: the namespace definition
  6325. * @name: the attribute name
  6326. *
  6327. * Remove an attribute carried by a node.
  6328. * Returns 0 if successful, -1 if not found
  6329. */
  6330. int
  6331. xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) {
  6332. xmlAttrPtr prop;
  6333. prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
  6334. if (prop == NULL)
  6335. return(-1);
  6336. xmlUnlinkNode((xmlNodePtr) prop);
  6337. xmlFreeProp(prop);
  6338. return(0);
  6339. }
  6340. #endif
  6341. #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)
  6342. /**
  6343. * xmlSetProp:
  6344. * @node: the node
  6345. * @name: the attribute name (a QName)
  6346. * @value: the attribute value
  6347. *
  6348. * Set (or reset) an attribute carried by a node.
  6349. * If @name has a prefix, then the corresponding
  6350. * namespace-binding will be used, if in scope; it is an
  6351. * error it there's no such ns-binding for the prefix in
  6352. * scope.
  6353. * Returns the attribute pointer.
  6354. *
  6355. */
  6356. xmlAttrPtr
  6357. xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
  6358. int len;
  6359. const xmlChar *nqname;
  6360. if ((node == NULL) || (name == NULL) || (node->type != XML_ELEMENT_NODE))
  6361. return(NULL);
  6362. /*
  6363. * handle QNames
  6364. */
  6365. nqname = xmlSplitQName3(name, &len);
  6366. if (nqname != NULL) {
  6367. xmlNsPtr ns;
  6368. xmlChar *prefix = xmlStrndup(name, len);
  6369. ns = xmlSearchNs(node->doc, node, prefix);
  6370. if (prefix != NULL)
  6371. xmlFree(prefix);
  6372. if (ns != NULL)
  6373. return(xmlSetNsProp(node, ns, nqname, value));
  6374. }
  6375. return(xmlSetNsProp(node, NULL, name, value));
  6376. }
  6377. /**
  6378. * xmlSetNsProp:
  6379. * @node: the node
  6380. * @ns: the namespace definition
  6381. * @name: the attribute name
  6382. * @value: the attribute value
  6383. *
  6384. * Set (or reset) an attribute carried by a node.
  6385. * The ns structure must be in scope, this is not checked
  6386. *
  6387. * Returns the attribute pointer.
  6388. */
  6389. xmlAttrPtr
  6390. xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
  6391. const xmlChar *value)
  6392. {
  6393. xmlAttrPtr prop;
  6394. if (ns && (ns->href == NULL))
  6395. return(NULL);
  6396. prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
  6397. if (prop != NULL) {
  6398. /*
  6399. * Modify the attribute's value.
  6400. */
  6401. if (prop->atype == XML_ATTRIBUTE_ID) {
  6402. xmlRemoveID(node->doc, prop);
  6403. prop->atype = XML_ATTRIBUTE_ID;
  6404. }
  6405. if (prop->children != NULL)
  6406. xmlFreeNodeList(prop->children);
  6407. prop->children = NULL;
  6408. prop->last = NULL;
  6409. prop->ns = ns;
  6410. if (value != NULL) {
  6411. xmlNodePtr tmp;
  6412. if(!xmlCheckUTF8(value)) {
  6413. xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) node->doc,
  6414. NULL);
  6415. if (node->doc != NULL)
  6416. node->doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
  6417. }
  6418. prop->children = xmlNewDocText(node->doc, value);
  6419. prop->last = NULL;
  6420. tmp = prop->children;
  6421. while (tmp != NULL) {
  6422. tmp->parent = (xmlNodePtr) prop;
  6423. if (tmp->next == NULL)
  6424. prop->last = tmp;
  6425. tmp = tmp->next;
  6426. }
  6427. }
  6428. if (prop->atype == XML_ATTRIBUTE_ID)
  6429. xmlAddID(NULL, node->doc, value, prop);
  6430. return(prop);
  6431. }
  6432. /*
  6433. * No equal attr found; create a new one.
  6434. */
  6435. return(xmlNewPropInternal(node, ns, name, value, 0));
  6436. }
  6437. #endif /* LIBXML_TREE_ENABLED */
  6438. /**
  6439. * xmlNodeIsText:
  6440. * @node: the node
  6441. *
  6442. * Is this node a Text node ?
  6443. * Returns 1 yes, 0 no
  6444. */
  6445. int
  6446. xmlNodeIsText(const xmlNode *node) {
  6447. if (node == NULL) return(0);
  6448. if (node->type == XML_TEXT_NODE) return(1);
  6449. return(0);
  6450. }
  6451. /**
  6452. * xmlIsBlankNode:
  6453. * @node: the node
  6454. *
  6455. * Checks whether this node is an empty or whitespace only
  6456. * (and possibly ignorable) text-node.
  6457. *
  6458. * Returns 1 yes, 0 no
  6459. */
  6460. int
  6461. xmlIsBlankNode(const xmlNode *node) {
  6462. const xmlChar *cur;
  6463. if (node == NULL) return(0);
  6464. if ((node->type != XML_TEXT_NODE) &&
  6465. (node->type != XML_CDATA_SECTION_NODE))
  6466. return(0);
  6467. if (node->content == NULL) return(1);
  6468. cur = node->content;
  6469. while (*cur != 0) {
  6470. if (!IS_BLANK_CH(*cur)) return(0);
  6471. cur++;
  6472. }
  6473. return(1);
  6474. }
  6475. /**
  6476. * xmlTextConcat:
  6477. * @node: the node
  6478. * @content: the content
  6479. * @len: @content length
  6480. *
  6481. * Concat the given string at the end of the existing node content
  6482. *
  6483. * Returns -1 in case of error, 0 otherwise
  6484. */
  6485. int
  6486. xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
  6487. if (node == NULL) return(-1);
  6488. if ((node->type != XML_TEXT_NODE) &&
  6489. (node->type != XML_CDATA_SECTION_NODE) &&
  6490. (node->type != XML_COMMENT_NODE) &&
  6491. (node->type != XML_PI_NODE)) {
  6492. #ifdef DEBUG_TREE
  6493. xmlGenericError(xmlGenericErrorContext,
  6494. "xmlTextConcat: node is not text nor CDATA\n");
  6495. #endif
  6496. return(-1);
  6497. }
  6498. /* need to check if content is currently in the dictionary */
  6499. if ((node->content == (xmlChar *) &(node->properties)) ||
  6500. ((node->doc != NULL) && (node->doc->dict != NULL) &&
  6501. xmlDictOwns(node->doc->dict, node->content))) {
  6502. node->content = xmlStrncatNew(node->content, content, len);
  6503. } else {
  6504. node->content = xmlStrncat(node->content, content, len);
  6505. }
  6506. node->properties = NULL;
  6507. if (node->content == NULL)
  6508. return(-1);
  6509. return(0);
  6510. }
  6511. /************************************************************************
  6512. * *
  6513. * Output : to a FILE or in memory *
  6514. * *
  6515. ************************************************************************/
  6516. /**
  6517. * xmlBufferCreate:
  6518. *
  6519. * routine to create an XML buffer.
  6520. * returns the new structure.
  6521. */
  6522. xmlBufferPtr
  6523. xmlBufferCreate(void) {
  6524. xmlBufferPtr ret;
  6525. ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
  6526. if (ret == NULL) {
  6527. xmlTreeErrMemory("creating buffer");
  6528. return(NULL);
  6529. }
  6530. ret->use = 0;
  6531. ret->size = xmlDefaultBufferSize;
  6532. ret->alloc = xmlBufferAllocScheme;
  6533. ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
  6534. if (ret->content == NULL) {
  6535. xmlTreeErrMemory("creating buffer");
  6536. xmlFree(ret);
  6537. return(NULL);
  6538. }
  6539. ret->content[0] = 0;
  6540. ret->contentIO = NULL;
  6541. return(ret);
  6542. }
  6543. /**
  6544. * xmlBufferCreateSize:
  6545. * @size: initial size of buffer
  6546. *
  6547. * routine to create an XML buffer.
  6548. * returns the new structure.
  6549. */
  6550. xmlBufferPtr
  6551. xmlBufferCreateSize(size_t size) {
  6552. xmlBufferPtr ret;
  6553. ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
  6554. if (ret == NULL) {
  6555. xmlTreeErrMemory("creating buffer");
  6556. return(NULL);
  6557. }
  6558. ret->use = 0;
  6559. ret->alloc = xmlBufferAllocScheme;
  6560. ret->size = (size ? size+2 : 0); /* +1 for ending null */
  6561. if (ret->size){
  6562. ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
  6563. if (ret->content == NULL) {
  6564. xmlTreeErrMemory("creating buffer");
  6565. xmlFree(ret);
  6566. return(NULL);
  6567. }
  6568. ret->content[0] = 0;
  6569. } else
  6570. ret->content = NULL;
  6571. ret->contentIO = NULL;
  6572. return(ret);
  6573. }
  6574. /**
  6575. * xmlBufferDetach:
  6576. * @buf: the buffer
  6577. *
  6578. * Remove the string contained in a buffer and gie it back to the
  6579. * caller. The buffer is reset to an empty content.
  6580. * This doesn't work with immutable buffers as they can't be reset.
  6581. *
  6582. * Returns the previous string contained by the buffer.
  6583. */
  6584. xmlChar *
  6585. xmlBufferDetach(xmlBufferPtr buf) {
  6586. xmlChar *ret;
  6587. if (buf == NULL)
  6588. return(NULL);
  6589. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
  6590. return(NULL);
  6591. ret = buf->content;
  6592. buf->content = NULL;
  6593. buf->size = 0;
  6594. buf->use = 0;
  6595. return ret;
  6596. }
  6597. /**
  6598. * xmlBufferCreateStatic:
  6599. * @mem: the memory area
  6600. * @size: the size in byte
  6601. *
  6602. * routine to create an XML buffer from an immutable memory area.
  6603. * The area won't be modified nor copied, and is expected to be
  6604. * present until the end of the buffer lifetime.
  6605. *
  6606. * returns the new structure.
  6607. */
  6608. xmlBufferPtr
  6609. xmlBufferCreateStatic(void *mem, size_t size) {
  6610. xmlBufferPtr ret;
  6611. if ((mem == NULL) || (size == 0))
  6612. return(NULL);
  6613. ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
  6614. if (ret == NULL) {
  6615. xmlTreeErrMemory("creating buffer");
  6616. return(NULL);
  6617. }
  6618. ret->use = size;
  6619. ret->size = size;
  6620. ret->alloc = XML_BUFFER_ALLOC_IMMUTABLE;
  6621. ret->content = (xmlChar *) mem;
  6622. return(ret);
  6623. }
  6624. /**
  6625. * xmlBufferSetAllocationScheme:
  6626. * @buf: the buffer to tune
  6627. * @scheme: allocation scheme to use
  6628. *
  6629. * Sets the allocation scheme for this buffer
  6630. */
  6631. void
  6632. xmlBufferSetAllocationScheme(xmlBufferPtr buf,
  6633. xmlBufferAllocationScheme scheme) {
  6634. if (buf == NULL) {
  6635. #ifdef DEBUG_BUFFER
  6636. xmlGenericError(xmlGenericErrorContext,
  6637. "xmlBufferSetAllocationScheme: buf == NULL\n");
  6638. #endif
  6639. return;
  6640. }
  6641. if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
  6642. (buf->alloc == XML_BUFFER_ALLOC_IO)) return;
  6643. if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
  6644. (scheme == XML_BUFFER_ALLOC_EXACT) ||
  6645. (scheme == XML_BUFFER_ALLOC_HYBRID) ||
  6646. (scheme == XML_BUFFER_ALLOC_IMMUTABLE))
  6647. buf->alloc = scheme;
  6648. }
  6649. /**
  6650. * xmlBufferFree:
  6651. * @buf: the buffer to free
  6652. *
  6653. * Frees an XML buffer. It frees both the content and the structure which
  6654. * encapsulate it.
  6655. */
  6656. void
  6657. xmlBufferFree(xmlBufferPtr buf) {
  6658. if (buf == NULL) {
  6659. #ifdef DEBUG_BUFFER
  6660. xmlGenericError(xmlGenericErrorContext,
  6661. "xmlBufferFree: buf == NULL\n");
  6662. #endif
  6663. return;
  6664. }
  6665. if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
  6666. (buf->contentIO != NULL)) {
  6667. xmlFree(buf->contentIO);
  6668. } else if ((buf->content != NULL) &&
  6669. (buf->alloc != XML_BUFFER_ALLOC_IMMUTABLE)) {
  6670. xmlFree(buf->content);
  6671. }
  6672. xmlFree(buf);
  6673. }
  6674. /**
  6675. * xmlBufferEmpty:
  6676. * @buf: the buffer
  6677. *
  6678. * empty a buffer.
  6679. */
  6680. void
  6681. xmlBufferEmpty(xmlBufferPtr buf) {
  6682. if (buf == NULL) return;
  6683. if (buf->content == NULL) return;
  6684. buf->use = 0;
  6685. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) {
  6686. buf->content = BAD_CAST "";
  6687. } else if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
  6688. (buf->contentIO != NULL)) {
  6689. size_t start_buf = buf->content - buf->contentIO;
  6690. buf->size += start_buf;
  6691. buf->content = buf->contentIO;
  6692. buf->content[0] = 0;
  6693. } else {
  6694. buf->content[0] = 0;
  6695. }
  6696. }
  6697. /**
  6698. * xmlBufferShrink:
  6699. * @buf: the buffer to dump
  6700. * @len: the number of xmlChar to remove
  6701. *
  6702. * Remove the beginning of an XML buffer.
  6703. *
  6704. * Returns the number of #xmlChar removed, or -1 in case of failure.
  6705. */
  6706. int
  6707. xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
  6708. if (buf == NULL) return(-1);
  6709. if (len == 0) return(0);
  6710. if (len > buf->use) return(-1);
  6711. buf->use -= len;
  6712. if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
  6713. ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL))) {
  6714. /*
  6715. * we just move the content pointer, but also make sure
  6716. * the perceived buffer size has shrinked accordingly
  6717. */
  6718. buf->content += len;
  6719. buf->size -= len;
  6720. /*
  6721. * sometimes though it maybe be better to really shrink
  6722. * on IO buffers
  6723. */
  6724. if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
  6725. size_t start_buf = buf->content - buf->contentIO;
  6726. if (start_buf >= buf->size) {
  6727. memmove(buf->contentIO, &buf->content[0], buf->use);
  6728. buf->content = buf->contentIO;
  6729. buf->content[buf->use] = 0;
  6730. buf->size += start_buf;
  6731. }
  6732. }
  6733. } else {
  6734. memmove(buf->content, &buf->content[len], buf->use);
  6735. buf->content[buf->use] = 0;
  6736. }
  6737. return(len);
  6738. }
  6739. /**
  6740. * xmlBufferGrow:
  6741. * @buf: the buffer
  6742. * @len: the minimum free size to allocate
  6743. *
  6744. * Grow the available space of an XML buffer.
  6745. *
  6746. * Returns the new available space or -1 in case of error
  6747. */
  6748. int
  6749. xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
  6750. int size;
  6751. xmlChar *newbuf;
  6752. if (buf == NULL) return(-1);
  6753. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
  6754. if (len + buf->use < buf->size) return(0);
  6755. /*
  6756. * Windows has a BIG problem on realloc timing, so we try to double
  6757. * the buffer size (if that's enough) (bug 146697)
  6758. * Apparently BSD too, and it's probably best for linux too
  6759. * On an embedded system this may be something to change
  6760. */
  6761. #if 1
  6762. if (buf->size > len)
  6763. size = buf->size * 2;
  6764. else
  6765. size = buf->use + len + 100;
  6766. #else
  6767. size = buf->use + len + 100;
  6768. #endif
  6769. if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
  6770. size_t start_buf = buf->content - buf->contentIO;
  6771. newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);
  6772. if (newbuf == NULL) {
  6773. xmlTreeErrMemory("growing buffer");
  6774. return(-1);
  6775. }
  6776. buf->contentIO = newbuf;
  6777. buf->content = newbuf + start_buf;
  6778. } else {
  6779. newbuf = (xmlChar *) xmlRealloc(buf->content, size);
  6780. if (newbuf == NULL) {
  6781. xmlTreeErrMemory("growing buffer");
  6782. return(-1);
  6783. }
  6784. buf->content = newbuf;
  6785. }
  6786. buf->size = size;
  6787. return(buf->size - buf->use);
  6788. }
  6789. /**
  6790. * xmlBufferDump:
  6791. * @file: the file output
  6792. * @buf: the buffer to dump
  6793. *
  6794. * Dumps an XML buffer to a FILE *.
  6795. * Returns the number of #xmlChar written
  6796. */
  6797. int
  6798. xmlBufferDump(FILE *file, xmlBufferPtr buf) {
  6799. int ret;
  6800. if (buf == NULL) {
  6801. #ifdef DEBUG_BUFFER
  6802. xmlGenericError(xmlGenericErrorContext,
  6803. "xmlBufferDump: buf == NULL\n");
  6804. #endif
  6805. return(0);
  6806. }
  6807. if (buf->content == NULL) {
  6808. #ifdef DEBUG_BUFFER
  6809. xmlGenericError(xmlGenericErrorContext,
  6810. "xmlBufferDump: buf->content == NULL\n");
  6811. #endif
  6812. return(0);
  6813. }
  6814. if (file == NULL)
  6815. file = stdout;
  6816. ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
  6817. return(ret);
  6818. }
  6819. /**
  6820. * xmlBufferContent:
  6821. * @buf: the buffer
  6822. *
  6823. * Function to extract the content of a buffer
  6824. *
  6825. * Returns the internal content
  6826. */
  6827. const xmlChar *
  6828. xmlBufferContent(const xmlBuffer *buf)
  6829. {
  6830. if(!buf)
  6831. return NULL;
  6832. return buf->content;
  6833. }
  6834. /**
  6835. * xmlBufferLength:
  6836. * @buf: the buffer
  6837. *
  6838. * Function to get the length of a buffer
  6839. *
  6840. * Returns the length of data in the internal content
  6841. */
  6842. int
  6843. xmlBufferLength(const xmlBuffer *buf)
  6844. {
  6845. if(!buf)
  6846. return 0;
  6847. return buf->use;
  6848. }
  6849. /**
  6850. * xmlBufferResize:
  6851. * @buf: the buffer to resize
  6852. * @size: the desired size
  6853. *
  6854. * Resize a buffer to accommodate minimum size of @size.
  6855. *
  6856. * Returns 0 in case of problems, 1 otherwise
  6857. */
  6858. int
  6859. xmlBufferResize(xmlBufferPtr buf, unsigned int size)
  6860. {
  6861. unsigned int newSize;
  6862. xmlChar* rebuf = NULL;
  6863. size_t start_buf;
  6864. if (buf == NULL)
  6865. return(0);
  6866. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
  6867. /* Don't resize if we don't have to */
  6868. if (size < buf->size)
  6869. return 1;
  6870. /* figure out new size */
  6871. switch (buf->alloc){
  6872. case XML_BUFFER_ALLOC_IO:
  6873. case XML_BUFFER_ALLOC_DOUBLEIT:
  6874. /*take care of empty case*/
  6875. newSize = (buf->size ? buf->size*2 : size + 10);
  6876. while (size > newSize) {
  6877. if (newSize > UINT_MAX / 2) {
  6878. xmlTreeErrMemory("growing buffer");
  6879. return 0;
  6880. }
  6881. newSize *= 2;
  6882. }
  6883. break;
  6884. case XML_BUFFER_ALLOC_EXACT:
  6885. newSize = size+10;
  6886. break;
  6887. case XML_BUFFER_ALLOC_HYBRID:
  6888. if (buf->use < BASE_BUFFER_SIZE)
  6889. newSize = size;
  6890. else {
  6891. newSize = buf->size * 2;
  6892. while (size > newSize) {
  6893. if (newSize > UINT_MAX / 2) {
  6894. xmlTreeErrMemory("growing buffer");
  6895. return 0;
  6896. }
  6897. newSize *= 2;
  6898. }
  6899. }
  6900. break;
  6901. default:
  6902. newSize = size+10;
  6903. break;
  6904. }
  6905. if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
  6906. start_buf = buf->content - buf->contentIO;
  6907. if (start_buf > newSize) {
  6908. /* move data back to start */
  6909. memmove(buf->contentIO, buf->content, buf->use);
  6910. buf->content = buf->contentIO;
  6911. buf->content[buf->use] = 0;
  6912. buf->size += start_buf;
  6913. } else {
  6914. rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);
  6915. if (rebuf == NULL) {
  6916. xmlTreeErrMemory("growing buffer");
  6917. return 0;
  6918. }
  6919. buf->contentIO = rebuf;
  6920. buf->content = rebuf + start_buf;
  6921. }
  6922. } else {
  6923. if (buf->content == NULL) {
  6924. rebuf = (xmlChar *) xmlMallocAtomic(newSize);
  6925. } else if (buf->size - buf->use < 100) {
  6926. rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);
  6927. } else {
  6928. /*
  6929. * if we are reallocating a buffer far from being full, it's
  6930. * better to make a new allocation and copy only the used range
  6931. * and free the old one.
  6932. */
  6933. rebuf = (xmlChar *) xmlMallocAtomic(newSize);
  6934. if (rebuf != NULL) {
  6935. memcpy(rebuf, buf->content, buf->use);
  6936. xmlFree(buf->content);
  6937. rebuf[buf->use] = 0;
  6938. }
  6939. }
  6940. if (rebuf == NULL) {
  6941. xmlTreeErrMemory("growing buffer");
  6942. return 0;
  6943. }
  6944. buf->content = rebuf;
  6945. }
  6946. buf->size = newSize;
  6947. return 1;
  6948. }
  6949. /**
  6950. * xmlBufferAdd:
  6951. * @buf: the buffer to dump
  6952. * @str: the #xmlChar string
  6953. * @len: the number of #xmlChar to add
  6954. *
  6955. * Add a string range to an XML buffer. if len == -1, the length of
  6956. * str is recomputed.
  6957. *
  6958. * Returns 0 successful, a positive error code number otherwise
  6959. * and -1 in case of internal or API error.
  6960. */
  6961. int
  6962. xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
  6963. unsigned int needSize;
  6964. if ((str == NULL) || (buf == NULL)) {
  6965. return -1;
  6966. }
  6967. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
  6968. if (len < -1) {
  6969. #ifdef DEBUG_BUFFER
  6970. xmlGenericError(xmlGenericErrorContext,
  6971. "xmlBufferAdd: len < 0\n");
  6972. #endif
  6973. return -1;
  6974. }
  6975. if (len == 0) return 0;
  6976. if (len < 0)
  6977. len = xmlStrlen(str);
  6978. if (len < 0) return -1;
  6979. if (len == 0) return 0;
  6980. needSize = buf->use + len + 2;
  6981. if (needSize > buf->size){
  6982. if (!xmlBufferResize(buf, needSize)){
  6983. xmlTreeErrMemory("growing buffer");
  6984. return XML_ERR_NO_MEMORY;
  6985. }
  6986. }
  6987. memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
  6988. buf->use += len;
  6989. buf->content[buf->use] = 0;
  6990. return 0;
  6991. }
  6992. /**
  6993. * xmlBufferAddHead:
  6994. * @buf: the buffer
  6995. * @str: the #xmlChar string
  6996. * @len: the number of #xmlChar to add
  6997. *
  6998. * Add a string range to the beginning of an XML buffer.
  6999. * if len == -1, the length of @str is recomputed.
  7000. *
  7001. * Returns 0 successful, a positive error code number otherwise
  7002. * and -1 in case of internal or API error.
  7003. */
  7004. int
  7005. xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
  7006. unsigned int needSize;
  7007. if (buf == NULL)
  7008. return(-1);
  7009. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
  7010. if (str == NULL) {
  7011. #ifdef DEBUG_BUFFER
  7012. xmlGenericError(xmlGenericErrorContext,
  7013. "xmlBufferAddHead: str == NULL\n");
  7014. #endif
  7015. return -1;
  7016. }
  7017. if (len < -1) {
  7018. #ifdef DEBUG_BUFFER
  7019. xmlGenericError(xmlGenericErrorContext,
  7020. "xmlBufferAddHead: len < 0\n");
  7021. #endif
  7022. return -1;
  7023. }
  7024. if (len == 0) return 0;
  7025. if (len < 0)
  7026. len = xmlStrlen(str);
  7027. if (len <= 0) return -1;
  7028. if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
  7029. size_t start_buf = buf->content - buf->contentIO;
  7030. if (start_buf > (unsigned int) len) {
  7031. /*
  7032. * We can add it in the space previously shrinked
  7033. */
  7034. buf->content -= len;
  7035. memmove(&buf->content[0], str, len);
  7036. buf->use += len;
  7037. buf->size += len;
  7038. return(0);
  7039. }
  7040. }
  7041. needSize = buf->use + len + 2;
  7042. if (needSize > buf->size){
  7043. if (!xmlBufferResize(buf, needSize)){
  7044. xmlTreeErrMemory("growing buffer");
  7045. return XML_ERR_NO_MEMORY;
  7046. }
  7047. }
  7048. memmove(&buf->content[len], &buf->content[0], buf->use);
  7049. memmove(&buf->content[0], str, len);
  7050. buf->use += len;
  7051. buf->content[buf->use] = 0;
  7052. return 0;
  7053. }
  7054. /**
  7055. * xmlBufferCat:
  7056. * @buf: the buffer to add to
  7057. * @str: the #xmlChar string
  7058. *
  7059. * Append a zero terminated string to an XML buffer.
  7060. *
  7061. * Returns 0 successful, a positive error code number otherwise
  7062. * and -1 in case of internal or API error.
  7063. */
  7064. int
  7065. xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
  7066. if (buf == NULL)
  7067. return(-1);
  7068. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
  7069. if (str == NULL) return -1;
  7070. return xmlBufferAdd(buf, str, -1);
  7071. }
  7072. /**
  7073. * xmlBufferCCat:
  7074. * @buf: the buffer to dump
  7075. * @str: the C char string
  7076. *
  7077. * Append a zero terminated C string to an XML buffer.
  7078. *
  7079. * Returns 0 successful, a positive error code number otherwise
  7080. * and -1 in case of internal or API error.
  7081. */
  7082. int
  7083. xmlBufferCCat(xmlBufferPtr buf, const char *str) {
  7084. const char *cur;
  7085. if (buf == NULL)
  7086. return(-1);
  7087. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
  7088. if (str == NULL) {
  7089. #ifdef DEBUG_BUFFER
  7090. xmlGenericError(xmlGenericErrorContext,
  7091. "xmlBufferCCat: str == NULL\n");
  7092. #endif
  7093. return -1;
  7094. }
  7095. for (cur = str;*cur != 0;cur++) {
  7096. if (buf->use + 10 >= buf->size) {
  7097. if (!xmlBufferResize(buf, buf->use+10)){
  7098. xmlTreeErrMemory("growing buffer");
  7099. return XML_ERR_NO_MEMORY;
  7100. }
  7101. }
  7102. buf->content[buf->use++] = *cur;
  7103. }
  7104. buf->content[buf->use] = 0;
  7105. return 0;
  7106. }
  7107. /**
  7108. * xmlBufferWriteCHAR:
  7109. * @buf: the XML buffer
  7110. * @string: the string to add
  7111. *
  7112. * routine which manages and grows an output buffer. This one adds
  7113. * xmlChars at the end of the buffer.
  7114. */
  7115. void
  7116. xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
  7117. if (buf == NULL)
  7118. return;
  7119. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
  7120. xmlBufferCat(buf, string);
  7121. }
  7122. /**
  7123. * xmlBufferWriteChar:
  7124. * @buf: the XML buffer output
  7125. * @string: the string to add
  7126. *
  7127. * routine which manage and grows an output buffer. This one add
  7128. * C chars at the end of the array.
  7129. */
  7130. void
  7131. xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
  7132. if (buf == NULL)
  7133. return;
  7134. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
  7135. xmlBufferCCat(buf, string);
  7136. }
  7137. /**
  7138. * xmlBufferWriteQuotedString:
  7139. * @buf: the XML buffer output
  7140. * @string: the string to add
  7141. *
  7142. * routine which manage and grows an output buffer. This one writes
  7143. * a quoted or double quoted #xmlChar string, checking first if it holds
  7144. * quote or double-quotes internally
  7145. */
  7146. void
  7147. xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
  7148. const xmlChar *cur, *base;
  7149. if (buf == NULL)
  7150. return;
  7151. if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
  7152. if (xmlStrchr(string, '\"')) {
  7153. if (xmlStrchr(string, '\'')) {
  7154. #ifdef DEBUG_BUFFER
  7155. xmlGenericError(xmlGenericErrorContext,
  7156. "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
  7157. #endif
  7158. xmlBufferCCat(buf, "\"");
  7159. base = cur = string;
  7160. while(*cur != 0){
  7161. if(*cur == '"'){
  7162. if (base != cur)
  7163. xmlBufferAdd(buf, base, cur - base);
  7164. xmlBufferAdd(buf, BAD_CAST "&quot;", 6);
  7165. cur++;
  7166. base = cur;
  7167. }
  7168. else {
  7169. cur++;
  7170. }
  7171. }
  7172. if (base != cur)
  7173. xmlBufferAdd(buf, base, cur - base);
  7174. xmlBufferCCat(buf, "\"");
  7175. }
  7176. else{
  7177. xmlBufferCCat(buf, "\'");
  7178. xmlBufferCat(buf, string);
  7179. xmlBufferCCat(buf, "\'");
  7180. }
  7181. } else {
  7182. xmlBufferCCat(buf, "\"");
  7183. xmlBufferCat(buf, string);
  7184. xmlBufferCCat(buf, "\"");
  7185. }
  7186. }
  7187. /**
  7188. * xmlGetDocCompressMode:
  7189. * @doc: the document
  7190. *
  7191. * get the compression ratio for a document, ZLIB based
  7192. * Returns 0 (uncompressed) to 9 (max compression)
  7193. */
  7194. int
  7195. xmlGetDocCompressMode (const xmlDoc *doc) {
  7196. if (doc == NULL) return(-1);
  7197. return(doc->compression);
  7198. }
  7199. /**
  7200. * xmlSetDocCompressMode:
  7201. * @doc: the document
  7202. * @mode: the compression ratio
  7203. *
  7204. * set the compression ratio for a document, ZLIB based
  7205. * Correct values: 0 (uncompressed) to 9 (max compression)
  7206. */
  7207. void
  7208. xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
  7209. if (doc == NULL) return;
  7210. if (mode < 0) doc->compression = 0;
  7211. else if (mode > 9) doc->compression = 9;
  7212. else doc->compression = mode;
  7213. }
  7214. /**
  7215. * xmlGetCompressMode:
  7216. *
  7217. * get the default compression mode used, ZLIB based.
  7218. * Returns 0 (uncompressed) to 9 (max compression)
  7219. */
  7220. int
  7221. xmlGetCompressMode(void)
  7222. {
  7223. return (xmlCompressMode);
  7224. }
  7225. /**
  7226. * xmlSetCompressMode:
  7227. * @mode: the compression ratio
  7228. *
  7229. * set the default compression mode used, ZLIB based
  7230. * Correct values: 0 (uncompressed) to 9 (max compression)
  7231. */
  7232. void
  7233. xmlSetCompressMode(int mode) {
  7234. if (mode < 0) xmlCompressMode = 0;
  7235. else if (mode > 9) xmlCompressMode = 9;
  7236. else xmlCompressMode = mode;
  7237. }
  7238. #define XML_TREE_NSMAP_PARENT -1
  7239. #define XML_TREE_NSMAP_XML -2
  7240. #define XML_TREE_NSMAP_DOC -3
  7241. #define XML_TREE_NSMAP_CUSTOM -4
  7242. typedef struct xmlNsMapItem *xmlNsMapItemPtr;
  7243. struct xmlNsMapItem {
  7244. xmlNsMapItemPtr next;
  7245. xmlNsMapItemPtr prev;
  7246. xmlNsPtr oldNs; /* old ns decl reference */
  7247. xmlNsPtr newNs; /* new ns decl reference */
  7248. int shadowDepth; /* Shadowed at this depth */
  7249. /*
  7250. * depth:
  7251. * >= 0 == @node's ns-decls
  7252. * -1 == @parent's ns-decls
  7253. * -2 == the doc->oldNs XML ns-decl
  7254. * -3 == the doc->oldNs storage ns-decls
  7255. * -4 == ns-decls provided via custom ns-handling
  7256. */
  7257. int depth;
  7258. };
  7259. typedef struct xmlNsMap *xmlNsMapPtr;
  7260. struct xmlNsMap {
  7261. xmlNsMapItemPtr first;
  7262. xmlNsMapItemPtr last;
  7263. xmlNsMapItemPtr pool;
  7264. };
  7265. #define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL))
  7266. #define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next)
  7267. #define XML_NSMAP_POP(m, i) \
  7268. i = (m)->last; \
  7269. (m)->last = (i)->prev; \
  7270. if ((m)->last == NULL) \
  7271. (m)->first = NULL; \
  7272. else \
  7273. (m)->last->next = NULL; \
  7274. (i)->next = (m)->pool; \
  7275. (m)->pool = i;
  7276. /*
  7277. * xmlDOMWrapNsMapFree:
  7278. * @map: the ns-map
  7279. *
  7280. * Frees the ns-map
  7281. */
  7282. static void
  7283. xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap)
  7284. {
  7285. xmlNsMapItemPtr cur, tmp;
  7286. if (nsmap == NULL)
  7287. return;
  7288. cur = nsmap->pool;
  7289. while (cur != NULL) {
  7290. tmp = cur;
  7291. cur = cur->next;
  7292. xmlFree(tmp);
  7293. }
  7294. cur = nsmap->first;
  7295. while (cur != NULL) {
  7296. tmp = cur;
  7297. cur = cur->next;
  7298. xmlFree(tmp);
  7299. }
  7300. xmlFree(nsmap);
  7301. }
  7302. /*
  7303. * xmlDOMWrapNsMapAddItem:
  7304. * @map: the ns-map
  7305. * @oldNs: the old ns-struct
  7306. * @newNs: the new ns-struct
  7307. * @depth: depth and ns-kind information
  7308. *
  7309. * Adds an ns-mapping item.
  7310. */
  7311. static xmlNsMapItemPtr
  7312. xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position,
  7313. xmlNsPtr oldNs, xmlNsPtr newNs, int depth)
  7314. {
  7315. xmlNsMapItemPtr ret;
  7316. xmlNsMapPtr map;
  7317. if (nsmap == NULL)
  7318. return(NULL);
  7319. if ((position != -1) && (position != 0))
  7320. return(NULL);
  7321. map = *nsmap;
  7322. if (map == NULL) {
  7323. /*
  7324. * Create the ns-map.
  7325. */
  7326. map = (xmlNsMapPtr) xmlMalloc(sizeof(struct xmlNsMap));
  7327. if (map == NULL) {
  7328. xmlTreeErrMemory("allocating namespace map");
  7329. return (NULL);
  7330. }
  7331. memset(map, 0, sizeof(struct xmlNsMap));
  7332. *nsmap = map;
  7333. }
  7334. if (map->pool != NULL) {
  7335. /*
  7336. * Reuse an item from the pool.
  7337. */
  7338. ret = map->pool;
  7339. map->pool = ret->next;
  7340. memset(ret, 0, sizeof(struct xmlNsMapItem));
  7341. } else {
  7342. /*
  7343. * Create a new item.
  7344. */
  7345. ret = (xmlNsMapItemPtr) xmlMalloc(sizeof(struct xmlNsMapItem));
  7346. if (ret == NULL) {
  7347. xmlTreeErrMemory("allocating namespace map item");
  7348. return (NULL);
  7349. }
  7350. memset(ret, 0, sizeof(struct xmlNsMapItem));
  7351. }
  7352. if (map->first == NULL) {
  7353. /*
  7354. * First ever.
  7355. */
  7356. map->first = ret;
  7357. map->last = ret;
  7358. } else if (position == -1) {
  7359. /*
  7360. * Append.
  7361. */
  7362. ret->prev = map->last;
  7363. map->last->next = ret;
  7364. map->last = ret;
  7365. } else if (position == 0) {
  7366. /*
  7367. * Set on first position.
  7368. */
  7369. map->first->prev = ret;
  7370. ret->next = map->first;
  7371. map->first = ret;
  7372. }
  7373. ret->oldNs = oldNs;
  7374. ret->newNs = newNs;
  7375. ret->shadowDepth = -1;
  7376. ret->depth = depth;
  7377. return (ret);
  7378. }
  7379. /*
  7380. * xmlDOMWrapStoreNs:
  7381. * @doc: the doc
  7382. * @nsName: the namespace name
  7383. * @prefix: the prefix
  7384. *
  7385. * Creates or reuses an xmlNs struct on doc->oldNs with
  7386. * the given prefix and namespace name.
  7387. *
  7388. * Returns the acquired ns struct or NULL in case of an API
  7389. * or internal error.
  7390. */
  7391. static xmlNsPtr
  7392. xmlDOMWrapStoreNs(xmlDocPtr doc,
  7393. const xmlChar *nsName,
  7394. const xmlChar *prefix)
  7395. {
  7396. xmlNsPtr ns;
  7397. if (doc == NULL)
  7398. return (NULL);
  7399. ns = xmlTreeEnsureXMLDecl(doc);
  7400. if (ns == NULL)
  7401. return (NULL);
  7402. if (ns->next != NULL) {
  7403. /* Reuse. */
  7404. ns = ns->next;
  7405. while (ns != NULL) {
  7406. if (((ns->prefix == prefix) ||
  7407. xmlStrEqual(ns->prefix, prefix)) &&
  7408. xmlStrEqual(ns->href, nsName)) {
  7409. return (ns);
  7410. }
  7411. if (ns->next == NULL)
  7412. break;
  7413. ns = ns->next;
  7414. }
  7415. }
  7416. /* Create. */
  7417. if (ns != NULL) {
  7418. ns->next = xmlNewNs(NULL, nsName, prefix);
  7419. return (ns->next);
  7420. }
  7421. return(NULL);
  7422. }
  7423. /*
  7424. * xmlDOMWrapNewCtxt:
  7425. *
  7426. * Allocates and initializes a new DOM-wrapper context.
  7427. *
  7428. * Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal error.
  7429. */
  7430. xmlDOMWrapCtxtPtr
  7431. xmlDOMWrapNewCtxt(void)
  7432. {
  7433. xmlDOMWrapCtxtPtr ret;
  7434. ret = xmlMalloc(sizeof(xmlDOMWrapCtxt));
  7435. if (ret == NULL) {
  7436. xmlTreeErrMemory("allocating DOM-wrapper context");
  7437. return (NULL);
  7438. }
  7439. memset(ret, 0, sizeof(xmlDOMWrapCtxt));
  7440. return (ret);
  7441. }
  7442. /*
  7443. * xmlDOMWrapFreeCtxt:
  7444. * @ctxt: the DOM-wrapper context
  7445. *
  7446. * Frees the DOM-wrapper context.
  7447. */
  7448. void
  7449. xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt)
  7450. {
  7451. if (ctxt == NULL)
  7452. return;
  7453. if (ctxt->namespaceMap != NULL)
  7454. xmlDOMWrapNsMapFree((xmlNsMapPtr) ctxt->namespaceMap);
  7455. /*
  7456. * TODO: Store the namespace map in the context.
  7457. */
  7458. xmlFree(ctxt);
  7459. }
  7460. /*
  7461. * xmlTreeLookupNsListByPrefix:
  7462. * @nsList: a list of ns-structs
  7463. * @prefix: the searched prefix
  7464. *
  7465. * Searches for a ns-decl with the given prefix in @nsList.
  7466. *
  7467. * Returns the ns-decl if found, NULL if not found and on
  7468. * API errors.
  7469. */
  7470. static xmlNsPtr
  7471. xmlTreeNSListLookupByPrefix(xmlNsPtr nsList, const xmlChar *prefix)
  7472. {
  7473. if (nsList == NULL)
  7474. return (NULL);
  7475. {
  7476. xmlNsPtr ns;
  7477. ns = nsList;
  7478. do {
  7479. if ((prefix == ns->prefix) ||
  7480. xmlStrEqual(prefix, ns->prefix)) {
  7481. return (ns);
  7482. }
  7483. ns = ns->next;
  7484. } while (ns != NULL);
  7485. }
  7486. return (NULL);
  7487. }
  7488. /*
  7489. *
  7490. * xmlDOMWrapNSNormGatherInScopeNs:
  7491. * @map: the namespace map
  7492. * @node: the node to start with
  7493. *
  7494. * Puts in-scope namespaces into the ns-map.
  7495. *
  7496. * Returns 0 on success, -1 on API or internal errors.
  7497. */
  7498. static int
  7499. xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr *map,
  7500. xmlNodePtr node)
  7501. {
  7502. xmlNodePtr cur;
  7503. xmlNsPtr ns;
  7504. xmlNsMapItemPtr mi;
  7505. int shadowed;
  7506. if ((map == NULL) || (*map != NULL))
  7507. return (-1);
  7508. if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
  7509. return (-1);
  7510. /*
  7511. * Get in-scope ns-decls of @parent.
  7512. */
  7513. cur = node;
  7514. while ((cur != NULL) && (cur != (xmlNodePtr) cur->doc)) {
  7515. if (cur->type == XML_ELEMENT_NODE) {
  7516. if (cur->nsDef != NULL) {
  7517. ns = cur->nsDef;
  7518. do {
  7519. shadowed = 0;
  7520. if (XML_NSMAP_NOTEMPTY(*map)) {
  7521. /*
  7522. * Skip shadowed prefixes.
  7523. */
  7524. XML_NSMAP_FOREACH(*map, mi) {
  7525. if ((ns->prefix == mi->newNs->prefix) ||
  7526. xmlStrEqual(ns->prefix, mi->newNs->prefix)) {
  7527. shadowed = 1;
  7528. break;
  7529. }
  7530. }
  7531. }
  7532. /*
  7533. * Insert mapping.
  7534. */
  7535. mi = xmlDOMWrapNsMapAddItem(map, 0, NULL,
  7536. ns, XML_TREE_NSMAP_PARENT);
  7537. if (mi == NULL)
  7538. return (-1);
  7539. if (shadowed)
  7540. mi->shadowDepth = 0;
  7541. ns = ns->next;
  7542. } while (ns != NULL);
  7543. }
  7544. }
  7545. cur = cur->parent;
  7546. }
  7547. return (0);
  7548. }
  7549. /*
  7550. * XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict;
  7551. * otherwise copy it, when it was in the source-dict.
  7552. */
  7553. #define XML_TREE_ADOPT_STR(str) \
  7554. if (adoptStr && (str != NULL)) { \
  7555. if (destDoc->dict) { \
  7556. const xmlChar *old = str; \
  7557. str = xmlDictLookup(destDoc->dict, str, -1); \
  7558. if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \
  7559. (!xmlDictOwns(sourceDoc->dict, old))) \
  7560. xmlFree((char *)old); \
  7561. } else if ((sourceDoc) && (sourceDoc->dict) && \
  7562. xmlDictOwns(sourceDoc->dict, str)) { \
  7563. str = BAD_CAST xmlStrdup(str); \
  7564. } \
  7565. }
  7566. /*
  7567. * XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then
  7568. * put it in dest-dict or copy it.
  7569. */
  7570. #define XML_TREE_ADOPT_STR_2(str) \
  7571. if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \
  7572. (sourceDoc->dict != NULL) && \
  7573. xmlDictOwns(sourceDoc->dict, cur->content)) { \
  7574. if (destDoc->dict) \
  7575. cur->content = (xmlChar *) \
  7576. xmlDictLookup(destDoc->dict, cur->content, -1); \
  7577. else \
  7578. cur->content = xmlStrdup(BAD_CAST cur->content); \
  7579. }
  7580. /*
  7581. * xmlDOMWrapNSNormAddNsMapItem2:
  7582. *
  7583. * For internal use. Adds a ns-decl mapping.
  7584. *
  7585. * Returns 0 on success, -1 on internal errors.
  7586. */
  7587. static int
  7588. xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number,
  7589. xmlNsPtr oldNs, xmlNsPtr newNs)
  7590. {
  7591. if (*list == NULL) {
  7592. *list = (xmlNsPtr *) xmlMalloc(6 * sizeof(xmlNsPtr));
  7593. if (*list == NULL) {
  7594. xmlTreeErrMemory("alloc ns map item");
  7595. return(-1);
  7596. }
  7597. *size = 3;
  7598. *number = 0;
  7599. } else if ((*number) >= (*size)) {
  7600. *size *= 2;
  7601. *list = (xmlNsPtr *) xmlRealloc(*list,
  7602. (*size) * 2 * sizeof(xmlNsPtr));
  7603. if (*list == NULL) {
  7604. xmlTreeErrMemory("realloc ns map item");
  7605. return(-1);
  7606. }
  7607. }
  7608. (*list)[2 * (*number)] = oldNs;
  7609. (*list)[2 * (*number) +1] = newNs;
  7610. (*number)++;
  7611. return (0);
  7612. }
  7613. /*
  7614. * xmlDOMWrapRemoveNode:
  7615. * @ctxt: a DOM wrapper context
  7616. * @doc: the doc
  7617. * @node: the node to be removed.
  7618. * @options: set of options, unused at the moment
  7619. *
  7620. * Unlinks the given node from its owner.
  7621. * This will substitute ns-references to node->nsDef for
  7622. * ns-references to doc->oldNs, thus ensuring the removed
  7623. * branch to be autark wrt ns-references.
  7624. *
  7625. * NOTE: This function was not intensively tested.
  7626. *
  7627. * Returns 0 on success, 1 if the node is not supported,
  7628. * -1 on API and internal errors.
  7629. */
  7630. int
  7631. xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc,
  7632. xmlNodePtr node, int options ATTRIBUTE_UNUSED)
  7633. {
  7634. xmlNsPtr *list = NULL;
  7635. int sizeList, nbList, i, j;
  7636. xmlNsPtr ns;
  7637. if ((node == NULL) || (doc == NULL) || (node->doc != doc))
  7638. return (-1);
  7639. /* TODO: 0 or -1 ? */
  7640. if (node->parent == NULL)
  7641. return (0);
  7642. switch (node->type) {
  7643. case XML_TEXT_NODE:
  7644. case XML_CDATA_SECTION_NODE:
  7645. case XML_ENTITY_REF_NODE:
  7646. case XML_PI_NODE:
  7647. case XML_COMMENT_NODE:
  7648. xmlUnlinkNode(node);
  7649. return (0);
  7650. case XML_ELEMENT_NODE:
  7651. case XML_ATTRIBUTE_NODE:
  7652. break;
  7653. default:
  7654. return (1);
  7655. }
  7656. xmlUnlinkNode(node);
  7657. /*
  7658. * Save out-of-scope ns-references in doc->oldNs.
  7659. */
  7660. do {
  7661. switch (node->type) {
  7662. case XML_ELEMENT_NODE:
  7663. if ((ctxt == NULL) && (node->nsDef != NULL)) {
  7664. ns = node->nsDef;
  7665. do {
  7666. if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,
  7667. &nbList, ns, ns) == -1)
  7668. goto internal_error;
  7669. ns = ns->next;
  7670. } while (ns != NULL);
  7671. }
  7672. /* Falls through. */
  7673. case XML_ATTRIBUTE_NODE:
  7674. if (node->ns != NULL) {
  7675. /*
  7676. * Find a mapping.
  7677. */
  7678. if (list != NULL) {
  7679. for (i = 0, j = 0; i < nbList; i++, j += 2) {
  7680. if (node->ns == list[j]) {
  7681. node->ns = list[++j];
  7682. goto next_node;
  7683. }
  7684. }
  7685. }
  7686. ns = NULL;
  7687. if (ctxt != NULL) {
  7688. /*
  7689. * User defined.
  7690. */
  7691. } else {
  7692. /*
  7693. * Add to doc's oldNs.
  7694. */
  7695. ns = xmlDOMWrapStoreNs(doc, node->ns->href,
  7696. node->ns->prefix);
  7697. if (ns == NULL)
  7698. goto internal_error;
  7699. }
  7700. if (ns != NULL) {
  7701. /*
  7702. * Add mapping.
  7703. */
  7704. if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,
  7705. &nbList, node->ns, ns) == -1)
  7706. goto internal_error;
  7707. }
  7708. node->ns = ns;
  7709. }
  7710. if ((node->type == XML_ELEMENT_NODE) &&
  7711. (node->properties != NULL)) {
  7712. node = (xmlNodePtr) node->properties;
  7713. continue;
  7714. }
  7715. break;
  7716. default:
  7717. goto next_sibling;
  7718. }
  7719. next_node:
  7720. if ((node->type == XML_ELEMENT_NODE) &&
  7721. (node->children != NULL)) {
  7722. node = node->children;
  7723. continue;
  7724. }
  7725. next_sibling:
  7726. if (node == NULL)
  7727. break;
  7728. if (node->next != NULL)
  7729. node = node->next;
  7730. else {
  7731. node = node->parent;
  7732. goto next_sibling;
  7733. }
  7734. } while (node != NULL);
  7735. if (list != NULL)
  7736. xmlFree(list);
  7737. return (0);
  7738. internal_error:
  7739. if (list != NULL)
  7740. xmlFree(list);
  7741. return (-1);
  7742. }
  7743. /*
  7744. * xmlSearchNsByNamespaceStrict:
  7745. * @doc: the document
  7746. * @node: the start node
  7747. * @nsName: the searched namespace name
  7748. * @retNs: the resulting ns-decl
  7749. * @prefixed: if the found ns-decl must have a prefix (for attributes)
  7750. *
  7751. * Dynamically searches for a ns-declaration which matches
  7752. * the given @nsName in the ancestor-or-self axis of @node.
  7753. *
  7754. * Returns 1 if a ns-decl was found, 0 if not and -1 on API
  7755. * and internal errors.
  7756. */
  7757. static int
  7758. xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node,
  7759. const xmlChar* nsName,
  7760. xmlNsPtr *retNs, int prefixed)
  7761. {
  7762. xmlNodePtr cur, prev = NULL, out = NULL;
  7763. xmlNsPtr ns, prevns;
  7764. if ((doc == NULL) || (nsName == NULL) || (retNs == NULL))
  7765. return (-1);
  7766. if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
  7767. return(-1);
  7768. *retNs = NULL;
  7769. if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
  7770. *retNs = xmlTreeEnsureXMLDecl(doc);
  7771. if (*retNs == NULL)
  7772. return (-1);
  7773. return (1);
  7774. }
  7775. cur = node;
  7776. do {
  7777. if (cur->type == XML_ELEMENT_NODE) {
  7778. if (cur->nsDef != NULL) {
  7779. for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
  7780. if (prefixed && (ns->prefix == NULL))
  7781. continue;
  7782. if (prev != NULL) {
  7783. /*
  7784. * Check the last level of ns-decls for a
  7785. * shadowing prefix.
  7786. */
  7787. prevns = prev->nsDef;
  7788. do {
  7789. if ((prevns->prefix == ns->prefix) ||
  7790. ((prevns->prefix != NULL) &&
  7791. (ns->prefix != NULL) &&
  7792. xmlStrEqual(prevns->prefix, ns->prefix))) {
  7793. /*
  7794. * Shadowed.
  7795. */
  7796. break;
  7797. }
  7798. prevns = prevns->next;
  7799. } while (prevns != NULL);
  7800. if (prevns != NULL)
  7801. continue;
  7802. }
  7803. /*
  7804. * Ns-name comparison.
  7805. */
  7806. if ((nsName == ns->href) ||
  7807. xmlStrEqual(nsName, ns->href)) {
  7808. /*
  7809. * At this point the prefix can only be shadowed,
  7810. * if we are the the (at least) 3rd level of
  7811. * ns-decls.
  7812. */
  7813. if (out) {
  7814. int ret;
  7815. ret = xmlNsInScope(doc, node, prev, ns->prefix);
  7816. if (ret < 0)
  7817. return (-1);
  7818. /*
  7819. * TODO: Should we try to find a matching ns-name
  7820. * only once? This here keeps on searching.
  7821. * I think we should try further since, there might
  7822. * be an other matching ns-decl with an unshadowed
  7823. * prefix.
  7824. */
  7825. if (! ret)
  7826. continue;
  7827. }
  7828. *retNs = ns;
  7829. return (1);
  7830. }
  7831. }
  7832. out = prev;
  7833. prev = cur;
  7834. }
  7835. } else if ((cur->type == XML_ENTITY_NODE) ||
  7836. (cur->type == XML_ENTITY_DECL))
  7837. return (0);
  7838. cur = cur->parent;
  7839. } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
  7840. return (0);
  7841. }
  7842. /*
  7843. * xmlSearchNsByPrefixStrict:
  7844. * @doc: the document
  7845. * @node: the start node
  7846. * @prefix: the searched namespace prefix
  7847. * @retNs: the resulting ns-decl
  7848. *
  7849. * Dynamically searches for a ns-declaration which matches
  7850. * the given @nsName in the ancestor-or-self axis of @node.
  7851. *
  7852. * Returns 1 if a ns-decl was found, 0 if not and -1 on API
  7853. * and internal errors.
  7854. */
  7855. static int
  7856. xmlSearchNsByPrefixStrict(xmlDocPtr doc, xmlNodePtr node,
  7857. const xmlChar* prefix,
  7858. xmlNsPtr *retNs)
  7859. {
  7860. xmlNodePtr cur;
  7861. xmlNsPtr ns;
  7862. if ((doc == NULL) || (node == NULL) || (node->type == XML_NAMESPACE_DECL))
  7863. return(-1);
  7864. if (retNs)
  7865. *retNs = NULL;
  7866. if (IS_STR_XML(prefix)) {
  7867. if (retNs) {
  7868. *retNs = xmlTreeEnsureXMLDecl(doc);
  7869. if (*retNs == NULL)
  7870. return (-1);
  7871. }
  7872. return (1);
  7873. }
  7874. cur = node;
  7875. do {
  7876. if (cur->type == XML_ELEMENT_NODE) {
  7877. if (cur->nsDef != NULL) {
  7878. ns = cur->nsDef;
  7879. do {
  7880. if ((prefix == ns->prefix) ||
  7881. xmlStrEqual(prefix, ns->prefix))
  7882. {
  7883. /*
  7884. * Disabled namespaces, e.g. xmlns:abc="".
  7885. */
  7886. if (ns->href == NULL)
  7887. return(0);
  7888. if (retNs)
  7889. *retNs = ns;
  7890. return (1);
  7891. }
  7892. ns = ns->next;
  7893. } while (ns != NULL);
  7894. }
  7895. } else if ((cur->type == XML_ENTITY_NODE) ||
  7896. (cur->type == XML_ENTITY_DECL))
  7897. return (0);
  7898. cur = cur->parent;
  7899. } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
  7900. return (0);
  7901. }
  7902. /*
  7903. * xmlDOMWrapNSNormDeclareNsForced:
  7904. * @doc: the doc
  7905. * @elem: the element-node to declare on
  7906. * @nsName: the namespace-name of the ns-decl
  7907. * @prefix: the preferred prefix of the ns-decl
  7908. * @checkShadow: ensure that the new ns-decl doesn't shadow ancestor ns-decls
  7909. *
  7910. * Declares a new namespace on @elem. It tries to use the
  7911. * given @prefix; if a ns-decl with the given prefix is already existent
  7912. * on @elem, it will generate an other prefix.
  7913. *
  7914. * Returns 1 if a ns-decl was found, 0 if not and -1 on API
  7915. * and internal errors.
  7916. */
  7917. static xmlNsPtr
  7918. xmlDOMWrapNSNormDeclareNsForced(xmlDocPtr doc,
  7919. xmlNodePtr elem,
  7920. const xmlChar *nsName,
  7921. const xmlChar *prefix,
  7922. int checkShadow)
  7923. {
  7924. xmlNsPtr ret;
  7925. char buf[50];
  7926. const xmlChar *pref;
  7927. int counter = 0;
  7928. if ((doc == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
  7929. return(NULL);
  7930. /*
  7931. * Create a ns-decl on @anchor.
  7932. */
  7933. pref = prefix;
  7934. while (1) {
  7935. /*
  7936. * Lookup whether the prefix is unused in elem's ns-decls.
  7937. */
  7938. if ((elem->nsDef != NULL) &&
  7939. (xmlTreeNSListLookupByPrefix(elem->nsDef, pref) != NULL))
  7940. goto ns_next_prefix;
  7941. if (checkShadow && elem->parent &&
  7942. ((xmlNodePtr) elem->parent->doc != elem->parent)) {
  7943. /*
  7944. * Does it shadow ancestor ns-decls?
  7945. */
  7946. if (xmlSearchNsByPrefixStrict(doc, elem->parent, pref, NULL) == 1)
  7947. goto ns_next_prefix;
  7948. }
  7949. ret = xmlNewNs(NULL, nsName, pref);
  7950. if (ret == NULL)
  7951. return (NULL);
  7952. if (elem->nsDef == NULL)
  7953. elem->nsDef = ret;
  7954. else {
  7955. xmlNsPtr ns2 = elem->nsDef;
  7956. while (ns2->next != NULL)
  7957. ns2 = ns2->next;
  7958. ns2->next = ret;
  7959. }
  7960. return (ret);
  7961. ns_next_prefix:
  7962. counter++;
  7963. if (counter > 1000)
  7964. return (NULL);
  7965. if (prefix == NULL) {
  7966. snprintf((char *) buf, sizeof(buf),
  7967. "ns_%d", counter);
  7968. } else
  7969. snprintf((char *) buf, sizeof(buf),
  7970. "%.30s_%d", (char *)prefix, counter);
  7971. pref = BAD_CAST buf;
  7972. }
  7973. }
  7974. /*
  7975. * xmlDOMWrapNSNormAcquireNormalizedNs:
  7976. * @doc: the doc
  7977. * @elem: the element-node to declare namespaces on
  7978. * @ns: the ns-struct to use for the search
  7979. * @retNs: the found/created ns-struct
  7980. * @nsMap: the ns-map
  7981. * @depth: the current tree depth
  7982. * @ancestorsOnly: search in ancestor ns-decls only
  7983. * @prefixed: if the searched ns-decl must have a prefix (for attributes)
  7984. *
  7985. * Searches for a matching ns-name in the ns-decls of @nsMap, if not
  7986. * found it will either declare it on @elem, or store it in doc->oldNs.
  7987. * If a new ns-decl needs to be declared on @elem, it tries to use the
  7988. * @ns->prefix for it, if this prefix is already in use on @elem, it will
  7989. * change the prefix or the new ns-decl.
  7990. *
  7991. * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
  7992. */
  7993. static int
  7994. xmlDOMWrapNSNormAcquireNormalizedNs(xmlDocPtr doc,
  7995. xmlNodePtr elem,
  7996. xmlNsPtr ns,
  7997. xmlNsPtr *retNs,
  7998. xmlNsMapPtr *nsMap,
  7999. int depth,
  8000. int ancestorsOnly,
  8001. int prefixed)
  8002. {
  8003. xmlNsMapItemPtr mi;
  8004. if ((doc == NULL) || (ns == NULL) || (retNs == NULL) ||
  8005. (nsMap == NULL))
  8006. return (-1);
  8007. *retNs = NULL;
  8008. /*
  8009. * Handle XML namespace.
  8010. */
  8011. if (IS_STR_XML(ns->prefix)) {
  8012. /*
  8013. * Insert XML namespace mapping.
  8014. */
  8015. *retNs = xmlTreeEnsureXMLDecl(doc);
  8016. if (*retNs == NULL)
  8017. return (-1);
  8018. return (0);
  8019. }
  8020. /*
  8021. * If the search should be done in ancestors only and no
  8022. * @elem (the first ancestor) was specified, then skip the search.
  8023. */
  8024. if ((XML_NSMAP_NOTEMPTY(*nsMap)) &&
  8025. (! (ancestorsOnly && (elem == NULL))))
  8026. {
  8027. /*
  8028. * Try to find an equal ns-name in in-scope ns-decls.
  8029. */
  8030. XML_NSMAP_FOREACH(*nsMap, mi) {
  8031. if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
  8032. /*
  8033. * ancestorsOnly: This should be turned on to gain speed,
  8034. * if one knows that the branch itself was already
  8035. * ns-wellformed and no stale references existed.
  8036. * I.e. it searches in the ancestor axis only.
  8037. */
  8038. ((! ancestorsOnly) || (mi->depth == XML_TREE_NSMAP_PARENT)) &&
  8039. /* Skip shadowed prefixes. */
  8040. (mi->shadowDepth == -1) &&
  8041. /* Skip xmlns="" or xmlns:foo="". */
  8042. ((mi->newNs->href != NULL) &&
  8043. (mi->newNs->href[0] != 0)) &&
  8044. /* Ensure a prefix if wanted. */
  8045. ((! prefixed) || (mi->newNs->prefix != NULL)) &&
  8046. /* Equal ns name */
  8047. ((mi->newNs->href == ns->href) ||
  8048. xmlStrEqual(mi->newNs->href, ns->href))) {
  8049. /* Set the mapping. */
  8050. mi->oldNs = ns;
  8051. *retNs = mi->newNs;
  8052. return (0);
  8053. }
  8054. }
  8055. }
  8056. /*
  8057. * No luck, the namespace is out of scope or shadowed.
  8058. */
  8059. if (elem == NULL) {
  8060. xmlNsPtr tmpns;
  8061. /*
  8062. * Store ns-decls in "oldNs" of the document-node.
  8063. */
  8064. tmpns = xmlDOMWrapStoreNs(doc, ns->href, ns->prefix);
  8065. if (tmpns == NULL)
  8066. return (-1);
  8067. /*
  8068. * Insert mapping.
  8069. */
  8070. if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns,
  8071. tmpns, XML_TREE_NSMAP_DOC) == NULL) {
  8072. xmlFreeNs(tmpns);
  8073. return (-1);
  8074. }
  8075. *retNs = tmpns;
  8076. } else {
  8077. xmlNsPtr tmpns;
  8078. tmpns = xmlDOMWrapNSNormDeclareNsForced(doc, elem, ns->href,
  8079. ns->prefix, 0);
  8080. if (tmpns == NULL)
  8081. return (-1);
  8082. if (*nsMap != NULL) {
  8083. /*
  8084. * Does it shadow ancestor ns-decls?
  8085. */
  8086. XML_NSMAP_FOREACH(*nsMap, mi) {
  8087. if ((mi->depth < depth) &&
  8088. (mi->shadowDepth == -1) &&
  8089. ((ns->prefix == mi->newNs->prefix) ||
  8090. xmlStrEqual(ns->prefix, mi->newNs->prefix))) {
  8091. /*
  8092. * Shadows.
  8093. */
  8094. mi->shadowDepth = depth;
  8095. break;
  8096. }
  8097. }
  8098. }
  8099. if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, tmpns, depth) == NULL) {
  8100. xmlFreeNs(tmpns);
  8101. return (-1);
  8102. }
  8103. *retNs = tmpns;
  8104. }
  8105. return (0);
  8106. }
  8107. typedef enum {
  8108. XML_DOM_RECONNS_REMOVEREDUND = 1<<0
  8109. } xmlDOMReconcileNSOptions;
  8110. /*
  8111. * xmlDOMWrapReconcileNamespaces:
  8112. * @ctxt: DOM wrapper context, unused at the moment
  8113. * @elem: the element-node
  8114. * @options: option flags
  8115. *
  8116. * Ensures that ns-references point to ns-decls hold on element-nodes.
  8117. * Ensures that the tree is namespace wellformed by creating additional
  8118. * ns-decls where needed. Note that, since prefixes of already existent
  8119. * ns-decls can be shadowed by this process, it could break QNames in
  8120. * attribute values or element content.
  8121. *
  8122. * NOTE: This function was not intensively tested.
  8123. *
  8124. * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
  8125. */
  8126. int
  8127. xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
  8128. xmlNodePtr elem,
  8129. int options)
  8130. {
  8131. int depth = -1, adoptns = 0, parnsdone = 0;
  8132. xmlNsPtr ns, prevns;
  8133. xmlDocPtr doc;
  8134. xmlNodePtr cur, curElem = NULL;
  8135. xmlNsMapPtr nsMap = NULL;
  8136. xmlNsMapItemPtr /* topmi = NULL, */ mi;
  8137. /* @ancestorsOnly should be set by an option flag. */
  8138. int ancestorsOnly = 0;
  8139. int optRemoveRedundantNS =
  8140. ((xmlDOMReconcileNSOptions) options & XML_DOM_RECONNS_REMOVEREDUND) ? 1 : 0;
  8141. xmlNsPtr *listRedund = NULL;
  8142. int sizeRedund = 0, nbRedund = 0, ret, i, j;
  8143. if ((elem == NULL) || (elem->doc == NULL) ||
  8144. (elem->type != XML_ELEMENT_NODE))
  8145. return (-1);
  8146. doc = elem->doc;
  8147. cur = elem;
  8148. do {
  8149. switch (cur->type) {
  8150. case XML_ELEMENT_NODE:
  8151. adoptns = 1;
  8152. curElem = cur;
  8153. depth++;
  8154. /*
  8155. * Namespace declarations.
  8156. */
  8157. if (cur->nsDef != NULL) {
  8158. prevns = NULL;
  8159. ns = cur->nsDef;
  8160. while (ns != NULL) {
  8161. if (! parnsdone) {
  8162. if ((elem->parent) &&
  8163. ((xmlNodePtr) elem->parent->doc != elem->parent)) {
  8164. /*
  8165. * Gather ancestor in-scope ns-decls.
  8166. */
  8167. if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
  8168. elem->parent) == -1)
  8169. goto internal_error;
  8170. }
  8171. parnsdone = 1;
  8172. }
  8173. /*
  8174. * Lookup the ns ancestor-axis for equal ns-decls in scope.
  8175. */
  8176. if (optRemoveRedundantNS && XML_NSMAP_NOTEMPTY(nsMap)) {
  8177. XML_NSMAP_FOREACH(nsMap, mi) {
  8178. if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
  8179. (mi->shadowDepth == -1) &&
  8180. ((ns->prefix == mi->newNs->prefix) ||
  8181. xmlStrEqual(ns->prefix, mi->newNs->prefix)) &&
  8182. ((ns->href == mi->newNs->href) ||
  8183. xmlStrEqual(ns->href, mi->newNs->href)))
  8184. {
  8185. /*
  8186. * A redundant ns-decl was found.
  8187. * Add it to the list of redundant ns-decls.
  8188. */
  8189. if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund,
  8190. &sizeRedund, &nbRedund, ns, mi->newNs) == -1)
  8191. goto internal_error;
  8192. /*
  8193. * Remove the ns-decl from the element-node.
  8194. */
  8195. if (prevns)
  8196. prevns->next = ns->next;
  8197. else
  8198. cur->nsDef = ns->next;
  8199. goto next_ns_decl;
  8200. }
  8201. }
  8202. }
  8203. /*
  8204. * Skip ns-references handling if the referenced
  8205. * ns-decl is declared on the same element.
  8206. */
  8207. if ((cur->ns != NULL) && adoptns && (cur->ns == ns))
  8208. adoptns = 0;
  8209. /*
  8210. * Does it shadow any ns-decl?
  8211. */
  8212. if (XML_NSMAP_NOTEMPTY(nsMap)) {
  8213. XML_NSMAP_FOREACH(nsMap, mi) {
  8214. if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
  8215. (mi->shadowDepth == -1) &&
  8216. ((ns->prefix == mi->newNs->prefix) ||
  8217. xmlStrEqual(ns->prefix, mi->newNs->prefix))) {
  8218. mi->shadowDepth = depth;
  8219. }
  8220. }
  8221. }
  8222. /*
  8223. * Push mapping.
  8224. */
  8225. if (xmlDOMWrapNsMapAddItem(&nsMap, -1, ns, ns,
  8226. depth) == NULL)
  8227. goto internal_error;
  8228. prevns = ns;
  8229. next_ns_decl:
  8230. ns = ns->next;
  8231. }
  8232. }
  8233. if (! adoptns)
  8234. goto ns_end;
  8235. /* Falls through. */
  8236. case XML_ATTRIBUTE_NODE:
  8237. /* No ns, no fun. */
  8238. if (cur->ns == NULL)
  8239. goto ns_end;
  8240. if (! parnsdone) {
  8241. if ((elem->parent) &&
  8242. ((xmlNodePtr) elem->parent->doc != elem->parent)) {
  8243. if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
  8244. elem->parent) == -1)
  8245. goto internal_error;
  8246. }
  8247. parnsdone = 1;
  8248. }
  8249. /*
  8250. * Adjust the reference if this was a redundant ns-decl.
  8251. */
  8252. if (listRedund) {
  8253. for (i = 0, j = 0; i < nbRedund; i++, j += 2) {
  8254. if (cur->ns == listRedund[j]) {
  8255. cur->ns = listRedund[++j];
  8256. break;
  8257. }
  8258. }
  8259. }
  8260. /*
  8261. * Adopt ns-references.
  8262. */
  8263. if (XML_NSMAP_NOTEMPTY(nsMap)) {
  8264. /*
  8265. * Search for a mapping.
  8266. */
  8267. XML_NSMAP_FOREACH(nsMap, mi) {
  8268. if ((mi->shadowDepth == -1) &&
  8269. (cur->ns == mi->oldNs)) {
  8270. cur->ns = mi->newNs;
  8271. goto ns_end;
  8272. }
  8273. }
  8274. }
  8275. /*
  8276. * Acquire a normalized ns-decl and add it to the map.
  8277. */
  8278. if (xmlDOMWrapNSNormAcquireNormalizedNs(doc, curElem,
  8279. cur->ns, &ns,
  8280. &nsMap, depth,
  8281. ancestorsOnly,
  8282. (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
  8283. goto internal_error;
  8284. cur->ns = ns;
  8285. ns_end:
  8286. if ((cur->type == XML_ELEMENT_NODE) &&
  8287. (cur->properties != NULL)) {
  8288. /*
  8289. * Process attributes.
  8290. */
  8291. cur = (xmlNodePtr) cur->properties;
  8292. continue;
  8293. }
  8294. break;
  8295. default:
  8296. goto next_sibling;
  8297. }
  8298. into_content:
  8299. if ((cur->type == XML_ELEMENT_NODE) &&
  8300. (cur->children != NULL)) {
  8301. /*
  8302. * Process content of element-nodes only.
  8303. */
  8304. cur = cur->children;
  8305. continue;
  8306. }
  8307. next_sibling:
  8308. if (cur == elem)
  8309. break;
  8310. if (cur->type == XML_ELEMENT_NODE) {
  8311. if (XML_NSMAP_NOTEMPTY(nsMap)) {
  8312. /*
  8313. * Pop mappings.
  8314. */
  8315. while ((nsMap->last != NULL) &&
  8316. (nsMap->last->depth >= depth))
  8317. {
  8318. XML_NSMAP_POP(nsMap, mi)
  8319. }
  8320. /*
  8321. * Unshadow.
  8322. */
  8323. XML_NSMAP_FOREACH(nsMap, mi) {
  8324. if (mi->shadowDepth >= depth)
  8325. mi->shadowDepth = -1;
  8326. }
  8327. }
  8328. depth--;
  8329. }
  8330. if (cur->next != NULL)
  8331. cur = cur->next;
  8332. else {
  8333. if (cur->type == XML_ATTRIBUTE_NODE) {
  8334. cur = cur->parent;
  8335. goto into_content;
  8336. }
  8337. cur = cur->parent;
  8338. goto next_sibling;
  8339. }
  8340. } while (cur != NULL);
  8341. ret = 0;
  8342. goto exit;
  8343. internal_error:
  8344. ret = -1;
  8345. exit:
  8346. if (listRedund) {
  8347. for (i = 0, j = 0; i < nbRedund; i++, j += 2) {
  8348. xmlFreeNs(listRedund[j]);
  8349. }
  8350. xmlFree(listRedund);
  8351. }
  8352. if (nsMap != NULL)
  8353. xmlDOMWrapNsMapFree(nsMap);
  8354. return (ret);
  8355. }
  8356. /*
  8357. * xmlDOMWrapAdoptBranch:
  8358. * @ctxt: the optional context for custom processing
  8359. * @sourceDoc: the optional sourceDoc
  8360. * @node: the element-node to start with
  8361. * @destDoc: the destination doc for adoption
  8362. * @destParent: the optional new parent of @node in @destDoc
  8363. * @options: option flags
  8364. *
  8365. * Ensures that ns-references point to @destDoc: either to
  8366. * elements->nsDef entries if @destParent is given, or to
  8367. * @destDoc->oldNs otherwise.
  8368. * If @destParent is given, it ensures that the tree is namespace
  8369. * wellformed by creating additional ns-decls where needed.
  8370. * Note that, since prefixes of already existent ns-decls can be
  8371. * shadowed by this process, it could break QNames in attribute
  8372. * values or element content.
  8373. *
  8374. * NOTE: This function was not intensively tested.
  8375. *
  8376. * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
  8377. */
  8378. static int
  8379. xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
  8380. xmlDocPtr sourceDoc,
  8381. xmlNodePtr node,
  8382. xmlDocPtr destDoc,
  8383. xmlNodePtr destParent,
  8384. int options ATTRIBUTE_UNUSED)
  8385. {
  8386. int ret = 0;
  8387. xmlNodePtr cur, curElem = NULL;
  8388. xmlNsMapPtr nsMap = NULL;
  8389. xmlNsMapItemPtr mi;
  8390. xmlNsPtr ns = NULL;
  8391. int depth = -1, adoptStr = 1;
  8392. /* gather @parent's ns-decls. */
  8393. int parnsdone;
  8394. /* @ancestorsOnly should be set per option. */
  8395. int ancestorsOnly = 0;
  8396. /*
  8397. * Optimize string adoption for equal or none dicts.
  8398. */
  8399. if ((sourceDoc != NULL) &&
  8400. (sourceDoc->dict == destDoc->dict))
  8401. adoptStr = 0;
  8402. else
  8403. adoptStr = 1;
  8404. /*
  8405. * Get the ns-map from the context if available.
  8406. */
  8407. if (ctxt)
  8408. nsMap = (xmlNsMapPtr) ctxt->namespaceMap;
  8409. /*
  8410. * Disable search for ns-decls in the parent-axis of the
  8411. * destination element, if:
  8412. * 1) there's no destination parent
  8413. * 2) custom ns-reference handling is used
  8414. */
  8415. if ((destParent == NULL) ||
  8416. (ctxt && ctxt->getNsForNodeFunc))
  8417. {
  8418. parnsdone = 1;
  8419. } else
  8420. parnsdone = 0;
  8421. cur = node;
  8422. if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
  8423. goto internal_error;
  8424. while (cur != NULL) {
  8425. /*
  8426. * Paranoid source-doc sanity check.
  8427. */
  8428. if (cur->doc != sourceDoc) {
  8429. /*
  8430. * We'll assume XIncluded nodes if the doc differs.
  8431. * TODO: Do we need to reconciliate XIncluded nodes?
  8432. * This here skips XIncluded nodes and tries to handle
  8433. * broken sequences.
  8434. */
  8435. if (cur->next == NULL)
  8436. goto leave_node;
  8437. do {
  8438. cur = cur->next;
  8439. if ((cur->type == XML_XINCLUDE_END) ||
  8440. (cur->doc == node->doc))
  8441. break;
  8442. } while (cur->next != NULL);
  8443. if (cur->doc != node->doc)
  8444. goto leave_node;
  8445. }
  8446. cur->doc = destDoc;
  8447. switch (cur->type) {
  8448. case XML_XINCLUDE_START:
  8449. case XML_XINCLUDE_END:
  8450. /*
  8451. * TODO
  8452. */
  8453. return (-1);
  8454. case XML_ELEMENT_NODE:
  8455. curElem = cur;
  8456. depth++;
  8457. /*
  8458. * Namespace declarations.
  8459. * - ns->href and ns->prefix are never in the dict, so
  8460. * we need not move the values over to the destination dict.
  8461. * - Note that for custom handling of ns-references,
  8462. * the ns-decls need not be stored in the ns-map,
  8463. * since they won't be referenced by node->ns.
  8464. */
  8465. if ((cur->nsDef) &&
  8466. ((ctxt == NULL) || (ctxt->getNsForNodeFunc == NULL)))
  8467. {
  8468. if (! parnsdone) {
  8469. /*
  8470. * Gather @parent's in-scope ns-decls.
  8471. */
  8472. if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
  8473. destParent) == -1)
  8474. goto internal_error;
  8475. parnsdone = 1;
  8476. }
  8477. for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
  8478. /*
  8479. * NOTE: ns->prefix and ns->href are never in the dict.
  8480. * XML_TREE_ADOPT_STR(ns->prefix)
  8481. * XML_TREE_ADOPT_STR(ns->href)
  8482. */
  8483. /*
  8484. * Does it shadow any ns-decl?
  8485. */
  8486. if (XML_NSMAP_NOTEMPTY(nsMap)) {
  8487. XML_NSMAP_FOREACH(nsMap, mi) {
  8488. if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
  8489. (mi->shadowDepth == -1) &&
  8490. ((ns->prefix == mi->newNs->prefix) ||
  8491. xmlStrEqual(ns->prefix,
  8492. mi->newNs->prefix))) {
  8493. mi->shadowDepth = depth;
  8494. }
  8495. }
  8496. }
  8497. /*
  8498. * Push mapping.
  8499. */
  8500. if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
  8501. ns, ns, depth) == NULL)
  8502. goto internal_error;
  8503. }
  8504. }
  8505. /* Falls through. */
  8506. case XML_ATTRIBUTE_NODE:
  8507. /* No namespace, no fun. */
  8508. if (cur->ns == NULL)
  8509. goto ns_end;
  8510. if (! parnsdone) {
  8511. if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
  8512. destParent) == -1)
  8513. goto internal_error;
  8514. parnsdone = 1;
  8515. }
  8516. /*
  8517. * Adopt ns-references.
  8518. */
  8519. if (XML_NSMAP_NOTEMPTY(nsMap)) {
  8520. /*
  8521. * Search for a mapping.
  8522. */
  8523. XML_NSMAP_FOREACH(nsMap, mi) {
  8524. if ((mi->shadowDepth == -1) &&
  8525. (cur->ns == mi->oldNs)) {
  8526. cur->ns = mi->newNs;
  8527. goto ns_end;
  8528. }
  8529. }
  8530. }
  8531. /*
  8532. * No matching namespace in scope. We need a new one.
  8533. */
  8534. if ((ctxt) && (ctxt->getNsForNodeFunc)) {
  8535. /*
  8536. * User-defined behaviour.
  8537. */
  8538. ns = ctxt->getNsForNodeFunc(ctxt, cur,
  8539. cur->ns->href, cur->ns->prefix);
  8540. /*
  8541. * Insert mapping if ns is available; it's the users fault
  8542. * if not.
  8543. */
  8544. if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
  8545. cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
  8546. goto internal_error;
  8547. cur->ns = ns;
  8548. } else {
  8549. /*
  8550. * Acquire a normalized ns-decl and add it to the map.
  8551. */
  8552. if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc,
  8553. /* ns-decls on curElem or on destDoc->oldNs */
  8554. destParent ? curElem : NULL,
  8555. cur->ns, &ns,
  8556. &nsMap, depth,
  8557. ancestorsOnly,
  8558. /* ns-decls must be prefixed for attributes. */
  8559. (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
  8560. goto internal_error;
  8561. cur->ns = ns;
  8562. }
  8563. ns_end:
  8564. /*
  8565. * Further node properties.
  8566. * TODO: Is this all?
  8567. */
  8568. XML_TREE_ADOPT_STR(cur->name)
  8569. if (cur->type == XML_ELEMENT_NODE) {
  8570. cur->psvi = NULL;
  8571. cur->line = 0;
  8572. cur->extra = 0;
  8573. /*
  8574. * Walk attributes.
  8575. */
  8576. if (cur->properties != NULL) {
  8577. /*
  8578. * Process first attribute node.
  8579. */
  8580. cur = (xmlNodePtr) cur->properties;
  8581. continue;
  8582. }
  8583. } else {
  8584. /*
  8585. * Attributes.
  8586. */
  8587. if ((sourceDoc != NULL) &&
  8588. (((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID))
  8589. {
  8590. xmlRemoveID(sourceDoc, (xmlAttrPtr) cur);
  8591. }
  8592. ((xmlAttrPtr) cur)->atype = 0;
  8593. ((xmlAttrPtr) cur)->psvi = NULL;
  8594. }
  8595. break;
  8596. case XML_TEXT_NODE:
  8597. case XML_CDATA_SECTION_NODE:
  8598. /*
  8599. * This puts the content in the dest dict, only if
  8600. * it was previously in the source dict.
  8601. */
  8602. XML_TREE_ADOPT_STR_2(cur->content)
  8603. goto leave_node;
  8604. case XML_ENTITY_REF_NODE:
  8605. /*
  8606. * Remove reference to the entity-node.
  8607. */
  8608. cur->content = NULL;
  8609. cur->children = NULL;
  8610. cur->last = NULL;
  8611. if ((destDoc->intSubset) || (destDoc->extSubset)) {
  8612. xmlEntityPtr ent;
  8613. /*
  8614. * Assign new entity-node if available.
  8615. */
  8616. ent = xmlGetDocEntity(destDoc, cur->name);
  8617. if (ent != NULL) {
  8618. cur->content = ent->content;
  8619. cur->children = (xmlNodePtr) ent;
  8620. cur->last = (xmlNodePtr) ent;
  8621. }
  8622. }
  8623. goto leave_node;
  8624. case XML_PI_NODE:
  8625. XML_TREE_ADOPT_STR(cur->name)
  8626. XML_TREE_ADOPT_STR_2(cur->content)
  8627. break;
  8628. case XML_COMMENT_NODE:
  8629. break;
  8630. default:
  8631. goto internal_error;
  8632. }
  8633. /*
  8634. * Walk the tree.
  8635. */
  8636. if (cur->children != NULL) {
  8637. cur = cur->children;
  8638. continue;
  8639. }
  8640. leave_node:
  8641. if (cur == node)
  8642. break;
  8643. if ((cur->type == XML_ELEMENT_NODE) ||
  8644. (cur->type == XML_XINCLUDE_START) ||
  8645. (cur->type == XML_XINCLUDE_END))
  8646. {
  8647. /*
  8648. * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
  8649. */
  8650. if (XML_NSMAP_NOTEMPTY(nsMap)) {
  8651. /*
  8652. * Pop mappings.
  8653. */
  8654. while ((nsMap->last != NULL) &&
  8655. (nsMap->last->depth >= depth))
  8656. {
  8657. XML_NSMAP_POP(nsMap, mi)
  8658. }
  8659. /*
  8660. * Unshadow.
  8661. */
  8662. XML_NSMAP_FOREACH(nsMap, mi) {
  8663. if (mi->shadowDepth >= depth)
  8664. mi->shadowDepth = -1;
  8665. }
  8666. }
  8667. depth--;
  8668. }
  8669. if (cur->next != NULL)
  8670. cur = cur->next;
  8671. else if ((cur->type == XML_ATTRIBUTE_NODE) &&
  8672. (cur->parent->children != NULL))
  8673. {
  8674. cur = cur->parent->children;
  8675. } else {
  8676. cur = cur->parent;
  8677. goto leave_node;
  8678. }
  8679. }
  8680. goto exit;
  8681. internal_error:
  8682. ret = -1;
  8683. exit:
  8684. /*
  8685. * Cleanup.
  8686. */
  8687. if (nsMap != NULL) {
  8688. if ((ctxt) && (ctxt->namespaceMap == nsMap)) {
  8689. /*
  8690. * Just cleanup the map but don't free.
  8691. */
  8692. if (nsMap->first) {
  8693. if (nsMap->pool)
  8694. nsMap->last->next = nsMap->pool;
  8695. nsMap->pool = nsMap->first;
  8696. nsMap->first = NULL;
  8697. }
  8698. } else
  8699. xmlDOMWrapNsMapFree(nsMap);
  8700. }
  8701. return(ret);
  8702. }
  8703. /*
  8704. * xmlDOMWrapCloneNode:
  8705. * @ctxt: the optional context for custom processing
  8706. * @sourceDoc: the optional sourceDoc
  8707. * @node: the node to start with
  8708. * @resNode: the clone of the given @node
  8709. * @destDoc: the destination doc
  8710. * @destParent: the optional new parent of @node in @destDoc
  8711. * @deep: descend into child if set
  8712. * @options: option flags
  8713. *
  8714. * References of out-of scope ns-decls are remapped to point to @destDoc:
  8715. * 1) If @destParent is given, then nsDef entries on element-nodes are used
  8716. * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used.
  8717. * This is the case when you don't know already where the cloned branch
  8718. * will be added to.
  8719. *
  8720. * If @destParent is given, it ensures that the tree is namespace
  8721. * wellformed by creating additional ns-decls where needed.
  8722. * Note that, since prefixes of already existent ns-decls can be
  8723. * shadowed by this process, it could break QNames in attribute
  8724. * values or element content.
  8725. * TODO:
  8726. * 1) What to do with XInclude? Currently this returns an error for XInclude.
  8727. *
  8728. * Returns 0 if the operation succeeded,
  8729. * 1 if a node of unsupported (or not yet supported) type was given,
  8730. * -1 on API/internal errors.
  8731. */
  8732. int
  8733. xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
  8734. xmlDocPtr sourceDoc,
  8735. xmlNodePtr node,
  8736. xmlNodePtr *resNode,
  8737. xmlDocPtr destDoc,
  8738. xmlNodePtr destParent,
  8739. int deep,
  8740. int options ATTRIBUTE_UNUSED)
  8741. {
  8742. int ret = 0;
  8743. xmlNodePtr cur, curElem = NULL;
  8744. xmlNsMapPtr nsMap = NULL;
  8745. xmlNsMapItemPtr mi;
  8746. xmlNsPtr ns;
  8747. int depth = -1;
  8748. /* int adoptStr = 1; */
  8749. /* gather @parent's ns-decls. */
  8750. int parnsdone = 0;
  8751. /*
  8752. * @ancestorsOnly:
  8753. * TODO: @ancestorsOnly should be set per option.
  8754. *
  8755. */
  8756. int ancestorsOnly = 0;
  8757. xmlNodePtr resultClone = NULL, clone = NULL, parentClone = NULL, prevClone = NULL;
  8758. xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL;
  8759. xmlDictPtr dict; /* The destination dict */
  8760. if ((node == NULL) || (resNode == NULL) || (destDoc == NULL))
  8761. return(-1);
  8762. /*
  8763. * TODO: Initially we support only element-nodes.
  8764. */
  8765. if (node->type != XML_ELEMENT_NODE)
  8766. return(1);
  8767. /*
  8768. * Check node->doc sanity.
  8769. */
  8770. if ((node->doc != NULL) && (sourceDoc != NULL) &&
  8771. (node->doc != sourceDoc)) {
  8772. /*
  8773. * Might be an XIncluded node.
  8774. */
  8775. return (-1);
  8776. }
  8777. if (sourceDoc == NULL)
  8778. sourceDoc = node->doc;
  8779. if (sourceDoc == NULL)
  8780. return (-1);
  8781. dict = destDoc->dict;
  8782. /*
  8783. * Reuse the namespace map of the context.
  8784. */
  8785. if (ctxt)
  8786. nsMap = (xmlNsMapPtr) ctxt->namespaceMap;
  8787. *resNode = NULL;
  8788. cur = node;
  8789. if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
  8790. return(-1);
  8791. while (cur != NULL) {
  8792. if (cur->doc != sourceDoc) {
  8793. /*
  8794. * We'll assume XIncluded nodes if the doc differs.
  8795. * TODO: Do we need to reconciliate XIncluded nodes?
  8796. * TODO: This here returns -1 in this case.
  8797. */
  8798. goto internal_error;
  8799. }
  8800. /*
  8801. * Create a new node.
  8802. */
  8803. switch (cur->type) {
  8804. case XML_XINCLUDE_START:
  8805. case XML_XINCLUDE_END:
  8806. /*
  8807. * TODO: What to do with XInclude?
  8808. */
  8809. goto internal_error;
  8810. break;
  8811. case XML_ELEMENT_NODE:
  8812. case XML_TEXT_NODE:
  8813. case XML_CDATA_SECTION_NODE:
  8814. case XML_COMMENT_NODE:
  8815. case XML_PI_NODE:
  8816. case XML_DOCUMENT_FRAG_NODE:
  8817. case XML_ENTITY_REF_NODE:
  8818. case XML_ENTITY_NODE:
  8819. /*
  8820. * Nodes of xmlNode structure.
  8821. */
  8822. clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  8823. if (clone == NULL) {
  8824. xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node");
  8825. goto internal_error;
  8826. }
  8827. memset(clone, 0, sizeof(xmlNode));
  8828. /*
  8829. * Set hierarchical links.
  8830. */
  8831. if (resultClone != NULL) {
  8832. clone->parent = parentClone;
  8833. if (prevClone) {
  8834. prevClone->next = clone;
  8835. clone->prev = prevClone;
  8836. } else
  8837. parentClone->children = clone;
  8838. } else
  8839. resultClone = clone;
  8840. break;
  8841. case XML_ATTRIBUTE_NODE:
  8842. /*
  8843. * Attributes (xmlAttr).
  8844. */
  8845. clone = (xmlNodePtr) xmlMalloc(sizeof(xmlAttr));
  8846. if (clone == NULL) {
  8847. xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node");
  8848. goto internal_error;
  8849. }
  8850. memset(clone, 0, sizeof(xmlAttr));
  8851. /*
  8852. * Set hierarchical links.
  8853. * TODO: Change this to add to the end of attributes.
  8854. */
  8855. if (resultClone != NULL) {
  8856. clone->parent = parentClone;
  8857. if (prevClone) {
  8858. prevClone->next = clone;
  8859. clone->prev = prevClone;
  8860. } else
  8861. parentClone->properties = (xmlAttrPtr) clone;
  8862. } else
  8863. resultClone = clone;
  8864. break;
  8865. default:
  8866. /*
  8867. * TODO QUESTION: Any other nodes expected?
  8868. */
  8869. goto internal_error;
  8870. }
  8871. clone->type = cur->type;
  8872. clone->doc = destDoc;
  8873. /*
  8874. * Clone the name of the node if any.
  8875. */
  8876. if (cur->name == xmlStringText)
  8877. clone->name = xmlStringText;
  8878. else if (cur->name == xmlStringTextNoenc)
  8879. /*
  8880. * NOTE: Although xmlStringTextNoenc is never assigned to a node
  8881. * in tree.c, it might be set in Libxslt via
  8882. * "xsl:disable-output-escaping".
  8883. */
  8884. clone->name = xmlStringTextNoenc;
  8885. else if (cur->name == xmlStringComment)
  8886. clone->name = xmlStringComment;
  8887. else if (cur->name != NULL) {
  8888. DICT_CONST_COPY(cur->name, clone->name);
  8889. }
  8890. switch (cur->type) {
  8891. case XML_XINCLUDE_START:
  8892. case XML_XINCLUDE_END:
  8893. /*
  8894. * TODO
  8895. */
  8896. return (-1);
  8897. case XML_ELEMENT_NODE:
  8898. curElem = cur;
  8899. depth++;
  8900. /*
  8901. * Namespace declarations.
  8902. */
  8903. if (cur->nsDef != NULL) {
  8904. if (! parnsdone) {
  8905. if (destParent && (ctxt == NULL)) {
  8906. /*
  8907. * Gather @parent's in-scope ns-decls.
  8908. */
  8909. if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
  8910. destParent) == -1)
  8911. goto internal_error;
  8912. }
  8913. parnsdone = 1;
  8914. }
  8915. /*
  8916. * Clone namespace declarations.
  8917. */
  8918. cloneNsDefSlot = &(clone->nsDef);
  8919. for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
  8920. /*
  8921. * Create a new xmlNs.
  8922. */
  8923. cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
  8924. if (cloneNs == NULL) {
  8925. xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
  8926. "allocating namespace");
  8927. return(-1);
  8928. }
  8929. memset(cloneNs, 0, sizeof(xmlNs));
  8930. cloneNs->type = XML_LOCAL_NAMESPACE;
  8931. if (ns->href != NULL)
  8932. cloneNs->href = xmlStrdup(ns->href);
  8933. if (ns->prefix != NULL)
  8934. cloneNs->prefix = xmlStrdup(ns->prefix);
  8935. *cloneNsDefSlot = cloneNs;
  8936. cloneNsDefSlot = &(cloneNs->next);
  8937. /*
  8938. * Note that for custom handling of ns-references,
  8939. * the ns-decls need not be stored in the ns-map,
  8940. * since they won't be referenced by node->ns.
  8941. */
  8942. if ((ctxt == NULL) ||
  8943. (ctxt->getNsForNodeFunc == NULL))
  8944. {
  8945. /*
  8946. * Does it shadow any ns-decl?
  8947. */
  8948. if (XML_NSMAP_NOTEMPTY(nsMap)) {
  8949. XML_NSMAP_FOREACH(nsMap, mi) {
  8950. if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
  8951. (mi->shadowDepth == -1) &&
  8952. ((ns->prefix == mi->newNs->prefix) ||
  8953. xmlStrEqual(ns->prefix,
  8954. mi->newNs->prefix))) {
  8955. /*
  8956. * Mark as shadowed at the current
  8957. * depth.
  8958. */
  8959. mi->shadowDepth = depth;
  8960. }
  8961. }
  8962. }
  8963. /*
  8964. * Push mapping.
  8965. */
  8966. if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
  8967. ns, cloneNs, depth) == NULL)
  8968. goto internal_error;
  8969. }
  8970. }
  8971. }
  8972. /* cur->ns will be processed further down. */
  8973. break;
  8974. case XML_ATTRIBUTE_NODE:
  8975. /* IDs will be processed further down. */
  8976. /* cur->ns will be processed further down. */
  8977. break;
  8978. case XML_TEXT_NODE:
  8979. case XML_CDATA_SECTION_NODE:
  8980. /*
  8981. * Note that this will also cover the values of attributes.
  8982. */
  8983. DICT_COPY(cur->content, clone->content);
  8984. goto leave_node;
  8985. case XML_ENTITY_NODE:
  8986. /* TODO: What to do here? */
  8987. goto leave_node;
  8988. case XML_ENTITY_REF_NODE:
  8989. if (sourceDoc != destDoc) {
  8990. if ((destDoc->intSubset) || (destDoc->extSubset)) {
  8991. xmlEntityPtr ent;
  8992. /*
  8993. * Different doc: Assign new entity-node if available.
  8994. */
  8995. ent = xmlGetDocEntity(destDoc, cur->name);
  8996. if (ent != NULL) {
  8997. clone->content = ent->content;
  8998. clone->children = (xmlNodePtr) ent;
  8999. clone->last = (xmlNodePtr) ent;
  9000. }
  9001. }
  9002. } else {
  9003. /*
  9004. * Same doc: Use the current node's entity declaration
  9005. * and value.
  9006. */
  9007. clone->content = cur->content;
  9008. clone->children = cur->children;
  9009. clone->last = cur->last;
  9010. }
  9011. goto leave_node;
  9012. case XML_PI_NODE:
  9013. DICT_COPY(cur->content, clone->content);
  9014. goto leave_node;
  9015. case XML_COMMENT_NODE:
  9016. DICT_COPY(cur->content, clone->content);
  9017. goto leave_node;
  9018. default:
  9019. goto internal_error;
  9020. }
  9021. if (cur->ns == NULL)
  9022. goto end_ns_reference;
  9023. /* handle_ns_reference: */
  9024. /*
  9025. ** The following will take care of references to ns-decls ********
  9026. ** and is intended only for element- and attribute-nodes.
  9027. **
  9028. */
  9029. if (! parnsdone) {
  9030. if (destParent && (ctxt == NULL)) {
  9031. if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1)
  9032. goto internal_error;
  9033. }
  9034. parnsdone = 1;
  9035. }
  9036. /*
  9037. * Adopt ns-references.
  9038. */
  9039. if (XML_NSMAP_NOTEMPTY(nsMap)) {
  9040. /*
  9041. * Search for a mapping.
  9042. */
  9043. XML_NSMAP_FOREACH(nsMap, mi) {
  9044. if ((mi->shadowDepth == -1) &&
  9045. (cur->ns == mi->oldNs)) {
  9046. /*
  9047. * This is the nice case: a mapping was found.
  9048. */
  9049. clone->ns = mi->newNs;
  9050. goto end_ns_reference;
  9051. }
  9052. }
  9053. }
  9054. /*
  9055. * No matching namespace in scope. We need a new one.
  9056. */
  9057. if ((ctxt != NULL) && (ctxt->getNsForNodeFunc != NULL)) {
  9058. /*
  9059. * User-defined behaviour.
  9060. */
  9061. ns = ctxt->getNsForNodeFunc(ctxt, cur,
  9062. cur->ns->href, cur->ns->prefix);
  9063. /*
  9064. * Add user's mapping.
  9065. */
  9066. if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
  9067. cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
  9068. goto internal_error;
  9069. clone->ns = ns;
  9070. } else {
  9071. /*
  9072. * Acquire a normalized ns-decl and add it to the map.
  9073. */
  9074. if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc,
  9075. /* ns-decls on curElem or on destDoc->oldNs */
  9076. destParent ? curElem : NULL,
  9077. cur->ns, &ns,
  9078. &nsMap, depth,
  9079. /* if we need to search only in the ancestor-axis */
  9080. ancestorsOnly,
  9081. /* ns-decls must be prefixed for attributes. */
  9082. (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
  9083. goto internal_error;
  9084. clone->ns = ns;
  9085. }
  9086. end_ns_reference:
  9087. /*
  9088. * Some post-processing.
  9089. *
  9090. * Handle ID attributes.
  9091. */
  9092. if ((clone->type == XML_ATTRIBUTE_NODE) &&
  9093. (clone->parent != NULL))
  9094. {
  9095. if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) {
  9096. xmlChar *idVal;
  9097. idVal = xmlNodeListGetString(cur->doc, cur->children, 1);
  9098. if (idVal != NULL) {
  9099. if (xmlAddID(NULL, destDoc, idVal, (xmlAttrPtr) cur) == NULL) {
  9100. /* TODO: error message. */
  9101. xmlFree(idVal);
  9102. goto internal_error;
  9103. }
  9104. xmlFree(idVal);
  9105. }
  9106. }
  9107. }
  9108. /*
  9109. **
  9110. ** The following will traverse the tree **************************
  9111. **
  9112. *
  9113. * Walk the element's attributes before descending into child-nodes.
  9114. */
  9115. if ((cur->type == XML_ELEMENT_NODE) && (cur->properties != NULL)) {
  9116. prevClone = NULL;
  9117. parentClone = clone;
  9118. cur = (xmlNodePtr) cur->properties;
  9119. continue;
  9120. }
  9121. into_content:
  9122. /*
  9123. * Descend into child-nodes.
  9124. */
  9125. if (cur->children != NULL) {
  9126. if (deep || (cur->type == XML_ATTRIBUTE_NODE)) {
  9127. prevClone = NULL;
  9128. parentClone = clone;
  9129. cur = cur->children;
  9130. continue;
  9131. }
  9132. }
  9133. leave_node:
  9134. /*
  9135. * At this point we are done with the node, its content
  9136. * and an element-nodes's attribute-nodes.
  9137. */
  9138. if (cur == node)
  9139. break;
  9140. if ((cur->type == XML_ELEMENT_NODE) ||
  9141. (cur->type == XML_XINCLUDE_START) ||
  9142. (cur->type == XML_XINCLUDE_END)) {
  9143. /*
  9144. * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
  9145. */
  9146. if (XML_NSMAP_NOTEMPTY(nsMap)) {
  9147. /*
  9148. * Pop mappings.
  9149. */
  9150. while ((nsMap->last != NULL) &&
  9151. (nsMap->last->depth >= depth))
  9152. {
  9153. XML_NSMAP_POP(nsMap, mi)
  9154. }
  9155. /*
  9156. * Unshadow.
  9157. */
  9158. XML_NSMAP_FOREACH(nsMap, mi) {
  9159. if (mi->shadowDepth >= depth)
  9160. mi->shadowDepth = -1;
  9161. }
  9162. }
  9163. depth--;
  9164. }
  9165. if (cur->next != NULL) {
  9166. prevClone = clone;
  9167. cur = cur->next;
  9168. } else if (cur->type != XML_ATTRIBUTE_NODE) {
  9169. /*
  9170. * Set clone->last.
  9171. */
  9172. if (clone->parent != NULL)
  9173. clone->parent->last = clone;
  9174. clone = clone->parent;
  9175. if (clone != NULL)
  9176. parentClone = clone->parent;
  9177. /*
  9178. * Process parent --> next;
  9179. */
  9180. cur = cur->parent;
  9181. goto leave_node;
  9182. } else {
  9183. /* This is for attributes only. */
  9184. clone = clone->parent;
  9185. parentClone = clone->parent;
  9186. /*
  9187. * Process parent-element --> children.
  9188. */
  9189. cur = cur->parent;
  9190. goto into_content;
  9191. }
  9192. }
  9193. goto exit;
  9194. internal_error:
  9195. ret = -1;
  9196. exit:
  9197. /*
  9198. * Cleanup.
  9199. */
  9200. if (nsMap != NULL) {
  9201. if ((ctxt) && (ctxt->namespaceMap == nsMap)) {
  9202. /*
  9203. * Just cleanup the map but don't free.
  9204. */
  9205. if (nsMap->first) {
  9206. if (nsMap->pool)
  9207. nsMap->last->next = nsMap->pool;
  9208. nsMap->pool = nsMap->first;
  9209. nsMap->first = NULL;
  9210. }
  9211. } else
  9212. xmlDOMWrapNsMapFree(nsMap);
  9213. }
  9214. /*
  9215. * TODO: Should we try a cleanup of the cloned node in case of a
  9216. * fatal error?
  9217. */
  9218. *resNode = resultClone;
  9219. return (ret);
  9220. }
  9221. /*
  9222. * xmlDOMWrapAdoptAttr:
  9223. * @ctxt: the optional context for custom processing
  9224. * @sourceDoc: the optional source document of attr
  9225. * @attr: the attribute-node to be adopted
  9226. * @destDoc: the destination doc for adoption
  9227. * @destParent: the optional new parent of @attr in @destDoc
  9228. * @options: option flags
  9229. *
  9230. * @attr is adopted by @destDoc.
  9231. * Ensures that ns-references point to @destDoc: either to
  9232. * elements->nsDef entries if @destParent is given, or to
  9233. * @destDoc->oldNs otherwise.
  9234. *
  9235. * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
  9236. */
  9237. static int
  9238. xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt,
  9239. xmlDocPtr sourceDoc,
  9240. xmlAttrPtr attr,
  9241. xmlDocPtr destDoc,
  9242. xmlNodePtr destParent,
  9243. int options ATTRIBUTE_UNUSED)
  9244. {
  9245. xmlNodePtr cur;
  9246. int adoptStr = 1;
  9247. if ((attr == NULL) || (destDoc == NULL))
  9248. return (-1);
  9249. attr->doc = destDoc;
  9250. if (attr->ns != NULL) {
  9251. xmlNsPtr ns = NULL;
  9252. if (ctxt != NULL) {
  9253. /* TODO: User defined. */
  9254. }
  9255. /* XML Namespace. */
  9256. if (IS_STR_XML(attr->ns->prefix)) {
  9257. ns = xmlTreeEnsureXMLDecl(destDoc);
  9258. } else if (destParent == NULL) {
  9259. /*
  9260. * Store in @destDoc->oldNs.
  9261. */
  9262. ns = xmlDOMWrapStoreNs(destDoc, attr->ns->href, attr->ns->prefix);
  9263. } else {
  9264. /*
  9265. * Declare on @destParent.
  9266. */
  9267. if (xmlSearchNsByNamespaceStrict(destDoc, destParent, attr->ns->href,
  9268. &ns, 1) == -1)
  9269. goto internal_error;
  9270. if (ns == NULL) {
  9271. ns = xmlDOMWrapNSNormDeclareNsForced(destDoc, destParent,
  9272. attr->ns->href, attr->ns->prefix, 1);
  9273. }
  9274. }
  9275. if (ns == NULL)
  9276. goto internal_error;
  9277. attr->ns = ns;
  9278. }
  9279. XML_TREE_ADOPT_STR(attr->name);
  9280. attr->atype = 0;
  9281. attr->psvi = NULL;
  9282. /*
  9283. * Walk content.
  9284. */
  9285. if (attr->children == NULL)
  9286. return (0);
  9287. cur = attr->children;
  9288. if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
  9289. goto internal_error;
  9290. while (cur != NULL) {
  9291. cur->doc = destDoc;
  9292. switch (cur->type) {
  9293. case XML_TEXT_NODE:
  9294. case XML_CDATA_SECTION_NODE:
  9295. XML_TREE_ADOPT_STR_2(cur->content)
  9296. break;
  9297. case XML_ENTITY_REF_NODE:
  9298. /*
  9299. * Remove reference to the entity-node.
  9300. */
  9301. cur->content = NULL;
  9302. cur->children = NULL;
  9303. cur->last = NULL;
  9304. if ((destDoc->intSubset) || (destDoc->extSubset)) {
  9305. xmlEntityPtr ent;
  9306. /*
  9307. * Assign new entity-node if available.
  9308. */
  9309. ent = xmlGetDocEntity(destDoc, cur->name);
  9310. if (ent != NULL) {
  9311. cur->content = ent->content;
  9312. cur->children = (xmlNodePtr) ent;
  9313. cur->last = (xmlNodePtr) ent;
  9314. }
  9315. }
  9316. break;
  9317. default:
  9318. break;
  9319. }
  9320. if (cur->children != NULL) {
  9321. cur = cur->children;
  9322. continue;
  9323. }
  9324. next_sibling:
  9325. if (cur == (xmlNodePtr) attr)
  9326. break;
  9327. if (cur->next != NULL)
  9328. cur = cur->next;
  9329. else {
  9330. cur = cur->parent;
  9331. goto next_sibling;
  9332. }
  9333. }
  9334. return (0);
  9335. internal_error:
  9336. return (-1);
  9337. }
  9338. /*
  9339. * xmlDOMWrapAdoptNode:
  9340. * @ctxt: the optional context for custom processing
  9341. * @sourceDoc: the optional sourceDoc
  9342. * @node: the node to start with
  9343. * @destDoc: the destination doc
  9344. * @destParent: the optional new parent of @node in @destDoc
  9345. * @options: option flags
  9346. *
  9347. * References of out-of scope ns-decls are remapped to point to @destDoc:
  9348. * 1) If @destParent is given, then nsDef entries on element-nodes are used
  9349. * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used
  9350. * This is the case when you have an unlinked node and just want to move it
  9351. * to the context of
  9352. *
  9353. * If @destParent is given, it ensures that the tree is namespace
  9354. * wellformed by creating additional ns-decls where needed.
  9355. * Note that, since prefixes of already existent ns-decls can be
  9356. * shadowed by this process, it could break QNames in attribute
  9357. * values or element content.
  9358. * NOTE: This function was not intensively tested.
  9359. *
  9360. * Returns 0 if the operation succeeded,
  9361. * 1 if a node of unsupported type was given,
  9362. * 2 if a node of not yet supported type was given and
  9363. * -1 on API/internal errors.
  9364. */
  9365. int
  9366. xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt,
  9367. xmlDocPtr sourceDoc,
  9368. xmlNodePtr node,
  9369. xmlDocPtr destDoc,
  9370. xmlNodePtr destParent,
  9371. int options)
  9372. {
  9373. if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
  9374. (destDoc == NULL) ||
  9375. ((destParent != NULL) && (destParent->doc != destDoc)))
  9376. return(-1);
  9377. /*
  9378. * Check node->doc sanity.
  9379. */
  9380. if ((node->doc != NULL) && (sourceDoc != NULL) &&
  9381. (node->doc != sourceDoc)) {
  9382. /*
  9383. * Might be an XIncluded node.
  9384. */
  9385. return (-1);
  9386. }
  9387. if (sourceDoc == NULL)
  9388. sourceDoc = node->doc;
  9389. if (sourceDoc == destDoc)
  9390. return (-1);
  9391. switch (node->type) {
  9392. case XML_ELEMENT_NODE:
  9393. case XML_ATTRIBUTE_NODE:
  9394. case XML_TEXT_NODE:
  9395. case XML_CDATA_SECTION_NODE:
  9396. case XML_ENTITY_REF_NODE:
  9397. case XML_PI_NODE:
  9398. case XML_COMMENT_NODE:
  9399. break;
  9400. case XML_DOCUMENT_FRAG_NODE:
  9401. /* TODO: Support document-fragment-nodes. */
  9402. return (2);
  9403. default:
  9404. return (1);
  9405. }
  9406. /*
  9407. * Unlink only if @node was not already added to @destParent.
  9408. */
  9409. if ((node->parent != NULL) && (destParent != node->parent))
  9410. xmlUnlinkNode(node);
  9411. if (node->type == XML_ELEMENT_NODE) {
  9412. return (xmlDOMWrapAdoptBranch(ctxt, sourceDoc, node,
  9413. destDoc, destParent, options));
  9414. } else if (node->type == XML_ATTRIBUTE_NODE) {
  9415. return (xmlDOMWrapAdoptAttr(ctxt, sourceDoc,
  9416. (xmlAttrPtr) node, destDoc, destParent, options));
  9417. } else {
  9418. xmlNodePtr cur = node;
  9419. int adoptStr = 1;
  9420. cur->doc = destDoc;
  9421. /*
  9422. * Optimize string adoption.
  9423. */
  9424. if ((sourceDoc != NULL) &&
  9425. (sourceDoc->dict == destDoc->dict))
  9426. adoptStr = 0;
  9427. switch (node->type) {
  9428. case XML_TEXT_NODE:
  9429. case XML_CDATA_SECTION_NODE:
  9430. XML_TREE_ADOPT_STR_2(node->content)
  9431. break;
  9432. case XML_ENTITY_REF_NODE:
  9433. /*
  9434. * Remove reference to the entity-node.
  9435. */
  9436. node->content = NULL;
  9437. node->children = NULL;
  9438. node->last = NULL;
  9439. if ((destDoc->intSubset) || (destDoc->extSubset)) {
  9440. xmlEntityPtr ent;
  9441. /*
  9442. * Assign new entity-node if available.
  9443. */
  9444. ent = xmlGetDocEntity(destDoc, node->name);
  9445. if (ent != NULL) {
  9446. node->content = ent->content;
  9447. node->children = (xmlNodePtr) ent;
  9448. node->last = (xmlNodePtr) ent;
  9449. }
  9450. }
  9451. XML_TREE_ADOPT_STR(node->name)
  9452. break;
  9453. case XML_PI_NODE: {
  9454. XML_TREE_ADOPT_STR(node->name)
  9455. XML_TREE_ADOPT_STR_2(node->content)
  9456. break;
  9457. }
  9458. default:
  9459. break;
  9460. }
  9461. }
  9462. return (0);
  9463. }
  9464. #define bottom_tree
  9465. #include "elfgcchack.h"