xslt.c 181 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044
  1. /*
  2. * xslt.c: Implemetation of an XSL Transformation 1.0 engine
  3. *
  4. * Reference:
  5. * XSLT specification
  6. * http://www.w3.org/TR/1999/REC-xslt-19991116
  7. *
  8. * Associating Style Sheets with XML documents
  9. * http://www.w3.org/1999/06/REC-xml-stylesheet-19990629
  10. *
  11. * See Copyright for the status of this software.
  12. *
  13. * daniel@veillard.com
  14. */
  15. #define IN_LIBXSLT
  16. #include "libxslt.h"
  17. #include <string.h>
  18. #include <libxml/xmlmemory.h>
  19. #include <libxml/parser.h>
  20. #include <libxml/tree.h>
  21. #include <libxml/valid.h>
  22. #include <libxml/hash.h>
  23. #include <libxml/uri.h>
  24. #include <libxml/xmlerror.h>
  25. #include <libxml/parserInternals.h>
  26. #include <libxml/xpathInternals.h>
  27. #include <libxml/xpath.h>
  28. #include "xslt.h"
  29. #include "xsltInternals.h"
  30. #include "pattern.h"
  31. #include "variables.h"
  32. #include "namespaces.h"
  33. #include "attributes.h"
  34. #include "xsltutils.h"
  35. #include "imports.h"
  36. #include "keys.h"
  37. #include "documents.h"
  38. #include "extensions.h"
  39. #include "preproc.h"
  40. #include "extra.h"
  41. #include "security.h"
  42. #include "xsltlocale.h"
  43. #ifdef WITH_XSLT_DEBUG
  44. #define WITH_XSLT_DEBUG_PARSING
  45. /* #define WITH_XSLT_DEBUG_BLANKS */
  46. #endif
  47. const char *xsltEngineVersion = LIBXSLT_VERSION_STRING LIBXSLT_VERSION_EXTRA;
  48. const int xsltLibxsltVersion = LIBXSLT_VERSION;
  49. const int xsltLibxmlVersion = LIBXML_VERSION;
  50. #ifdef XSLT_REFACTORED
  51. const xmlChar *xsltConstNamespaceNameXSLT = (const xmlChar *) XSLT_NAMESPACE;
  52. #define XSLT_ELEMENT_CATEGORY_XSLT 0
  53. #define XSLT_ELEMENT_CATEGORY_EXTENSION 1
  54. #define XSLT_ELEMENT_CATEGORY_LRE 2
  55. /*
  56. * xsltLiteralResultMarker:
  57. * Marker for Literal result elements, in order to avoid multiple attempts
  58. * to recognize such elements in the stylesheet's tree.
  59. * This marker is set on node->psvi during the initial traversal
  60. * of a stylesheet's node tree.
  61. *
  62. const xmlChar *xsltLiteralResultMarker =
  63. (const xmlChar *) "Literal Result Element";
  64. */
  65. /*
  66. * xsltXSLTTextMarker:
  67. * Marker for xsl:text elements. Used to recognize xsl:text elements
  68. * for post-processing of the stylesheet's tree, where those
  69. * elements are removed from the tree.
  70. */
  71. const xmlChar *xsltXSLTTextMarker = (const xmlChar *) "XSLT Text Element";
  72. /*
  73. * xsltXSLTAttrMarker:
  74. * Marker for XSLT attribute on Literal Result Elements.
  75. */
  76. const xmlChar *xsltXSLTAttrMarker = (const xmlChar *) "LRE XSLT Attr";
  77. #endif
  78. #ifdef XSLT_LOCALE_WINAPI
  79. extern xmlRMutexPtr xsltLocaleMutex;
  80. #endif
  81. /*
  82. * Harmless but avoiding a problem when compiling against a
  83. * libxml <= 2.3.11 without LIBXML_DEBUG_ENABLED
  84. */
  85. #ifndef LIBXML_DEBUG_ENABLED
  86. double xmlXPathStringEvalNumber(const xmlChar *str);
  87. #endif
  88. /*
  89. * Useful macros
  90. */
  91. #ifdef IS_BLANK
  92. #undef IS_BLANK
  93. #endif
  94. #define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \
  95. ((c) == 0x0D))
  96. #ifdef IS_BLANK_NODE
  97. #undef IS_BLANK_NODE
  98. #endif
  99. #define IS_BLANK_NODE(n) \
  100. (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
  101. /**
  102. * xsltParseContentError:
  103. *
  104. * @style: the stylesheet
  105. * @node: the node where the error occured
  106. *
  107. * Compile-time error function.
  108. */
  109. static void
  110. xsltParseContentError(xsltStylesheetPtr style,
  111. xmlNodePtr node)
  112. {
  113. if ((style == NULL) || (node == NULL))
  114. return;
  115. if (IS_XSLT_ELEM(node))
  116. xsltTransformError(NULL, style, node,
  117. "The XSLT-element '%s' is not allowed at this position.\n",
  118. node->name);
  119. else
  120. xsltTransformError(NULL, style, node,
  121. "The element '%s' is not allowed at this position.\n",
  122. node->name);
  123. style->errors++;
  124. }
  125. #ifdef XSLT_REFACTORED
  126. #else
  127. /**
  128. * exclPrefixPush:
  129. * @style: the transformation stylesheet
  130. * @value: the excluded namespace name to push on the stack
  131. *
  132. * Push an excluded namespace name on the stack
  133. *
  134. * Returns the new index in the stack or -1 if already present or
  135. * in case of error
  136. */
  137. static int
  138. exclPrefixPush(xsltStylesheetPtr style, xmlChar * value)
  139. {
  140. int i;
  141. if (style->exclPrefixMax == 0) {
  142. style->exclPrefixMax = 4;
  143. style->exclPrefixTab =
  144. (xmlChar * *)xmlMalloc(style->exclPrefixMax *
  145. sizeof(style->exclPrefixTab[0]));
  146. if (style->exclPrefixTab == NULL) {
  147. xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
  148. return (-1);
  149. }
  150. }
  151. /* do not push duplicates */
  152. for (i = 0;i < style->exclPrefixNr;i++) {
  153. if (xmlStrEqual(style->exclPrefixTab[i], value))
  154. return(-1);
  155. }
  156. if (style->exclPrefixNr >= style->exclPrefixMax) {
  157. style->exclPrefixMax *= 2;
  158. style->exclPrefixTab =
  159. (xmlChar * *)xmlRealloc(style->exclPrefixTab,
  160. style->exclPrefixMax *
  161. sizeof(style->exclPrefixTab[0]));
  162. if (style->exclPrefixTab == NULL) {
  163. xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
  164. return (-1);
  165. }
  166. }
  167. style->exclPrefixTab[style->exclPrefixNr] = value;
  168. style->exclPrefix = value;
  169. return (style->exclPrefixNr++);
  170. }
  171. /**
  172. * exclPrefixPop:
  173. * @style: the transformation stylesheet
  174. *
  175. * Pop an excluded prefix value from the stack
  176. *
  177. * Returns the stored excluded prefix value
  178. */
  179. static xmlChar *
  180. exclPrefixPop(xsltStylesheetPtr style)
  181. {
  182. xmlChar *ret;
  183. if (style->exclPrefixNr <= 0)
  184. return (0);
  185. style->exclPrefixNr--;
  186. if (style->exclPrefixNr > 0)
  187. style->exclPrefix = style->exclPrefixTab[style->exclPrefixNr - 1];
  188. else
  189. style->exclPrefix = NULL;
  190. ret = style->exclPrefixTab[style->exclPrefixNr];
  191. style->exclPrefixTab[style->exclPrefixNr] = 0;
  192. return (ret);
  193. }
  194. #endif
  195. /************************************************************************
  196. * *
  197. * Helper functions *
  198. * *
  199. ************************************************************************/
  200. static int initialized = 0;
  201. /**
  202. * xsltInit:
  203. *
  204. * Initializes the processor (e.g. registers built-in extensions,
  205. * etc.)
  206. */
  207. void
  208. xsltInit (void) {
  209. if (initialized == 0) {
  210. initialized = 1;
  211. #ifdef XSLT_LOCALE_WINAPI
  212. xsltLocaleMutex = xmlNewRMutex();
  213. #endif
  214. xsltRegisterAllExtras();
  215. }
  216. }
  217. /**
  218. * xsltUninit:
  219. *
  220. * Uninitializes the processor.
  221. */
  222. void
  223. xsltUninit (void) {
  224. #ifdef XSLT_LOCALE_WINAPI
  225. xmlFreeRMutex(xsltLocaleMutex);
  226. xsltLocaleMutex = NULL;
  227. #endif
  228. initialized = 0;
  229. }
  230. /**
  231. * xsltIsBlank:
  232. * @str: a string
  233. *
  234. * Check if a string is ignorable
  235. *
  236. * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
  237. */
  238. int
  239. xsltIsBlank(xmlChar *str) {
  240. if (str == NULL)
  241. return(1);
  242. while (*str != 0) {
  243. if (!(IS_BLANK(*str))) return(0);
  244. str++;
  245. }
  246. return(1);
  247. }
  248. /************************************************************************
  249. * *
  250. * Routines to handle XSLT data structures *
  251. * *
  252. ************************************************************************/
  253. static xsltDecimalFormatPtr
  254. xsltNewDecimalFormat(const xmlChar *nsUri, xmlChar *name)
  255. {
  256. xsltDecimalFormatPtr self;
  257. /* UTF-8 for 0x2030 */
  258. static const xmlChar permille[4] = {0xe2, 0x80, 0xb0, 0};
  259. self = xmlMalloc(sizeof(xsltDecimalFormat));
  260. if (self != NULL) {
  261. self->next = NULL;
  262. self->nsUri = nsUri;
  263. self->name = name;
  264. /* Default values */
  265. self->digit = xmlStrdup(BAD_CAST("#"));
  266. self->patternSeparator = xmlStrdup(BAD_CAST(";"));
  267. self->decimalPoint = xmlStrdup(BAD_CAST("."));
  268. self->grouping = xmlStrdup(BAD_CAST(","));
  269. self->percent = xmlStrdup(BAD_CAST("%"));
  270. self->permille = xmlStrdup(BAD_CAST(permille));
  271. self->zeroDigit = xmlStrdup(BAD_CAST("0"));
  272. self->minusSign = xmlStrdup(BAD_CAST("-"));
  273. self->infinity = xmlStrdup(BAD_CAST("Infinity"));
  274. self->noNumber = xmlStrdup(BAD_CAST("NaN"));
  275. }
  276. return self;
  277. }
  278. static void
  279. xsltFreeDecimalFormat(xsltDecimalFormatPtr self)
  280. {
  281. if (self != NULL) {
  282. if (self->digit)
  283. xmlFree(self->digit);
  284. if (self->patternSeparator)
  285. xmlFree(self->patternSeparator);
  286. if (self->decimalPoint)
  287. xmlFree(self->decimalPoint);
  288. if (self->grouping)
  289. xmlFree(self->grouping);
  290. if (self->percent)
  291. xmlFree(self->percent);
  292. if (self->permille)
  293. xmlFree(self->permille);
  294. if (self->zeroDigit)
  295. xmlFree(self->zeroDigit);
  296. if (self->minusSign)
  297. xmlFree(self->minusSign);
  298. if (self->infinity)
  299. xmlFree(self->infinity);
  300. if (self->noNumber)
  301. xmlFree(self->noNumber);
  302. if (self->name)
  303. xmlFree(self->name);
  304. xmlFree(self);
  305. }
  306. }
  307. static void
  308. xsltFreeDecimalFormatList(xsltStylesheetPtr self)
  309. {
  310. xsltDecimalFormatPtr iter;
  311. xsltDecimalFormatPtr tmp;
  312. if (self == NULL)
  313. return;
  314. iter = self->decimalFormat;
  315. while (iter != NULL) {
  316. tmp = iter->next;
  317. xsltFreeDecimalFormat(iter);
  318. iter = tmp;
  319. }
  320. }
  321. /**
  322. * xsltDecimalFormatGetByName:
  323. * @style: the XSLT stylesheet
  324. * @name: the decimal-format name to find
  325. *
  326. * Find decimal-format by name
  327. *
  328. * Returns the xsltDecimalFormatPtr
  329. */
  330. xsltDecimalFormatPtr
  331. xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name)
  332. {
  333. xsltDecimalFormatPtr result = NULL;
  334. if (name == NULL)
  335. return style->decimalFormat;
  336. while (style != NULL) {
  337. for (result = style->decimalFormat->next;
  338. result != NULL;
  339. result = result->next) {
  340. if ((result->nsUri == NULL) && xmlStrEqual(name, result->name))
  341. return result;
  342. }
  343. style = xsltNextImport(style);
  344. }
  345. return result;
  346. }
  347. /**
  348. * xsltDecimalFormatGetByQName:
  349. * @style: the XSLT stylesheet
  350. * @nsUri: the namespace URI of the QName
  351. * @name: the local part of the QName
  352. *
  353. * Find decimal-format by QName
  354. *
  355. * Returns the xsltDecimalFormatPtr
  356. */
  357. xsltDecimalFormatPtr
  358. xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri,
  359. const xmlChar *name)
  360. {
  361. xsltDecimalFormatPtr result = NULL;
  362. if (name == NULL)
  363. return style->decimalFormat;
  364. while (style != NULL) {
  365. for (result = style->decimalFormat->next;
  366. result != NULL;
  367. result = result->next) {
  368. if (xmlStrEqual(nsUri, result->nsUri) &&
  369. xmlStrEqual(name, result->name))
  370. return result;
  371. }
  372. style = xsltNextImport(style);
  373. }
  374. return result;
  375. }
  376. /**
  377. * xsltNewTemplate:
  378. *
  379. * Create a new XSLT Template
  380. *
  381. * Returns the newly allocated xsltTemplatePtr or NULL in case of error
  382. */
  383. static xsltTemplatePtr
  384. xsltNewTemplate(void) {
  385. xsltTemplatePtr cur;
  386. cur = (xsltTemplatePtr) xmlMalloc(sizeof(xsltTemplate));
  387. if (cur == NULL) {
  388. xsltTransformError(NULL, NULL, NULL,
  389. "xsltNewTemplate : malloc failed\n");
  390. return(NULL);
  391. }
  392. memset(cur, 0, sizeof(xsltTemplate));
  393. cur->priority = XSLT_PAT_NO_PRIORITY;
  394. return(cur);
  395. }
  396. /**
  397. * xsltFreeTemplate:
  398. * @template: an XSLT template
  399. *
  400. * Free up the memory allocated by @template
  401. */
  402. static void
  403. xsltFreeTemplate(xsltTemplatePtr template) {
  404. if (template == NULL)
  405. return;
  406. if (template->match) xmlFree(template->match);
  407. /*
  408. * NOTE: @name and @nameURI are put into the string dict now.
  409. * if (template->name) xmlFree(template->name);
  410. * if (template->nameURI) xmlFree(template->nameURI);
  411. */
  412. /*
  413. if (template->mode) xmlFree(template->mode);
  414. if (template->modeURI) xmlFree(template->modeURI);
  415. */
  416. if (template->inheritedNs) xmlFree(template->inheritedNs);
  417. /* free profiling data */
  418. if (template->templCalledTab) xmlFree(template->templCalledTab);
  419. if (template->templCountTab) xmlFree(template->templCountTab);
  420. memset(template, -1, sizeof(xsltTemplate));
  421. xmlFree(template);
  422. }
  423. /**
  424. * xsltFreeTemplateList:
  425. * @template: an XSLT template list
  426. *
  427. * Free up the memory allocated by all the elements of @template
  428. */
  429. static void
  430. xsltFreeTemplateList(xsltTemplatePtr template) {
  431. xsltTemplatePtr cur;
  432. while (template != NULL) {
  433. cur = template;
  434. template = template->next;
  435. xsltFreeTemplate(cur);
  436. }
  437. }
  438. #ifdef XSLT_REFACTORED
  439. static void
  440. xsltFreeNsAliasList(xsltNsAliasPtr item)
  441. {
  442. xsltNsAliasPtr tmp;
  443. while (item) {
  444. tmp = item;
  445. item = item->next;
  446. xmlFree(tmp);
  447. }
  448. return;
  449. }
  450. #ifdef XSLT_REFACTORED_XSLT_NSCOMP
  451. static void
  452. xsltFreeNamespaceMap(xsltNsMapPtr item)
  453. {
  454. xsltNsMapPtr tmp;
  455. while (item) {
  456. tmp = item;
  457. item = item->next;
  458. xmlFree(tmp);
  459. }
  460. return;
  461. }
  462. static xsltNsMapPtr
  463. xsltNewNamespaceMapItem(xsltCompilerCtxtPtr cctxt,
  464. xmlDocPtr doc,
  465. xmlNsPtr ns,
  466. xmlNodePtr elem)
  467. {
  468. xsltNsMapPtr ret;
  469. if ((cctxt == NULL) || (doc == NULL) || (ns == NULL))
  470. return(NULL);
  471. ret = (xsltNsMapPtr) xmlMalloc(sizeof(xsltNsMap));
  472. if (ret == NULL) {
  473. xsltTransformError(NULL, cctxt->style, elem,
  474. "Internal error: (xsltNewNamespaceMapItem) "
  475. "memory allocation failed.\n");
  476. return(NULL);
  477. }
  478. memset(ret, 0, sizeof(xsltNsMap));
  479. ret->doc = doc;
  480. ret->ns = ns;
  481. ret->origNsName = ns->href;
  482. /*
  483. * Store the item at current stylesheet-level.
  484. */
  485. if (cctxt->psData->nsMap != NULL)
  486. ret->next = cctxt->psData->nsMap;
  487. cctxt->psData->nsMap = ret;
  488. return(ret);
  489. }
  490. #endif /* XSLT_REFACTORED_XSLT_NSCOMP */
  491. /**
  492. * xsltCompilerVarInfoFree:
  493. * @cctxt: the compilation context
  494. *
  495. * Frees the list of information for vars/params.
  496. */
  497. static void
  498. xsltCompilerVarInfoFree(xsltCompilerCtxtPtr cctxt)
  499. {
  500. xsltVarInfoPtr ivar = cctxt->ivars, ivartmp;
  501. while (ivar) {
  502. ivartmp = ivar;
  503. ivar = ivar->next;
  504. xmlFree(ivartmp);
  505. }
  506. }
  507. /**
  508. * xsltCompilerCtxtFree:
  509. *
  510. * Free an XSLT compiler context.
  511. */
  512. static void
  513. xsltCompilationCtxtFree(xsltCompilerCtxtPtr cctxt)
  514. {
  515. if (cctxt == NULL)
  516. return;
  517. #ifdef WITH_XSLT_DEBUG_PARSING
  518. xsltGenericDebug(xsltGenericDebugContext,
  519. "Freeing compilation context\n");
  520. xsltGenericDebug(xsltGenericDebugContext,
  521. "### Max inodes: %d\n", cctxt->maxNodeInfos);
  522. xsltGenericDebug(xsltGenericDebugContext,
  523. "### Max LREs : %d\n", cctxt->maxLREs);
  524. #endif
  525. /*
  526. * Free node-infos.
  527. */
  528. if (cctxt->inodeList != NULL) {
  529. xsltCompilerNodeInfoPtr tmp, cur = cctxt->inodeList;
  530. while (cur != NULL) {
  531. tmp = cur;
  532. cur = cur->next;
  533. xmlFree(tmp);
  534. }
  535. }
  536. if (cctxt->tmpList != NULL)
  537. xsltPointerListFree(cctxt->tmpList);
  538. if (cctxt->nsAliases != NULL)
  539. xsltFreeNsAliasList(cctxt->nsAliases);
  540. if (cctxt->ivars)
  541. xsltCompilerVarInfoFree(cctxt);
  542. xmlFree(cctxt);
  543. }
  544. /**
  545. * xsltCompilerCreate:
  546. *
  547. * Creates an XSLT compiler context.
  548. *
  549. * Returns the pointer to the created xsltCompilerCtxt or
  550. * NULL in case of an internal error.
  551. */
  552. static xsltCompilerCtxtPtr
  553. xsltCompilationCtxtCreate(xsltStylesheetPtr style) {
  554. xsltCompilerCtxtPtr ret;
  555. ret = (xsltCompilerCtxtPtr) xmlMalloc(sizeof(xsltCompilerCtxt));
  556. if (ret == NULL) {
  557. xsltTransformError(NULL, style, NULL,
  558. "xsltCompilerCreate: allocation of compiler "
  559. "context failed.\n");
  560. return(NULL);
  561. }
  562. memset(ret, 0, sizeof(xsltCompilerCtxt));
  563. ret->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
  564. ret->tmpList = xsltPointerListCreate(20);
  565. if (ret->tmpList == NULL) {
  566. goto internal_err;
  567. }
  568. return(ret);
  569. internal_err:
  570. xsltCompilationCtxtFree(ret);
  571. return(NULL);
  572. }
  573. static void
  574. xsltLREEffectiveNsNodesFree(xsltEffectiveNsPtr first)
  575. {
  576. xsltEffectiveNsPtr tmp;
  577. while (first != NULL) {
  578. tmp = first;
  579. first = first->nextInStore;
  580. xmlFree(tmp);
  581. }
  582. }
  583. static void
  584. xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)
  585. {
  586. if (data == NULL)
  587. return;
  588. if (data->inScopeNamespaces != NULL) {
  589. int i;
  590. xsltNsListContainerPtr nsi;
  591. xsltPointerListPtr list =
  592. (xsltPointerListPtr) data->inScopeNamespaces;
  593. for (i = 0; i < list->number; i++) {
  594. /*
  595. * REVISIT TODO: Free info of in-scope namespaces.
  596. */
  597. nsi = (xsltNsListContainerPtr) list->items[i];
  598. if (nsi->list != NULL)
  599. xmlFree(nsi->list);
  600. xmlFree(nsi);
  601. }
  602. xsltPointerListFree(list);
  603. data->inScopeNamespaces = NULL;
  604. }
  605. if (data->exclResultNamespaces != NULL) {
  606. int i;
  607. xsltPointerListPtr list = (xsltPointerListPtr)
  608. data->exclResultNamespaces;
  609. for (i = 0; i < list->number; i++)
  610. xsltPointerListFree((xsltPointerListPtr) list->items[i]);
  611. xsltPointerListFree(list);
  612. data->exclResultNamespaces = NULL;
  613. }
  614. if (data->extElemNamespaces != NULL) {
  615. xsltPointerListPtr list = (xsltPointerListPtr)
  616. data->extElemNamespaces;
  617. int i;
  618. for (i = 0; i < list->number; i++)
  619. xsltPointerListFree((xsltPointerListPtr) list->items[i]);
  620. xsltPointerListFree(list);
  621. data->extElemNamespaces = NULL;
  622. }
  623. if (data->effectiveNs) {
  624. xsltLREEffectiveNsNodesFree(data->effectiveNs);
  625. data->effectiveNs = NULL;
  626. }
  627. #ifdef XSLT_REFACTORED_XSLT_NSCOMP
  628. xsltFreeNamespaceMap(data->nsMap);
  629. #endif
  630. xmlFree(data);
  631. }
  632. static xsltPrincipalStylesheetDataPtr
  633. xsltNewPrincipalStylesheetData(void)
  634. {
  635. xsltPrincipalStylesheetDataPtr ret;
  636. ret = (xsltPrincipalStylesheetDataPtr)
  637. xmlMalloc(sizeof(xsltPrincipalStylesheetData));
  638. if (ret == NULL) {
  639. xsltTransformError(NULL, NULL, NULL,
  640. "xsltNewPrincipalStylesheetData: memory allocation failed.\n");
  641. return(NULL);
  642. }
  643. memset(ret, 0, sizeof(xsltPrincipalStylesheetData));
  644. /*
  645. * Global list of in-scope namespaces.
  646. */
  647. ret->inScopeNamespaces = xsltPointerListCreate(-1);
  648. if (ret->inScopeNamespaces == NULL)
  649. goto internal_err;
  650. /*
  651. * Global list of excluded result ns-decls.
  652. */
  653. ret->exclResultNamespaces = xsltPointerListCreate(-1);
  654. if (ret->exclResultNamespaces == NULL)
  655. goto internal_err;
  656. /*
  657. * Global list of extension instruction namespace names.
  658. */
  659. ret->extElemNamespaces = xsltPointerListCreate(-1);
  660. if (ret->extElemNamespaces == NULL)
  661. goto internal_err;
  662. return(ret);
  663. internal_err:
  664. return(NULL);
  665. }
  666. #endif
  667. /**
  668. * xsltNewStylesheetInternal:
  669. * @parent: the parent stylesheet or NULL
  670. *
  671. * Create a new XSLT Stylesheet
  672. *
  673. * Returns the newly allocated xsltStylesheetPtr or NULL in case of error
  674. */
  675. static xsltStylesheetPtr
  676. xsltNewStylesheetInternal(xsltStylesheetPtr parent) {
  677. xsltStylesheetPtr ret = NULL;
  678. ret = (xsltStylesheetPtr) xmlMalloc(sizeof(xsltStylesheet));
  679. if (ret == NULL) {
  680. xsltTransformError(NULL, NULL, NULL,
  681. "xsltNewStylesheet : malloc failed\n");
  682. goto internal_err;
  683. }
  684. memset(ret, 0, sizeof(xsltStylesheet));
  685. ret->parent = parent;
  686. ret->omitXmlDeclaration = -1;
  687. ret->standalone = -1;
  688. ret->decimalFormat = xsltNewDecimalFormat(NULL, NULL);
  689. ret->indent = -1;
  690. ret->errors = 0;
  691. ret->warnings = 0;
  692. ret->exclPrefixNr = 0;
  693. ret->exclPrefixMax = 0;
  694. ret->exclPrefixTab = NULL;
  695. ret->extInfos = NULL;
  696. ret->extrasNr = 0;
  697. ret->internalized = 1;
  698. ret->literal_result = 0;
  699. ret->forwards_compatible = 0;
  700. ret->dict = xmlDictCreate();
  701. #ifdef WITH_XSLT_DEBUG
  702. xsltGenericDebug(xsltGenericDebugContext,
  703. "creating dictionary for stylesheet\n");
  704. #endif
  705. if (parent == NULL) {
  706. ret->principal = ret;
  707. ret->xpathCtxt = xmlXPathNewContext(NULL);
  708. if (ret->xpathCtxt == NULL) {
  709. xsltTransformError(NULL, NULL, NULL,
  710. "xsltNewStylesheet: xmlXPathNewContext failed\n");
  711. goto internal_err;
  712. }
  713. if (xmlXPathContextSetCache(ret->xpathCtxt, 1, -1, 0) == -1)
  714. goto internal_err;
  715. } else {
  716. ret->principal = parent->principal;
  717. }
  718. xsltInit();
  719. return(ret);
  720. internal_err:
  721. if (ret != NULL)
  722. xsltFreeStylesheet(ret);
  723. return(NULL);
  724. }
  725. /**
  726. * xsltNewStylesheet:
  727. *
  728. * Create a new XSLT Stylesheet
  729. *
  730. * Returns the newly allocated xsltStylesheetPtr or NULL in case of error
  731. */
  732. xsltStylesheetPtr
  733. xsltNewStylesheet(void) {
  734. return xsltNewStylesheetInternal(NULL);
  735. }
  736. /**
  737. * xsltAllocateExtra:
  738. * @style: an XSLT stylesheet
  739. *
  740. * Allocate an extra runtime information slot statically while compiling
  741. * the stylesheet and return its number
  742. *
  743. * Returns the number of the slot
  744. */
  745. int
  746. xsltAllocateExtra(xsltStylesheetPtr style)
  747. {
  748. return(style->extrasNr++);
  749. }
  750. /**
  751. * xsltAllocateExtraCtxt:
  752. * @ctxt: an XSLT transformation context
  753. *
  754. * Allocate an extra runtime information slot at run-time
  755. * and return its number
  756. * This make sure there is a slot ready in the transformation context
  757. *
  758. * Returns the number of the slot
  759. */
  760. int
  761. xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
  762. {
  763. if (ctxt->extrasNr >= ctxt->extrasMax) {
  764. int i;
  765. if (ctxt->extrasNr == 0) {
  766. ctxt->extrasMax = 20;
  767. ctxt->extras = (xsltRuntimeExtraPtr)
  768. xmlMalloc(ctxt->extrasMax * sizeof(xsltRuntimeExtra));
  769. if (ctxt->extras == NULL) {
  770. xsltTransformError(ctxt, NULL, NULL,
  771. "xsltAllocateExtraCtxt: out of memory\n");
  772. return(0);
  773. }
  774. for (i = 0;i < ctxt->extrasMax;i++) {
  775. ctxt->extras[i].info = NULL;
  776. ctxt->extras[i].deallocate = NULL;
  777. ctxt->extras[i].val.ptr = NULL;
  778. }
  779. } else {
  780. xsltRuntimeExtraPtr tmp;
  781. ctxt->extrasMax += 100;
  782. tmp = (xsltRuntimeExtraPtr) xmlRealloc(ctxt->extras,
  783. ctxt->extrasMax * sizeof(xsltRuntimeExtra));
  784. if (tmp == NULL) {
  785. xsltTransformError(ctxt, NULL, NULL,
  786. "xsltAllocateExtraCtxt: out of memory\n");
  787. return(0);
  788. }
  789. ctxt->extras = tmp;
  790. for (i = ctxt->extrasNr;i < ctxt->extrasMax;i++) {
  791. ctxt->extras[i].info = NULL;
  792. ctxt->extras[i].deallocate = NULL;
  793. ctxt->extras[i].val.ptr = NULL;
  794. }
  795. }
  796. }
  797. return(ctxt->extrasNr++);
  798. }
  799. /**
  800. * xsltFreeStylesheetList:
  801. * @style: an XSLT stylesheet list
  802. *
  803. * Free up the memory allocated by the list @style
  804. */
  805. static void
  806. xsltFreeStylesheetList(xsltStylesheetPtr style) {
  807. xsltStylesheetPtr next;
  808. while (style != NULL) {
  809. next = style->next;
  810. xsltFreeStylesheet(style);
  811. style = next;
  812. }
  813. }
  814. /**
  815. * xsltCleanupStylesheetTree:
  816. *
  817. * @doc: the document-node
  818. * @node: the element where the stylesheet is rooted at
  819. *
  820. * Actually @node need not be the document-element, but
  821. * currently Libxslt does not support embedded stylesheets.
  822. *
  823. * Returns 0 if OK, -1 on API or internal errors.
  824. */
  825. static int
  826. xsltCleanupStylesheetTree(xmlDocPtr doc ATTRIBUTE_UNUSED,
  827. xmlNodePtr rootElem ATTRIBUTE_UNUSED)
  828. {
  829. #if 0 /* TODO: Currently disabled, since probably not needed. */
  830. xmlNodePtr cur;
  831. if ((doc == NULL) || (rootElem == NULL) ||
  832. (rootElem->type != XML_ELEMENT_NODE) ||
  833. (doc != rootElem->doc))
  834. return(-1);
  835. /*
  836. * Cleanup was suggested by Aleksey Sanin:
  837. * Clear the PSVI field to avoid problems if the
  838. * node-tree of the stylesheet is intended to be used for
  839. * further processing by the user (e.g. for compiling it
  840. * once again - although not recommended).
  841. */
  842. cur = rootElem;
  843. while (cur != NULL) {
  844. if (cur->type == XML_ELEMENT_NODE) {
  845. /*
  846. * Clear the PSVI field.
  847. */
  848. cur->psvi = NULL;
  849. if (cur->children) {
  850. cur = cur->children;
  851. continue;
  852. }
  853. }
  854. leave_node:
  855. if (cur == rootElem)
  856. break;
  857. if (cur->next != NULL)
  858. cur = cur->next;
  859. else {
  860. cur = cur->parent;
  861. if (cur == NULL)
  862. break;
  863. goto leave_node;
  864. }
  865. }
  866. #endif /* #if 0 */
  867. return(0);
  868. }
  869. /**
  870. * xsltFreeStylesheet:
  871. * @style: an XSLT stylesheet
  872. *
  873. * Free up the memory allocated by @style
  874. */
  875. void
  876. xsltFreeStylesheet(xsltStylesheetPtr style)
  877. {
  878. if (style == NULL)
  879. return;
  880. #ifdef XSLT_REFACTORED
  881. /*
  882. * Start with a cleanup of the main stylesheet's doc.
  883. */
  884. if ((style->principal == style) && (style->doc))
  885. xsltCleanupStylesheetTree(style->doc,
  886. xmlDocGetRootElement(style->doc));
  887. #ifdef XSLT_REFACTORED_XSLT_NSCOMP
  888. /*
  889. * Restore changed ns-decls before freeing the document.
  890. */
  891. if ((style->doc != NULL) &&
  892. XSLT_HAS_INTERNAL_NSMAP(style))
  893. {
  894. xsltRestoreDocumentNamespaces(XSLT_GET_INTERNAL_NSMAP(style),
  895. style->doc);
  896. }
  897. #endif /* XSLT_REFACTORED_XSLT_NSCOMP */
  898. #else
  899. /*
  900. * Start with a cleanup of the main stylesheet's doc.
  901. */
  902. if ((style->parent == NULL) && (style->doc))
  903. xsltCleanupStylesheetTree(style->doc,
  904. xmlDocGetRootElement(style->doc));
  905. #endif /* XSLT_REFACTORED */
  906. xsltFreeKeys(style);
  907. xsltFreeExts(style);
  908. xsltFreeTemplateHashes(style);
  909. xsltFreeDecimalFormatList(style);
  910. xsltFreeTemplateList(style->templates);
  911. xsltFreeAttributeSetsHashes(style);
  912. xsltFreeNamespaceAliasHashes(style);
  913. xsltFreeStylePreComps(style);
  914. /*
  915. * Free documents of all included stylsheet modules of this
  916. * stylesheet level.
  917. */
  918. xsltFreeStyleDocuments(style);
  919. /*
  920. * TODO: Best time to shutdown extension stuff?
  921. */
  922. xsltShutdownExts(style);
  923. if (style->variables != NULL)
  924. xsltFreeStackElemList(style->variables);
  925. if (style->cdataSection != NULL)
  926. xmlHashFree(style->cdataSection, NULL);
  927. if (style->stripSpaces != NULL)
  928. xmlHashFree(style->stripSpaces, NULL);
  929. if (style->nsHash != NULL)
  930. xmlHashFree(style->nsHash, NULL);
  931. if (style->exclPrefixTab != NULL)
  932. xmlFree(style->exclPrefixTab);
  933. if (style->method != NULL)
  934. xmlFree(style->method);
  935. if (style->methodURI != NULL)
  936. xmlFree(style->methodURI);
  937. if (style->version != NULL)
  938. xmlFree(style->version);
  939. if (style->encoding != NULL)
  940. xmlFree(style->encoding);
  941. if (style->doctypePublic != NULL)
  942. xmlFree(style->doctypePublic);
  943. if (style->doctypeSystem != NULL)
  944. xmlFree(style->doctypeSystem);
  945. if (style->mediaType != NULL)
  946. xmlFree(style->mediaType);
  947. if (style->attVTs)
  948. xsltFreeAVTList(style->attVTs);
  949. if (style->imports != NULL)
  950. xsltFreeStylesheetList(style->imports);
  951. #ifdef XSLT_REFACTORED
  952. /*
  953. * If this is the principal stylesheet, then
  954. * free its internal data.
  955. */
  956. if (style->principal == style) {
  957. if (style->principalData) {
  958. xsltFreePrincipalStylesheetData(style->principalData);
  959. style->principalData = NULL;
  960. }
  961. }
  962. #endif
  963. /*
  964. * Better to free the main document of this stylesheet level
  965. * at the end - so here.
  966. */
  967. if (style->doc != NULL) {
  968. xmlFreeDoc(style->doc);
  969. }
  970. #ifdef WITH_XSLT_DEBUG
  971. xsltGenericDebug(xsltGenericDebugContext,
  972. "freeing dictionary from stylesheet\n");
  973. #endif
  974. xmlDictFree(style->dict);
  975. if (style->xpathCtxt != NULL)
  976. xmlXPathFreeContext(style->xpathCtxt);
  977. memset(style, -1, sizeof(xsltStylesheet));
  978. xmlFree(style);
  979. }
  980. /************************************************************************
  981. * *
  982. * Parsing of an XSLT Stylesheet *
  983. * *
  984. ************************************************************************/
  985. #ifdef XSLT_REFACTORED
  986. /*
  987. * This is now performed in an optimized way in xsltParseXSLTTemplate.
  988. */
  989. #else
  990. /**
  991. * xsltGetInheritedNsList:
  992. * @style: the stylesheet
  993. * @template: the template
  994. * @node: the current node
  995. *
  996. * Search all the namespace applying to a given element except the ones
  997. * from excluded output prefixes currently in scope. Initialize the
  998. * template inheritedNs list with it.
  999. *
  1000. * Returns the number of entries found
  1001. */
  1002. static int
  1003. xsltGetInheritedNsList(xsltStylesheetPtr style,
  1004. xsltTemplatePtr template,
  1005. xmlNodePtr node)
  1006. {
  1007. xmlNsPtr cur;
  1008. xmlNsPtr *ret = NULL;
  1009. int nbns = 0;
  1010. int maxns = 10;
  1011. int i;
  1012. if ((style == NULL) || (template == NULL) || (node == NULL) ||
  1013. (template->inheritedNsNr != 0) || (template->inheritedNs != NULL))
  1014. return(0);
  1015. while (node != NULL) {
  1016. if (node->type == XML_ELEMENT_NODE) {
  1017. cur = node->nsDef;
  1018. while (cur != NULL) {
  1019. if (xmlStrEqual(cur->href, XSLT_NAMESPACE))
  1020. goto skip_ns;
  1021. if ((cur->prefix != NULL) &&
  1022. (xsltCheckExtPrefix(style, cur->prefix)))
  1023. goto skip_ns;
  1024. /*
  1025. * Check if this namespace was excluded.
  1026. * Note that at this point only the exclusions defined
  1027. * on the topmost stylesheet element are in the exclusion-list.
  1028. */
  1029. for (i = 0;i < style->exclPrefixNr;i++) {
  1030. if (xmlStrEqual(cur->href, style->exclPrefixTab[i]))
  1031. goto skip_ns;
  1032. }
  1033. if (ret == NULL) {
  1034. ret =
  1035. (xmlNsPtr *) xmlMalloc((maxns + 1) *
  1036. sizeof(xmlNsPtr));
  1037. if (ret == NULL) {
  1038. xmlGenericError(xmlGenericErrorContext,
  1039. "xsltGetInheritedNsList : out of memory!\n");
  1040. return(0);
  1041. }
  1042. ret[nbns] = NULL;
  1043. }
  1044. /*
  1045. * Skip shadowed namespace bindings.
  1046. */
  1047. for (i = 0; i < nbns; i++) {
  1048. if ((cur->prefix == ret[i]->prefix) ||
  1049. (xmlStrEqual(cur->prefix, ret[i]->prefix)))
  1050. break;
  1051. }
  1052. if (i >= nbns) {
  1053. if (nbns >= maxns) {
  1054. maxns *= 2;
  1055. ret = (xmlNsPtr *) xmlRealloc(ret,
  1056. (maxns +
  1057. 1) *
  1058. sizeof(xmlNsPtr));
  1059. if (ret == NULL) {
  1060. xmlGenericError(xmlGenericErrorContext,
  1061. "xsltGetInheritedNsList : realloc failed!\n");
  1062. return(0);
  1063. }
  1064. }
  1065. ret[nbns++] = cur;
  1066. ret[nbns] = NULL;
  1067. }
  1068. skip_ns:
  1069. cur = cur->next;
  1070. }
  1071. }
  1072. node = node->parent;
  1073. }
  1074. if (nbns != 0) {
  1075. #ifdef WITH_XSLT_DEBUG_PARSING
  1076. xsltGenericDebug(xsltGenericDebugContext,
  1077. "template has %d inherited namespaces\n", nbns);
  1078. #endif
  1079. template->inheritedNsNr = nbns;
  1080. template->inheritedNs = ret;
  1081. }
  1082. return (nbns);
  1083. }
  1084. #endif /* else of XSLT_REFACTORED */
  1085. /**
  1086. * xsltParseStylesheetOutput:
  1087. * @style: the XSLT stylesheet
  1088. * @cur: the "output" element
  1089. *
  1090. * parse an XSLT stylesheet output element and record
  1091. * information related to the stylesheet output
  1092. */
  1093. void
  1094. xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
  1095. {
  1096. xmlChar *elements,
  1097. *prop;
  1098. xmlChar *element,
  1099. *end;
  1100. if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
  1101. return;
  1102. prop = xmlGetNsProp(cur, (const xmlChar *) "version", NULL);
  1103. if (prop != NULL) {
  1104. if (style->version != NULL)
  1105. xmlFree(style->version);
  1106. style->version = prop;
  1107. }
  1108. prop = xmlGetNsProp(cur, (const xmlChar *) "encoding", NULL);
  1109. if (prop != NULL) {
  1110. if (style->encoding != NULL)
  1111. xmlFree(style->encoding);
  1112. style->encoding = prop;
  1113. }
  1114. /* relaxed to support xt:document
  1115. * TODO KB: What does "relaxed to support xt:document" mean?
  1116. */
  1117. prop = xmlGetNsProp(cur, (const xmlChar *) "method", NULL);
  1118. if (prop != NULL) {
  1119. const xmlChar *URI;
  1120. if (style->method != NULL)
  1121. xmlFree(style->method);
  1122. style->method = NULL;
  1123. if (style->methodURI != NULL)
  1124. xmlFree(style->methodURI);
  1125. style->methodURI = NULL;
  1126. /*
  1127. * TODO: Don't use xsltGetQNameURI().
  1128. */
  1129. URI = xsltGetQNameURI(cur, &prop);
  1130. if (prop == NULL) {
  1131. if (style != NULL) style->errors++;
  1132. } else if (URI == NULL) {
  1133. if ((xmlStrEqual(prop, (const xmlChar *) "xml")) ||
  1134. (xmlStrEqual(prop, (const xmlChar *) "html")) ||
  1135. (xmlStrEqual(prop, (const xmlChar *) "text"))) {
  1136. style->method = prop;
  1137. } else {
  1138. xsltTransformError(NULL, style, cur,
  1139. "invalid value for method: %s\n", prop);
  1140. if (style != NULL) style->warnings++;
  1141. xmlFree(prop);
  1142. }
  1143. } else {
  1144. style->method = prop;
  1145. style->methodURI = xmlStrdup(URI);
  1146. }
  1147. }
  1148. prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-system", NULL);
  1149. if (prop != NULL) {
  1150. if (style->doctypeSystem != NULL)
  1151. xmlFree(style->doctypeSystem);
  1152. style->doctypeSystem = prop;
  1153. }
  1154. prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-public", NULL);
  1155. if (prop != NULL) {
  1156. if (style->doctypePublic != NULL)
  1157. xmlFree(style->doctypePublic);
  1158. style->doctypePublic = prop;
  1159. }
  1160. prop = xmlGetNsProp(cur, (const xmlChar *) "standalone", NULL);
  1161. if (prop != NULL) {
  1162. if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
  1163. style->standalone = 1;
  1164. } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
  1165. style->standalone = 0;
  1166. } else {
  1167. xsltTransformError(NULL, style, cur,
  1168. "invalid value for standalone: %s\n", prop);
  1169. style->errors++;
  1170. }
  1171. xmlFree(prop);
  1172. }
  1173. prop = xmlGetNsProp(cur, (const xmlChar *) "indent", NULL);
  1174. if (prop != NULL) {
  1175. if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
  1176. style->indent = 1;
  1177. } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
  1178. style->indent = 0;
  1179. } else {
  1180. xsltTransformError(NULL, style, cur,
  1181. "invalid value for indent: %s\n", prop);
  1182. style->errors++;
  1183. }
  1184. xmlFree(prop);
  1185. }
  1186. prop = xmlGetNsProp(cur, (const xmlChar *) "omit-xml-declaration", NULL);
  1187. if (prop != NULL) {
  1188. if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
  1189. style->omitXmlDeclaration = 1;
  1190. } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
  1191. style->omitXmlDeclaration = 0;
  1192. } else {
  1193. xsltTransformError(NULL, style, cur,
  1194. "invalid value for omit-xml-declaration: %s\n",
  1195. prop);
  1196. style->errors++;
  1197. }
  1198. xmlFree(prop);
  1199. }
  1200. elements = xmlGetNsProp(cur, (const xmlChar *) "cdata-section-elements",
  1201. NULL);
  1202. if (elements != NULL) {
  1203. if (style->cdataSection == NULL)
  1204. style->cdataSection = xmlHashCreate(10);
  1205. if (style->cdataSection == NULL)
  1206. return;
  1207. element = elements;
  1208. while (*element != 0) {
  1209. while (IS_BLANK(*element))
  1210. element++;
  1211. if (*element == 0)
  1212. break;
  1213. end = element;
  1214. while ((*end != 0) && (!IS_BLANK(*end)))
  1215. end++;
  1216. element = xmlStrndup(element, end - element);
  1217. if (element) {
  1218. #ifdef WITH_XSLT_DEBUG_PARSING
  1219. xsltGenericDebug(xsltGenericDebugContext,
  1220. "add cdata section output element %s\n",
  1221. element);
  1222. #endif
  1223. if (xmlValidateQName(BAD_CAST element, 0) != 0) {
  1224. xsltTransformError(NULL, style, cur,
  1225. "Attribute 'cdata-section-elements': The value "
  1226. "'%s' is not a valid QName.\n", element);
  1227. xmlFree(element);
  1228. style->errors++;
  1229. } else {
  1230. const xmlChar *URI;
  1231. /*
  1232. * TODO: Don't use xsltGetQNameURI().
  1233. */
  1234. URI = xsltGetQNameURI(cur, &element);
  1235. if (element == NULL) {
  1236. /*
  1237. * TODO: We'll report additionally an error
  1238. * via the stylesheet's error handling.
  1239. */
  1240. xsltTransformError(NULL, style, cur,
  1241. "Attribute 'cdata-section-elements': "
  1242. "Not a valid QName.\n");
  1243. style->errors++;
  1244. } else {
  1245. xmlNsPtr ns;
  1246. /*
  1247. * XSLT-1.0 "Each QName is expanded into an
  1248. * expanded-name using the namespace declarations in
  1249. * effect on the xsl:output element in which the QName
  1250. * occurs; if there is a default namespace, it is used
  1251. * for QNames that do not have a prefix"
  1252. * NOTE: Fix of bug #339570.
  1253. */
  1254. if (URI == NULL) {
  1255. ns = xmlSearchNs(style->doc, cur, NULL);
  1256. if (ns != NULL)
  1257. URI = ns->href;
  1258. }
  1259. xmlHashAddEntry2(style->cdataSection, element, URI,
  1260. (void *) "cdata");
  1261. xmlFree(element);
  1262. }
  1263. }
  1264. }
  1265. element = end;
  1266. }
  1267. xmlFree(elements);
  1268. }
  1269. prop = xmlGetNsProp(cur, (const xmlChar *) "media-type", NULL);
  1270. if (prop != NULL) {
  1271. if (style->mediaType)
  1272. xmlFree(style->mediaType);
  1273. style->mediaType = prop;
  1274. }
  1275. if (cur->children != NULL) {
  1276. xsltParseContentError(style, cur->children);
  1277. }
  1278. }
  1279. /**
  1280. * xsltParseStylesheetDecimalFormat:
  1281. * @style: the XSLT stylesheet
  1282. * @cur: the "decimal-format" element
  1283. *
  1284. * <!-- Category: top-level-element -->
  1285. * <xsl:decimal-format
  1286. * name = qname, decimal-separator = char, grouping-separator = char,
  1287. * infinity = string, minus-sign = char, NaN = string, percent = char
  1288. * per-mille = char, zero-digit = char, digit = char,
  1289. * pattern-separator = char />
  1290. *
  1291. * parse an XSLT stylesheet decimal-format element and
  1292. * and record the formatting characteristics
  1293. */
  1294. static void
  1295. xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur)
  1296. {
  1297. xmlChar *prop;
  1298. xsltDecimalFormatPtr format;
  1299. xsltDecimalFormatPtr iter;
  1300. if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
  1301. return;
  1302. format = style->decimalFormat;
  1303. prop = xmlGetNsProp(cur, BAD_CAST("name"), NULL);
  1304. if (prop != NULL) {
  1305. const xmlChar *nsUri;
  1306. if (xmlValidateQName(prop, 0) != 0) {
  1307. xsltTransformError(NULL, style, cur,
  1308. "xsl:decimal-format: Invalid QName '%s'.\n", prop);
  1309. style->warnings++;
  1310. xmlFree(prop);
  1311. return;
  1312. }
  1313. /*
  1314. * TODO: Don't use xsltGetQNameURI().
  1315. */
  1316. nsUri = xsltGetQNameURI(cur, &prop);
  1317. if (prop == NULL) {
  1318. style->warnings++;
  1319. return;
  1320. }
  1321. format = xsltDecimalFormatGetByQName(style, nsUri, prop);
  1322. if (format != NULL) {
  1323. xsltTransformError(NULL, style, cur,
  1324. "xsltParseStylestyleDecimalFormat: %s already exists\n", prop);
  1325. style->warnings++;
  1326. xmlFree(prop);
  1327. return;
  1328. }
  1329. format = xsltNewDecimalFormat(nsUri, prop);
  1330. if (format == NULL) {
  1331. xsltTransformError(NULL, style, cur,
  1332. "xsltParseStylestyleDecimalFormat: failed creating new decimal-format\n");
  1333. style->errors++;
  1334. xmlFree(prop);
  1335. return;
  1336. }
  1337. /* Append new decimal-format structure */
  1338. for (iter = style->decimalFormat; iter->next; iter = iter->next)
  1339. ;
  1340. if (iter)
  1341. iter->next = format;
  1342. }
  1343. prop = xmlGetNsProp(cur, (const xmlChar *)"decimal-separator", NULL);
  1344. if (prop != NULL) {
  1345. if (format->decimalPoint != NULL) xmlFree(format->decimalPoint);
  1346. format->decimalPoint = prop;
  1347. }
  1348. prop = xmlGetNsProp(cur, (const xmlChar *)"grouping-separator", NULL);
  1349. if (prop != NULL) {
  1350. if (format->grouping != NULL) xmlFree(format->grouping);
  1351. format->grouping = prop;
  1352. }
  1353. prop = xmlGetNsProp(cur, (const xmlChar *)"infinity", NULL);
  1354. if (prop != NULL) {
  1355. if (format->infinity != NULL) xmlFree(format->infinity);
  1356. format->infinity = prop;
  1357. }
  1358. prop = xmlGetNsProp(cur, (const xmlChar *)"minus-sign", NULL);
  1359. if (prop != NULL) {
  1360. if (format->minusSign != NULL) xmlFree(format->minusSign);
  1361. format->minusSign = prop;
  1362. }
  1363. prop = xmlGetNsProp(cur, (const xmlChar *)"NaN", NULL);
  1364. if (prop != NULL) {
  1365. if (format->noNumber != NULL) xmlFree(format->noNumber);
  1366. format->noNumber = prop;
  1367. }
  1368. prop = xmlGetNsProp(cur, (const xmlChar *)"percent", NULL);
  1369. if (prop != NULL) {
  1370. if (format->percent != NULL) xmlFree(format->percent);
  1371. format->percent = prop;
  1372. }
  1373. prop = xmlGetNsProp(cur, (const xmlChar *)"per-mille", NULL);
  1374. if (prop != NULL) {
  1375. if (format->permille != NULL) xmlFree(format->permille);
  1376. format->permille = prop;
  1377. }
  1378. prop = xmlGetNsProp(cur, (const xmlChar *)"zero-digit", NULL);
  1379. if (prop != NULL) {
  1380. if (format->zeroDigit != NULL) xmlFree(format->zeroDigit);
  1381. format->zeroDigit = prop;
  1382. }
  1383. prop = xmlGetNsProp(cur, (const xmlChar *)"digit", NULL);
  1384. if (prop != NULL) {
  1385. if (format->digit != NULL) xmlFree(format->digit);
  1386. format->digit = prop;
  1387. }
  1388. prop = xmlGetNsProp(cur, (const xmlChar *)"pattern-separator", NULL);
  1389. if (prop != NULL) {
  1390. if (format->patternSeparator != NULL) xmlFree(format->patternSeparator);
  1391. format->patternSeparator = prop;
  1392. }
  1393. if (cur->children != NULL) {
  1394. xsltParseContentError(style, cur->children);
  1395. }
  1396. }
  1397. /**
  1398. * xsltParseStylesheetPreserveSpace:
  1399. * @style: the XSLT stylesheet
  1400. * @cur: the "preserve-space" element
  1401. *
  1402. * parse an XSLT stylesheet preserve-space element and record
  1403. * elements needing preserving
  1404. */
  1405. static void
  1406. xsltParseStylesheetPreserveSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
  1407. xmlChar *elements;
  1408. xmlChar *element, *end;
  1409. if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
  1410. return;
  1411. elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);
  1412. if (elements == NULL) {
  1413. xsltTransformError(NULL, style, cur,
  1414. "xsltParseStylesheetPreserveSpace: missing elements attribute\n");
  1415. if (style != NULL) style->warnings++;
  1416. return;
  1417. }
  1418. if (style->stripSpaces == NULL)
  1419. style->stripSpaces = xmlHashCreate(10);
  1420. if (style->stripSpaces == NULL)
  1421. return;
  1422. element = elements;
  1423. while (*element != 0) {
  1424. while (IS_BLANK(*element)) element++;
  1425. if (*element == 0)
  1426. break;
  1427. end = element;
  1428. while ((*end != 0) && (!IS_BLANK(*end))) end++;
  1429. element = xmlStrndup(element, end - element);
  1430. if (element) {
  1431. #ifdef WITH_XSLT_DEBUG_PARSING
  1432. xsltGenericDebug(xsltGenericDebugContext,
  1433. "add preserved space element %s\n", element);
  1434. #endif
  1435. if (xmlStrEqual(element, (const xmlChar *)"*")) {
  1436. style->stripAll = -1;
  1437. } else {
  1438. const xmlChar *URI;
  1439. /*
  1440. * TODO: Don't use xsltGetQNameURI().
  1441. */
  1442. URI = xsltGetQNameURI(cur, &element);
  1443. xmlHashAddEntry2(style->stripSpaces, element, URI,
  1444. (xmlChar *) "preserve");
  1445. }
  1446. xmlFree(element);
  1447. }
  1448. element = end;
  1449. }
  1450. xmlFree(elements);
  1451. if (cur->children != NULL) {
  1452. xsltParseContentError(style, cur->children);
  1453. }
  1454. }
  1455. #ifdef XSLT_REFACTORED
  1456. #else
  1457. /**
  1458. * xsltParseStylesheetExtPrefix:
  1459. * @style: the XSLT stylesheet
  1460. * @template: the "extension-element-prefixes" prefix
  1461. *
  1462. * parse an XSLT stylesheet's "extension-element-prefix" attribute value
  1463. * and register the namespaces of extension instruction.
  1464. * SPEC "A namespace is designated as an extension namespace by using
  1465. * an extension-element-prefixes attribute on:
  1466. * 1) an xsl:stylesheet element
  1467. * 2) an xsl:extension-element-prefixes attribute on a
  1468. * literal result element
  1469. * 3) an extension instruction."
  1470. */
  1471. static void
  1472. xsltParseStylesheetExtPrefix(xsltStylesheetPtr style, xmlNodePtr cur,
  1473. int isXsltElem) {
  1474. xmlChar *prefixes;
  1475. xmlChar *prefix, *end;
  1476. if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
  1477. return;
  1478. if (isXsltElem) {
  1479. /* For xsl:stylesheet/xsl:transform. */
  1480. prefixes = xmlGetNsProp(cur,
  1481. (const xmlChar *)"extension-element-prefixes", NULL);
  1482. } else {
  1483. /* For literal result elements and extension instructions. */
  1484. prefixes = xmlGetNsProp(cur,
  1485. (const xmlChar *)"extension-element-prefixes", XSLT_NAMESPACE);
  1486. }
  1487. if (prefixes == NULL) {
  1488. return;
  1489. }
  1490. prefix = prefixes;
  1491. while (*prefix != 0) {
  1492. while (IS_BLANK(*prefix)) prefix++;
  1493. if (*prefix == 0)
  1494. break;
  1495. end = prefix;
  1496. while ((*end != 0) && (!IS_BLANK(*end))) end++;
  1497. prefix = xmlStrndup(prefix, end - prefix);
  1498. if (prefix) {
  1499. xmlNsPtr ns;
  1500. if (xmlStrEqual(prefix, (const xmlChar *)"#default"))
  1501. ns = xmlSearchNs(style->doc, cur, NULL);
  1502. else
  1503. ns = xmlSearchNs(style->doc, cur, prefix);
  1504. if (ns == NULL) {
  1505. xsltTransformError(NULL, style, cur,
  1506. "xsl:extension-element-prefix : undefined namespace %s\n",
  1507. prefix);
  1508. if (style != NULL) style->warnings++;
  1509. } else {
  1510. #ifdef WITH_XSLT_DEBUG_PARSING
  1511. xsltGenericDebug(xsltGenericDebugContext,
  1512. "add extension prefix %s\n", prefix);
  1513. #endif
  1514. xsltRegisterExtPrefix(style, prefix, ns->href);
  1515. }
  1516. xmlFree(prefix);
  1517. }
  1518. prefix = end;
  1519. }
  1520. xmlFree(prefixes);
  1521. }
  1522. #endif /* else of XSLT_REFACTORED */
  1523. /**
  1524. * xsltParseStylesheetStripSpace:
  1525. * @style: the XSLT stylesheet
  1526. * @cur: the "strip-space" element
  1527. *
  1528. * parse an XSLT stylesheet's strip-space element and record
  1529. * the elements needing stripping
  1530. */
  1531. static void
  1532. xsltParseStylesheetStripSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
  1533. xmlChar *elements;
  1534. xmlChar *element, *end;
  1535. if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
  1536. return;
  1537. elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);
  1538. if (elements == NULL) {
  1539. xsltTransformError(NULL, style, cur,
  1540. "xsltParseStylesheetStripSpace: missing elements attribute\n");
  1541. if (style != NULL) style->warnings++;
  1542. return;
  1543. }
  1544. if (style->stripSpaces == NULL)
  1545. style->stripSpaces = xmlHashCreate(10);
  1546. if (style->stripSpaces == NULL)
  1547. return;
  1548. element = elements;
  1549. while (*element != 0) {
  1550. while (IS_BLANK(*element)) element++;
  1551. if (*element == 0)
  1552. break;
  1553. end = element;
  1554. while ((*end != 0) && (!IS_BLANK(*end))) end++;
  1555. element = xmlStrndup(element, end - element);
  1556. if (element) {
  1557. #ifdef WITH_XSLT_DEBUG_PARSING
  1558. xsltGenericDebug(xsltGenericDebugContext,
  1559. "add stripped space element %s\n", element);
  1560. #endif
  1561. if (xmlStrEqual(element, (const xmlChar *)"*")) {
  1562. style->stripAll = 1;
  1563. } else {
  1564. const xmlChar *URI;
  1565. /*
  1566. * TODO: Don't use xsltGetQNameURI().
  1567. */
  1568. URI = xsltGetQNameURI(cur, &element);
  1569. xmlHashAddEntry2(style->stripSpaces, element, URI,
  1570. (xmlChar *) "strip");
  1571. }
  1572. xmlFree(element);
  1573. }
  1574. element = end;
  1575. }
  1576. xmlFree(elements);
  1577. if (cur->children != NULL) {
  1578. xsltParseContentError(style, cur->children);
  1579. }
  1580. }
  1581. #ifdef XSLT_REFACTORED
  1582. #else
  1583. /**
  1584. * xsltParseStylesheetExcludePrefix:
  1585. * @style: the XSLT stylesheet
  1586. * @cur: the current point in the stylesheet
  1587. *
  1588. * parse an XSLT stylesheet exclude prefix and record
  1589. * namespaces needing stripping
  1590. *
  1591. * Returns the number of Excluded prefixes added at that level
  1592. */
  1593. static int
  1594. xsltParseStylesheetExcludePrefix(xsltStylesheetPtr style, xmlNodePtr cur,
  1595. int isXsltElem)
  1596. {
  1597. int nb = 0;
  1598. xmlChar *prefixes;
  1599. xmlChar *prefix, *end;
  1600. if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
  1601. return(0);
  1602. if (isXsltElem)
  1603. prefixes = xmlGetNsProp(cur,
  1604. (const xmlChar *)"exclude-result-prefixes", NULL);
  1605. else
  1606. prefixes = xmlGetNsProp(cur,
  1607. (const xmlChar *)"exclude-result-prefixes", XSLT_NAMESPACE);
  1608. if (prefixes == NULL) {
  1609. return(0);
  1610. }
  1611. prefix = prefixes;
  1612. while (*prefix != 0) {
  1613. while (IS_BLANK(*prefix)) prefix++;
  1614. if (*prefix == 0)
  1615. break;
  1616. end = prefix;
  1617. while ((*end != 0) && (!IS_BLANK(*end))) end++;
  1618. prefix = xmlStrndup(prefix, end - prefix);
  1619. if (prefix) {
  1620. xmlNsPtr ns;
  1621. if (xmlStrEqual(prefix, (const xmlChar *)"#default"))
  1622. ns = xmlSearchNs(style->doc, cur, NULL);
  1623. else
  1624. ns = xmlSearchNs(style->doc, cur, prefix);
  1625. if (ns == NULL) {
  1626. xsltTransformError(NULL, style, cur,
  1627. "xsl:exclude-result-prefixes : undefined namespace %s\n",
  1628. prefix);
  1629. if (style != NULL) style->warnings++;
  1630. } else {
  1631. if (exclPrefixPush(style, (xmlChar *) ns->href) >= 0) {
  1632. #ifdef WITH_XSLT_DEBUG_PARSING
  1633. xsltGenericDebug(xsltGenericDebugContext,
  1634. "exclude result prefix %s\n", prefix);
  1635. #endif
  1636. nb++;
  1637. }
  1638. }
  1639. xmlFree(prefix);
  1640. }
  1641. prefix = end;
  1642. }
  1643. xmlFree(prefixes);
  1644. return(nb);
  1645. }
  1646. #endif /* else of XSLT_REFACTORED */
  1647. #ifdef XSLT_REFACTORED
  1648. /*
  1649. * xsltTreeEnsureXMLDecl:
  1650. * @doc: the doc
  1651. *
  1652. * BIG NOTE:
  1653. * This was copy&pasted from Libxml2's xmlTreeEnsureXMLDecl() in "tree.c".
  1654. * Ensures that there is an XML namespace declaration on the doc.
  1655. *
  1656. * Returns the XML ns-struct or NULL on API and internal errors.
  1657. */
  1658. static xmlNsPtr
  1659. xsltTreeEnsureXMLDecl(xmlDocPtr doc)
  1660. {
  1661. if (doc == NULL)
  1662. return (NULL);
  1663. if (doc->oldNs != NULL)
  1664. return (doc->oldNs);
  1665. {
  1666. xmlNsPtr ns;
  1667. ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
  1668. if (ns == NULL) {
  1669. xmlGenericError(xmlGenericErrorContext,
  1670. "xsltTreeEnsureXMLDecl: Failed to allocate "
  1671. "the XML namespace.\n");
  1672. return (NULL);
  1673. }
  1674. memset(ns, 0, sizeof(xmlNs));
  1675. ns->type = XML_LOCAL_NAMESPACE;
  1676. /*
  1677. * URGENT TODO: revisit this.
  1678. */
  1679. #ifdef LIBXML_NAMESPACE_DICT
  1680. if (doc->dict)
  1681. ns->href = xmlDictLookup(doc->dict, XML_XML_NAMESPACE, -1);
  1682. else
  1683. ns->href = xmlStrdup(XML_XML_NAMESPACE);
  1684. #else
  1685. ns->href = xmlStrdup(XML_XML_NAMESPACE);
  1686. #endif
  1687. ns->prefix = xmlStrdup((const xmlChar *)"xml");
  1688. doc->oldNs = ns;
  1689. return (ns);
  1690. }
  1691. }
  1692. /*
  1693. * xsltTreeAcquireStoredNs:
  1694. * @doc: the doc
  1695. * @nsName: the namespace name
  1696. * @prefix: the prefix
  1697. *
  1698. * BIG NOTE:
  1699. * This was copy&pasted from Libxml2's xmlDOMWrapStoreNs() in "tree.c".
  1700. * Creates or reuses an xmlNs struct on doc->oldNs with
  1701. * the given prefix and namespace name.
  1702. *
  1703. * Returns the aquired ns struct or NULL in case of an API
  1704. * or internal error.
  1705. */
  1706. static xmlNsPtr
  1707. xsltTreeAcquireStoredNs(xmlDocPtr doc,
  1708. const xmlChar *nsName,
  1709. const xmlChar *prefix)
  1710. {
  1711. xmlNsPtr ns;
  1712. if (doc == NULL)
  1713. return (NULL);
  1714. if (doc->oldNs != NULL)
  1715. ns = doc->oldNs;
  1716. else
  1717. ns = xsltTreeEnsureXMLDecl(doc);
  1718. if (ns == NULL)
  1719. return (NULL);
  1720. if (ns->next != NULL) {
  1721. /* Reuse. */
  1722. ns = ns->next;
  1723. while (ns != NULL) {
  1724. if ((ns->prefix == NULL) != (prefix == NULL)) {
  1725. /* NOP */
  1726. } else if (prefix == NULL) {
  1727. if (xmlStrEqual(ns->href, nsName))
  1728. return (ns);
  1729. } else {
  1730. if ((ns->prefix[0] == prefix[0]) &&
  1731. xmlStrEqual(ns->prefix, prefix) &&
  1732. xmlStrEqual(ns->href, nsName))
  1733. return (ns);
  1734. }
  1735. if (ns->next == NULL)
  1736. break;
  1737. ns = ns->next;
  1738. }
  1739. }
  1740. /* Create. */
  1741. ns->next = xmlNewNs(NULL, nsName, prefix);
  1742. return (ns->next);
  1743. }
  1744. /**
  1745. * xsltLREBuildEffectiveNs:
  1746. *
  1747. * Apply ns-aliasing on the namespace of the given @elem and
  1748. * its attributes.
  1749. */
  1750. static int
  1751. xsltLREBuildEffectiveNs(xsltCompilerCtxtPtr cctxt,
  1752. xmlNodePtr elem)
  1753. {
  1754. xmlNsPtr ns;
  1755. xsltNsAliasPtr alias;
  1756. if ((cctxt == NULL) || (elem == NULL))
  1757. return(-1);
  1758. if ((cctxt->nsAliases == NULL) || (! cctxt->hasNsAliases))
  1759. return(0);
  1760. alias = cctxt->nsAliases;
  1761. while (alias != NULL) {
  1762. if ( /* If both namespaces are NULL... */
  1763. ( (elem->ns == NULL) &&
  1764. ((alias->literalNs == NULL) ||
  1765. (alias->literalNs->href == NULL)) ) ||
  1766. /* ... or both namespace are equal */
  1767. ( (elem->ns != NULL) &&
  1768. (alias->literalNs != NULL) &&
  1769. xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )
  1770. {
  1771. if ((alias->targetNs != NULL) &&
  1772. (alias->targetNs->href != NULL))
  1773. {
  1774. /*
  1775. * Convert namespace.
  1776. */
  1777. if (elem->doc == alias->docOfTargetNs) {
  1778. /*
  1779. * This is the nice case: same docs.
  1780. * This will eventually assign a ns-decl which
  1781. * is shadowed, but this has no negative effect on
  1782. * the generation of the result tree.
  1783. */
  1784. elem->ns = alias->targetNs;
  1785. } else {
  1786. /*
  1787. * This target xmlNs originates from a different
  1788. * stylesheet tree. Try to locate it in the
  1789. * in-scope namespaces.
  1790. * OPTIMIZE TODO: Use the compiler-node-info inScopeNs.
  1791. */
  1792. ns = xmlSearchNs(elem->doc, elem,
  1793. alias->targetNs->prefix);
  1794. /*
  1795. * If no matching ns-decl found, then assign a
  1796. * ns-decl stored in xmlDoc.
  1797. */
  1798. if ((ns == NULL) ||
  1799. (! xmlStrEqual(ns->href, alias->targetNs->href)))
  1800. {
  1801. /*
  1802. * BIG NOTE: The use of xsltTreeAcquireStoredNs()
  1803. * is not very efficient, but currently I don't
  1804. * see an other way of *safely* changing a node's
  1805. * namespace, since the xmlNs struct in
  1806. * alias->targetNs might come from an other
  1807. * stylesheet tree. So we need to anchor it in the
  1808. * current document, without adding it to the tree,
  1809. * which would otherwise change the in-scope-ns
  1810. * semantic of the tree.
  1811. */
  1812. ns = xsltTreeAcquireStoredNs(elem->doc,
  1813. alias->targetNs->href,
  1814. alias->targetNs->prefix);
  1815. if (ns == NULL) {
  1816. xsltTransformError(NULL, cctxt->style, elem,
  1817. "Internal error in "
  1818. "xsltLREBuildEffectiveNs(): "
  1819. "failed to acquire a stored "
  1820. "ns-declaration.\n");
  1821. cctxt->style->errors++;
  1822. return(-1);
  1823. }
  1824. }
  1825. elem->ns = ns;
  1826. }
  1827. } else {
  1828. /*
  1829. * Move into or leave in the NULL namespace.
  1830. */
  1831. elem->ns = NULL;
  1832. }
  1833. break;
  1834. }
  1835. alias = alias->next;
  1836. }
  1837. /*
  1838. * Same with attributes of literal result elements.
  1839. */
  1840. if (elem->properties != NULL) {
  1841. xmlAttrPtr attr = elem->properties;
  1842. while (attr != NULL) {
  1843. if (attr->ns == NULL) {
  1844. attr = attr->next;
  1845. continue;
  1846. }
  1847. alias = cctxt->nsAliases;
  1848. while (alias != NULL) {
  1849. if ( /* If both namespaces are NULL... */
  1850. ( (elem->ns == NULL) &&
  1851. ((alias->literalNs == NULL) ||
  1852. (alias->literalNs->href == NULL)) ) ||
  1853. /* ... or both namespace are equal */
  1854. ( (elem->ns != NULL) &&
  1855. (alias->literalNs != NULL) &&
  1856. xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )
  1857. {
  1858. if ((alias->targetNs != NULL) &&
  1859. (alias->targetNs->href != NULL))
  1860. {
  1861. if (elem->doc == alias->docOfTargetNs) {
  1862. elem->ns = alias->targetNs;
  1863. } else {
  1864. ns = xmlSearchNs(elem->doc, elem,
  1865. alias->targetNs->prefix);
  1866. if ((ns == NULL) ||
  1867. (! xmlStrEqual(ns->href, alias->targetNs->href)))
  1868. {
  1869. ns = xsltTreeAcquireStoredNs(elem->doc,
  1870. alias->targetNs->href,
  1871. alias->targetNs->prefix);
  1872. if (ns == NULL) {
  1873. xsltTransformError(NULL, cctxt->style, elem,
  1874. "Internal error in "
  1875. "xsltLREBuildEffectiveNs(): "
  1876. "failed to acquire a stored "
  1877. "ns-declaration.\n");
  1878. cctxt->style->errors++;
  1879. return(-1);
  1880. }
  1881. }
  1882. elem->ns = ns;
  1883. }
  1884. } else {
  1885. /*
  1886. * Move into or leave in the NULL namespace.
  1887. */
  1888. elem->ns = NULL;
  1889. }
  1890. break;
  1891. }
  1892. alias = alias->next;
  1893. }
  1894. attr = attr->next;
  1895. }
  1896. }
  1897. return(0);
  1898. }
  1899. /**
  1900. * xsltLREBuildEffectiveNsNodes:
  1901. *
  1902. * Computes the effective namespaces nodes for a literal result
  1903. * element.
  1904. * @effectiveNs is the set of effective ns-nodes
  1905. * on the literal result element, which will be added to the result
  1906. * element if not already existing in the result tree.
  1907. * This means that excluded namespaces (via exclude-result-prefixes,
  1908. * extension-element-prefixes and the XSLT namespace) not added
  1909. * to the set.
  1910. * Namespace-aliasing was applied on the @effectiveNs.
  1911. */
  1912. static int
  1913. xsltLREBuildEffectiveNsNodes(xsltCompilerCtxtPtr cctxt,
  1914. xsltStyleItemLRElementInfoPtr item,
  1915. xmlNodePtr elem,
  1916. int isLRE)
  1917. {
  1918. xmlNsPtr ns, tmpns;
  1919. xsltEffectiveNsPtr effNs, lastEffNs = NULL;
  1920. int i, j, holdByElem;
  1921. xsltPointerListPtr extElemNs = cctxt->inode->extElemNs;
  1922. xsltPointerListPtr exclResultNs = cctxt->inode->exclResultNs;
  1923. if ((cctxt == NULL) || (cctxt->inode == NULL) || (elem == NULL) ||
  1924. (item == NULL) || (item->effectiveNs != NULL))
  1925. return(-1);
  1926. if (item->inScopeNs == NULL)
  1927. return(0);
  1928. extElemNs = cctxt->inode->extElemNs;
  1929. exclResultNs = cctxt->inode->exclResultNs;
  1930. for (i = 0; i < item->inScopeNs->totalNumber; i++) {
  1931. ns = item->inScopeNs->list[i];
  1932. /*
  1933. * Skip namespaces designated as excluded namespaces
  1934. * -------------------------------------------------
  1935. *
  1936. * XSLT-20 TODO: In XSLT 2.0 we need to keep namespaces
  1937. * which are target namespaces of namespace-aliases
  1938. * regardless if designated as excluded.
  1939. *
  1940. * Exclude the XSLT namespace.
  1941. */
  1942. if (xmlStrEqual(ns->href, XSLT_NAMESPACE))
  1943. goto skip_ns;
  1944. /*
  1945. * Apply namespace aliasing
  1946. * ------------------------
  1947. *
  1948. * SPEC XSLT 2.0
  1949. * "- A namespace node whose string value is a literal namespace
  1950. * URI is not copied to the result tree.
  1951. * - A namespace node whose string value is a target namespace URI
  1952. * is copied to the result tree, whether or not the URI
  1953. * identifies an excluded namespace."
  1954. *
  1955. * NOTE: The ns-aliasing machanism is non-cascading.
  1956. * (checked with Saxon, Xalan and MSXML .NET).
  1957. * URGENT TODO: is style->nsAliases the effective list of
  1958. * ns-aliases, or do we need to lookup the whole
  1959. * import-tree?
  1960. * TODO: Get rid of import-tree lookup.
  1961. */
  1962. if (cctxt->hasNsAliases) {
  1963. xsltNsAliasPtr alias;
  1964. /*
  1965. * First check for being a target namespace.
  1966. */
  1967. alias = cctxt->nsAliases;
  1968. do {
  1969. /*
  1970. * TODO: Is xmlns="" handled already?
  1971. */
  1972. if ((alias->targetNs != NULL) &&
  1973. (xmlStrEqual(alias->targetNs->href, ns->href)))
  1974. {
  1975. /*
  1976. * Recognized as a target namespace; use it regardless
  1977. * if excluded otherwise.
  1978. */
  1979. goto add_effective_ns;
  1980. }
  1981. alias = alias->next;
  1982. } while (alias != NULL);
  1983. alias = cctxt->nsAliases;
  1984. do {
  1985. /*
  1986. * TODO: Is xmlns="" handled already?
  1987. */
  1988. if ((alias->literalNs != NULL) &&
  1989. (xmlStrEqual(alias->literalNs->href, ns->href)))
  1990. {
  1991. /*
  1992. * Recognized as an namespace alias; do not use it.
  1993. */
  1994. goto skip_ns;
  1995. }
  1996. alias = alias->next;
  1997. } while (alias != NULL);
  1998. }
  1999. /*
  2000. * Exclude excluded result namespaces.
  2001. */
  2002. if (exclResultNs) {
  2003. for (j = 0; j < exclResultNs->number; j++)
  2004. if (xmlStrEqual(ns->href, BAD_CAST exclResultNs->items[j]))
  2005. goto skip_ns;
  2006. }
  2007. /*
  2008. * Exclude extension-element namespaces.
  2009. */
  2010. if (extElemNs) {
  2011. for (j = 0; j < extElemNs->number; j++)
  2012. if (xmlStrEqual(ns->href, BAD_CAST extElemNs->items[j]))
  2013. goto skip_ns;
  2014. }
  2015. add_effective_ns:
  2016. /*
  2017. * OPTIMIZE TODO: This information may not be needed.
  2018. */
  2019. if (isLRE && (elem->nsDef != NULL)) {
  2020. holdByElem = 0;
  2021. tmpns = elem->nsDef;
  2022. do {
  2023. if (tmpns == ns) {
  2024. holdByElem = 1;
  2025. break;
  2026. }
  2027. tmpns = tmpns->next;
  2028. } while (tmpns != NULL);
  2029. } else
  2030. holdByElem = 0;
  2031. /*
  2032. * Add the effective namespace declaration.
  2033. */
  2034. effNs = (xsltEffectiveNsPtr) xmlMalloc(sizeof(xsltEffectiveNs));
  2035. if (effNs == NULL) {
  2036. xsltTransformError(NULL, cctxt->style, elem,
  2037. "Internal error in xsltLREBuildEffectiveNs(): "
  2038. "failed to allocate memory.\n");
  2039. cctxt->style->errors++;
  2040. return(-1);
  2041. }
  2042. if (cctxt->psData->effectiveNs == NULL) {
  2043. cctxt->psData->effectiveNs = effNs;
  2044. effNs->nextInStore = NULL;
  2045. } else {
  2046. effNs->nextInStore = cctxt->psData->effectiveNs;
  2047. cctxt->psData->effectiveNs = effNs;
  2048. }
  2049. effNs->next = NULL;
  2050. effNs->prefix = ns->prefix;
  2051. effNs->nsName = ns->href;
  2052. effNs->holdByElem = holdByElem;
  2053. if (lastEffNs == NULL)
  2054. item->effectiveNs = effNs;
  2055. else
  2056. lastEffNs->next = effNs;
  2057. lastEffNs = effNs;
  2058. skip_ns:
  2059. {}
  2060. }
  2061. return(0);
  2062. }
  2063. /**
  2064. * xsltLREInfoCreate:
  2065. *
  2066. * @isLRE: indicates if the given @elem is a literal result element
  2067. *
  2068. * Creates a new info for a literal result element.
  2069. */
  2070. static int
  2071. xsltLREInfoCreate(xsltCompilerCtxtPtr cctxt,
  2072. xmlNodePtr elem,
  2073. int isLRE)
  2074. {
  2075. xsltStyleItemLRElementInfoPtr item;
  2076. if ((cctxt == NULL) || (cctxt->inode == NULL))
  2077. return(-1);
  2078. item = (xsltStyleItemLRElementInfoPtr)
  2079. xmlMalloc(sizeof(xsltStyleItemLRElementInfo));
  2080. if (item == NULL) {
  2081. xsltTransformError(NULL, cctxt->style, NULL,
  2082. "Internal error in xsltLREInfoCreate(): "
  2083. "memory allocation failed.\n");
  2084. cctxt->style->errors++;
  2085. return(-1);
  2086. }
  2087. memset(item, 0, sizeof(xsltStyleItemLRElementInfo));
  2088. item->type = XSLT_FUNC_LITERAL_RESULT_ELEMENT;
  2089. /*
  2090. * Store it in the stylesheet.
  2091. */
  2092. item->next = cctxt->style->preComps;
  2093. cctxt->style->preComps = (xsltElemPreCompPtr) item;
  2094. /*
  2095. * @inScopeNs are used for execution of XPath expressions
  2096. * in AVTs.
  2097. */
  2098. item->inScopeNs = cctxt->inode->inScopeNs;
  2099. if (elem)
  2100. xsltLREBuildEffectiveNsNodes(cctxt, item, elem, isLRE);
  2101. cctxt->inode->litResElemInfo = item;
  2102. cctxt->inode->nsChanged = 0;
  2103. cctxt->maxLREs++;
  2104. return(0);
  2105. }
  2106. /**
  2107. * xsltCompilerVarInfoPush:
  2108. * @cctxt: the compilation context
  2109. *
  2110. * Pushes a new var/param info onto the stack.
  2111. *
  2112. * Returns the acquired variable info.
  2113. */
  2114. static xsltVarInfoPtr
  2115. xsltCompilerVarInfoPush(xsltCompilerCtxtPtr cctxt,
  2116. xmlNodePtr inst,
  2117. const xmlChar *name,
  2118. const xmlChar *nsName)
  2119. {
  2120. xsltVarInfoPtr ivar;
  2121. if ((cctxt->ivar != NULL) && (cctxt->ivar->next != NULL)) {
  2122. ivar = cctxt->ivar->next;
  2123. } else if ((cctxt->ivar == NULL) && (cctxt->ivars != NULL)) {
  2124. ivar = cctxt->ivars;
  2125. } else {
  2126. ivar = (xsltVarInfoPtr) xmlMalloc(sizeof(xsltVarInfo));
  2127. if (ivar == NULL) {
  2128. xsltTransformError(NULL, cctxt->style, inst,
  2129. "xsltParseInScopeVarPush: xmlMalloc() failed!\n");
  2130. cctxt->style->errors++;
  2131. return(NULL);
  2132. }
  2133. /* memset(retVar, 0, sizeof(xsltInScopeVar)); */
  2134. if (cctxt->ivars == NULL) {
  2135. cctxt->ivars = ivar;
  2136. ivar->prev = NULL;
  2137. } else {
  2138. cctxt->ivar->next = ivar;
  2139. ivar->prev = cctxt->ivar;
  2140. }
  2141. cctxt->ivar = ivar;
  2142. ivar->next = NULL;
  2143. }
  2144. ivar->depth = cctxt->depth;
  2145. ivar->name = name;
  2146. ivar->nsName = nsName;
  2147. return(ivar);
  2148. }
  2149. /**
  2150. * xsltCompilerVarInfoPop:
  2151. * @cctxt: the compilation context
  2152. *
  2153. * Pops all var/param infos from the stack, which
  2154. * have the current depth.
  2155. */
  2156. static void
  2157. xsltCompilerVarInfoPop(xsltCompilerCtxtPtr cctxt)
  2158. {
  2159. while ((cctxt->ivar != NULL) &&
  2160. (cctxt->ivar->depth > cctxt->depth))
  2161. {
  2162. cctxt->ivar = cctxt->ivar->prev;
  2163. }
  2164. }
  2165. /*
  2166. * xsltCompilerNodePush:
  2167. *
  2168. * @cctxt: the compilation context
  2169. * @node: the node to be pushed (this can also be the doc-node)
  2170. *
  2171. *
  2172. *
  2173. * Returns the current node info structure or
  2174. * NULL in case of an internal error.
  2175. */
  2176. static xsltCompilerNodeInfoPtr
  2177. xsltCompilerNodePush(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
  2178. {
  2179. xsltCompilerNodeInfoPtr inode, iprev;
  2180. if ((cctxt->inode != NULL) && (cctxt->inode->next != NULL)) {
  2181. inode = cctxt->inode->next;
  2182. } else if ((cctxt->inode == NULL) && (cctxt->inodeList != NULL)) {
  2183. inode = cctxt->inodeList;
  2184. } else {
  2185. /*
  2186. * Create a new node-info.
  2187. */
  2188. inode = (xsltCompilerNodeInfoPtr)
  2189. xmlMalloc(sizeof(xsltCompilerNodeInfo));
  2190. if (inode == NULL) {
  2191. xsltTransformError(NULL, cctxt->style, NULL,
  2192. "xsltCompilerNodePush: malloc failed.\n");
  2193. return(NULL);
  2194. }
  2195. memset(inode, 0, sizeof(xsltCompilerNodeInfo));
  2196. if (cctxt->inodeList == NULL)
  2197. cctxt->inodeList = inode;
  2198. else {
  2199. cctxt->inodeLast->next = inode;
  2200. inode->prev = cctxt->inodeLast;
  2201. }
  2202. cctxt->inodeLast = inode;
  2203. cctxt->maxNodeInfos++;
  2204. if (cctxt->inode == NULL) {
  2205. cctxt->inode = inode;
  2206. /*
  2207. * Create an initial literal result element info for
  2208. * the root of the stylesheet.
  2209. */
  2210. xsltLREInfoCreate(cctxt, NULL, 0);
  2211. }
  2212. }
  2213. cctxt->depth++;
  2214. cctxt->inode = inode;
  2215. /*
  2216. * REVISIT TODO: Keep the reset always complete.
  2217. * NOTE: Be carefull with the @node, since it might be
  2218. * a doc-node.
  2219. */
  2220. inode->node = node;
  2221. inode->depth = cctxt->depth;
  2222. inode->templ = NULL;
  2223. inode->category = XSLT_ELEMENT_CATEGORY_XSLT;
  2224. inode->type = 0;
  2225. inode->item = NULL;
  2226. inode->curChildType = 0;
  2227. inode->extContentHandled = 0;
  2228. inode->isRoot = 0;
  2229. if (inode->prev != NULL) {
  2230. iprev = inode->prev;
  2231. /*
  2232. * Inherit the following information:
  2233. * ---------------------------------
  2234. *
  2235. * In-scope namespaces
  2236. */
  2237. inode->inScopeNs = iprev->inScopeNs;
  2238. /*
  2239. * Info for literal result elements
  2240. */
  2241. inode->litResElemInfo = iprev->litResElemInfo;
  2242. inode->nsChanged = iprev->nsChanged;
  2243. /*
  2244. * Excluded result namespaces
  2245. */
  2246. inode->exclResultNs = iprev->exclResultNs;
  2247. /*
  2248. * Extension instruction namespaces
  2249. */
  2250. inode->extElemNs = iprev->extElemNs;
  2251. /*
  2252. * Whitespace preservation
  2253. */
  2254. inode->preserveWhitespace = iprev->preserveWhitespace;
  2255. /*
  2256. * Forwards-compatible mode
  2257. */
  2258. inode->forwardsCompat = iprev->forwardsCompat;
  2259. } else {
  2260. inode->inScopeNs = NULL;
  2261. inode->exclResultNs = NULL;
  2262. inode->extElemNs = NULL;
  2263. inode->preserveWhitespace = 0;
  2264. inode->forwardsCompat = 0;
  2265. }
  2266. return(inode);
  2267. }
  2268. /*
  2269. * xsltCompilerNodePop:
  2270. *
  2271. * @cctxt: the compilation context
  2272. * @node: the node to be pushed (this can also be the doc-node)
  2273. *
  2274. * Pops the current node info.
  2275. */
  2276. static void
  2277. xsltCompilerNodePop(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
  2278. {
  2279. if (cctxt->inode == NULL) {
  2280. xmlGenericError(xmlGenericErrorContext,
  2281. "xsltCompilerNodePop: Top-node mismatch.\n");
  2282. return;
  2283. }
  2284. /*
  2285. * NOTE: Be carefull with the @node, since it might be
  2286. * a doc-node.
  2287. */
  2288. if (cctxt->inode->node != node) {
  2289. xmlGenericError(xmlGenericErrorContext,
  2290. "xsltCompilerNodePop: Node mismatch.\n");
  2291. goto mismatch;
  2292. }
  2293. if (cctxt->inode->depth != cctxt->depth) {
  2294. xmlGenericError(xmlGenericErrorContext,
  2295. "xsltCompilerNodePop: Depth mismatch.\n");
  2296. goto mismatch;
  2297. }
  2298. cctxt->depth--;
  2299. /*
  2300. * Pop information of variables.
  2301. */
  2302. if ((cctxt->ivar) && (cctxt->ivar->depth > cctxt->depth))
  2303. xsltCompilerVarInfoPop(cctxt);
  2304. cctxt->inode = cctxt->inode->prev;
  2305. if (cctxt->inode != NULL)
  2306. cctxt->inode->curChildType = 0;
  2307. return;
  2308. mismatch:
  2309. {
  2310. const xmlChar *nsName = NULL, *name = NULL;
  2311. const xmlChar *infnsName = NULL, *infname = NULL;
  2312. if (node) {
  2313. if (node->type == XML_ELEMENT_NODE) {
  2314. name = node->name;
  2315. if (node->ns != NULL)
  2316. nsName = node->ns->href;
  2317. else
  2318. nsName = BAD_CAST "";
  2319. } else {
  2320. name = BAD_CAST "#document";
  2321. nsName = BAD_CAST "";
  2322. }
  2323. } else
  2324. name = BAD_CAST "Not given";
  2325. if (cctxt->inode->node) {
  2326. if (node->type == XML_ELEMENT_NODE) {
  2327. infname = cctxt->inode->node->name;
  2328. if (cctxt->inode->node->ns != NULL)
  2329. infnsName = cctxt->inode->node->ns->href;
  2330. else
  2331. infnsName = BAD_CAST "";
  2332. } else {
  2333. infname = BAD_CAST "#document";
  2334. infnsName = BAD_CAST "";
  2335. }
  2336. } else
  2337. infname = BAD_CAST "Not given";
  2338. xmlGenericError(xmlGenericErrorContext,
  2339. "xsltCompilerNodePop: Given : '%s' URI '%s'\n",
  2340. name, nsName);
  2341. xmlGenericError(xmlGenericErrorContext,
  2342. "xsltCompilerNodePop: Expected: '%s' URI '%s'\n",
  2343. infname, infnsName);
  2344. }
  2345. }
  2346. /*
  2347. * xsltCompilerBuildInScopeNsList:
  2348. *
  2349. * Create and store the list of in-scope namespaces for the given
  2350. * node in the stylesheet. If there are no changes in the in-scope
  2351. * namespaces then the last ns-info of the ancestor axis will be returned.
  2352. * Compilation-time only.
  2353. *
  2354. * Returns the ns-info or NULL if there are no namespaces in scope.
  2355. */
  2356. static xsltNsListContainerPtr
  2357. xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
  2358. {
  2359. xsltNsListContainerPtr nsi = NULL;
  2360. xmlNsPtr *list = NULL, ns;
  2361. int i, maxns = 5;
  2362. /*
  2363. * Create a new ns-list for this position in the node-tree.
  2364. * xmlGetNsList() will return NULL, if there are no ns-decls in the
  2365. * tree. Note that the ns-decl for the XML namespace is not added
  2366. * to the resulting list; the XPath module handles the XML namespace
  2367. * internally.
  2368. */
  2369. while (node != NULL) {
  2370. if (node->type == XML_ELEMENT_NODE) {
  2371. ns = node->nsDef;
  2372. while (ns != NULL) {
  2373. if (nsi == NULL) {
  2374. nsi = (xsltNsListContainerPtr)
  2375. xmlMalloc(sizeof(xsltNsListContainer));
  2376. if (nsi == NULL) {
  2377. xsltTransformError(NULL, cctxt->style, NULL,
  2378. "xsltCompilerBuildInScopeNsList: "
  2379. "malloc failed!\n");
  2380. goto internal_err;
  2381. }
  2382. memset(nsi, 0, sizeof(xsltNsListContainer));
  2383. nsi->list =
  2384. (xmlNsPtr *) xmlMalloc(maxns * sizeof(xmlNsPtr));
  2385. if (nsi->list == NULL) {
  2386. xsltTransformError(NULL, cctxt->style, NULL,
  2387. "xsltCompilerBuildInScopeNsList: "
  2388. "malloc failed!\n");
  2389. goto internal_err;
  2390. }
  2391. nsi->list[0] = NULL;
  2392. }
  2393. /*
  2394. * Skip shadowed namespace bindings.
  2395. */
  2396. for (i = 0; i < nsi->totalNumber; i++) {
  2397. if ((ns->prefix == nsi->list[i]->prefix) ||
  2398. (xmlStrEqual(ns->prefix, nsi->list[i]->prefix)))
  2399. break;
  2400. }
  2401. if (i >= nsi->totalNumber) {
  2402. if (nsi->totalNumber +1 >= maxns) {
  2403. maxns *= 2;
  2404. nsi->list =
  2405. (xmlNsPtr *) xmlRealloc(nsi->list,
  2406. maxns * sizeof(xmlNsPtr));
  2407. if (nsi->list == NULL) {
  2408. xsltTransformError(NULL, cctxt->style, NULL,
  2409. "xsltCompilerBuildInScopeNsList: "
  2410. "realloc failed!\n");
  2411. goto internal_err;
  2412. }
  2413. }
  2414. nsi->list[nsi->totalNumber++] = ns;
  2415. nsi->list[nsi->totalNumber] = NULL;
  2416. }
  2417. ns = ns->next;
  2418. }
  2419. }
  2420. node = node->parent;
  2421. }
  2422. if (nsi == NULL)
  2423. return(NULL);
  2424. /*
  2425. * Move the default namespace to last position.
  2426. */
  2427. nsi->xpathNumber = nsi->totalNumber;
  2428. for (i = 0; i < nsi->totalNumber; i++) {
  2429. if (nsi->list[i]->prefix == NULL) {
  2430. ns = nsi->list[i];
  2431. nsi->list[i] = nsi->list[nsi->totalNumber-1];
  2432. nsi->list[nsi->totalNumber-1] = ns;
  2433. nsi->xpathNumber--;
  2434. break;
  2435. }
  2436. }
  2437. /*
  2438. * Store the ns-list in the stylesheet.
  2439. */
  2440. if (xsltPointerListAddSize(
  2441. (xsltPointerListPtr)cctxt->psData->inScopeNamespaces,
  2442. (void *) nsi, 5) == -1)
  2443. {
  2444. xmlFree(nsi);
  2445. nsi = NULL;
  2446. xsltTransformError(NULL, cctxt->style, NULL,
  2447. "xsltCompilerBuildInScopeNsList: failed to add ns-info.\n");
  2448. goto internal_err;
  2449. }
  2450. /*
  2451. * Notify of change in status wrt namespaces.
  2452. */
  2453. if (cctxt->inode != NULL)
  2454. cctxt->inode->nsChanged = 1;
  2455. return(nsi);
  2456. internal_err:
  2457. if (list != NULL)
  2458. xmlFree(list);
  2459. cctxt->style->errors++;
  2460. return(NULL);
  2461. }
  2462. static int
  2463. xsltParseNsPrefixList(xsltCompilerCtxtPtr cctxt,
  2464. xsltPointerListPtr list,
  2465. xmlNodePtr node,
  2466. const xmlChar *value)
  2467. {
  2468. xmlChar *cur, *end;
  2469. xmlNsPtr ns;
  2470. if ((cctxt == NULL) || (value == NULL) || (list == NULL))
  2471. return(-1);
  2472. list->number = 0;
  2473. cur = (xmlChar *) value;
  2474. while (*cur != 0) {
  2475. while (IS_BLANK(*cur)) cur++;
  2476. if (*cur == 0)
  2477. break;
  2478. end = cur;
  2479. while ((*end != 0) && (!IS_BLANK(*end))) end++;
  2480. cur = xmlStrndup(cur, end - cur);
  2481. if (cur == NULL) {
  2482. cur = end;
  2483. continue;
  2484. }
  2485. /*
  2486. * TODO: Export and use xmlSearchNsByPrefixStrict()
  2487. * in Libxml2, tree.c, since xmlSearchNs() is in most
  2488. * cases not efficient and in some cases not correct.
  2489. *
  2490. * XSLT-2 TODO: XSLT 2.0 allows an additional "#all" value.
  2491. */
  2492. if ((cur[0] == '#') &&
  2493. xmlStrEqual(cur, (const xmlChar *)"#default"))
  2494. ns = xmlSearchNs(cctxt->style->doc, node, NULL);
  2495. else
  2496. ns = xmlSearchNs(cctxt->style->doc, node, cur);
  2497. if (ns == NULL) {
  2498. /*
  2499. * TODO: Better to report the attr-node, otherwise
  2500. * the user won't know which attribute was invalid.
  2501. */
  2502. xsltTransformError(NULL, cctxt->style, node,
  2503. "No namespace binding in scope for prefix '%s'.\n", cur);
  2504. /*
  2505. * XSLT-1.0: "It is an error if there is no namespace
  2506. * bound to the prefix on the element bearing the
  2507. * exclude-result-prefixes or xsl:exclude-result-prefixes
  2508. * attribute."
  2509. */
  2510. cctxt->style->errors++;
  2511. } else {
  2512. #ifdef WITH_XSLT_DEBUG_PARSING
  2513. xsltGenericDebug(xsltGenericDebugContext,
  2514. "resolved prefix '%s'\n", cur);
  2515. #endif
  2516. /*
  2517. * Note that we put the namespace name into the dict.
  2518. */
  2519. if (xsltPointerListAddSize(list,
  2520. (void *) xmlDictLookup(cctxt->style->dict,
  2521. ns->href, -1), 5) == -1)
  2522. {
  2523. xmlFree(cur);
  2524. goto internal_err;
  2525. }
  2526. }
  2527. xmlFree(cur);
  2528. cur = end;
  2529. }
  2530. return(0);
  2531. internal_err:
  2532. cctxt->style->errors++;
  2533. return(-1);
  2534. }
  2535. /**
  2536. * xsltCompilerUtilsCreateMergedList:
  2537. * @dest: the destination list (optional)
  2538. * @first: the first list
  2539. * @second: the second list (optional)
  2540. *
  2541. * Appends the content of @second to @first into @destination.
  2542. * If @destination is NULL a new list will be created.
  2543. *
  2544. * Returns the merged list of items or NULL if there's nothing to merge.
  2545. */
  2546. static xsltPointerListPtr
  2547. xsltCompilerUtilsCreateMergedList(xsltPointerListPtr first,
  2548. xsltPointerListPtr second)
  2549. {
  2550. xsltPointerListPtr ret;
  2551. size_t num;
  2552. if (first)
  2553. num = first->number;
  2554. else
  2555. num = 0;
  2556. if (second)
  2557. num += second->number;
  2558. if (num == 0)
  2559. return(NULL);
  2560. ret = xsltPointerListCreate(num);
  2561. if (ret == NULL)
  2562. return(NULL);
  2563. /*
  2564. * Copy contents.
  2565. */
  2566. if ((first != NULL) && (first->number != 0)) {
  2567. memcpy(ret->items, first->items,
  2568. first->number * sizeof(void *));
  2569. if ((second != NULL) && (second->number != 0))
  2570. memcpy(ret->items + first->number, second->items,
  2571. second->number * sizeof(void *));
  2572. } else if ((second != NULL) && (second->number != 0))
  2573. memcpy(ret->items, (void *) second->items,
  2574. second->number * sizeof(void *));
  2575. ret->number = num;
  2576. return(ret);
  2577. }
  2578. /*
  2579. * xsltParseExclResultPrefixes:
  2580. *
  2581. * Create and store the list of in-scope namespaces for the given
  2582. * node in the stylesheet. If there are no changes in the in-scope
  2583. * namespaces then the last ns-info of the ancestor axis will be returned.
  2584. * Compilation-time only.
  2585. *
  2586. * Returns the ns-info or NULL if there are no namespaces in scope.
  2587. */
  2588. static xsltPointerListPtr
  2589. xsltParseExclResultPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
  2590. xsltPointerListPtr def,
  2591. int instrCategory)
  2592. {
  2593. xsltPointerListPtr list = NULL;
  2594. xmlChar *value;
  2595. xmlAttrPtr attr;
  2596. if ((cctxt == NULL) || (node == NULL))
  2597. return(NULL);
  2598. if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
  2599. attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes", NULL);
  2600. else
  2601. attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes",
  2602. XSLT_NAMESPACE);
  2603. if (attr == NULL)
  2604. return(def);
  2605. if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
  2606. /*
  2607. * Mark the XSLT attr.
  2608. */
  2609. attr->psvi = (void *) xsltXSLTAttrMarker;
  2610. }
  2611. if ((attr->children != NULL) &&
  2612. (attr->children->content != NULL))
  2613. value = attr->children->content;
  2614. else {
  2615. xsltTransformError(NULL, cctxt->style, node,
  2616. "Attribute 'exclude-result-prefixes': Invalid value.\n");
  2617. cctxt->style->errors++;
  2618. return(def);
  2619. }
  2620. if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,
  2621. BAD_CAST value) != 0)
  2622. goto exit;
  2623. if (cctxt->tmpList->number == 0)
  2624. goto exit;
  2625. /*
  2626. * Merge the list with the inherited list.
  2627. */
  2628. list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);
  2629. if (list == NULL)
  2630. goto exit;
  2631. /*
  2632. * Store the list in the stylesheet/compiler context.
  2633. */
  2634. if (xsltPointerListAddSize(
  2635. cctxt->psData->exclResultNamespaces, list, 5) == -1)
  2636. {
  2637. xsltPointerListFree(list);
  2638. list = NULL;
  2639. goto exit;
  2640. }
  2641. /*
  2642. * Notify of change in status wrt namespaces.
  2643. */
  2644. if (cctxt->inode != NULL)
  2645. cctxt->inode->nsChanged = 1;
  2646. exit:
  2647. if (list != NULL)
  2648. return(list);
  2649. else
  2650. return(def);
  2651. }
  2652. /*
  2653. * xsltParseExtElemPrefixes:
  2654. *
  2655. * Create and store the list of in-scope namespaces for the given
  2656. * node in the stylesheet. If there are no changes in the in-scope
  2657. * namespaces then the last ns-info of the ancestor axis will be returned.
  2658. * Compilation-time only.
  2659. *
  2660. * Returns the ns-info or NULL if there are no namespaces in scope.
  2661. */
  2662. static xsltPointerListPtr
  2663. xsltParseExtElemPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
  2664. xsltPointerListPtr def,
  2665. int instrCategory)
  2666. {
  2667. xsltPointerListPtr list = NULL;
  2668. xmlAttrPtr attr;
  2669. xmlChar *value;
  2670. int i;
  2671. if ((cctxt == NULL) || (node == NULL))
  2672. return(NULL);
  2673. if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
  2674. attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes", NULL);
  2675. else
  2676. attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes",
  2677. XSLT_NAMESPACE);
  2678. if (attr == NULL)
  2679. return(def);
  2680. if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
  2681. /*
  2682. * Mark the XSLT attr.
  2683. */
  2684. attr->psvi = (void *) xsltXSLTAttrMarker;
  2685. }
  2686. if ((attr->children != NULL) &&
  2687. (attr->children->content != NULL))
  2688. value = attr->children->content;
  2689. else {
  2690. xsltTransformError(NULL, cctxt->style, node,
  2691. "Attribute 'extension-element-prefixes': Invalid value.\n");
  2692. cctxt->style->errors++;
  2693. return(def);
  2694. }
  2695. if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,
  2696. BAD_CAST value) != 0)
  2697. goto exit;
  2698. if (cctxt->tmpList->number == 0)
  2699. goto exit;
  2700. /*
  2701. * REVISIT: Register the extension namespaces.
  2702. */
  2703. for (i = 0; i < cctxt->tmpList->number; i++)
  2704. xsltRegisterExtPrefix(cctxt->style, NULL,
  2705. BAD_CAST cctxt->tmpList->items[i]);
  2706. /*
  2707. * Merge the list with the inherited list.
  2708. */
  2709. list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);
  2710. if (list == NULL)
  2711. goto exit;
  2712. /*
  2713. * Store the list in the stylesheet.
  2714. */
  2715. if (xsltPointerListAddSize(
  2716. cctxt->psData->extElemNamespaces, list, 5) == -1)
  2717. {
  2718. xsltPointerListFree(list);
  2719. list = NULL;
  2720. goto exit;
  2721. }
  2722. /*
  2723. * Notify of change in status wrt namespaces.
  2724. */
  2725. if (cctxt->inode != NULL)
  2726. cctxt->inode->nsChanged = 1;
  2727. exit:
  2728. if (list != NULL)
  2729. return(list);
  2730. else
  2731. return(def);
  2732. }
  2733. /*
  2734. * xsltParseAttrXSLTVersion:
  2735. *
  2736. * @cctxt: the compilation context
  2737. * @node: the element-node
  2738. * @isXsltElem: whether this is an XSLT element
  2739. *
  2740. * Parses the attribute xsl:version.
  2741. *
  2742. * Returns 1 if there was such an attribute, 0 if not and
  2743. * -1 if an internal or API error occured.
  2744. */
  2745. static int
  2746. xsltParseAttrXSLTVersion(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
  2747. int instrCategory)
  2748. {
  2749. xmlChar *value;
  2750. xmlAttrPtr attr;
  2751. if ((cctxt == NULL) || (node == NULL))
  2752. return(-1);
  2753. if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
  2754. attr = xmlHasNsProp(node, BAD_CAST "version", NULL);
  2755. else
  2756. attr = xmlHasNsProp(node, BAD_CAST "version", XSLT_NAMESPACE);
  2757. if (attr == NULL)
  2758. return(0);
  2759. attr->psvi = (void *) xsltXSLTAttrMarker;
  2760. if ((attr->children != NULL) &&
  2761. (attr->children->content != NULL))
  2762. value = attr->children->content;
  2763. else {
  2764. xsltTransformError(NULL, cctxt->style, node,
  2765. "Attribute 'version': Invalid value.\n");
  2766. cctxt->style->errors++;
  2767. return(1);
  2768. }
  2769. if (! xmlStrEqual(value, (const xmlChar *)"1.0")) {
  2770. cctxt->inode->forwardsCompat = 1;
  2771. /*
  2772. * TODO: To what extent do we support the
  2773. * forwards-compatible mode?
  2774. */
  2775. /*
  2776. * Report this only once per compilation episode.
  2777. */
  2778. if (! cctxt->hasForwardsCompat) {
  2779. cctxt->hasForwardsCompat = 1;
  2780. cctxt->errSeverity = XSLT_ERROR_SEVERITY_WARNING;
  2781. xsltTransformError(NULL, cctxt->style, node,
  2782. "Warning: the attribute xsl:version specifies a value "
  2783. "different from '1.0'. Switching to forwards-compatible "
  2784. "mode. Only features of XSLT 1.0 are supported by this "
  2785. "processor.\n");
  2786. cctxt->style->warnings++;
  2787. cctxt->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
  2788. }
  2789. } else {
  2790. cctxt->inode->forwardsCompat = 0;
  2791. }
  2792. if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
  2793. /*
  2794. * Set a marker on XSLT attributes.
  2795. */
  2796. attr->psvi = (void *) xsltXSLTAttrMarker;
  2797. }
  2798. return(1);
  2799. }
  2800. static int
  2801. xsltParsePreprocessStylesheetTree(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
  2802. {
  2803. xmlNodePtr deleteNode, cur, txt, textNode = NULL;
  2804. xmlDocPtr doc;
  2805. xsltStylesheetPtr style;
  2806. int internalize = 0, findSpaceAttr;
  2807. int xsltStylesheetElemDepth;
  2808. xmlAttrPtr attr;
  2809. xmlChar *value;
  2810. const xmlChar *name, *nsNameXSLT = NULL;
  2811. int strictWhitespace, inXSLText = 0;
  2812. #ifdef XSLT_REFACTORED_XSLT_NSCOMP
  2813. xsltNsMapPtr nsMapItem;
  2814. #endif
  2815. if ((cctxt == NULL) || (cctxt->style == NULL) ||
  2816. (node == NULL) || (node->type != XML_ELEMENT_NODE))
  2817. return(-1);
  2818. doc = node->doc;
  2819. if (doc == NULL)
  2820. goto internal_err;
  2821. style = cctxt->style;
  2822. if ((style->dict != NULL) && (doc->dict == style->dict))
  2823. internalize = 1;
  2824. else
  2825. style->internalized = 0;
  2826. /*
  2827. * Init value of xml:space. Since this might be an embedded
  2828. * stylesheet, this is needed to be performed on the element
  2829. * where the stylesheet is rooted at, taking xml:space of
  2830. * ancestors into account.
  2831. */
  2832. if (! cctxt->simplified)
  2833. xsltStylesheetElemDepth = cctxt->depth +1;
  2834. else
  2835. xsltStylesheetElemDepth = 0;
  2836. if (xmlNodeGetSpacePreserve(node) != 1)
  2837. cctxt->inode->preserveWhitespace = 0;
  2838. else
  2839. cctxt->inode->preserveWhitespace = 1;
  2840. /*
  2841. * Eval if we should keep the old incorrect behaviour.
  2842. */
  2843. strictWhitespace = (cctxt->strict != 0) ? 1 : 0;
  2844. nsNameXSLT = xsltConstNamespaceNameXSLT;
  2845. deleteNode = NULL;
  2846. cur = node;
  2847. while (cur != NULL) {
  2848. if (deleteNode != NULL) {
  2849. #ifdef WITH_XSLT_DEBUG_BLANKS
  2850. xsltGenericDebug(xsltGenericDebugContext,
  2851. "xsltParsePreprocessStylesheetTree: removing node\n");
  2852. #endif
  2853. xmlUnlinkNode(deleteNode);
  2854. xmlFreeNode(deleteNode);
  2855. deleteNode = NULL;
  2856. }
  2857. if (cur->type == XML_ELEMENT_NODE) {
  2858. /*
  2859. * Clear the PSVI field.
  2860. */
  2861. cur->psvi = NULL;
  2862. xsltCompilerNodePush(cctxt, cur);
  2863. inXSLText = 0;
  2864. textNode = NULL;
  2865. findSpaceAttr = 1;
  2866. cctxt->inode->stripWhitespace = 0;
  2867. /*
  2868. * TODO: I'd love to use a string pointer comparison here :-/
  2869. */
  2870. if (IS_XSLT_ELEM(cur)) {
  2871. #ifdef XSLT_REFACTORED_XSLT_NSCOMP
  2872. if (cur->ns->href != nsNameXSLT) {
  2873. nsMapItem = xsltNewNamespaceMapItem(cctxt,
  2874. doc, cur->ns, cur);
  2875. if (nsMapItem == NULL)
  2876. goto internal_err;
  2877. cur->ns->href = nsNameXSLT;
  2878. }
  2879. #endif
  2880. if (cur->name == NULL)
  2881. goto process_attributes;
  2882. /*
  2883. * Mark the XSLT element for later recognition.
  2884. * TODO: Using the marker is still too dangerous, since if
  2885. * the parsing mechanism leaves out an XSLT element, then
  2886. * this might hit the transformation-mechanism, which
  2887. * will break if it doesn't expect such a marker.
  2888. */
  2889. /* cur->psvi = (void *) xsltXSLTElemMarker; */
  2890. /*
  2891. * XSLT 2.0: "Any whitespace text node whose parent is
  2892. * one of the following elements is removed from the "
  2893. * tree, regardless of any xml:space attributes:..."
  2894. * xsl:apply-imports,
  2895. * xsl:apply-templates,
  2896. * xsl:attribute-set,
  2897. * xsl:call-template,
  2898. * xsl:choose,
  2899. * xsl:stylesheet, xsl:transform.
  2900. * XSLT 2.0: xsl:analyze-string,
  2901. * xsl:character-map,
  2902. * xsl:next-match
  2903. *
  2904. * TODO: I'd love to use a string pointer comparison here :-/
  2905. */
  2906. name = cur->name;
  2907. switch (*name) {
  2908. case 't':
  2909. if ((name[0] == 't') && (name[1] == 'e') &&
  2910. (name[2] == 'x') && (name[3] == 't') &&
  2911. (name[4] == 0))
  2912. {
  2913. /*
  2914. * Process the xsl:text element.
  2915. * ----------------------------
  2916. * Mark it for later recognition.
  2917. */
  2918. cur->psvi = (void *) xsltXSLTTextMarker;
  2919. /*
  2920. * For stylesheets, the set of
  2921. * whitespace-preserving element names
  2922. * consists of just xsl:text.
  2923. */
  2924. findSpaceAttr = 0;
  2925. cctxt->inode->preserveWhitespace = 1;
  2926. inXSLText = 1;
  2927. }
  2928. break;
  2929. case 'c':
  2930. if (xmlStrEqual(name, BAD_CAST "choose") ||
  2931. xmlStrEqual(name, BAD_CAST "call-template"))
  2932. cctxt->inode->stripWhitespace = 1;
  2933. break;
  2934. case 'a':
  2935. if (xmlStrEqual(name, BAD_CAST "apply-templates") ||
  2936. xmlStrEqual(name, BAD_CAST "apply-imports") ||
  2937. xmlStrEqual(name, BAD_CAST "attribute-set"))
  2938. cctxt->inode->stripWhitespace = 1;
  2939. break;
  2940. default:
  2941. if (xsltStylesheetElemDepth == cctxt->depth) {
  2942. /*
  2943. * This is a xsl:stylesheet/xsl:transform.
  2944. */
  2945. cctxt->inode->stripWhitespace = 1;
  2946. break;
  2947. }
  2948. if ((cur->prev != NULL) &&
  2949. (cur->prev->type == XML_TEXT_NODE))
  2950. {
  2951. /*
  2952. * XSLT 2.0 : "Any whitespace text node whose
  2953. * following-sibling node is an xsl:param or
  2954. * xsl:sort element is removed from the tree,
  2955. * regardless of any xml:space attributes."
  2956. */
  2957. if (((*name == 'p') || (*name == 's')) &&
  2958. (xmlStrEqual(name, BAD_CAST "param") ||
  2959. xmlStrEqual(name, BAD_CAST "sort")))
  2960. {
  2961. do {
  2962. if (IS_BLANK_NODE(cur->prev)) {
  2963. txt = cur->prev;
  2964. xmlUnlinkNode(txt);
  2965. xmlFreeNode(txt);
  2966. } else {
  2967. /*
  2968. * This will result in a content
  2969. * error, when hitting the parsing
  2970. * functions.
  2971. */
  2972. break;
  2973. }
  2974. } while (cur->prev);
  2975. }
  2976. }
  2977. break;
  2978. }
  2979. }
  2980. process_attributes:
  2981. /*
  2982. * Process attributes.
  2983. * ------------------
  2984. */
  2985. if (cur->properties != NULL) {
  2986. if (cur->children == NULL)
  2987. findSpaceAttr = 0;
  2988. attr = cur->properties;
  2989. do {
  2990. #ifdef XSLT_REFACTORED_XSLT_NSCOMP
  2991. if ((attr->ns) && (attr->ns->href != nsNameXSLT) &&
  2992. xmlStrEqual(attr->ns->href, nsNameXSLT))
  2993. {
  2994. nsMapItem = xsltNewNamespaceMapItem(cctxt,
  2995. doc, attr->ns, cur);
  2996. if (nsMapItem == NULL)
  2997. goto internal_err;
  2998. attr->ns->href = nsNameXSLT;
  2999. }
  3000. #endif
  3001. if (internalize) {
  3002. /*
  3003. * Internalize the attribute's value; the goal is to
  3004. * speed up operations and minimize used space by
  3005. * compiled stylesheets.
  3006. */
  3007. txt = attr->children;
  3008. /*
  3009. * NOTE that this assumes only one
  3010. * text-node in the attribute's content.
  3011. */
  3012. if ((txt != NULL) && (txt->content != NULL) &&
  3013. (!xmlDictOwns(style->dict, txt->content)))
  3014. {
  3015. value = (xmlChar *) xmlDictLookup(style->dict,
  3016. txt->content, -1);
  3017. xmlNodeSetContent(txt, NULL);
  3018. txt->content = value;
  3019. }
  3020. }
  3021. /*
  3022. * Process xml:space attributes.
  3023. * ----------------------------
  3024. */
  3025. if ((findSpaceAttr != 0) &&
  3026. (attr->ns != NULL) &&
  3027. (attr->name != NULL) &&
  3028. (attr->name[0] == 's') &&
  3029. (attr->ns->prefix != NULL) &&
  3030. (attr->ns->prefix[0] == 'x') &&
  3031. (attr->ns->prefix[1] == 'm') &&
  3032. (attr->ns->prefix[2] == 'l') &&
  3033. (attr->ns->prefix[3] == 0))
  3034. {
  3035. value = xmlGetNsProp(cur, BAD_CAST "space",
  3036. XML_XML_NAMESPACE);
  3037. if (value != NULL) {
  3038. if (xmlStrEqual(value, BAD_CAST "preserve")) {
  3039. cctxt->inode->preserveWhitespace = 1;
  3040. } else if (xmlStrEqual(value, BAD_CAST "default")) {
  3041. cctxt->inode->preserveWhitespace = 0;
  3042. } else {
  3043. /* Invalid value for xml:space. */
  3044. xsltTransformError(NULL, style, cur,
  3045. "Attribute xml:space: Invalid value.\n");
  3046. cctxt->style->warnings++;
  3047. }
  3048. findSpaceAttr = 0;
  3049. xmlFree(value);
  3050. }
  3051. }
  3052. attr = attr->next;
  3053. } while (attr != NULL);
  3054. }
  3055. /*
  3056. * We'll descend into the children of element nodes only.
  3057. */
  3058. if (cur->children != NULL) {
  3059. cur = cur->children;
  3060. continue;
  3061. }
  3062. } else if ((cur->type == XML_TEXT_NODE) ||
  3063. (cur->type == XML_CDATA_SECTION_NODE))
  3064. {
  3065. /*
  3066. * Merge adjacent text/CDATA-section-nodes
  3067. * ---------------------------------------
  3068. * In order to avoid breaking of existing stylesheets,
  3069. * if the old behaviour is wanted (strictWhitespace == 0),
  3070. * then we *won't* merge adjacent text-nodes
  3071. * (except in xsl:text); this will ensure that whitespace-only
  3072. * text nodes are (incorrectly) not stripped in some cases.
  3073. *
  3074. * Example: : <foo> <!-- bar -->zoo</foo>
  3075. * Corrent (strict) result: <foo> zoo</foo>
  3076. * Incorrect (old) result : <foo>zoo</foo>
  3077. *
  3078. * NOTE that we *will* merge adjacent text-nodes if
  3079. * they are in xsl:text.
  3080. * Example, the following:
  3081. * <xsl:text> <!-- bar -->zoo<xsl:text>
  3082. * will result in both cases in:
  3083. * <xsl:text> zoo<xsl:text>
  3084. */
  3085. cur->type = XML_TEXT_NODE;
  3086. if ((strictWhitespace != 0) || (inXSLText != 0)) {
  3087. /*
  3088. * New behaviour; merge nodes.
  3089. */
  3090. if (textNode == NULL)
  3091. textNode = cur;
  3092. else {
  3093. if (cur->content != NULL)
  3094. xmlNodeAddContent(textNode, cur->content);
  3095. deleteNode = cur;
  3096. }
  3097. if ((cur->next == NULL) ||
  3098. (cur->next->type == XML_ELEMENT_NODE))
  3099. goto end_of_text;
  3100. else
  3101. goto next_sibling;
  3102. } else {
  3103. /*
  3104. * Old behaviour.
  3105. */
  3106. if (textNode == NULL)
  3107. textNode = cur;
  3108. goto end_of_text;
  3109. }
  3110. } else if ((cur->type == XML_COMMENT_NODE) ||
  3111. (cur->type == XML_PI_NODE))
  3112. {
  3113. /*
  3114. * Remove processing instructions and comments.
  3115. */
  3116. deleteNode = cur;
  3117. if ((cur->next == NULL) ||
  3118. (cur->next->type == XML_ELEMENT_NODE))
  3119. goto end_of_text;
  3120. else
  3121. goto next_sibling;
  3122. } else {
  3123. textNode = NULL;
  3124. /*
  3125. * Invalid node-type for this data-model.
  3126. */
  3127. xsltTransformError(NULL, style, cur,
  3128. "Invalid type of node for the XSLT data model.\n");
  3129. cctxt->style->errors++;
  3130. goto next_sibling;
  3131. }
  3132. end_of_text:
  3133. if (textNode) {
  3134. value = textNode->content;
  3135. /*
  3136. * At this point all adjacent text/CDATA-section nodes
  3137. * have been merged.
  3138. *
  3139. * Strip whitespace-only text-nodes.
  3140. * (cctxt->inode->stripWhitespace)
  3141. */
  3142. if ((value == NULL) || (*value == 0) ||
  3143. (((cctxt->inode->stripWhitespace) ||
  3144. (! cctxt->inode->preserveWhitespace)) &&
  3145. IS_BLANK(*value) &&
  3146. xsltIsBlank(value)))
  3147. {
  3148. if (textNode != cur) {
  3149. xmlUnlinkNode(textNode);
  3150. xmlFreeNode(textNode);
  3151. } else
  3152. deleteNode = textNode;
  3153. textNode = NULL;
  3154. goto next_sibling;
  3155. }
  3156. /*
  3157. * Convert CDATA-section nodes to text-nodes.
  3158. * TODO: Can this produce problems?
  3159. */
  3160. if (textNode->type != XML_TEXT_NODE) {
  3161. textNode->type = XML_TEXT_NODE;
  3162. textNode->name = xmlStringText;
  3163. }
  3164. if (internalize &&
  3165. (textNode->content != NULL) &&
  3166. (!xmlDictOwns(style->dict, textNode->content)))
  3167. {
  3168. /*
  3169. * Internalize the string.
  3170. */
  3171. value = (xmlChar *) xmlDictLookup(style->dict,
  3172. textNode->content, -1);
  3173. xmlNodeSetContent(textNode, NULL);
  3174. textNode->content = value;
  3175. }
  3176. textNode = NULL;
  3177. /*
  3178. * Note that "disable-output-escaping" of the xsl:text
  3179. * element will be applied at a later level, when
  3180. * XSLT elements are processed.
  3181. */
  3182. }
  3183. next_sibling:
  3184. if (cur->type == XML_ELEMENT_NODE) {
  3185. xsltCompilerNodePop(cctxt, cur);
  3186. }
  3187. if (cur == node)
  3188. break;
  3189. if (cur->next != NULL) {
  3190. cur = cur->next;
  3191. } else {
  3192. cur = cur->parent;
  3193. inXSLText = 0;
  3194. goto next_sibling;
  3195. };
  3196. }
  3197. if (deleteNode != NULL) {
  3198. #ifdef WITH_XSLT_DEBUG_PARSING
  3199. xsltGenericDebug(xsltGenericDebugContext,
  3200. "xsltParsePreprocessStylesheetTree: removing node\n");
  3201. #endif
  3202. xmlUnlinkNode(deleteNode);
  3203. xmlFreeNode(deleteNode);
  3204. }
  3205. return(0);
  3206. internal_err:
  3207. return(-1);
  3208. }
  3209. #endif /* XSLT_REFACTORED */
  3210. #ifdef XSLT_REFACTORED
  3211. #else
  3212. static void
  3213. xsltPreprocessStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
  3214. {
  3215. xmlNodePtr deleteNode, styleelem;
  3216. int internalize = 0;
  3217. if ((style == NULL) || (cur == NULL))
  3218. return;
  3219. if ((cur->doc != NULL) && (style->dict != NULL) &&
  3220. (cur->doc->dict == style->dict))
  3221. internalize = 1;
  3222. else
  3223. style->internalized = 0;
  3224. if ((cur != NULL) && (IS_XSLT_ELEM(cur)) &&
  3225. (IS_XSLT_NAME(cur, "stylesheet"))) {
  3226. styleelem = cur;
  3227. } else {
  3228. styleelem = NULL;
  3229. }
  3230. /*
  3231. * This content comes from the stylesheet
  3232. * For stylesheets, the set of whitespace-preserving
  3233. * element names consists of just xsl:text.
  3234. */
  3235. deleteNode = NULL;
  3236. while (cur != NULL) {
  3237. if (deleteNode != NULL) {
  3238. #ifdef WITH_XSLT_DEBUG_BLANKS
  3239. xsltGenericDebug(xsltGenericDebugContext,
  3240. "xsltPreprocessStylesheet: removing ignorable blank node\n");
  3241. #endif
  3242. xmlUnlinkNode(deleteNode);
  3243. xmlFreeNode(deleteNode);
  3244. deleteNode = NULL;
  3245. }
  3246. if (cur->type == XML_ELEMENT_NODE) {
  3247. int exclPrefixes;
  3248. /*
  3249. * Internalize attributes values.
  3250. */
  3251. if ((internalize) && (cur->properties != NULL)) {
  3252. xmlAttrPtr attr = cur->properties;
  3253. xmlNodePtr txt;
  3254. while (attr != NULL) {
  3255. txt = attr->children;
  3256. if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
  3257. (txt->content != NULL) &&
  3258. (!xmlDictOwns(style->dict, txt->content)))
  3259. {
  3260. xmlChar *tmp;
  3261. /*
  3262. * internalize the text string, goal is to speed
  3263. * up operations and minimize used space by compiled
  3264. * stylesheets.
  3265. */
  3266. tmp = (xmlChar *) xmlDictLookup(style->dict,
  3267. txt->content, -1);
  3268. if (tmp != txt->content) {
  3269. xmlNodeSetContent(txt, NULL);
  3270. txt->content = tmp;
  3271. }
  3272. }
  3273. attr = attr->next;
  3274. }
  3275. }
  3276. if (IS_XSLT_ELEM(cur)) {
  3277. exclPrefixes = 0;
  3278. if (IS_XSLT_NAME(cur, "text")) {
  3279. for (;exclPrefixes > 0;exclPrefixes--)
  3280. exclPrefixPop(style);
  3281. goto skip_children;
  3282. }
  3283. } else {
  3284. exclPrefixes = xsltParseStylesheetExcludePrefix(style, cur, 0);
  3285. }
  3286. if ((cur->nsDef != NULL) && (style->exclPrefixNr > 0)) {
  3287. xmlNsPtr ns = cur->nsDef, prev = NULL, next;
  3288. xmlNodePtr root = NULL;
  3289. int i, moved;
  3290. root = xmlDocGetRootElement(cur->doc);
  3291. if ((root != NULL) && (root != cur)) {
  3292. while (ns != NULL) {
  3293. moved = 0;
  3294. next = ns->next;
  3295. for (i = 0;i < style->exclPrefixNr;i++) {
  3296. if ((ns->prefix != NULL) &&
  3297. (xmlStrEqual(ns->href,
  3298. style->exclPrefixTab[i]))) {
  3299. /*
  3300. * Move the namespace definition on the root
  3301. * element to avoid duplicating it without
  3302. * loosing it.
  3303. */
  3304. if (prev == NULL) {
  3305. cur->nsDef = ns->next;
  3306. } else {
  3307. prev->next = ns->next;
  3308. }
  3309. ns->next = root->nsDef;
  3310. root->nsDef = ns;
  3311. moved = 1;
  3312. break;
  3313. }
  3314. }
  3315. if (moved == 0)
  3316. prev = ns;
  3317. ns = next;
  3318. }
  3319. }
  3320. }
  3321. /*
  3322. * If we have prefixes locally, recurse and pop them up when
  3323. * going back
  3324. */
  3325. if (exclPrefixes > 0) {
  3326. xsltPreprocessStylesheet(style, cur->children);
  3327. for (;exclPrefixes > 0;exclPrefixes--)
  3328. exclPrefixPop(style);
  3329. goto skip_children;
  3330. }
  3331. } else if (cur->type == XML_TEXT_NODE) {
  3332. if (IS_BLANK_NODE(cur)) {
  3333. if (xmlNodeGetSpacePreserve(cur->parent) != 1) {
  3334. deleteNode = cur;
  3335. }
  3336. } else if ((cur->content != NULL) && (internalize) &&
  3337. (!xmlDictOwns(style->dict, cur->content))) {
  3338. xmlChar *tmp;
  3339. /*
  3340. * internalize the text string, goal is to speed
  3341. * up operations and minimize used space by compiled
  3342. * stylesheets.
  3343. */
  3344. tmp = (xmlChar *) xmlDictLookup(style->dict, cur->content, -1);
  3345. xmlNodeSetContent(cur, NULL);
  3346. cur->content = tmp;
  3347. }
  3348. } else if ((cur->type != XML_ELEMENT_NODE) &&
  3349. (cur->type != XML_CDATA_SECTION_NODE)) {
  3350. deleteNode = cur;
  3351. goto skip_children;
  3352. }
  3353. /*
  3354. * Skip to next node. In case of a namespaced element children of
  3355. * the stylesheet and not in the XSLT namespace and not an extension
  3356. * element, ignore its content.
  3357. */
  3358. if ((cur->type == XML_ELEMENT_NODE) && (cur->ns != NULL) &&
  3359. (styleelem != NULL) && (cur->parent == styleelem) &&
  3360. (!xmlStrEqual(cur->ns->href, XSLT_NAMESPACE)) &&
  3361. (!xsltCheckExtURI(style, cur->ns->href))) {
  3362. goto skip_children;
  3363. } else if (cur->children != NULL) {
  3364. cur = cur->children;
  3365. continue;
  3366. }
  3367. skip_children:
  3368. if (cur->next != NULL) {
  3369. cur = cur->next;
  3370. continue;
  3371. }
  3372. do {
  3373. cur = cur->parent;
  3374. if (cur == NULL)
  3375. break;
  3376. if (cur == (xmlNodePtr) style->doc) {
  3377. cur = NULL;
  3378. break;
  3379. }
  3380. if (cur->next != NULL) {
  3381. cur = cur->next;
  3382. break;
  3383. }
  3384. } while (cur != NULL);
  3385. }
  3386. if (deleteNode != NULL) {
  3387. #ifdef WITH_XSLT_DEBUG_PARSING
  3388. xsltGenericDebug(xsltGenericDebugContext,
  3389. "xsltPreprocessStylesheet: removing ignorable blank node\n");
  3390. #endif
  3391. xmlUnlinkNode(deleteNode);
  3392. xmlFreeNode(deleteNode);
  3393. }
  3394. }
  3395. #endif /* end of else XSLT_REFACTORED */
  3396. /**
  3397. * xsltGatherNamespaces:
  3398. * @style: the XSLT stylesheet
  3399. *
  3400. * Browse the stylesheet and build the namspace hash table which
  3401. * will be used for XPath interpretation. If needed do a bit of normalization
  3402. */
  3403. static void
  3404. xsltGatherNamespaces(xsltStylesheetPtr style) {
  3405. xmlNodePtr cur;
  3406. const xmlChar *URI;
  3407. if (style == NULL)
  3408. return;
  3409. /*
  3410. * TODO: basically if the stylesheet uses the same prefix for different
  3411. * patterns, well they may be in problem, hopefully they will get
  3412. * a warning first.
  3413. */
  3414. /*
  3415. * TODO: Eliminate the use of the hash for XPath expressions.
  3416. * An expression should be evaluated in the context of the in-scope
  3417. * namespaces; eliminate the restriction of an XML document to contain
  3418. * no duplicate prefixes for different namespace names.
  3419. *
  3420. */
  3421. cur = xmlDocGetRootElement(style->doc);
  3422. while (cur != NULL) {
  3423. if (cur->type == XML_ELEMENT_NODE) {
  3424. xmlNsPtr ns = cur->nsDef;
  3425. while (ns != NULL) {
  3426. if (ns->prefix != NULL) {
  3427. if (style->nsHash == NULL) {
  3428. style->nsHash = xmlHashCreate(10);
  3429. if (style->nsHash == NULL) {
  3430. xsltTransformError(NULL, style, cur,
  3431. "xsltGatherNamespaces: failed to create hash table\n");
  3432. style->errors++;
  3433. return;
  3434. }
  3435. }
  3436. URI = xmlHashLookup(style->nsHash, ns->prefix);
  3437. if ((URI != NULL) && (!xmlStrEqual(URI, ns->href))) {
  3438. xsltTransformError(NULL, style, cur,
  3439. "Namespaces prefix %s used for multiple namespaces\n",ns->prefix);
  3440. style->warnings++;
  3441. } else if (URI == NULL) {
  3442. xmlHashUpdateEntry(style->nsHash, ns->prefix,
  3443. (void *) ns->href, NULL);
  3444. #ifdef WITH_XSLT_DEBUG_PARSING
  3445. xsltGenericDebug(xsltGenericDebugContext,
  3446. "Added namespace: %s mapped to %s\n", ns->prefix, ns->href);
  3447. #endif
  3448. }
  3449. }
  3450. ns = ns->next;
  3451. }
  3452. }
  3453. /*
  3454. * Skip to next node
  3455. */
  3456. if (cur->children != NULL) {
  3457. if (cur->children->type != XML_ENTITY_DECL) {
  3458. cur = cur->children;
  3459. continue;
  3460. }
  3461. }
  3462. if (cur->next != NULL) {
  3463. cur = cur->next;
  3464. continue;
  3465. }
  3466. do {
  3467. cur = cur->parent;
  3468. if (cur == NULL)
  3469. break;
  3470. if (cur == (xmlNodePtr) style->doc) {
  3471. cur = NULL;
  3472. break;
  3473. }
  3474. if (cur->next != NULL) {
  3475. cur = cur->next;
  3476. break;
  3477. }
  3478. } while (cur != NULL);
  3479. }
  3480. }
  3481. #ifdef XSLT_REFACTORED
  3482. static xsltStyleType
  3483. xsltGetXSLTElementTypeByNode(xsltCompilerCtxtPtr cctxt,
  3484. xmlNodePtr node)
  3485. {
  3486. if ((node == NULL) || (node->type != XML_ELEMENT_NODE) ||
  3487. (node->name == NULL))
  3488. return(0);
  3489. if (node->name[0] == 'a') {
  3490. if (IS_XSLT_NAME(node, "apply-templates"))
  3491. return(XSLT_FUNC_APPLYTEMPLATES);
  3492. else if (IS_XSLT_NAME(node, "attribute"))
  3493. return(XSLT_FUNC_ATTRIBUTE);
  3494. else if (IS_XSLT_NAME(node, "apply-imports"))
  3495. return(XSLT_FUNC_APPLYIMPORTS);
  3496. else if (IS_XSLT_NAME(node, "attribute-set"))
  3497. return(0);
  3498. } else if (node->name[0] == 'c') {
  3499. if (IS_XSLT_NAME(node, "choose"))
  3500. return(XSLT_FUNC_CHOOSE);
  3501. else if (IS_XSLT_NAME(node, "copy"))
  3502. return(XSLT_FUNC_COPY);
  3503. else if (IS_XSLT_NAME(node, "copy-of"))
  3504. return(XSLT_FUNC_COPYOF);
  3505. else if (IS_XSLT_NAME(node, "call-template"))
  3506. return(XSLT_FUNC_CALLTEMPLATE);
  3507. else if (IS_XSLT_NAME(node, "comment"))
  3508. return(XSLT_FUNC_COMMENT);
  3509. } else if (node->name[0] == 'd') {
  3510. if (IS_XSLT_NAME(node, "document"))
  3511. return(XSLT_FUNC_DOCUMENT);
  3512. else if (IS_XSLT_NAME(node, "decimal-format"))
  3513. return(0);
  3514. } else if (node->name[0] == 'e') {
  3515. if (IS_XSLT_NAME(node, "element"))
  3516. return(XSLT_FUNC_ELEMENT);
  3517. } else if (node->name[0] == 'f') {
  3518. if (IS_XSLT_NAME(node, "for-each"))
  3519. return(XSLT_FUNC_FOREACH);
  3520. else if (IS_XSLT_NAME(node, "fallback"))
  3521. return(XSLT_FUNC_FALLBACK);
  3522. } else if (*(node->name) == 'i') {
  3523. if (IS_XSLT_NAME(node, "if"))
  3524. return(XSLT_FUNC_IF);
  3525. else if (IS_XSLT_NAME(node, "include"))
  3526. return(0);
  3527. else if (IS_XSLT_NAME(node, "import"))
  3528. return(0);
  3529. } else if (*(node->name) == 'k') {
  3530. if (IS_XSLT_NAME(node, "key"))
  3531. return(0);
  3532. } else if (*(node->name) == 'm') {
  3533. if (IS_XSLT_NAME(node, "message"))
  3534. return(XSLT_FUNC_MESSAGE);
  3535. } else if (*(node->name) == 'n') {
  3536. if (IS_XSLT_NAME(node, "number"))
  3537. return(XSLT_FUNC_NUMBER);
  3538. else if (IS_XSLT_NAME(node, "namespace-alias"))
  3539. return(0);
  3540. } else if (*(node->name) == 'o') {
  3541. if (IS_XSLT_NAME(node, "otherwise"))
  3542. return(XSLT_FUNC_OTHERWISE);
  3543. else if (IS_XSLT_NAME(node, "output"))
  3544. return(0);
  3545. } else if (*(node->name) == 'p') {
  3546. if (IS_XSLT_NAME(node, "param"))
  3547. return(XSLT_FUNC_PARAM);
  3548. else if (IS_XSLT_NAME(node, "processing-instruction"))
  3549. return(XSLT_FUNC_PI);
  3550. else if (IS_XSLT_NAME(node, "preserve-space"))
  3551. return(0);
  3552. } else if (*(node->name) == 's') {
  3553. if (IS_XSLT_NAME(node, "sort"))
  3554. return(XSLT_FUNC_SORT);
  3555. else if (IS_XSLT_NAME(node, "strip-space"))
  3556. return(0);
  3557. else if (IS_XSLT_NAME(node, "stylesheet"))
  3558. return(0);
  3559. } else if (node->name[0] == 't') {
  3560. if (IS_XSLT_NAME(node, "text"))
  3561. return(XSLT_FUNC_TEXT);
  3562. else if (IS_XSLT_NAME(node, "template"))
  3563. return(0);
  3564. else if (IS_XSLT_NAME(node, "transform"))
  3565. return(0);
  3566. } else if (*(node->name) == 'v') {
  3567. if (IS_XSLT_NAME(node, "value-of"))
  3568. return(XSLT_FUNC_VALUEOF);
  3569. else if (IS_XSLT_NAME(node, "variable"))
  3570. return(XSLT_FUNC_VARIABLE);
  3571. } else if (*(node->name) == 'w') {
  3572. if (IS_XSLT_NAME(node, "when"))
  3573. return(XSLT_FUNC_WHEN);
  3574. if (IS_XSLT_NAME(node, "with-param"))
  3575. return(XSLT_FUNC_WITHPARAM);
  3576. }
  3577. return(0);
  3578. }
  3579. /**
  3580. * xsltParseAnyXSLTElem:
  3581. *
  3582. * @cctxt: the compilation context
  3583. * @elem: the element node of the XSLT instruction
  3584. *
  3585. * Parses, validates the content models and compiles XSLT instructions.
  3586. *
  3587. * Returns 0 if everything's fine;
  3588. * -1 on API or internal errors.
  3589. */
  3590. int
  3591. xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
  3592. {
  3593. if ((cctxt == NULL) || (elem == NULL) ||
  3594. (elem->type != XML_ELEMENT_NODE))
  3595. return(-1);
  3596. elem->psvi = NULL;
  3597. if (! (IS_XSLT_ELEM_FAST(elem)))
  3598. return(-1);
  3599. /*
  3600. * Detection of handled content of extension instructions.
  3601. */
  3602. if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
  3603. cctxt->inode->extContentHandled = 1;
  3604. }
  3605. xsltCompilerNodePush(cctxt, elem);
  3606. /*
  3607. * URGENT TODO: Find a way to speed up this annoying redundant
  3608. * textual node-name and namespace comparison.
  3609. */
  3610. if (cctxt->inode->prev->curChildType != 0)
  3611. cctxt->inode->type = cctxt->inode->prev->curChildType;
  3612. else
  3613. cctxt->inode->type = xsltGetXSLTElementTypeByNode(cctxt, elem);
  3614. /*
  3615. * Update the in-scope namespaces if needed.
  3616. */
  3617. if (elem->nsDef != NULL)
  3618. cctxt->inode->inScopeNs =
  3619. xsltCompilerBuildInScopeNsList(cctxt, elem);
  3620. /*
  3621. * xsltStylePreCompute():
  3622. * This will compile the information found on the current
  3623. * element's attributes. NOTE that this won't process the
  3624. * children of the instruction.
  3625. */
  3626. xsltStylePreCompute(cctxt->style, elem);
  3627. /*
  3628. * TODO: How to react on errors in xsltStylePreCompute() ?
  3629. */
  3630. /*
  3631. * Validate the content model of the XSLT-element.
  3632. */
  3633. switch (cctxt->inode->type) {
  3634. case XSLT_FUNC_APPLYIMPORTS:
  3635. /* EMPTY */
  3636. goto empty_content;
  3637. case XSLT_FUNC_APPLYTEMPLATES:
  3638. /* <!-- Content: (xsl:sort | xsl:with-param)* --> */
  3639. goto apply_templates;
  3640. case XSLT_FUNC_ATTRIBUTE:
  3641. /* <!-- Content: template --> */
  3642. goto sequence_constructor;
  3643. case XSLT_FUNC_CALLTEMPLATE:
  3644. /* <!-- Content: xsl:with-param* --> */
  3645. goto call_template;
  3646. case XSLT_FUNC_CHOOSE:
  3647. /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */
  3648. goto choose;
  3649. case XSLT_FUNC_COMMENT:
  3650. /* <!-- Content: template --> */
  3651. goto sequence_constructor;
  3652. case XSLT_FUNC_COPY:
  3653. /* <!-- Content: template --> */
  3654. goto sequence_constructor;
  3655. case XSLT_FUNC_COPYOF:
  3656. /* EMPTY */
  3657. goto empty_content;
  3658. case XSLT_FUNC_DOCUMENT: /* Extra one */
  3659. /* ?? template ?? */
  3660. goto sequence_constructor;
  3661. case XSLT_FUNC_ELEMENT:
  3662. /* <!-- Content: template --> */
  3663. goto sequence_constructor;
  3664. case XSLT_FUNC_FALLBACK:
  3665. /* <!-- Content: template --> */
  3666. goto sequence_constructor;
  3667. case XSLT_FUNC_FOREACH:
  3668. /* <!-- Content: (xsl:sort*, template) --> */
  3669. goto for_each;
  3670. case XSLT_FUNC_IF:
  3671. /* <!-- Content: template --> */
  3672. goto sequence_constructor;
  3673. case XSLT_FUNC_OTHERWISE:
  3674. /* <!-- Content: template --> */
  3675. goto sequence_constructor;
  3676. case XSLT_FUNC_MESSAGE:
  3677. /* <!-- Content: template --> */
  3678. goto sequence_constructor;
  3679. case XSLT_FUNC_NUMBER:
  3680. /* EMPTY */
  3681. goto empty_content;
  3682. case XSLT_FUNC_PARAM:
  3683. /*
  3684. * Check for redefinition.
  3685. */
  3686. if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
  3687. xsltVarInfoPtr ivar = cctxt->ivar;
  3688. do {
  3689. if ((ivar->name ==
  3690. ((xsltStyleItemParamPtr) elem->psvi)->name) &&
  3691. (ivar->nsName ==
  3692. ((xsltStyleItemParamPtr) elem->psvi)->ns))
  3693. {
  3694. elem->psvi = NULL;
  3695. xsltTransformError(NULL, cctxt->style, elem,
  3696. "Redefinition of variable or parameter '%s'.\n",
  3697. ivar->name);
  3698. cctxt->style->errors++;
  3699. goto error;
  3700. }
  3701. ivar = ivar->prev;
  3702. } while (ivar != NULL);
  3703. }
  3704. /* <!-- Content: template --> */
  3705. goto sequence_constructor;
  3706. case XSLT_FUNC_PI:
  3707. /* <!-- Content: template --> */
  3708. goto sequence_constructor;
  3709. case XSLT_FUNC_SORT:
  3710. /* EMPTY */
  3711. goto empty_content;
  3712. case XSLT_FUNC_TEXT:
  3713. /* <!-- Content: #PCDATA --> */
  3714. goto text;
  3715. case XSLT_FUNC_VALUEOF:
  3716. /* EMPTY */
  3717. goto empty_content;
  3718. case XSLT_FUNC_VARIABLE:
  3719. /*
  3720. * Check for redefinition.
  3721. */
  3722. if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
  3723. xsltVarInfoPtr ivar = cctxt->ivar;
  3724. do {
  3725. if ((ivar->name ==
  3726. ((xsltStyleItemVariablePtr) elem->psvi)->name) &&
  3727. (ivar->nsName ==
  3728. ((xsltStyleItemVariablePtr) elem->psvi)->ns))
  3729. {
  3730. elem->psvi = NULL;
  3731. xsltTransformError(NULL, cctxt->style, elem,
  3732. "Redefinition of variable or parameter '%s'.\n",
  3733. ivar->name);
  3734. cctxt->style->errors++;
  3735. goto error;
  3736. }
  3737. ivar = ivar->prev;
  3738. } while (ivar != NULL);
  3739. }
  3740. /* <!-- Content: template --> */
  3741. goto sequence_constructor;
  3742. case XSLT_FUNC_WHEN:
  3743. /* <!-- Content: template --> */
  3744. goto sequence_constructor;
  3745. case XSLT_FUNC_WITHPARAM:
  3746. /* <!-- Content: template --> */
  3747. goto sequence_constructor;
  3748. default:
  3749. #ifdef WITH_XSLT_DEBUG_PARSING
  3750. xsltGenericDebug(xsltGenericDebugContext,
  3751. "xsltParseXSLTNode: Unhandled XSLT element '%s'.\n",
  3752. elem->name);
  3753. #endif
  3754. xsltTransformError(NULL, cctxt->style, elem,
  3755. "xsltParseXSLTNode: Internal error; "
  3756. "unhandled XSLT element '%s'.\n", elem->name);
  3757. cctxt->style->errors++;
  3758. goto internal_err;
  3759. }
  3760. apply_templates:
  3761. /* <!-- Content: (xsl:sort | xsl:with-param)* --> */
  3762. if (elem->children != NULL) {
  3763. xmlNodePtr child = elem->children;
  3764. do {
  3765. if (child->type == XML_ELEMENT_NODE) {
  3766. if (IS_XSLT_ELEM_FAST(child)) {
  3767. if (xmlStrEqual(child->name, BAD_CAST "with-param")) {
  3768. cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
  3769. xsltParseAnyXSLTElem(cctxt, child);
  3770. } else if (xmlStrEqual(child->name, BAD_CAST "sort")) {
  3771. cctxt->inode->curChildType = XSLT_FUNC_SORT;
  3772. xsltParseAnyXSLTElem(cctxt, child);
  3773. } else
  3774. xsltParseContentError(cctxt->style, child);
  3775. } else
  3776. xsltParseContentError(cctxt->style, child);
  3777. }
  3778. child = child->next;
  3779. } while (child != NULL);
  3780. }
  3781. goto exit;
  3782. call_template:
  3783. /* <!-- Content: xsl:with-param* --> */
  3784. if (elem->children != NULL) {
  3785. xmlNodePtr child = elem->children;
  3786. do {
  3787. if (child->type == XML_ELEMENT_NODE) {
  3788. if (IS_XSLT_ELEM_FAST(child)) {
  3789. xsltStyleType type;
  3790. type = xsltGetXSLTElementTypeByNode(cctxt, child);
  3791. if (type == XSLT_FUNC_WITHPARAM) {
  3792. cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
  3793. xsltParseAnyXSLTElem(cctxt, child);
  3794. } else {
  3795. xsltParseContentError(cctxt->style, child);
  3796. }
  3797. } else
  3798. xsltParseContentError(cctxt->style, child);
  3799. }
  3800. child = child->next;
  3801. } while (child != NULL);
  3802. }
  3803. goto exit;
  3804. text:
  3805. if (elem->children != NULL) {
  3806. xmlNodePtr child = elem->children;
  3807. do {
  3808. if ((child->type != XML_TEXT_NODE) &&
  3809. (child->type != XML_CDATA_SECTION_NODE))
  3810. {
  3811. xsltTransformError(NULL, cctxt->style, elem,
  3812. "The XSLT 'text' element must have only character "
  3813. "data as content.\n");
  3814. }
  3815. child = child->next;
  3816. } while (child != NULL);
  3817. }
  3818. goto exit;
  3819. empty_content:
  3820. if (elem->children != NULL) {
  3821. xmlNodePtr child = elem->children;
  3822. /*
  3823. * Relaxed behaviour: we will allow whitespace-only text-nodes.
  3824. */
  3825. do {
  3826. if (((child->type != XML_TEXT_NODE) &&
  3827. (child->type != XML_CDATA_SECTION_NODE)) ||
  3828. (! IS_BLANK_NODE(child)))
  3829. {
  3830. xsltTransformError(NULL, cctxt->style, elem,
  3831. "This XSLT element must have no content.\n");
  3832. cctxt->style->errors++;
  3833. break;
  3834. }
  3835. child = child->next;
  3836. } while (child != NULL);
  3837. }
  3838. goto exit;
  3839. choose:
  3840. /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */
  3841. /*
  3842. * TODO: text-nodes in between are *not* allowed in XSLT 1.0.
  3843. * The old behaviour did not check this.
  3844. * NOTE: In XSLT 2.0 they are stripped beforehand
  3845. * if whitespace-only (regardless of xml:space).
  3846. */
  3847. if (elem->children != NULL) {
  3848. xmlNodePtr child = elem->children;
  3849. int nbWhen = 0, nbOtherwise = 0, err = 0;
  3850. do {
  3851. if (child->type == XML_ELEMENT_NODE) {
  3852. if (IS_XSLT_ELEM_FAST(child)) {
  3853. xsltStyleType type;
  3854. type = xsltGetXSLTElementTypeByNode(cctxt, child);
  3855. if (type == XSLT_FUNC_WHEN) {
  3856. nbWhen++;
  3857. if (nbOtherwise) {
  3858. xsltParseContentError(cctxt->style, child);
  3859. err = 1;
  3860. break;
  3861. }
  3862. cctxt->inode->curChildType = XSLT_FUNC_WHEN;
  3863. xsltParseAnyXSLTElem(cctxt, child);
  3864. } else if (type == XSLT_FUNC_OTHERWISE) {
  3865. if (! nbWhen) {
  3866. xsltParseContentError(cctxt->style, child);
  3867. err = 1;
  3868. break;
  3869. }
  3870. if (nbOtherwise) {
  3871. xsltTransformError(NULL, cctxt->style, elem,
  3872. "The XSLT 'choose' element must not contain "
  3873. "more than one XSLT 'otherwise' element.\n");
  3874. cctxt->style->errors++;
  3875. err = 1;
  3876. break;
  3877. }
  3878. nbOtherwise++;
  3879. cctxt->inode->curChildType = XSLT_FUNC_OTHERWISE;
  3880. xsltParseAnyXSLTElem(cctxt, child);
  3881. } else
  3882. xsltParseContentError(cctxt->style, child);
  3883. } else
  3884. xsltParseContentError(cctxt->style, child);
  3885. }
  3886. /*
  3887. else
  3888. xsltParseContentError(cctxt, child);
  3889. */
  3890. child = child->next;
  3891. } while (child != NULL);
  3892. if ((! err) && (! nbWhen)) {
  3893. xsltTransformError(NULL, cctxt->style, elem,
  3894. "The XSLT element 'choose' must contain at least one "
  3895. "XSLT element 'when'.\n");
  3896. cctxt->style->errors++;
  3897. }
  3898. }
  3899. goto exit;
  3900. for_each:
  3901. /* <!-- Content: (xsl:sort*, template) --> */
  3902. /*
  3903. * NOTE: Text-nodes before xsl:sort are *not* allowed in XSLT 1.0.
  3904. * The old behaviour did not allow this, but it catched this
  3905. * only at transformation-time.
  3906. * In XSLT 2.0 they are stripped beforehand if whitespace-only
  3907. * (regardless of xml:space).
  3908. */
  3909. if (elem->children != NULL) {
  3910. xmlNodePtr child = elem->children;
  3911. /*
  3912. * Parse xsl:sort first.
  3913. */
  3914. do {
  3915. if ((child->type == XML_ELEMENT_NODE) &&
  3916. IS_XSLT_ELEM_FAST(child))
  3917. {
  3918. if (xsltGetXSLTElementTypeByNode(cctxt, child) ==
  3919. XSLT_FUNC_SORT)
  3920. {
  3921. cctxt->inode->curChildType = XSLT_FUNC_SORT;
  3922. xsltParseAnyXSLTElem(cctxt, child);
  3923. } else
  3924. break;
  3925. } else
  3926. break;
  3927. child = child->next;
  3928. } while (child != NULL);
  3929. /*
  3930. * Parse the sequece constructor.
  3931. */
  3932. if (child != NULL)
  3933. xsltParseSequenceConstructor(cctxt, child);
  3934. }
  3935. goto exit;
  3936. sequence_constructor:
  3937. /*
  3938. * Parse the sequence constructor.
  3939. */
  3940. if (elem->children != NULL)
  3941. xsltParseSequenceConstructor(cctxt, elem->children);
  3942. /*
  3943. * Register information for vars/params. Only needed if there
  3944. * are any following siblings.
  3945. */
  3946. if ((elem->next != NULL) &&
  3947. ((cctxt->inode->type == XSLT_FUNC_VARIABLE) ||
  3948. (cctxt->inode->type == XSLT_FUNC_PARAM)))
  3949. {
  3950. if ((elem->psvi != NULL) &&
  3951. (((xsltStyleBasicItemVariablePtr) elem->psvi)->name))
  3952. {
  3953. xsltCompilerVarInfoPush(cctxt, elem,
  3954. ((xsltStyleBasicItemVariablePtr) elem->psvi)->name,
  3955. ((xsltStyleBasicItemVariablePtr) elem->psvi)->ns);
  3956. }
  3957. }
  3958. error:
  3959. exit:
  3960. xsltCompilerNodePop(cctxt, elem);
  3961. return(0);
  3962. internal_err:
  3963. xsltCompilerNodePop(cctxt, elem);
  3964. return(-1);
  3965. }
  3966. /**
  3967. * xsltForwardsCompatUnkownItemCreate:
  3968. *
  3969. * @cctxt: the compilation context
  3970. *
  3971. * Creates a compiled representation of the unknown
  3972. * XSLT instruction.
  3973. *
  3974. * Returns the compiled representation.
  3975. */
  3976. static xsltStyleItemUknownPtr
  3977. xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)
  3978. {
  3979. xsltStyleItemUknownPtr item;
  3980. item = (xsltStyleItemUknownPtr) xmlMalloc(sizeof(xsltStyleItemUknown));
  3981. if (item == NULL) {
  3982. xsltTransformError(NULL, cctxt->style, NULL,
  3983. "Internal error in xsltForwardsCompatUnkownItemCreate(): "
  3984. "Failed to allocate memory.\n");
  3985. cctxt->style->errors++;
  3986. return(NULL);
  3987. }
  3988. memset(item, 0, sizeof(xsltStyleItemUknown));
  3989. item->type = XSLT_FUNC_UNKOWN_FORWARDS_COMPAT;
  3990. /*
  3991. * Store it in the stylesheet.
  3992. */
  3993. item->next = cctxt->style->preComps;
  3994. cctxt->style->preComps = (xsltElemPreCompPtr) item;
  3995. return(item);
  3996. }
  3997. /**
  3998. * xsltParseUnknownXSLTElem:
  3999. *
  4000. * @cctxt: the compilation context
  4001. * @node: the element of the unknown XSLT instruction
  4002. *
  4003. * Parses an unknown XSLT element.
  4004. * If forwards compatible mode is enabled this will allow
  4005. * such an unknown XSLT and; otherwise it is rejected.
  4006. *
  4007. * Returns 1 in the unknown XSLT instruction is rejected,
  4008. * 0 if everything's fine and
  4009. * -1 on API or internal errors.
  4010. */
  4011. static int
  4012. xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,
  4013. xmlNodePtr node)
  4014. {
  4015. if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
  4016. return(-1);
  4017. /*
  4018. * Detection of handled content of extension instructions.
  4019. */
  4020. if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
  4021. cctxt->inode->extContentHandled = 1;
  4022. }
  4023. if (cctxt->inode->forwardsCompat == 0) {
  4024. /*
  4025. * We are not in forwards-compatible mode, so raise an error.
  4026. */
  4027. xsltTransformError(NULL, cctxt->style, node,
  4028. "Unknown XSLT element '%s'.\n", node->name);
  4029. cctxt->style->errors++;
  4030. return(1);
  4031. }
  4032. /*
  4033. * Forwards-compatible mode.
  4034. * ------------------------
  4035. *
  4036. * Parse/compile xsl:fallback elements.
  4037. *
  4038. * QUESTION: Do we have to raise an error if there's no xsl:fallback?
  4039. * ANSWER: No, since in the stylesheet the fallback behaviour might
  4040. * also be provided by using the XSLT function "element-available".
  4041. */
  4042. if (cctxt->unknownItem == NULL) {
  4043. /*
  4044. * Create a singleton for all unknown XSLT instructions.
  4045. */
  4046. cctxt->unknownItem = xsltForwardsCompatUnkownItemCreate(cctxt);
  4047. if (cctxt->unknownItem == NULL) {
  4048. node->psvi = NULL;
  4049. return(-1);
  4050. }
  4051. }
  4052. node->psvi = cctxt->unknownItem;
  4053. if (node->children == NULL)
  4054. return(0);
  4055. else {
  4056. xmlNodePtr child = node->children;
  4057. xsltCompilerNodePush(cctxt, node);
  4058. /*
  4059. * Update the in-scope namespaces if needed.
  4060. */
  4061. if (node->nsDef != NULL)
  4062. cctxt->inode->inScopeNs =
  4063. xsltCompilerBuildInScopeNsList(cctxt, node);
  4064. /*
  4065. * Parse all xsl:fallback children.
  4066. */
  4067. do {
  4068. if ((child->type == XML_ELEMENT_NODE) &&
  4069. IS_XSLT_ELEM_FAST(child) &&
  4070. IS_XSLT_NAME(child, "fallback"))
  4071. {
  4072. cctxt->inode->curChildType = XSLT_FUNC_FALLBACK;
  4073. xsltParseAnyXSLTElem(cctxt, child);
  4074. }
  4075. child = child->next;
  4076. } while (child != NULL);
  4077. xsltCompilerNodePop(cctxt, node);
  4078. }
  4079. return(0);
  4080. }
  4081. /**
  4082. * xsltParseSequenceConstructor:
  4083. *
  4084. * @cctxt: the compilation context
  4085. * @cur: the start-node of the content to be parsed
  4086. *
  4087. * Parses a "template" content (or "sequence constructor" in XSLT 2.0 terms).
  4088. * This will additionally remove xsl:text elements from the tree.
  4089. */
  4090. void
  4091. xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
  4092. {
  4093. xsltStyleType type;
  4094. xmlNodePtr deleteNode = NULL;
  4095. if (cctxt == NULL) {
  4096. xmlGenericError(xmlGenericErrorContext,
  4097. "xsltParseSequenceConstructor: Bad arguments\n");
  4098. cctxt->style->errors++;
  4099. return;
  4100. }
  4101. /*
  4102. * Detection of handled content of extension instructions.
  4103. */
  4104. if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
  4105. cctxt->inode->extContentHandled = 1;
  4106. }
  4107. if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
  4108. return;
  4109. /*
  4110. * This is the content reffered to as a "template".
  4111. * E.g. an xsl:element has such content model:
  4112. * <xsl:element
  4113. * name = { qname }
  4114. * namespace = { uri-reference }
  4115. * use-attribute-sets = qnames>
  4116. * <!-- Content: template -->
  4117. *
  4118. * NOTE that in XSLT-2 the term "template" was abandoned due to
  4119. * confusion with xsl:template and the term "sequence constructor"
  4120. * was introduced instead.
  4121. *
  4122. * The following XSLT-instructions are allowed to appear:
  4123. * xsl:apply-templates, xsl:call-template, xsl:apply-imports,
  4124. * xsl:for-each, xsl:value-of, xsl:copy-of, xsl:number,
  4125. * xsl:choose, xsl:if, xsl:text, xsl:copy, xsl:variable,
  4126. * xsl:message, xsl:fallback,
  4127. * xsl:processing-instruction, xsl:comment, xsl:element
  4128. * xsl:attribute.
  4129. * Additional allowed content:
  4130. * 1) extension instructions
  4131. * 2) literal result elements
  4132. * 3) PCDATA
  4133. *
  4134. * NOTE that this content model does *not* allow xsl:param.
  4135. */
  4136. while (cur != NULL) {
  4137. if (deleteNode != NULL) {
  4138. #ifdef WITH_XSLT_DEBUG_BLANKS
  4139. xsltGenericDebug(xsltGenericDebugContext,
  4140. "xsltParseSequenceConstructor: removing xsl:text element\n");
  4141. #endif
  4142. xmlUnlinkNode(deleteNode);
  4143. xmlFreeNode(deleteNode);
  4144. deleteNode = NULL;
  4145. }
  4146. if (cur->type == XML_ELEMENT_NODE) {
  4147. if (cur->psvi == xsltXSLTTextMarker) {
  4148. /*
  4149. * xsl:text elements
  4150. * --------------------------------------------------------
  4151. */
  4152. xmlNodePtr tmp;
  4153. cur->psvi = NULL;
  4154. /*
  4155. * Mark the xsl:text element for later deletion.
  4156. */
  4157. deleteNode = cur;
  4158. /*
  4159. * Validate content.
  4160. */
  4161. tmp = cur->children;
  4162. if (tmp) {
  4163. /*
  4164. * We don't expect more than one text-node in the
  4165. * content, since we already merged adjacent
  4166. * text/CDATA-nodes and eliminated PI/comment-nodes.
  4167. */
  4168. if ((tmp->type == XML_TEXT_NODE) ||
  4169. (tmp->next == NULL))
  4170. {
  4171. /*
  4172. * Leave the contained text-node in the tree.
  4173. */
  4174. xmlUnlinkNode(tmp);
  4175. xmlAddPrevSibling(cur, tmp);
  4176. } else {
  4177. tmp = NULL;
  4178. xsltTransformError(NULL, cctxt->style, cur,
  4179. "Element 'xsl:text': Invalid type "
  4180. "of node found in content.\n");
  4181. cctxt->style->errors++;
  4182. }
  4183. }
  4184. if (cur->properties) {
  4185. xmlAttrPtr attr;
  4186. /*
  4187. * TODO: We need to report errors for
  4188. * invalid attrs.
  4189. */
  4190. attr = cur->properties;
  4191. do {
  4192. if ((attr->ns == NULL) &&
  4193. (attr->name != NULL) &&
  4194. (attr->name[0] == 'd') &&
  4195. xmlStrEqual(attr->name,
  4196. BAD_CAST "disable-output-escaping"))
  4197. {
  4198. /*
  4199. * Attr "disable-output-escaping".
  4200. * XSLT-2: This attribute is deprecated.
  4201. */
  4202. if ((attr->children != NULL) &&
  4203. xmlStrEqual(attr->children->content,
  4204. BAD_CAST "yes"))
  4205. {
  4206. /*
  4207. * Disable output escaping for this
  4208. * text node.
  4209. */
  4210. if (tmp)
  4211. tmp->name = xmlStringTextNoenc;
  4212. } else if ((attr->children == NULL) ||
  4213. (attr->children->content == NULL) ||
  4214. (!xmlStrEqual(attr->children->content,
  4215. BAD_CAST "no")))
  4216. {
  4217. xsltTransformError(NULL, cctxt->style,
  4218. cur,
  4219. "Attribute 'disable-output-escaping': "
  4220. "Invalid value. Expected is "
  4221. "'yes' or 'no'.\n");
  4222. cctxt->style->errors++;
  4223. }
  4224. break;
  4225. }
  4226. attr = attr->next;
  4227. } while (attr != NULL);
  4228. }
  4229. } else if (IS_XSLT_ELEM_FAST(cur)) {
  4230. /*
  4231. * TODO: Using the XSLT-marker is still not stable yet.
  4232. */
  4233. /* if (cur->psvi == xsltXSLTElemMarker) { */
  4234. /*
  4235. * XSLT instructions
  4236. * --------------------------------------------------------
  4237. */
  4238. cur->psvi = NULL;
  4239. type = xsltGetXSLTElementTypeByNode(cctxt, cur);
  4240. switch (type) {
  4241. case XSLT_FUNC_APPLYIMPORTS:
  4242. case XSLT_FUNC_APPLYTEMPLATES:
  4243. case XSLT_FUNC_ATTRIBUTE:
  4244. case XSLT_FUNC_CALLTEMPLATE:
  4245. case XSLT_FUNC_CHOOSE:
  4246. case XSLT_FUNC_COMMENT:
  4247. case XSLT_FUNC_COPY:
  4248. case XSLT_FUNC_COPYOF:
  4249. case XSLT_FUNC_DOCUMENT: /* Extra one */
  4250. case XSLT_FUNC_ELEMENT:
  4251. case XSLT_FUNC_FALLBACK:
  4252. case XSLT_FUNC_FOREACH:
  4253. case XSLT_FUNC_IF:
  4254. case XSLT_FUNC_MESSAGE:
  4255. case XSLT_FUNC_NUMBER:
  4256. case XSLT_FUNC_PI:
  4257. case XSLT_FUNC_TEXT:
  4258. case XSLT_FUNC_VALUEOF:
  4259. case XSLT_FUNC_VARIABLE:
  4260. /*
  4261. * Parse the XSLT element.
  4262. */
  4263. cctxt->inode->curChildType = type;
  4264. xsltParseAnyXSLTElem(cctxt, cur);
  4265. break;
  4266. default:
  4267. xsltParseUnknownXSLTElem(cctxt, cur);
  4268. cur = cur->next;
  4269. continue;
  4270. }
  4271. } else {
  4272. /*
  4273. * Non-XSLT elements
  4274. * -----------------
  4275. */
  4276. xsltCompilerNodePush(cctxt, cur);
  4277. /*
  4278. * Update the in-scope namespaces if needed.
  4279. */
  4280. if (cur->nsDef != NULL)
  4281. cctxt->inode->inScopeNs =
  4282. xsltCompilerBuildInScopeNsList(cctxt, cur);
  4283. /*
  4284. * The current element is either a literal result element
  4285. * or an extension instruction.
  4286. *
  4287. * Process attr "xsl:extension-element-prefixes".
  4288. * FUTURE TODO: IIRC in XSLT 2.0 this attribute must be
  4289. * processed by the implementor of the extension function;
  4290. * i.e., it won't be handled by the XSLT processor.
  4291. */
  4292. /* SPEC 1.0:
  4293. * "exclude-result-prefixes" is only allowed on literal
  4294. * result elements and "xsl:exclude-result-prefixes"
  4295. * on xsl:stylesheet/xsl:transform.
  4296. * SPEC 2.0:
  4297. * "There are a number of standard attributes
  4298. * that may appear on any XSLT element: specifically
  4299. * version, exclude-result-prefixes,
  4300. * extension-element-prefixes, xpath-default-namespace,
  4301. * default-collation, and use-when."
  4302. *
  4303. * SPEC 2.0:
  4304. * For literal result elements:
  4305. * "xsl:version, xsl:exclude-result-prefixes,
  4306. * xsl:extension-element-prefixes,
  4307. * xsl:xpath-default-namespace,
  4308. * xsl:default-collation, or xsl:use-when."
  4309. */
  4310. if (cur->properties)
  4311. cctxt->inode->extElemNs =
  4312. xsltParseExtElemPrefixes(cctxt,
  4313. cur, cctxt->inode->extElemNs,
  4314. XSLT_ELEMENT_CATEGORY_LRE);
  4315. /*
  4316. * Eval if we have an extension instruction here.
  4317. */
  4318. if ((cur->ns != NULL) &&
  4319. (cctxt->inode->extElemNs != NULL) &&
  4320. (xsltCheckExtPrefix(cctxt->style, cur->ns->href) == 1))
  4321. {
  4322. /*
  4323. * Extension instructions
  4324. * ----------------------------------------------------
  4325. * Mark the node information.
  4326. */
  4327. cctxt->inode->category = XSLT_ELEMENT_CATEGORY_EXTENSION;
  4328. cctxt->inode->extContentHandled = 0;
  4329. if (cur->psvi != NULL) {
  4330. cur->psvi = NULL;
  4331. /*
  4332. * TODO: Temporary sanity check.
  4333. */
  4334. xsltTransformError(NULL, cctxt->style, cur,
  4335. "Internal error in xsltParseSequenceConstructor(): "
  4336. "Occupied PSVI field.\n");
  4337. cctxt->style->errors++;
  4338. cur = cur->next;
  4339. continue;
  4340. }
  4341. cur->psvi = (void *)
  4342. xsltPreComputeExtModuleElement(cctxt->style, cur);
  4343. if (cur->psvi == NULL) {
  4344. /*
  4345. * OLD COMMENT: "Unknown element, maybe registered
  4346. * at the context level. Mark it for later
  4347. * recognition."
  4348. * QUESTION: What does the xsltExtMarker mean?
  4349. * ANSWER: It is used in
  4350. * xsltApplySequenceConstructor() at
  4351. * transformation-time to look out for extension
  4352. * registered in the transformation context.
  4353. */
  4354. cur->psvi = (void *) xsltExtMarker;
  4355. }
  4356. /*
  4357. * BIG NOTE: Now the ugly part. In previous versions
  4358. * of Libxslt (until 1.1.16), all the content of an
  4359. * extension instruction was processed and compiled without
  4360. * the need of the extension-author to explicitely call
  4361. * such a processing;.We now need to mimic this old
  4362. * behaviour in order to avoid breaking old code
  4363. * on the extension-author's side.
  4364. * The mechanism:
  4365. * 1) If the author does *not* set the
  4366. * compile-time-flag @extContentHandled, then we'll
  4367. * parse the content assuming that it's a "template"
  4368. * (or "sequence constructor in XSLT 2.0 terms).
  4369. * NOTE: If the extension is registered at
  4370. * transformation-time only, then there's no way of
  4371. * knowing that content shall be valid, and we'll
  4372. * process the content the same way.
  4373. * 2) If the author *does* set the flag, then we'll assume
  4374. * that the author has handled the parsing him/herself
  4375. * (e.g. called xsltParseSequenceConstructor(), etc.
  4376. * explicitely in his/her code).
  4377. */
  4378. if ((cur->children != NULL) &&
  4379. (cctxt->inode->extContentHandled == 0))
  4380. {
  4381. /*
  4382. * Default parsing of the content using the
  4383. * sequence-constructor model.
  4384. */
  4385. xsltParseSequenceConstructor(cctxt, cur->children);
  4386. }
  4387. } else {
  4388. /*
  4389. * Literal result element
  4390. * ----------------------------------------------------
  4391. * Allowed XSLT attributes:
  4392. * xsl:extension-element-prefixes CDATA #IMPLIED
  4393. * xsl:exclude-result-prefixes CDATA #IMPLIED
  4394. * TODO: xsl:use-attribute-sets %qnames; #IMPLIED
  4395. * xsl:version NMTOKEN #IMPLIED
  4396. */
  4397. cur->psvi = NULL;
  4398. cctxt->inode->category = XSLT_ELEMENT_CATEGORY_LRE;
  4399. if (cur->properties != NULL) {
  4400. xmlAttrPtr attr = cur->properties;
  4401. /*
  4402. * Attribute "xsl:exclude-result-prefixes".
  4403. */
  4404. cctxt->inode->exclResultNs =
  4405. xsltParseExclResultPrefixes(cctxt, cur,
  4406. cctxt->inode->exclResultNs,
  4407. XSLT_ELEMENT_CATEGORY_LRE);
  4408. /*
  4409. * Attribute "xsl:version".
  4410. */
  4411. xsltParseAttrXSLTVersion(cctxt, cur,
  4412. XSLT_ELEMENT_CATEGORY_LRE);
  4413. /*
  4414. * Report invalid XSLT attributes.
  4415. * For XSLT 1.0 only xsl:use-attribute-sets is allowed
  4416. * next to xsl:version, xsl:exclude-result-prefixes and
  4417. * xsl:extension-element-prefixes.
  4418. *
  4419. * Mark all XSLT attributes, in order to skip such
  4420. * attributes when instantiating the LRE.
  4421. */
  4422. do {
  4423. if ((attr->psvi != xsltXSLTAttrMarker) &&
  4424. IS_XSLT_ATTR_FAST(attr))
  4425. {
  4426. if (! xmlStrEqual(attr->name,
  4427. BAD_CAST "use-attribute-sets"))
  4428. {
  4429. xsltTransformError(NULL, cctxt->style,
  4430. cur,
  4431. "Unknown XSLT attribute '%s'.\n",
  4432. attr->name);
  4433. cctxt->style->errors++;
  4434. } else {
  4435. /*
  4436. * XSLT attr marker.
  4437. */
  4438. attr->psvi = (void *) xsltXSLTAttrMarker;
  4439. }
  4440. }
  4441. attr = attr->next;
  4442. } while (attr != NULL);
  4443. }
  4444. /*
  4445. * Create/reuse info for the literal result element.
  4446. */
  4447. if (cctxt->inode->nsChanged)
  4448. xsltLREInfoCreate(cctxt, cur, 1);
  4449. cur->psvi = cctxt->inode->litResElemInfo;
  4450. /*
  4451. * Apply ns-aliasing on the element and on its attributes.
  4452. */
  4453. if (cctxt->hasNsAliases)
  4454. xsltLREBuildEffectiveNs(cctxt, cur);
  4455. /*
  4456. * Compile attribute value templates (AVT).
  4457. */
  4458. if (cur->properties) {
  4459. xmlAttrPtr attr = cur->properties;
  4460. while (attr != NULL) {
  4461. xsltCompileAttr(cctxt->style, attr);
  4462. attr = attr->next;
  4463. }
  4464. }
  4465. /*
  4466. * Parse the content, which is defined to be a "template"
  4467. * (or "sequence constructor" in XSLT 2.0 terms).
  4468. */
  4469. if (cur->children != NULL) {
  4470. xsltParseSequenceConstructor(cctxt, cur->children);
  4471. }
  4472. }
  4473. /*
  4474. * Leave the non-XSLT element.
  4475. */
  4476. xsltCompilerNodePop(cctxt, cur);
  4477. }
  4478. }
  4479. cur = cur->next;
  4480. }
  4481. if (deleteNode != NULL) {
  4482. #ifdef WITH_XSLT_DEBUG_BLANKS
  4483. xsltGenericDebug(xsltGenericDebugContext,
  4484. "xsltParseSequenceConstructor: removing xsl:text element\n");
  4485. #endif
  4486. xmlUnlinkNode(deleteNode);
  4487. xmlFreeNode(deleteNode);
  4488. deleteNode = NULL;
  4489. }
  4490. }
  4491. /**
  4492. * xsltParseTemplateContent:
  4493. * @style: the XSLT stylesheet
  4494. * @templ: the node containing the content to be parsed
  4495. *
  4496. * Parses and compiles the content-model of an xsl:template element.
  4497. * Note that this is *not* the "template" content model (or "sequence
  4498. * constructor" in XSLT 2.0); it it allows addional xsl:param
  4499. * elements as immediate children of @templ.
  4500. *
  4501. * Called by:
  4502. * exsltFuncFunctionComp() (EXSLT, functions.c)
  4503. * So this is intended to be called from extension functions.
  4504. */
  4505. void
  4506. xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
  4507. if ((style == NULL) || (templ == NULL) ||
  4508. (templ->type == XML_NAMESPACE_DECL))
  4509. return;
  4510. /*
  4511. * Detection of handled content of extension instructions.
  4512. */
  4513. if (XSLT_CCTXT(style)->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
  4514. XSLT_CCTXT(style)->inode->extContentHandled = 1;
  4515. }
  4516. if (templ->children != NULL) {
  4517. xmlNodePtr child = templ->children;
  4518. /*
  4519. * Process xsl:param elements, which can only occur as the
  4520. * immediate children of xsl:template (well, and of any
  4521. * user-defined extension instruction if needed).
  4522. */
  4523. do {
  4524. if ((child->type == XML_ELEMENT_NODE) &&
  4525. IS_XSLT_ELEM_FAST(child) &&
  4526. IS_XSLT_NAME(child, "param"))
  4527. {
  4528. XSLT_CCTXT(style)->inode->curChildType = XSLT_FUNC_PARAM;
  4529. xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
  4530. } else
  4531. break;
  4532. child = child->next;
  4533. } while (child != NULL);
  4534. /*
  4535. * Parse the content and register the pattern.
  4536. */
  4537. xsltParseSequenceConstructor(XSLT_CCTXT(style), child);
  4538. }
  4539. }
  4540. #else /* XSLT_REFACTORED */
  4541. /**
  4542. * xsltParseTemplateContent:
  4543. * @style: the XSLT stylesheet
  4544. * @templ: the container node (can be a document for literal results)
  4545. *
  4546. * parse a template content-model
  4547. * Clean-up the template content from unwanted ignorable blank nodes
  4548. * and process xslt:text
  4549. */
  4550. void
  4551. xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
  4552. xmlNodePtr cur, delete;
  4553. if ((style == NULL) || (templ == NULL) ||
  4554. (templ->type == XML_NAMESPACE_DECL)) return;
  4555. /*
  4556. * This content comes from the stylesheet
  4557. * For stylesheets, the set of whitespace-preserving
  4558. * element names consists of just xsl:text.
  4559. */
  4560. cur = templ->children;
  4561. delete = NULL;
  4562. while (cur != NULL) {
  4563. if (delete != NULL) {
  4564. #ifdef WITH_XSLT_DEBUG_BLANKS
  4565. xsltGenericDebug(xsltGenericDebugContext,
  4566. "xsltParseTemplateContent: removing text\n");
  4567. #endif
  4568. xmlUnlinkNode(delete);
  4569. xmlFreeNode(delete);
  4570. delete = NULL;
  4571. }
  4572. if (IS_XSLT_ELEM(cur)) {
  4573. xsltStylePreCompute(style, cur);
  4574. if (IS_XSLT_NAME(cur, "text")) {
  4575. /*
  4576. * TODO: Processing of xsl:text should be moved to
  4577. * xsltPreprocessStylesheet(), since otherwise this
  4578. * will be performed for every multiply included
  4579. * stylesheet; i.e. this here is not skipped with
  4580. * the use of the style->nopreproc flag.
  4581. */
  4582. if (cur->children != NULL) {
  4583. xmlChar *prop;
  4584. xmlNodePtr text = cur->children, next;
  4585. int noesc = 0;
  4586. prop = xmlGetNsProp(cur,
  4587. (const xmlChar *)"disable-output-escaping",
  4588. NULL);
  4589. if (prop != NULL) {
  4590. #ifdef WITH_XSLT_DEBUG_PARSING
  4591. xsltGenericDebug(xsltGenericDebugContext,
  4592. "Disable escaping: %s\n", text->content);
  4593. #endif
  4594. if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
  4595. noesc = 1;
  4596. } else if (!xmlStrEqual(prop,
  4597. (const xmlChar *)"no")){
  4598. xsltTransformError(NULL, style, cur,
  4599. "xsl:text: disable-output-escaping allows only yes or no\n");
  4600. style->warnings++;
  4601. }
  4602. xmlFree(prop);
  4603. }
  4604. while (text != NULL) {
  4605. if (text->type == XML_COMMENT_NODE) {
  4606. text = text->next;
  4607. continue;
  4608. }
  4609. if ((text->type != XML_TEXT_NODE) &&
  4610. (text->type != XML_CDATA_SECTION_NODE)) {
  4611. xsltTransformError(NULL, style, cur,
  4612. "xsltParseTemplateContent: xslt:text content problem\n");
  4613. style->errors++;
  4614. break;
  4615. }
  4616. if ((noesc) && (text->type != XML_CDATA_SECTION_NODE))
  4617. text->name = xmlStringTextNoenc;
  4618. text = text->next;
  4619. }
  4620. /*
  4621. * replace xsl:text by the list of childs
  4622. */
  4623. if (text == NULL) {
  4624. text = cur->children;
  4625. while (text != NULL) {
  4626. if ((style->internalized) &&
  4627. (text->content != NULL) &&
  4628. (!xmlDictOwns(style->dict, text->content))) {
  4629. /*
  4630. * internalize the text string
  4631. */
  4632. if (text->doc->dict != NULL) {
  4633. const xmlChar *tmp;
  4634. tmp = xmlDictLookup(text->doc->dict,
  4635. text->content, -1);
  4636. if (tmp != text->content) {
  4637. xmlNodeSetContent(text, NULL);
  4638. text->content = (xmlChar *) tmp;
  4639. }
  4640. }
  4641. }
  4642. next = text->next;
  4643. xmlUnlinkNode(text);
  4644. xmlAddPrevSibling(cur, text);
  4645. text = next;
  4646. }
  4647. }
  4648. }
  4649. delete = cur;
  4650. goto skip_children;
  4651. }
  4652. }
  4653. else if ((cur->ns != NULL) && (style->nsDefs != NULL) &&
  4654. (xsltCheckExtPrefix(style, cur->ns->prefix)))
  4655. {
  4656. /*
  4657. * okay this is an extension element compile it too
  4658. */
  4659. xsltStylePreCompute(style, cur);
  4660. }
  4661. else if (cur->type == XML_ELEMENT_NODE)
  4662. {
  4663. /*
  4664. * This is an element which will be output as part of the
  4665. * template exectution, precompile AVT if found.
  4666. */
  4667. if ((cur->ns == NULL) && (style->defaultAlias != NULL)) {
  4668. cur->ns = xmlSearchNsByHref(cur->doc, cur,
  4669. style->defaultAlias);
  4670. }
  4671. if (cur->properties != NULL) {
  4672. xmlAttrPtr attr = cur->properties;
  4673. while (attr != NULL) {
  4674. xsltCompileAttr(style, attr);
  4675. attr = attr->next;
  4676. }
  4677. }
  4678. }
  4679. /*
  4680. * Skip to next node
  4681. */
  4682. if (cur->children != NULL) {
  4683. if (cur->children->type != XML_ENTITY_DECL) {
  4684. cur = cur->children;
  4685. continue;
  4686. }
  4687. }
  4688. skip_children:
  4689. if (cur->next != NULL) {
  4690. cur = cur->next;
  4691. continue;
  4692. }
  4693. do {
  4694. cur = cur->parent;
  4695. if (cur == NULL)
  4696. break;
  4697. if (cur == templ) {
  4698. cur = NULL;
  4699. break;
  4700. }
  4701. if (cur->next != NULL) {
  4702. cur = cur->next;
  4703. break;
  4704. }
  4705. } while (cur != NULL);
  4706. }
  4707. if (delete != NULL) {
  4708. #ifdef WITH_XSLT_DEBUG_PARSING
  4709. xsltGenericDebug(xsltGenericDebugContext,
  4710. "xsltParseTemplateContent: removing text\n");
  4711. #endif
  4712. xmlUnlinkNode(delete);
  4713. xmlFreeNode(delete);
  4714. delete = NULL;
  4715. }
  4716. /*
  4717. * Skip the first params
  4718. */
  4719. cur = templ->children;
  4720. while (cur != NULL) {
  4721. if ((IS_XSLT_ELEM(cur)) && (!(IS_XSLT_NAME(cur, "param"))))
  4722. break;
  4723. cur = cur->next;
  4724. }
  4725. /*
  4726. * Browse the remainder of the template
  4727. */
  4728. while (cur != NULL) {
  4729. if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "param"))) {
  4730. xmlNodePtr param = cur;
  4731. xsltTransformError(NULL, style, cur,
  4732. "xsltParseTemplateContent: ignoring misplaced param element\n");
  4733. if (style != NULL) style->warnings++;
  4734. cur = cur->next;
  4735. xmlUnlinkNode(param);
  4736. xmlFreeNode(param);
  4737. } else
  4738. break;
  4739. }
  4740. }
  4741. #endif /* else XSLT_REFACTORED */
  4742. /**
  4743. * xsltParseStylesheetKey:
  4744. * @style: the XSLT stylesheet
  4745. * @key: the "key" element
  4746. *
  4747. * <!-- Category: top-level-element -->
  4748. * <xsl:key name = qname, match = pattern, use = expression />
  4749. *
  4750. * parse an XSLT stylesheet key definition and register it
  4751. */
  4752. static void
  4753. xsltParseStylesheetKey(xsltStylesheetPtr style, xmlNodePtr key) {
  4754. xmlChar *prop = NULL;
  4755. xmlChar *use = NULL;
  4756. xmlChar *match = NULL;
  4757. xmlChar *name = NULL;
  4758. xmlChar *nameURI = NULL;
  4759. if ((style == NULL) || (key == NULL) || (key->type != XML_ELEMENT_NODE))
  4760. return;
  4761. /*
  4762. * Get arguments
  4763. */
  4764. prop = xmlGetNsProp(key, (const xmlChar *)"name", NULL);
  4765. if (prop != NULL) {
  4766. const xmlChar *URI;
  4767. /*
  4768. * TODO: Don't use xsltGetQNameURI().
  4769. */
  4770. URI = xsltGetQNameURI(key, &prop);
  4771. if (prop == NULL) {
  4772. if (style != NULL) style->errors++;
  4773. goto error;
  4774. } else {
  4775. name = prop;
  4776. if (URI != NULL)
  4777. nameURI = xmlStrdup(URI);
  4778. }
  4779. #ifdef WITH_XSLT_DEBUG_PARSING
  4780. xsltGenericDebug(xsltGenericDebugContext,
  4781. "xsltParseStylesheetKey: name %s\n", name);
  4782. #endif
  4783. } else {
  4784. xsltTransformError(NULL, style, key,
  4785. "xsl:key : error missing name\n");
  4786. if (style != NULL) style->errors++;
  4787. goto error;
  4788. }
  4789. match = xmlGetNsProp(key, (const xmlChar *)"match", NULL);
  4790. if (match == NULL) {
  4791. xsltTransformError(NULL, style, key,
  4792. "xsl:key : error missing match\n");
  4793. if (style != NULL) style->errors++;
  4794. goto error;
  4795. }
  4796. use = xmlGetNsProp(key, (const xmlChar *)"use", NULL);
  4797. if (use == NULL) {
  4798. xsltTransformError(NULL, style, key,
  4799. "xsl:key : error missing use\n");
  4800. if (style != NULL) style->errors++;
  4801. goto error;
  4802. }
  4803. /*
  4804. * register the keys
  4805. */
  4806. xsltAddKey(style, name, nameURI, match, use, key);
  4807. error:
  4808. if (use != NULL)
  4809. xmlFree(use);
  4810. if (match != NULL)
  4811. xmlFree(match);
  4812. if (name != NULL)
  4813. xmlFree(name);
  4814. if (nameURI != NULL)
  4815. xmlFree(nameURI);
  4816. if (key->children != NULL) {
  4817. xsltParseContentError(style, key->children);
  4818. }
  4819. }
  4820. #ifdef XSLT_REFACTORED
  4821. /**
  4822. * xsltParseXSLTTemplate:
  4823. * @style: the XSLT stylesheet
  4824. * @template: the "template" element
  4825. *
  4826. * parse an XSLT stylesheet template building the associated structures
  4827. * TODO: Is @style ever expected to be NULL?
  4828. *
  4829. * Called from:
  4830. * xsltParseXSLTStylesheet()
  4831. * xsltParseStylesheetTop()
  4832. */
  4833. static void
  4834. xsltParseXSLTTemplate(xsltCompilerCtxtPtr cctxt, xmlNodePtr templNode) {
  4835. xsltTemplatePtr templ;
  4836. xmlChar *prop;
  4837. double priority;
  4838. if ((cctxt == NULL) || (templNode == NULL) ||
  4839. (templNode->type != XML_ELEMENT_NODE))
  4840. return;
  4841. /*
  4842. * Create and link the structure
  4843. */
  4844. templ = xsltNewTemplate();
  4845. if (templ == NULL)
  4846. return;
  4847. xsltCompilerNodePush(cctxt, templNode);
  4848. if (templNode->nsDef != NULL)
  4849. cctxt->inode->inScopeNs =
  4850. xsltCompilerBuildInScopeNsList(cctxt, templNode);
  4851. templ->next = cctxt->style->templates;
  4852. cctxt->style->templates = templ;
  4853. templ->style = cctxt->style;
  4854. /*
  4855. * Attribute "mode".
  4856. */
  4857. prop = xmlGetNsProp(templNode, (const xmlChar *)"mode", NULL);
  4858. if (prop != NULL) {
  4859. const xmlChar *modeURI;
  4860. /*
  4861. * TODO: We need a standardized function for extraction
  4862. * of namespace names and local names from QNames.
  4863. * Don't use xsltGetQNameURI() as it cannot channe�
  4864. * reports through the context.
  4865. */
  4866. modeURI = xsltGetQNameURI(templNode, &prop);
  4867. if (prop == NULL) {
  4868. cctxt->style->errors++;
  4869. goto error;
  4870. }
  4871. templ->mode = xmlDictLookup(cctxt->style->dict, prop, -1);
  4872. xmlFree(prop);
  4873. prop = NULL;
  4874. if (xmlValidateNCName(templ->mode, 0)) {
  4875. xsltTransformError(NULL, cctxt->style, templNode,
  4876. "xsl:template: Attribute 'mode': The local part '%s' "
  4877. "of the value is not a valid NCName.\n", templ->name);
  4878. cctxt->style->errors++;
  4879. goto error;
  4880. }
  4881. if (modeURI != NULL)
  4882. templ->modeURI = xmlDictLookup(cctxt->style->dict, modeURI, -1);
  4883. #ifdef WITH_XSLT_DEBUG_PARSING
  4884. xsltGenericDebug(xsltGenericDebugContext,
  4885. "xsltParseXSLTTemplate: mode %s\n", templ->mode);
  4886. #endif
  4887. }
  4888. /*
  4889. * Attribute "match".
  4890. */
  4891. prop = xmlGetNsProp(templNode, (const xmlChar *)"match", NULL);
  4892. if (prop != NULL) {
  4893. templ->match = prop;
  4894. prop = NULL;
  4895. }
  4896. /*
  4897. * Attribute "priority".
  4898. */
  4899. prop = xmlGetNsProp(templNode, (const xmlChar *)"priority", NULL);
  4900. if (prop != NULL) {
  4901. priority = xmlXPathStringEvalNumber(prop);
  4902. templ->priority = (float) priority;
  4903. xmlFree(prop);
  4904. prop = NULL;
  4905. }
  4906. /*
  4907. * Attribute "name".
  4908. */
  4909. prop = xmlGetNsProp(templNode, (const xmlChar *)"name", NULL);
  4910. if (prop != NULL) {
  4911. const xmlChar *nameURI;
  4912. xsltTemplatePtr curTempl;
  4913. /*
  4914. * TODO: Don't use xsltGetQNameURI().
  4915. */
  4916. nameURI = xsltGetQNameURI(templNode, &prop);
  4917. if (prop == NULL) {
  4918. cctxt->style->errors++;
  4919. goto error;
  4920. }
  4921. templ->name = xmlDictLookup(cctxt->style->dict, prop, -1);
  4922. xmlFree(prop);
  4923. prop = NULL;
  4924. if (xmlValidateNCName(templ->name, 0)) {
  4925. xsltTransformError(NULL, cctxt->style, templNode,
  4926. "xsl:template: Attribute 'name': The local part '%s' of "
  4927. "the value is not a valid NCName.\n", templ->name);
  4928. cctxt->style->errors++;
  4929. goto error;
  4930. }
  4931. if (nameURI != NULL)
  4932. templ->nameURI = xmlDictLookup(cctxt->style->dict, nameURI, -1);
  4933. curTempl = templ->next;
  4934. while (curTempl != NULL) {
  4935. if ((nameURI != NULL && xmlStrEqual(curTempl->name, templ->name) &&
  4936. xmlStrEqual(curTempl->nameURI, nameURI) ) ||
  4937. (nameURI == NULL && curTempl->nameURI == NULL &&
  4938. xmlStrEqual(curTempl->name, templ->name)))
  4939. {
  4940. xsltTransformError(NULL, cctxt->style, templNode,
  4941. "xsl:template: error duplicate name '%s'\n", templ->name);
  4942. cctxt->style->errors++;
  4943. goto error;
  4944. }
  4945. curTempl = curTempl->next;
  4946. }
  4947. }
  4948. if (templNode->children != NULL) {
  4949. xsltParseTemplateContent(cctxt->style, templNode);
  4950. /*
  4951. * MAYBE TODO: Custom behaviour: In order to stay compatible with
  4952. * Xalan and MSXML(.NET), we could allow whitespace
  4953. * to appear before an xml:param element; this whitespace
  4954. * will additionally become part of the "template".
  4955. * NOTE that this is totally deviates from the spec, but
  4956. * is the de facto behaviour of Xalan and MSXML(.NET).
  4957. * Personally I wouldn't allow this, since if we have:
  4958. * <xsl:template ...xml:space="preserve">
  4959. * <xsl:param name="foo"/>
  4960. * <xsl:param name="bar"/>
  4961. * <xsl:param name="zoo"/>
  4962. * ... the whitespace between every xsl:param would be
  4963. * added to the result tree.
  4964. */
  4965. }
  4966. templ->elem = templNode;
  4967. templ->content = templNode->children;
  4968. xsltAddTemplate(cctxt->style, templ, templ->mode, templ->modeURI);
  4969. error:
  4970. xsltCompilerNodePop(cctxt, templNode);
  4971. return;
  4972. }
  4973. #else /* XSLT_REFACTORED */
  4974. /**
  4975. * xsltParseStylesheetTemplate:
  4976. * @style: the XSLT stylesheet
  4977. * @template: the "template" element
  4978. *
  4979. * parse an XSLT stylesheet template building the associated structures
  4980. */
  4981. static void
  4982. xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
  4983. xsltTemplatePtr ret;
  4984. xmlChar *prop;
  4985. xmlChar *mode = NULL;
  4986. xmlChar *modeURI = NULL;
  4987. double priority;
  4988. if ((style == NULL) || (template == NULL) ||
  4989. (template->type != XML_ELEMENT_NODE))
  4990. return;
  4991. /*
  4992. * Create and link the structure
  4993. */
  4994. ret = xsltNewTemplate();
  4995. if (ret == NULL)
  4996. return;
  4997. ret->next = style->templates;
  4998. style->templates = ret;
  4999. ret->style = style;
  5000. /*
  5001. * Get inherited namespaces
  5002. */
  5003. /*
  5004. * TODO: Apply the optimized in-scope-namespace mechanism
  5005. * as for the other XSLT instructions.
  5006. */
  5007. xsltGetInheritedNsList(style, ret, template);
  5008. /*
  5009. * Get arguments
  5010. */
  5011. prop = xmlGetNsProp(template, (const xmlChar *)"mode", NULL);
  5012. if (prop != NULL) {
  5013. const xmlChar *URI;
  5014. /*
  5015. * TODO: Don't use xsltGetQNameURI().
  5016. */
  5017. URI = xsltGetQNameURI(template, &prop);
  5018. if (prop == NULL) {
  5019. if (style != NULL) style->errors++;
  5020. goto error;
  5021. } else {
  5022. mode = prop;
  5023. if (URI != NULL)
  5024. modeURI = xmlStrdup(URI);
  5025. }
  5026. ret->mode = xmlDictLookup(style->dict, mode, -1);
  5027. ret->modeURI = xmlDictLookup(style->dict, modeURI, -1);
  5028. #ifdef WITH_XSLT_DEBUG_PARSING
  5029. xsltGenericDebug(xsltGenericDebugContext,
  5030. "xsltParseStylesheetTemplate: mode %s\n", mode);
  5031. #endif
  5032. if (mode != NULL) xmlFree(mode);
  5033. if (modeURI != NULL) xmlFree(modeURI);
  5034. }
  5035. prop = xmlGetNsProp(template, (const xmlChar *)"match", NULL);
  5036. if (prop != NULL) {
  5037. if (ret->match != NULL) xmlFree(ret->match);
  5038. ret->match = prop;
  5039. }
  5040. prop = xmlGetNsProp(template, (const xmlChar *)"priority", NULL);
  5041. if (prop != NULL) {
  5042. priority = xmlXPathStringEvalNumber(prop);
  5043. ret->priority = (float) priority;
  5044. xmlFree(prop);
  5045. }
  5046. prop = xmlGetNsProp(template, (const xmlChar *)"name", NULL);
  5047. if (prop != NULL) {
  5048. const xmlChar *URI;
  5049. /*
  5050. * TODO: Don't use xsltGetQNameURI().
  5051. */
  5052. URI = xsltGetQNameURI(template, &prop);
  5053. if (prop == NULL) {
  5054. if (style != NULL) style->errors++;
  5055. goto error;
  5056. } else {
  5057. if (xmlValidateNCName(prop,0)) {
  5058. xsltTransformError(NULL, style, template,
  5059. "xsl:template : error invalid name '%s'\n", prop);
  5060. if (style != NULL) style->errors++;
  5061. xmlFree(prop);
  5062. goto error;
  5063. }
  5064. ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1);
  5065. xmlFree(prop);
  5066. prop = NULL;
  5067. if (URI != NULL)
  5068. ret->nameURI = xmlDictLookup(style->dict, BAD_CAST URI, -1);
  5069. else
  5070. ret->nameURI = NULL;
  5071. }
  5072. }
  5073. /*
  5074. * parse the content and register the pattern
  5075. */
  5076. xsltParseTemplateContent(style, template);
  5077. ret->elem = template;
  5078. ret->content = template->children;
  5079. xsltAddTemplate(style, ret, ret->mode, ret->modeURI);
  5080. error:
  5081. return;
  5082. }
  5083. #endif /* else XSLT_REFACTORED */
  5084. #ifdef XSLT_REFACTORED
  5085. /**
  5086. * xsltIncludeComp:
  5087. * @cctxt: the compilation context
  5088. * @node: the xsl:include node
  5089. *
  5090. * Process the xslt include node on the source node
  5091. */
  5092. static xsltStyleItemIncludePtr
  5093. xsltCompileXSLTIncludeElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node) {
  5094. xsltStyleItemIncludePtr item;
  5095. if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
  5096. return(NULL);
  5097. node->psvi = NULL;
  5098. item = (xsltStyleItemIncludePtr) xmlMalloc(sizeof(xsltStyleItemInclude));
  5099. if (item == NULL) {
  5100. xsltTransformError(NULL, cctxt->style, node,
  5101. "xsltIncludeComp : malloc failed\n");
  5102. cctxt->style->errors++;
  5103. return(NULL);
  5104. }
  5105. memset(item, 0, sizeof(xsltStyleItemInclude));
  5106. node->psvi = item;
  5107. item->inst = node;
  5108. item->type = XSLT_FUNC_INCLUDE;
  5109. item->next = cctxt->style->preComps;
  5110. cctxt->style->preComps = (xsltElemPreCompPtr) item;
  5111. return(item);
  5112. }
  5113. /**
  5114. * xsltParseFindTopLevelElem:
  5115. */
  5116. static int
  5117. xsltParseFindTopLevelElem(xsltCompilerCtxtPtr cctxt,
  5118. xmlNodePtr cur,
  5119. const xmlChar *name,
  5120. const xmlChar *namespaceURI,
  5121. int breakOnOtherElem,
  5122. xmlNodePtr *resultNode)
  5123. {
  5124. if (name == NULL)
  5125. return(-1);
  5126. *resultNode = NULL;
  5127. while (cur != NULL) {
  5128. if (cur->type == XML_ELEMENT_NODE) {
  5129. if ((cur->ns != NULL) && (cur->name != NULL)) {
  5130. if ((*(cur->name) == *name) &&
  5131. xmlStrEqual(cur->name, name) &&
  5132. xmlStrEqual(cur->ns->href, namespaceURI))
  5133. {
  5134. *resultNode = cur;
  5135. return(1);
  5136. }
  5137. }
  5138. if (breakOnOtherElem)
  5139. break;
  5140. }
  5141. cur = cur->next;
  5142. }
  5143. *resultNode = cur;
  5144. return(0);
  5145. }
  5146. static int
  5147. xsltParseTopLevelXSLTElem(xsltCompilerCtxtPtr cctxt,
  5148. xmlNodePtr node,
  5149. xsltStyleType type)
  5150. {
  5151. int ret = 0;
  5152. /*
  5153. * TODO: The reason why this function exists:
  5154. * due to historical reasons some of the
  5155. * top-level declarations are processed by functions
  5156. * in other files. Since we need still to set
  5157. * up the node-info and generate information like
  5158. * in-scope namespaces, this is a wrapper around
  5159. * those old parsing functions.
  5160. */
  5161. xsltCompilerNodePush(cctxt, node);
  5162. if (node->nsDef != NULL)
  5163. cctxt->inode->inScopeNs =
  5164. xsltCompilerBuildInScopeNsList(cctxt, node);
  5165. cctxt->inode->type = type;
  5166. switch (type) {
  5167. case XSLT_FUNC_INCLUDE:
  5168. {
  5169. int oldIsInclude;
  5170. if (xsltCompileXSLTIncludeElem(cctxt, node) == NULL)
  5171. goto exit;
  5172. /*
  5173. * Mark this stylesheet tree as being currently included.
  5174. */
  5175. oldIsInclude = cctxt->isInclude;
  5176. cctxt->isInclude = 1;
  5177. if (xsltParseStylesheetInclude(cctxt->style, node) != 0) {
  5178. cctxt->style->errors++;
  5179. }
  5180. cctxt->isInclude = oldIsInclude;
  5181. }
  5182. break;
  5183. case XSLT_FUNC_PARAM:
  5184. xsltStylePreCompute(cctxt->style, node);
  5185. xsltParseGlobalParam(cctxt->style, node);
  5186. break;
  5187. case XSLT_FUNC_VARIABLE:
  5188. xsltStylePreCompute(cctxt->style, node);
  5189. xsltParseGlobalVariable(cctxt->style, node);
  5190. break;
  5191. case XSLT_FUNC_ATTRSET:
  5192. xsltParseStylesheetAttributeSet(cctxt->style, node);
  5193. break;
  5194. default:
  5195. xsltTransformError(NULL, cctxt->style, node,
  5196. "Internal error: (xsltParseTopLevelXSLTElem) "
  5197. "Cannot handle this top-level declaration.\n");
  5198. cctxt->style->errors++;
  5199. ret = -1;
  5200. }
  5201. exit:
  5202. xsltCompilerNodePop(cctxt, node);
  5203. return(ret);
  5204. }
  5205. #if 0
  5206. static int
  5207. xsltParseRemoveWhitespace(xmlNodePtr node)
  5208. {
  5209. if ((node == NULL) || (node->children == NULL))
  5210. return(0);
  5211. else {
  5212. xmlNodePtr delNode = NULL, child = node->children;
  5213. do {
  5214. if (delNode) {
  5215. xmlUnlinkNode(delNode);
  5216. xmlFreeNode(delNode);
  5217. delNode = NULL;
  5218. }
  5219. if (((child->type == XML_TEXT_NODE) ||
  5220. (child->type == XML_CDATA_SECTION_NODE)) &&
  5221. (IS_BLANK_NODE(child)))
  5222. delNode = child;
  5223. child = child->next;
  5224. } while (child != NULL);
  5225. if (delNode) {
  5226. xmlUnlinkNode(delNode);
  5227. xmlFreeNode(delNode);
  5228. delNode = NULL;
  5229. }
  5230. }
  5231. return(0);
  5232. }
  5233. #endif
  5234. static int
  5235. xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
  5236. {
  5237. #ifdef WITH_XSLT_DEBUG_PARSING
  5238. int templates = 0;
  5239. #endif
  5240. xmlNodePtr cur, start = NULL;
  5241. xsltStylesheetPtr style;
  5242. if ((cctxt == NULL) || (node == NULL) ||
  5243. (node->type != XML_ELEMENT_NODE))
  5244. return(-1);
  5245. style = cctxt->style;
  5246. /*
  5247. * At this stage all import declarations of all stylesheet modules
  5248. * with the same stylesheet level have been processed.
  5249. * Now we can safely parse the rest of the declarations.
  5250. */
  5251. if (IS_XSLT_ELEM_FAST(node) && IS_XSLT_NAME(node, "include"))
  5252. {
  5253. xsltDocumentPtr include;
  5254. /*
  5255. * URGENT TODO: Make this work with simplified stylesheets!
  5256. * I.e., when we won't find an xsl:stylesheet element.
  5257. */
  5258. /*
  5259. * This is as include declaration.
  5260. */
  5261. include = ((xsltStyleItemIncludePtr) node->psvi)->include;
  5262. if (include == NULL) {
  5263. /* TODO: raise error? */
  5264. return(-1);
  5265. }
  5266. /*
  5267. * TODO: Actually an xsl:include should locate an embedded
  5268. * stylesheet as well; so the document-element won't always
  5269. * be the element where the actual stylesheet is rooted at.
  5270. * But such embedded stylesheets are not supported by Libxslt yet.
  5271. */
  5272. node = xmlDocGetRootElement(include->doc);
  5273. if (node == NULL) {
  5274. return(-1);
  5275. }
  5276. }
  5277. if (node->children == NULL)
  5278. return(0);
  5279. /*
  5280. * Push the xsl:stylesheet/xsl:transform element.
  5281. */
  5282. xsltCompilerNodePush(cctxt, node);
  5283. cctxt->inode->isRoot = 1;
  5284. cctxt->inode->nsChanged = 0;
  5285. /*
  5286. * Start with the naked dummy info for literal result elements.
  5287. */
  5288. cctxt->inode->litResElemInfo = cctxt->inodeList->litResElemInfo;
  5289. /*
  5290. * In every case, we need to have
  5291. * the in-scope namespaces of the element, where the
  5292. * stylesheet is rooted at, regardless if it's an XSLT
  5293. * instruction or a literal result instruction (or if
  5294. * this is an embedded stylesheet).
  5295. */
  5296. cctxt->inode->inScopeNs =
  5297. xsltCompilerBuildInScopeNsList(cctxt, node);
  5298. /*
  5299. * Process attributes of xsl:stylesheet/xsl:transform.
  5300. * --------------------------------------------------
  5301. * Allowed are:
  5302. * id = id
  5303. * extension-element-prefixes = tokens
  5304. * exclude-result-prefixes = tokens
  5305. * version = number (mandatory)
  5306. */
  5307. if (xsltParseAttrXSLTVersion(cctxt, node,
  5308. XSLT_ELEMENT_CATEGORY_XSLT) == 0)
  5309. {
  5310. /*
  5311. * Attribute "version".
  5312. * XSLT 1.0: "An xsl:stylesheet element *must* have a version
  5313. * attribute, indicating the version of XSLT that the
  5314. * stylesheet requires".
  5315. * The root element of a simplified stylesheet must also have
  5316. * this attribute.
  5317. */
  5318. #ifdef XSLT_REFACTORED_MANDATORY_VERSION
  5319. if (isXsltElem)
  5320. xsltTransformError(NULL, cctxt->style, node,
  5321. "The attribute 'version' is missing.\n");
  5322. cctxt->style->errors++;
  5323. #else
  5324. /* OLD behaviour. */
  5325. xsltTransformError(NULL, cctxt->style, node,
  5326. "xsl:version is missing: document may not be a stylesheet\n");
  5327. cctxt->style->warnings++;
  5328. #endif
  5329. }
  5330. /*
  5331. * The namespaces declared by the attributes
  5332. * "extension-element-prefixes" and
  5333. * "exclude-result-prefixes" are local to *this*
  5334. * stylesheet tree; i.e., they are *not* visible to
  5335. * other stylesheet-modules, whether imported or included.
  5336. *
  5337. * Attribute "extension-element-prefixes".
  5338. */
  5339. cctxt->inode->extElemNs =
  5340. xsltParseExtElemPrefixes(cctxt, node, NULL,
  5341. XSLT_ELEMENT_CATEGORY_XSLT);
  5342. /*
  5343. * Attribute "exclude-result-prefixes".
  5344. */
  5345. cctxt->inode->exclResultNs =
  5346. xsltParseExclResultPrefixes(cctxt, node, NULL,
  5347. XSLT_ELEMENT_CATEGORY_XSLT);
  5348. /*
  5349. * Create/reuse info for the literal result element.
  5350. */
  5351. if (cctxt->inode->nsChanged)
  5352. xsltLREInfoCreate(cctxt, node, 0);
  5353. /*
  5354. * Processed top-level elements:
  5355. * ----------------------------
  5356. * xsl:variable, xsl:param (QName, in-scope ns,
  5357. * expression (vars allowed))
  5358. * xsl:attribute-set (QName, in-scope ns)
  5359. * xsl:strip-space, xsl:preserve-space (XPath NameTests,
  5360. * in-scope ns)
  5361. * I *think* global scope, merge with includes
  5362. * xsl:output (QName, in-scope ns)
  5363. * xsl:key (QName, in-scope ns, pattern,
  5364. * expression (vars *not* allowed))
  5365. * xsl:decimal-format (QName, needs in-scope ns)
  5366. * xsl:namespace-alias (in-scope ns)
  5367. * global scope, merge with includes
  5368. * xsl:template (last, QName, pattern)
  5369. *
  5370. * (whitespace-only text-nodes have *not* been removed
  5371. * yet; this will be done in xsltParseSequenceConstructor)
  5372. *
  5373. * Report misplaced child-nodes first.
  5374. */
  5375. cur = node->children;
  5376. while (cur != NULL) {
  5377. if (cur->type == XML_TEXT_NODE) {
  5378. xsltTransformError(NULL, style, cur,
  5379. "Misplaced text node (content: '%s').\n",
  5380. (cur->content != NULL) ? cur->content : BAD_CAST "");
  5381. style->errors++;
  5382. } else if (cur->type != XML_ELEMENT_NODE) {
  5383. xsltTransformError(NULL, style, cur, "Misplaced node.\n");
  5384. style->errors++;
  5385. }
  5386. cur = cur->next;
  5387. }
  5388. /*
  5389. * Skip xsl:import elements; they have been processed
  5390. * already.
  5391. */
  5392. cur = node->children;
  5393. while ((cur != NULL) && xsltParseFindTopLevelElem(cctxt, cur,
  5394. BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)
  5395. cur = cur->next;
  5396. if (cur == NULL)
  5397. goto exit;
  5398. start = cur;
  5399. /*
  5400. * Process all top-level xsl:param elements.
  5401. */
  5402. while ((cur != NULL) &&
  5403. xsltParseFindTopLevelElem(cctxt, cur,
  5404. BAD_CAST "param", XSLT_NAMESPACE, 0, &cur) == 1)
  5405. {
  5406. xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_PARAM);
  5407. cur = cur->next;
  5408. }
  5409. /*
  5410. * Process all top-level xsl:variable elements.
  5411. */
  5412. cur = start;
  5413. while ((cur != NULL) &&
  5414. xsltParseFindTopLevelElem(cctxt, cur,
  5415. BAD_CAST "variable", XSLT_NAMESPACE, 0, &cur) == 1)
  5416. {
  5417. xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_VARIABLE);
  5418. cur = cur->next;
  5419. }
  5420. /*
  5421. * Process all the rest of top-level elements.
  5422. */
  5423. cur = start;
  5424. while (cur != NULL) {
  5425. /*
  5426. * Process element nodes.
  5427. */
  5428. if (cur->type == XML_ELEMENT_NODE) {
  5429. if (cur->ns == NULL) {
  5430. xsltTransformError(NULL, style, cur,
  5431. "Unexpected top-level element in no namespace.\n");
  5432. style->errors++;
  5433. cur = cur->next;
  5434. continue;
  5435. }
  5436. /*
  5437. * Process all XSLT elements.
  5438. */
  5439. if (IS_XSLT_ELEM_FAST(cur)) {
  5440. /*
  5441. * xsl:import is only allowed at the beginning.
  5442. */
  5443. if (IS_XSLT_NAME(cur, "import")) {
  5444. xsltTransformError(NULL, style, cur,
  5445. "Misplaced xsl:import element.\n");
  5446. style->errors++;
  5447. cur = cur->next;
  5448. continue;
  5449. }
  5450. /*
  5451. * TODO: Change the return type of the parsing functions
  5452. * to int.
  5453. */
  5454. if (IS_XSLT_NAME(cur, "template")) {
  5455. #ifdef WITH_XSLT_DEBUG_PARSING
  5456. templates++;
  5457. #endif
  5458. /*
  5459. * TODO: Is the position of xsl:template in the
  5460. * tree significant? If not it would be easier to
  5461. * parse them at a later stage.
  5462. */
  5463. xsltParseXSLTTemplate(cctxt, cur);
  5464. } else if (IS_XSLT_NAME(cur, "variable")) {
  5465. /* NOP; done already */
  5466. } else if (IS_XSLT_NAME(cur, "param")) {
  5467. /* NOP; done already */
  5468. } else if (IS_XSLT_NAME(cur, "include")) {
  5469. if (cur->psvi != NULL)
  5470. xsltParseXSLTStylesheetElemCore(cctxt, cur);
  5471. else {
  5472. xsltTransformError(NULL, style, cur,
  5473. "Internal error: "
  5474. "(xsltParseXSLTStylesheetElemCore) "
  5475. "The xsl:include element was not compiled.\n");
  5476. style->errors++;
  5477. }
  5478. } else if (IS_XSLT_NAME(cur, "strip-space")) {
  5479. /* No node info needed. */
  5480. xsltParseStylesheetStripSpace(style, cur);
  5481. } else if (IS_XSLT_NAME(cur, "preserve-space")) {
  5482. /* No node info needed. */
  5483. xsltParseStylesheetPreserveSpace(style, cur);
  5484. } else if (IS_XSLT_NAME(cur, "output")) {
  5485. /* No node-info needed. */
  5486. xsltParseStylesheetOutput(style, cur);
  5487. } else if (IS_XSLT_NAME(cur, "key")) {
  5488. /* TODO: node-info needed for expressions ? */
  5489. xsltParseStylesheetKey(style, cur);
  5490. } else if (IS_XSLT_NAME(cur, "decimal-format")) {
  5491. /* No node-info needed. */
  5492. xsltParseStylesheetDecimalFormat(style, cur);
  5493. } else if (IS_XSLT_NAME(cur, "attribute-set")) {
  5494. xsltParseTopLevelXSLTElem(cctxt, cur,
  5495. XSLT_FUNC_ATTRSET);
  5496. } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
  5497. /* NOP; done already */
  5498. } else {
  5499. if (cctxt->inode->forwardsCompat) {
  5500. /*
  5501. * Forwards-compatible mode:
  5502. *
  5503. * XSLT-1: "if it is a top-level element and
  5504. * XSLT 1.0 does not allow such elements as top-level
  5505. * elements, then the element must be ignored along
  5506. * with its content;"
  5507. */
  5508. /*
  5509. * TODO: I don't think we should generate a warning.
  5510. */
  5511. xsltTransformError(NULL, style, cur,
  5512. "Forwards-compatible mode: Ignoring unknown XSLT "
  5513. "element '%s'.\n", cur->name);
  5514. style->warnings++;
  5515. } else {
  5516. xsltTransformError(NULL, style, cur,
  5517. "Unknown XSLT element '%s'.\n", cur->name);
  5518. style->errors++;
  5519. }
  5520. }
  5521. } else {
  5522. xsltTopLevelFunction function;
  5523. /*
  5524. * Process non-XSLT elements, which are in a
  5525. * non-NULL namespace.
  5526. */
  5527. /*
  5528. * QUESTION: What does xsltExtModuleTopLevelLookup()
  5529. * do exactly?
  5530. */
  5531. function = xsltExtModuleTopLevelLookup(cur->name,
  5532. cur->ns->href);
  5533. if (function != NULL)
  5534. function(style, cur);
  5535. #ifdef WITH_XSLT_DEBUG_PARSING
  5536. xsltGenericDebug(xsltGenericDebugContext,
  5537. "xsltParseXSLTStylesheetElemCore : User-defined "
  5538. "data element '%s'.\n", cur->name);
  5539. #endif
  5540. }
  5541. }
  5542. cur = cur->next;
  5543. }
  5544. exit:
  5545. #ifdef WITH_XSLT_DEBUG_PARSING
  5546. xsltGenericDebug(xsltGenericDebugContext,
  5547. "### END of parsing top-level elements of doc '%s'.\n",
  5548. node->doc->URL);
  5549. xsltGenericDebug(xsltGenericDebugContext,
  5550. "### Templates: %d\n", templates);
  5551. #ifdef XSLT_REFACTORED
  5552. xsltGenericDebug(xsltGenericDebugContext,
  5553. "### Max inodes: %d\n", cctxt->maxNodeInfos);
  5554. xsltGenericDebug(xsltGenericDebugContext,
  5555. "### Max LREs : %d\n", cctxt->maxLREs);
  5556. #endif /* XSLT_REFACTORED */
  5557. #endif /* WITH_XSLT_DEBUG_PARSING */
  5558. xsltCompilerNodePop(cctxt, node);
  5559. return(0);
  5560. }
  5561. /**
  5562. * xsltParseXSLTStylesheet:
  5563. * @cctxt: the compiler context
  5564. * @node: the xsl:stylesheet/xsl:transform element-node
  5565. *
  5566. * Parses the xsl:stylesheet and xsl:transform element.
  5567. *
  5568. * <xsl:stylesheet
  5569. * id = id
  5570. * extension-element-prefixes = tokens
  5571. * exclude-result-prefixes = tokens
  5572. * version = number>
  5573. * <!-- Content: (xsl:import*, top-level-elements) -->
  5574. * </xsl:stylesheet>
  5575. *
  5576. * BIG TODO: The xsl:include stuff.
  5577. *
  5578. * Called by xsltParseStylesheetTree()
  5579. *
  5580. * Returns 0 on success, a positive result on errors and
  5581. * -1 on API or internal errors.
  5582. */
  5583. static int
  5584. xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
  5585. {
  5586. xmlNodePtr cur, start;
  5587. if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
  5588. return(-1);
  5589. if (node->children == NULL)
  5590. goto exit;
  5591. /*
  5592. * Process top-level elements:
  5593. * xsl:import (must be first)
  5594. * xsl:include (this is just a pre-processing)
  5595. */
  5596. cur = node->children;
  5597. /*
  5598. * Process xsl:import elements.
  5599. * XSLT 1.0: "The xsl:import element children must precede all
  5600. * other element children of an xsl:stylesheet element,
  5601. * including any xsl:include element children."
  5602. */
  5603. while ((cur != NULL) &&
  5604. xsltParseFindTopLevelElem(cctxt, cur,
  5605. BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)
  5606. {
  5607. if (xsltParseStylesheetImport(cctxt->style, cur) != 0) {
  5608. cctxt->style->errors++;
  5609. }
  5610. cur = cur->next;
  5611. }
  5612. if (cur == NULL)
  5613. goto exit;
  5614. start = cur;
  5615. /*
  5616. * Pre-process all xsl:include elements.
  5617. */
  5618. cur = start;
  5619. while ((cur != NULL) &&
  5620. xsltParseFindTopLevelElem(cctxt, cur,
  5621. BAD_CAST "include", XSLT_NAMESPACE, 0, &cur) == 1)
  5622. {
  5623. xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_INCLUDE);
  5624. cur = cur->next;
  5625. }
  5626. /*
  5627. * Pre-process all xsl:namespace-alias elements.
  5628. * URGENT TODO: This won't work correctly: the order of included
  5629. * aliases and aliases defined here is significant.
  5630. */
  5631. cur = start;
  5632. while ((cur != NULL) &&
  5633. xsltParseFindTopLevelElem(cctxt, cur,
  5634. BAD_CAST "namespace-alias", XSLT_NAMESPACE, 0, &cur) == 1)
  5635. {
  5636. xsltNamespaceAlias(cctxt->style, cur);
  5637. cur = cur->next;
  5638. }
  5639. if (cctxt->isInclude) {
  5640. /*
  5641. * If this stylesheet is intended for inclusion, then
  5642. * we will process only imports and includes.
  5643. */
  5644. goto exit;
  5645. }
  5646. /*
  5647. * Now parse the rest of the top-level elements.
  5648. */
  5649. xsltParseXSLTStylesheetElemCore(cctxt, node);
  5650. exit:
  5651. return(0);
  5652. }
  5653. #else /* XSLT_REFACTORED */
  5654. /**
  5655. * xsltParseStylesheetTop:
  5656. * @style: the XSLT stylesheet
  5657. * @top: the top level "stylesheet" or "transform" element
  5658. *
  5659. * scan the top level elements of an XSL stylesheet
  5660. */
  5661. static void
  5662. xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
  5663. xmlNodePtr cur;
  5664. xmlChar *prop;
  5665. #ifdef WITH_XSLT_DEBUG_PARSING
  5666. int templates = 0;
  5667. #endif
  5668. if ((top == NULL) || (top->type != XML_ELEMENT_NODE))
  5669. return;
  5670. prop = xmlGetNsProp(top, (const xmlChar *)"version", NULL);
  5671. if (prop == NULL) {
  5672. xsltTransformError(NULL, style, top,
  5673. "xsl:version is missing: document may not be a stylesheet\n");
  5674. if (style != NULL) style->warnings++;
  5675. } else {
  5676. if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
  5677. (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
  5678. xsltTransformError(NULL, style, top,
  5679. "xsl:version: only 1.1 features are supported\n");
  5680. if (style != NULL) {
  5681. style->forwards_compatible = 1;
  5682. style->warnings++;
  5683. }
  5684. }
  5685. xmlFree(prop);
  5686. }
  5687. /*
  5688. * process xsl:import elements
  5689. */
  5690. cur = top->children;
  5691. while (cur != NULL) {
  5692. if (IS_BLANK_NODE(cur)) {
  5693. cur = cur->next;
  5694. continue;
  5695. }
  5696. if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "import")) {
  5697. if (xsltParseStylesheetImport(style, cur) != 0)
  5698. if (style != NULL) style->errors++;
  5699. } else
  5700. break;
  5701. cur = cur->next;
  5702. }
  5703. /*
  5704. * process other top-level elements
  5705. */
  5706. while (cur != NULL) {
  5707. if (IS_BLANK_NODE(cur)) {
  5708. cur = cur->next;
  5709. continue;
  5710. }
  5711. if (cur->type == XML_TEXT_NODE) {
  5712. if (cur->content != NULL) {
  5713. xsltTransformError(NULL, style, cur,
  5714. "misplaced text node: '%s'\n", cur->content);
  5715. }
  5716. if (style != NULL) style->errors++;
  5717. cur = cur->next;
  5718. continue;
  5719. }
  5720. if ((cur->type == XML_ELEMENT_NODE) && (cur->ns == NULL)) {
  5721. xsltGenericError(xsltGenericErrorContext,
  5722. "Found a top-level element %s with null namespace URI\n",
  5723. cur->name);
  5724. if (style != NULL) style->errors++;
  5725. cur = cur->next;
  5726. continue;
  5727. }
  5728. if ((cur->type == XML_ELEMENT_NODE) && (!(IS_XSLT_ELEM(cur)))) {
  5729. xsltTopLevelFunction function;
  5730. function = xsltExtModuleTopLevelLookup(cur->name,
  5731. cur->ns->href);
  5732. if (function != NULL)
  5733. function(style, cur);
  5734. #ifdef WITH_XSLT_DEBUG_PARSING
  5735. xsltGenericDebug(xsltGenericDebugContext,
  5736. "xsltParseStylesheetTop : found foreign element %s\n",
  5737. cur->name);
  5738. #endif
  5739. cur = cur->next;
  5740. continue;
  5741. }
  5742. if (IS_XSLT_NAME(cur, "import")) {
  5743. xsltTransformError(NULL, style, cur,
  5744. "xsltParseStylesheetTop: ignoring misplaced import element\n");
  5745. if (style != NULL) style->errors++;
  5746. } else if (IS_XSLT_NAME(cur, "include")) {
  5747. if (xsltParseStylesheetInclude(style, cur) != 0)
  5748. if (style != NULL) style->errors++;
  5749. } else if (IS_XSLT_NAME(cur, "strip-space")) {
  5750. xsltParseStylesheetStripSpace(style, cur);
  5751. } else if (IS_XSLT_NAME(cur, "preserve-space")) {
  5752. xsltParseStylesheetPreserveSpace(style, cur);
  5753. } else if (IS_XSLT_NAME(cur, "output")) {
  5754. xsltParseStylesheetOutput(style, cur);
  5755. } else if (IS_XSLT_NAME(cur, "key")) {
  5756. xsltParseStylesheetKey(style, cur);
  5757. } else if (IS_XSLT_NAME(cur, "decimal-format")) {
  5758. xsltParseStylesheetDecimalFormat(style, cur);
  5759. } else if (IS_XSLT_NAME(cur, "attribute-set")) {
  5760. xsltParseStylesheetAttributeSet(style, cur);
  5761. } else if (IS_XSLT_NAME(cur, "variable")) {
  5762. xsltParseGlobalVariable(style, cur);
  5763. } else if (IS_XSLT_NAME(cur, "param")) {
  5764. xsltParseGlobalParam(style, cur);
  5765. } else if (IS_XSLT_NAME(cur, "template")) {
  5766. #ifdef WITH_XSLT_DEBUG_PARSING
  5767. templates++;
  5768. #endif
  5769. xsltParseStylesheetTemplate(style, cur);
  5770. } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
  5771. xsltNamespaceAlias(style, cur);
  5772. } else {
  5773. if ((style != NULL) && (style->forwards_compatible == 0)) {
  5774. xsltTransformError(NULL, style, cur,
  5775. "xsltParseStylesheetTop: unknown %s element\n",
  5776. cur->name);
  5777. if (style != NULL) style->errors++;
  5778. }
  5779. }
  5780. cur = cur->next;
  5781. }
  5782. #ifdef WITH_XSLT_DEBUG_PARSING
  5783. xsltGenericDebug(xsltGenericDebugContext,
  5784. "parsed %d templates\n", templates);
  5785. #endif
  5786. }
  5787. #endif /* else of XSLT_REFACTORED */
  5788. #ifdef XSLT_REFACTORED
  5789. /**
  5790. * xsltParseSimplifiedStylesheetTree:
  5791. *
  5792. * @style: the stylesheet (TODO: Change this to the compiler context)
  5793. * @doc: the document containing the stylesheet.
  5794. * @node: the node where the stylesheet is rooted at
  5795. *
  5796. * Returns 0 in case of success, a positive result if an error occurred
  5797. * and -1 on API and internal errors.
  5798. */
  5799. static int
  5800. xsltParseSimplifiedStylesheetTree(xsltCompilerCtxtPtr cctxt,
  5801. xmlDocPtr doc,
  5802. xmlNodePtr node)
  5803. {
  5804. xsltTemplatePtr templ;
  5805. if ((cctxt == NULL) || (node == NULL))
  5806. return(-1);
  5807. if (xsltParseAttrXSLTVersion(cctxt, node, 0) == XSLT_ELEMENT_CATEGORY_LRE)
  5808. {
  5809. /*
  5810. * TODO: Adjust report, since this might be an
  5811. * embedded stylesheet.
  5812. */
  5813. xsltTransformError(NULL, cctxt->style, node,
  5814. "The attribute 'xsl:version' is missing; cannot identify "
  5815. "this document as an XSLT stylesheet document.\n");
  5816. cctxt->style->errors++;
  5817. return(1);
  5818. }
  5819. #ifdef WITH_XSLT_DEBUG_PARSING
  5820. xsltGenericDebug(xsltGenericDebugContext,
  5821. "xsltParseSimplifiedStylesheetTree: document is stylesheet\n");
  5822. #endif
  5823. /*
  5824. * Create and link the template
  5825. */
  5826. templ = xsltNewTemplate();
  5827. if (templ == NULL) {
  5828. return(-1);
  5829. }
  5830. templ->next = cctxt->style->templates;
  5831. cctxt->style->templates = templ;
  5832. templ->match = xmlStrdup(BAD_CAST "/");
  5833. /*
  5834. * Note that we push the document-node in this special case.
  5835. */
  5836. xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);
  5837. /*
  5838. * In every case, we need to have
  5839. * the in-scope namespaces of the element, where the
  5840. * stylesheet is rooted at, regardless if it's an XSLT
  5841. * instruction or a literal result instruction (or if
  5842. * this is an embedded stylesheet).
  5843. */
  5844. cctxt->inode->inScopeNs =
  5845. xsltCompilerBuildInScopeNsList(cctxt, node);
  5846. /*
  5847. * Parse the content and register the match-pattern.
  5848. */
  5849. xsltParseSequenceConstructor(cctxt, node);
  5850. xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);
  5851. templ->elem = (xmlNodePtr) doc;
  5852. templ->content = node;
  5853. xsltAddTemplate(cctxt->style, templ, NULL, NULL);
  5854. cctxt->style->literal_result = 1;
  5855. return(0);
  5856. }
  5857. #ifdef XSLT_REFACTORED_XSLT_NSCOMP
  5858. /**
  5859. * xsltRestoreDocumentNamespaces:
  5860. * @ns: map of namespaces
  5861. * @doc: the document
  5862. *
  5863. * Restore the namespaces for the document
  5864. *
  5865. * Returns 0 in case of success, -1 in case of failure
  5866. */
  5867. int
  5868. xsltRestoreDocumentNamespaces(xsltNsMapPtr ns, xmlDocPtr doc)
  5869. {
  5870. if (doc == NULL)
  5871. return(-1);
  5872. /*
  5873. * Revert the changes we have applied to the namespace-URIs of
  5874. * ns-decls.
  5875. */
  5876. while (ns != NULL) {
  5877. if ((ns->doc == doc) && (ns->ns != NULL)) {
  5878. ns->ns->href = ns->origNsName;
  5879. ns->origNsName = NULL;
  5880. ns->ns = NULL;
  5881. }
  5882. ns = ns->next;
  5883. }
  5884. return(0);
  5885. }
  5886. #endif /* XSLT_REFACTORED_XSLT_NSCOMP */
  5887. /**
  5888. * xsltParseStylesheetProcess:
  5889. * @style: the XSLT stylesheet (the current stylesheet-level)
  5890. * @doc: and xmlDoc parsed XML
  5891. *
  5892. * Parses an XSLT stylesheet, adding the associated structures.
  5893. * Called by:
  5894. * xsltParseStylesheetImportedDoc() (xslt.c)
  5895. * xsltParseStylesheetInclude() (imports.c)
  5896. *
  5897. * Returns the value of the @style parameter if everything
  5898. * went right, NULL if something went amiss.
  5899. */
  5900. xsltStylesheetPtr
  5901. xsltParseStylesheetProcess(xsltStylesheetPtr style, xmlDocPtr doc)
  5902. {
  5903. xsltCompilerCtxtPtr cctxt;
  5904. xmlNodePtr cur;
  5905. int oldIsSimplifiedStylesheet;
  5906. xsltInitGlobals();
  5907. if ((style == NULL) || (doc == NULL))
  5908. return(NULL);
  5909. cctxt = XSLT_CCTXT(style);
  5910. cur = xmlDocGetRootElement(doc);
  5911. if (cur == NULL) {
  5912. xsltTransformError(NULL, style, (xmlNodePtr) doc,
  5913. "xsltParseStylesheetProcess : empty stylesheet\n");
  5914. return(NULL);
  5915. }
  5916. oldIsSimplifiedStylesheet = cctxt->simplified;
  5917. if ((IS_XSLT_ELEM(cur)) &&
  5918. ((IS_XSLT_NAME(cur, "stylesheet")) ||
  5919. (IS_XSLT_NAME(cur, "transform")))) {
  5920. #ifdef WITH_XSLT_DEBUG_PARSING
  5921. xsltGenericDebug(xsltGenericDebugContext,
  5922. "xsltParseStylesheetProcess : found stylesheet\n");
  5923. #endif
  5924. cctxt->simplified = 0;
  5925. style->literal_result = 0;
  5926. } else {
  5927. cctxt->simplified = 1;
  5928. style->literal_result = 1;
  5929. }
  5930. /*
  5931. * Pre-process the stylesheet if not already done before.
  5932. * This will remove PIs and comments, merge adjacent
  5933. * text nodes, internalize strings, etc.
  5934. */
  5935. if (! style->nopreproc)
  5936. xsltParsePreprocessStylesheetTree(cctxt, cur);
  5937. /*
  5938. * Parse and compile the stylesheet.
  5939. */
  5940. if (style->literal_result == 0) {
  5941. if (xsltParseXSLTStylesheetElem(cctxt, cur) != 0)
  5942. return(NULL);
  5943. } else {
  5944. if (xsltParseSimplifiedStylesheetTree(cctxt, doc, cur) != 0)
  5945. return(NULL);
  5946. }
  5947. cctxt->simplified = oldIsSimplifiedStylesheet;
  5948. return(style);
  5949. }
  5950. #else /* XSLT_REFACTORED */
  5951. /**
  5952. * xsltParseStylesheetProcess:
  5953. * @ret: the XSLT stylesheet (the current stylesheet-level)
  5954. * @doc: and xmlDoc parsed XML
  5955. *
  5956. * Parses an XSLT stylesheet, adding the associated structures.
  5957. * Called by:
  5958. * xsltParseStylesheetImportedDoc() (xslt.c)
  5959. * xsltParseStylesheetInclude() (imports.c)
  5960. *
  5961. * Returns the value of the @style parameter if everything
  5962. * went right, NULL if something went amiss.
  5963. */
  5964. xsltStylesheetPtr
  5965. xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
  5966. xmlNodePtr cur;
  5967. xsltInitGlobals();
  5968. if (doc == NULL)
  5969. return(NULL);
  5970. if (ret == NULL)
  5971. return(ret);
  5972. /*
  5973. * First steps, remove blank nodes,
  5974. * locate the xsl:stylesheet element and the
  5975. * namespace declaration.
  5976. */
  5977. cur = xmlDocGetRootElement(doc);
  5978. if (cur == NULL) {
  5979. xsltTransformError(NULL, ret, (xmlNodePtr) doc,
  5980. "xsltParseStylesheetProcess : empty stylesheet\n");
  5981. return(NULL);
  5982. }
  5983. if ((IS_XSLT_ELEM(cur)) &&
  5984. ((IS_XSLT_NAME(cur, "stylesheet")) ||
  5985. (IS_XSLT_NAME(cur, "transform")))) {
  5986. #ifdef WITH_XSLT_DEBUG_PARSING
  5987. xsltGenericDebug(xsltGenericDebugContext,
  5988. "xsltParseStylesheetProcess : found stylesheet\n");
  5989. #endif
  5990. ret->literal_result = 0;
  5991. xsltParseStylesheetExcludePrefix(ret, cur, 1);
  5992. xsltParseStylesheetExtPrefix(ret, cur, 1);
  5993. } else {
  5994. xsltParseStylesheetExcludePrefix(ret, cur, 0);
  5995. xsltParseStylesheetExtPrefix(ret, cur, 0);
  5996. ret->literal_result = 1;
  5997. }
  5998. if (!ret->nopreproc) {
  5999. xsltPreprocessStylesheet(ret, cur);
  6000. }
  6001. if (ret->literal_result == 0) {
  6002. xsltParseStylesheetTop(ret, cur);
  6003. } else {
  6004. xmlChar *prop;
  6005. xsltTemplatePtr template;
  6006. /*
  6007. * the document itself might be the template, check xsl:version
  6008. */
  6009. prop = xmlGetNsProp(cur, (const xmlChar *)"version", XSLT_NAMESPACE);
  6010. if (prop == NULL) {
  6011. xsltTransformError(NULL, ret, cur,
  6012. "xsltParseStylesheetProcess : document is not a stylesheet\n");
  6013. return(NULL);
  6014. }
  6015. #ifdef WITH_XSLT_DEBUG_PARSING
  6016. xsltGenericDebug(xsltGenericDebugContext,
  6017. "xsltParseStylesheetProcess : document is stylesheet\n");
  6018. #endif
  6019. if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
  6020. (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
  6021. xsltTransformError(NULL, ret, cur,
  6022. "xsl:version: only 1.1 features are supported\n");
  6023. ret->forwards_compatible = 1;
  6024. ret->warnings++;
  6025. }
  6026. xmlFree(prop);
  6027. /*
  6028. * Create and link the template
  6029. */
  6030. template = xsltNewTemplate();
  6031. if (template == NULL) {
  6032. return(NULL);
  6033. }
  6034. template->next = ret->templates;
  6035. ret->templates = template;
  6036. template->match = xmlStrdup((const xmlChar *)"/");
  6037. /*
  6038. * parse the content and register the pattern
  6039. */
  6040. xsltParseTemplateContent(ret, (xmlNodePtr) doc);
  6041. template->elem = (xmlNodePtr) doc;
  6042. template->content = doc->children;
  6043. xsltAddTemplate(ret, template, NULL, NULL);
  6044. ret->literal_result = 1;
  6045. }
  6046. return(ret);
  6047. }
  6048. #endif /* else of XSLT_REFACTORED */
  6049. /**
  6050. * xsltParseStylesheetImportedDoc:
  6051. * @doc: an xmlDoc parsed XML
  6052. * @parentStyle: pointer to the parent stylesheet (if it exists)
  6053. *
  6054. * parse an XSLT stylesheet building the associated structures
  6055. * except the processing not needed for imported documents.
  6056. *
  6057. * Returns a new XSLT stylesheet structure.
  6058. */
  6059. xsltStylesheetPtr
  6060. xsltParseStylesheetImportedDoc(xmlDocPtr doc,
  6061. xsltStylesheetPtr parentStyle) {
  6062. xsltStylesheetPtr retStyle;
  6063. if (doc == NULL)
  6064. return(NULL);
  6065. retStyle = xsltNewStylesheetInternal(parentStyle);
  6066. if (retStyle == NULL)
  6067. return(NULL);
  6068. if (xsltParseStylesheetUser(retStyle, doc) != 0) {
  6069. xsltFreeStylesheet(retStyle);
  6070. return(NULL);
  6071. }
  6072. return(retStyle);
  6073. }
  6074. /**
  6075. * xsltParseStylesheetUser:
  6076. * @style: pointer to the stylesheet
  6077. * @doc: an xmlDoc parsed XML
  6078. *
  6079. * Parse an XSLT stylesheet with a user-provided stylesheet struct.
  6080. *
  6081. * Returns 0 if successful, -1 in case of error.
  6082. */
  6083. int
  6084. xsltParseStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc) {
  6085. if ((style == NULL) || (doc == NULL))
  6086. return(-1);
  6087. /*
  6088. * Adjust the string dict.
  6089. */
  6090. if (doc->dict != NULL) {
  6091. xmlDictFree(style->dict);
  6092. style->dict = doc->dict;
  6093. #ifdef WITH_XSLT_DEBUG
  6094. xsltGenericDebug(xsltGenericDebugContext,
  6095. "reusing dictionary from %s for stylesheet\n",
  6096. doc->URL);
  6097. #endif
  6098. xmlDictReference(style->dict);
  6099. }
  6100. /*
  6101. * TODO: Eliminate xsltGatherNamespaces(); we must not restrict
  6102. * the stylesheet to containt distinct namespace prefixes.
  6103. */
  6104. xsltGatherNamespaces(style);
  6105. #ifdef XSLT_REFACTORED
  6106. {
  6107. xsltCompilerCtxtPtr cctxt;
  6108. xsltStylesheetPtr oldCurSheet;
  6109. if (style->parent == NULL) {
  6110. xsltPrincipalStylesheetDataPtr principalData;
  6111. /*
  6112. * Create extra data for the principal stylesheet.
  6113. */
  6114. principalData = xsltNewPrincipalStylesheetData();
  6115. if (principalData == NULL) {
  6116. return(-1);
  6117. }
  6118. style->principalData = principalData;
  6119. /*
  6120. * Create the compilation context
  6121. * ------------------------------
  6122. * (only once; for the principal stylesheet).
  6123. * This is currently the only function where the
  6124. * compilation context is created.
  6125. */
  6126. cctxt = xsltCompilationCtxtCreate(style);
  6127. if (cctxt == NULL) {
  6128. return(-1);
  6129. }
  6130. style->compCtxt = (void *) cctxt;
  6131. cctxt->style = style;
  6132. cctxt->dict = style->dict;
  6133. cctxt->psData = principalData;
  6134. /*
  6135. * Push initial dummy node info.
  6136. */
  6137. cctxt->depth = -1;
  6138. xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);
  6139. } else {
  6140. /*
  6141. * Imported stylesheet.
  6142. */
  6143. cctxt = style->parent->compCtxt;
  6144. style->compCtxt = cctxt;
  6145. }
  6146. /*
  6147. * Save the old and set the current stylesheet structure in the
  6148. * compilation context.
  6149. */
  6150. oldCurSheet = cctxt->style;
  6151. cctxt->style = style;
  6152. style->doc = doc;
  6153. xsltParseStylesheetProcess(style, doc);
  6154. cctxt->style = oldCurSheet;
  6155. if (style->parent == NULL) {
  6156. /*
  6157. * Pop the initial dummy node info.
  6158. */
  6159. xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);
  6160. } else {
  6161. /*
  6162. * Clear the compilation context of imported
  6163. * stylesheets.
  6164. * TODO: really?
  6165. */
  6166. /* style->compCtxt = NULL; */
  6167. }
  6168. #ifdef XSLT_REFACTORED_XSLT_NSCOMP
  6169. if (style->errors != 0) {
  6170. /*
  6171. * Restore all changes made to namespace URIs of ns-decls.
  6172. */
  6173. if (cctxt->psData->nsMap)
  6174. xsltRestoreDocumentNamespaces(cctxt->psData->nsMap, doc);
  6175. }
  6176. #endif
  6177. if (style->parent == NULL) {
  6178. xsltCompilationCtxtFree(style->compCtxt);
  6179. style->compCtxt = NULL;
  6180. }
  6181. }
  6182. #else /* XSLT_REFACTORED */
  6183. /*
  6184. * Old behaviour.
  6185. */
  6186. style->doc = doc;
  6187. if (xsltParseStylesheetProcess(style, doc) == NULL) {
  6188. style->doc = NULL;
  6189. return(-1);
  6190. }
  6191. #endif /* else of XSLT_REFACTORED */
  6192. if (style->errors != 0) {
  6193. /*
  6194. * Detach the doc from the stylesheet; otherwise the doc
  6195. * will be freed in xsltFreeStylesheet().
  6196. */
  6197. style->doc = NULL;
  6198. /*
  6199. * Cleanup the doc if its the main stylesheet.
  6200. */
  6201. if (style->parent == NULL)
  6202. xsltCleanupStylesheetTree(doc, xmlDocGetRootElement(doc));
  6203. return(-1);
  6204. }
  6205. if (style->parent == NULL)
  6206. xsltResolveStylesheetAttributeSet(style);
  6207. return(0);
  6208. }
  6209. /**
  6210. * xsltParseStylesheetDoc:
  6211. * @doc: and xmlDoc parsed XML
  6212. *
  6213. * parse an XSLT stylesheet, building the associated structures. doc
  6214. * is kept as a reference within the returned stylesheet, so changes
  6215. * to doc after the parsing will be reflected when the stylesheet
  6216. * is applied, and the doc is automatically freed when the
  6217. * stylesheet is closed.
  6218. *
  6219. * Returns a new XSLT stylesheet structure.
  6220. */
  6221. xsltStylesheetPtr
  6222. xsltParseStylesheetDoc(xmlDocPtr doc) {
  6223. xsltInitGlobals();
  6224. return(xsltParseStylesheetImportedDoc(doc, NULL));
  6225. }
  6226. /**
  6227. * xsltParseStylesheetFile:
  6228. * @filename: the filename/URL to the stylesheet
  6229. *
  6230. * Load and parse an XSLT stylesheet
  6231. *
  6232. * Returns a new XSLT stylesheet structure.
  6233. */
  6234. xsltStylesheetPtr
  6235. xsltParseStylesheetFile(const xmlChar* filename) {
  6236. xsltSecurityPrefsPtr sec;
  6237. xsltStylesheetPtr ret;
  6238. xmlDocPtr doc;
  6239. xsltInitGlobals();
  6240. if (filename == NULL)
  6241. return(NULL);
  6242. #ifdef WITH_XSLT_DEBUG_PARSING
  6243. xsltGenericDebug(xsltGenericDebugContext,
  6244. "xsltParseStylesheetFile : parse %s\n", filename);
  6245. #endif
  6246. /*
  6247. * Security framework check
  6248. */
  6249. sec = xsltGetDefaultSecurityPrefs();
  6250. if (sec != NULL) {
  6251. int res;
  6252. res = xsltCheckRead(sec, NULL, filename);
  6253. if (res <= 0) {
  6254. if (res == 0)
  6255. xsltTransformError(NULL, NULL, NULL,
  6256. "xsltParseStylesheetFile: read rights for %s denied\n",
  6257. filename);
  6258. return(NULL);
  6259. }
  6260. }
  6261. doc = xsltDocDefaultLoader(filename, NULL, XSLT_PARSE_OPTIONS,
  6262. NULL, XSLT_LOAD_START);
  6263. if (doc == NULL) {
  6264. xsltTransformError(NULL, NULL, NULL,
  6265. "xsltParseStylesheetFile : cannot parse %s\n", filename);
  6266. return(NULL);
  6267. }
  6268. ret = xsltParseStylesheetDoc(doc);
  6269. if (ret == NULL) {
  6270. xmlFreeDoc(doc);
  6271. return(NULL);
  6272. }
  6273. return(ret);
  6274. }
  6275. /************************************************************************
  6276. * *
  6277. * Handling of Stylesheet PI *
  6278. * *
  6279. ************************************************************************/
  6280. #define CUR (*cur)
  6281. #define SKIP(val) cur += (val)
  6282. #define NXT(val) cur[(val)]
  6283. #define SKIP_BLANKS \
  6284. while (IS_BLANK(CUR)) NEXT
  6285. #define NEXT ((*cur) ? cur++ : cur)
  6286. /**
  6287. * xsltParseStylesheetPI:
  6288. * @value: the value of the PI
  6289. *
  6290. * This function checks that the type is text/xml and extracts
  6291. * the URI-Reference for the stylesheet
  6292. *
  6293. * Returns the URI-Reference for the stylesheet or NULL (it need to
  6294. * be freed by the caller)
  6295. */
  6296. static xmlChar *
  6297. xsltParseStylesheetPI(const xmlChar *value) {
  6298. const xmlChar *cur;
  6299. const xmlChar *start;
  6300. xmlChar *val;
  6301. xmlChar tmp;
  6302. xmlChar *href = NULL;
  6303. int isXml = 0;
  6304. if (value == NULL)
  6305. return(NULL);
  6306. cur = value;
  6307. while (CUR != 0) {
  6308. SKIP_BLANKS;
  6309. if ((CUR == 't') && (NXT(1) == 'y') && (NXT(2) == 'p') &&
  6310. (NXT(3) == 'e')) {
  6311. SKIP(4);
  6312. SKIP_BLANKS;
  6313. if (CUR != '=')
  6314. continue;
  6315. NEXT;
  6316. if ((CUR != '\'') && (CUR != '"'))
  6317. continue;
  6318. tmp = CUR;
  6319. NEXT;
  6320. start = cur;
  6321. while ((CUR != 0) && (CUR != tmp))
  6322. NEXT;
  6323. if (CUR != tmp)
  6324. continue;
  6325. val = xmlStrndup(start, cur - start);
  6326. NEXT;
  6327. if (val == NULL)
  6328. return(NULL);
  6329. if ((xmlStrcasecmp(val, BAD_CAST "text/xml")) &&
  6330. (xmlStrcasecmp(val, BAD_CAST "text/xsl"))) {
  6331. xmlFree(val);
  6332. break;
  6333. }
  6334. isXml = 1;
  6335. xmlFree(val);
  6336. } else if ((CUR == 'h') && (NXT(1) == 'r') && (NXT(2) == 'e') &&
  6337. (NXT(3) == 'f')) {
  6338. SKIP(4);
  6339. SKIP_BLANKS;
  6340. if (CUR != '=')
  6341. continue;
  6342. NEXT;
  6343. if ((CUR != '\'') && (CUR != '"'))
  6344. continue;
  6345. tmp = CUR;
  6346. NEXT;
  6347. start = cur;
  6348. while ((CUR != 0) && (CUR != tmp))
  6349. NEXT;
  6350. if (CUR != tmp)
  6351. continue;
  6352. if (href == NULL)
  6353. href = xmlStrndup(start, cur - start);
  6354. NEXT;
  6355. } else {
  6356. while ((CUR != 0) && (!IS_BLANK(CUR)))
  6357. NEXT;
  6358. }
  6359. }
  6360. if (!isXml) {
  6361. if (href != NULL)
  6362. xmlFree(href);
  6363. href = NULL;
  6364. }
  6365. return(href);
  6366. }
  6367. /**
  6368. * xsltLoadStylesheetPI:
  6369. * @doc: a document to process
  6370. *
  6371. * This function tries to locate the stylesheet PI in the given document
  6372. * If found, and if contained within the document, it will extract
  6373. * that subtree to build the stylesheet to process @doc (doc itself will
  6374. * be modified). If found but referencing an external document it will
  6375. * attempt to load it and generate a stylesheet from it. In both cases,
  6376. * the resulting stylesheet and the document need to be freed once the
  6377. * transformation is done.
  6378. *
  6379. * Returns a new XSLT stylesheet structure or NULL if not found.
  6380. */
  6381. xsltStylesheetPtr
  6382. xsltLoadStylesheetPI(xmlDocPtr doc) {
  6383. xmlNodePtr child;
  6384. xsltStylesheetPtr ret = NULL;
  6385. xmlChar *href = NULL;
  6386. xmlURIPtr URI;
  6387. xsltInitGlobals();
  6388. if (doc == NULL)
  6389. return(NULL);
  6390. /*
  6391. * Find the text/xml stylesheet PI id any before the root
  6392. */
  6393. child = doc->children;
  6394. while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) {
  6395. if ((child->type == XML_PI_NODE) &&
  6396. (xmlStrEqual(child->name, BAD_CAST "xml-stylesheet"))) {
  6397. href = xsltParseStylesheetPI(child->content);
  6398. if (href != NULL)
  6399. break;
  6400. }
  6401. child = child->next;
  6402. }
  6403. /*
  6404. * If found check the href to select processing
  6405. */
  6406. if (href != NULL) {
  6407. #ifdef WITH_XSLT_DEBUG_PARSING
  6408. xsltGenericDebug(xsltGenericDebugContext,
  6409. "xsltLoadStylesheetPI : found PI href=%s\n", href);
  6410. #endif
  6411. URI = xmlParseURI((const char *) href);
  6412. if (URI == NULL) {
  6413. xsltTransformError(NULL, NULL, child,
  6414. "xml-stylesheet : href %s is not valid\n", href);
  6415. xmlFree(href);
  6416. return(NULL);
  6417. }
  6418. if ((URI->fragment != NULL) && (URI->scheme == NULL) &&
  6419. (URI->opaque == NULL) && (URI->authority == NULL) &&
  6420. (URI->server == NULL) && (URI->user == NULL) &&
  6421. (URI->path == NULL) && (URI->query == NULL)) {
  6422. xmlAttrPtr ID;
  6423. #ifdef WITH_XSLT_DEBUG_PARSING
  6424. xsltGenericDebug(xsltGenericDebugContext,
  6425. "xsltLoadStylesheetPI : Reference to ID %s\n", href);
  6426. #endif
  6427. if (URI->fragment[0] == '#')
  6428. ID = xmlGetID(doc, (const xmlChar *) &(URI->fragment[1]));
  6429. else
  6430. ID = xmlGetID(doc, (const xmlChar *) URI->fragment);
  6431. if (ID == NULL) {
  6432. xsltTransformError(NULL, NULL, child,
  6433. "xml-stylesheet : no ID %s found\n", URI->fragment);
  6434. } else {
  6435. xmlDocPtr fake;
  6436. xmlNodePtr subtree, newtree;
  6437. xmlNsPtr ns;
  6438. #ifdef WITH_XSLT_DEBUG
  6439. xsltGenericDebug(xsltGenericDebugContext,
  6440. "creating new document from %s for embedded stylesheet\n",
  6441. doc->URL);
  6442. #endif
  6443. /*
  6444. * move the subtree in a new document passed to
  6445. * the stylesheet analyzer
  6446. */
  6447. subtree = ID->parent;
  6448. fake = xmlNewDoc(NULL);
  6449. if (fake != NULL) {
  6450. /*
  6451. * Should the dictionary still be shared even though
  6452. * the nodes are being copied rather than moved?
  6453. */
  6454. fake->dict = doc->dict;
  6455. xmlDictReference(doc->dict);
  6456. #ifdef WITH_XSLT_DEBUG
  6457. xsltGenericDebug(xsltGenericDebugContext,
  6458. "reusing dictionary from %s for embedded stylesheet\n",
  6459. doc->URL);
  6460. #endif
  6461. newtree = xmlDocCopyNode(subtree, fake, 1);
  6462. fake->URL = xmlNodeGetBase(doc, subtree->parent);
  6463. #ifdef WITH_XSLT_DEBUG
  6464. xsltGenericDebug(xsltGenericDebugContext,
  6465. "set base URI for embedded stylesheet as %s\n",
  6466. fake->URL);
  6467. #endif
  6468. /*
  6469. * Add all namespaces in scope of embedded stylesheet to
  6470. * root element of newly created stylesheet document
  6471. */
  6472. while ((subtree = subtree->parent) != (xmlNodePtr)doc) {
  6473. for (ns = subtree->ns; ns; ns = ns->next) {
  6474. xmlNewNs(newtree, ns->href, ns->prefix);
  6475. }
  6476. }
  6477. xmlAddChild((xmlNodePtr)fake, newtree);
  6478. ret = xsltParseStylesheetDoc(fake);
  6479. if (ret == NULL)
  6480. xmlFreeDoc(fake);
  6481. }
  6482. }
  6483. } else {
  6484. xmlChar *URL, *base;
  6485. /*
  6486. * Reference to an external stylesheet
  6487. */
  6488. base = xmlNodeGetBase(doc, (xmlNodePtr) doc);
  6489. URL = xmlBuildURI(href, base);
  6490. if (URL != NULL) {
  6491. #ifdef WITH_XSLT_DEBUG_PARSING
  6492. xsltGenericDebug(xsltGenericDebugContext,
  6493. "xsltLoadStylesheetPI : fetching %s\n", URL);
  6494. #endif
  6495. ret = xsltParseStylesheetFile(URL);
  6496. xmlFree(URL);
  6497. } else {
  6498. #ifdef WITH_XSLT_DEBUG_PARSING
  6499. xsltGenericDebug(xsltGenericDebugContext,
  6500. "xsltLoadStylesheetPI : fetching %s\n", href);
  6501. #endif
  6502. ret = xsltParseStylesheetFile(href);
  6503. }
  6504. if (base != NULL)
  6505. xmlFree(base);
  6506. }
  6507. xmlFreeURI(URI);
  6508. xmlFree(href);
  6509. }
  6510. return(ret);
  6511. }