xslt.c 181 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047
  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. if ((cur->children->type != XML_ENTITY_DECL) &&
  3365. (cur->children->type != XML_ENTITY_REF_NODE) &&
  3366. (cur->children->type != XML_ENTITY_NODE)) {
  3367. cur = cur->children;
  3368. continue;
  3369. }
  3370. }
  3371. skip_children:
  3372. if (cur->next != NULL) {
  3373. cur = cur->next;
  3374. continue;
  3375. }
  3376. do {
  3377. cur = cur->parent;
  3378. if (cur == NULL)
  3379. break;
  3380. if (cur == (xmlNodePtr) style->doc) {
  3381. cur = NULL;
  3382. break;
  3383. }
  3384. if (cur->next != NULL) {
  3385. cur = cur->next;
  3386. break;
  3387. }
  3388. } while (cur != NULL);
  3389. }
  3390. if (deleteNode != NULL) {
  3391. #ifdef WITH_XSLT_DEBUG_PARSING
  3392. xsltGenericDebug(xsltGenericDebugContext,
  3393. "xsltPreprocessStylesheet: removing ignorable blank node\n");
  3394. #endif
  3395. xmlUnlinkNode(deleteNode);
  3396. xmlFreeNode(deleteNode);
  3397. }
  3398. }
  3399. #endif /* end of else XSLT_REFACTORED */
  3400. /**
  3401. * xsltGatherNamespaces:
  3402. * @style: the XSLT stylesheet
  3403. *
  3404. * Browse the stylesheet and build the namspace hash table which
  3405. * will be used for XPath interpretation. If needed do a bit of normalization
  3406. */
  3407. static void
  3408. xsltGatherNamespaces(xsltStylesheetPtr style) {
  3409. xmlNodePtr cur;
  3410. const xmlChar *URI;
  3411. if (style == NULL)
  3412. return;
  3413. /*
  3414. * TODO: basically if the stylesheet uses the same prefix for different
  3415. * patterns, well they may be in problem, hopefully they will get
  3416. * a warning first.
  3417. */
  3418. /*
  3419. * TODO: Eliminate the use of the hash for XPath expressions.
  3420. * An expression should be evaluated in the context of the in-scope
  3421. * namespaces; eliminate the restriction of an XML document to contain
  3422. * no duplicate prefixes for different namespace names.
  3423. *
  3424. */
  3425. cur = xmlDocGetRootElement(style->doc);
  3426. while (cur != NULL) {
  3427. if (cur->type == XML_ELEMENT_NODE) {
  3428. xmlNsPtr ns = cur->nsDef;
  3429. while (ns != NULL) {
  3430. if (ns->prefix != NULL) {
  3431. if (style->nsHash == NULL) {
  3432. style->nsHash = xmlHashCreate(10);
  3433. if (style->nsHash == NULL) {
  3434. xsltTransformError(NULL, style, cur,
  3435. "xsltGatherNamespaces: failed to create hash table\n");
  3436. style->errors++;
  3437. return;
  3438. }
  3439. }
  3440. URI = xmlHashLookup(style->nsHash, ns->prefix);
  3441. if ((URI != NULL) && (!xmlStrEqual(URI, ns->href))) {
  3442. xsltTransformError(NULL, style, cur,
  3443. "Namespaces prefix %s used for multiple namespaces\n",ns->prefix);
  3444. style->warnings++;
  3445. } else if (URI == NULL) {
  3446. xmlHashUpdateEntry(style->nsHash, ns->prefix,
  3447. (void *) ns->href, NULL);
  3448. #ifdef WITH_XSLT_DEBUG_PARSING
  3449. xsltGenericDebug(xsltGenericDebugContext,
  3450. "Added namespace: %s mapped to %s\n", ns->prefix, ns->href);
  3451. #endif
  3452. }
  3453. }
  3454. ns = ns->next;
  3455. }
  3456. }
  3457. /*
  3458. * Skip to next node
  3459. */
  3460. if (cur->children != NULL) {
  3461. if (cur->children->type != XML_ENTITY_DECL) {
  3462. cur = cur->children;
  3463. continue;
  3464. }
  3465. }
  3466. if (cur->next != NULL) {
  3467. cur = cur->next;
  3468. continue;
  3469. }
  3470. do {
  3471. cur = cur->parent;
  3472. if (cur == NULL)
  3473. break;
  3474. if (cur == (xmlNodePtr) style->doc) {
  3475. cur = NULL;
  3476. break;
  3477. }
  3478. if (cur->next != NULL) {
  3479. cur = cur->next;
  3480. break;
  3481. }
  3482. } while (cur != NULL);
  3483. }
  3484. }
  3485. #ifdef XSLT_REFACTORED
  3486. static xsltStyleType
  3487. xsltGetXSLTElementTypeByNode(xsltCompilerCtxtPtr cctxt,
  3488. xmlNodePtr node)
  3489. {
  3490. if ((node == NULL) || (node->type != XML_ELEMENT_NODE) ||
  3491. (node->name == NULL))
  3492. return(0);
  3493. if (node->name[0] == 'a') {
  3494. if (IS_XSLT_NAME(node, "apply-templates"))
  3495. return(XSLT_FUNC_APPLYTEMPLATES);
  3496. else if (IS_XSLT_NAME(node, "attribute"))
  3497. return(XSLT_FUNC_ATTRIBUTE);
  3498. else if (IS_XSLT_NAME(node, "apply-imports"))
  3499. return(XSLT_FUNC_APPLYIMPORTS);
  3500. else if (IS_XSLT_NAME(node, "attribute-set"))
  3501. return(0);
  3502. } else if (node->name[0] == 'c') {
  3503. if (IS_XSLT_NAME(node, "choose"))
  3504. return(XSLT_FUNC_CHOOSE);
  3505. else if (IS_XSLT_NAME(node, "copy"))
  3506. return(XSLT_FUNC_COPY);
  3507. else if (IS_XSLT_NAME(node, "copy-of"))
  3508. return(XSLT_FUNC_COPYOF);
  3509. else if (IS_XSLT_NAME(node, "call-template"))
  3510. return(XSLT_FUNC_CALLTEMPLATE);
  3511. else if (IS_XSLT_NAME(node, "comment"))
  3512. return(XSLT_FUNC_COMMENT);
  3513. } else if (node->name[0] == 'd') {
  3514. if (IS_XSLT_NAME(node, "document"))
  3515. return(XSLT_FUNC_DOCUMENT);
  3516. else if (IS_XSLT_NAME(node, "decimal-format"))
  3517. return(0);
  3518. } else if (node->name[0] == 'e') {
  3519. if (IS_XSLT_NAME(node, "element"))
  3520. return(XSLT_FUNC_ELEMENT);
  3521. } else if (node->name[0] == 'f') {
  3522. if (IS_XSLT_NAME(node, "for-each"))
  3523. return(XSLT_FUNC_FOREACH);
  3524. else if (IS_XSLT_NAME(node, "fallback"))
  3525. return(XSLT_FUNC_FALLBACK);
  3526. } else if (*(node->name) == 'i') {
  3527. if (IS_XSLT_NAME(node, "if"))
  3528. return(XSLT_FUNC_IF);
  3529. else if (IS_XSLT_NAME(node, "include"))
  3530. return(0);
  3531. else if (IS_XSLT_NAME(node, "import"))
  3532. return(0);
  3533. } else if (*(node->name) == 'k') {
  3534. if (IS_XSLT_NAME(node, "key"))
  3535. return(0);
  3536. } else if (*(node->name) == 'm') {
  3537. if (IS_XSLT_NAME(node, "message"))
  3538. return(XSLT_FUNC_MESSAGE);
  3539. } else if (*(node->name) == 'n') {
  3540. if (IS_XSLT_NAME(node, "number"))
  3541. return(XSLT_FUNC_NUMBER);
  3542. else if (IS_XSLT_NAME(node, "namespace-alias"))
  3543. return(0);
  3544. } else if (*(node->name) == 'o') {
  3545. if (IS_XSLT_NAME(node, "otherwise"))
  3546. return(XSLT_FUNC_OTHERWISE);
  3547. else if (IS_XSLT_NAME(node, "output"))
  3548. return(0);
  3549. } else if (*(node->name) == 'p') {
  3550. if (IS_XSLT_NAME(node, "param"))
  3551. return(XSLT_FUNC_PARAM);
  3552. else if (IS_XSLT_NAME(node, "processing-instruction"))
  3553. return(XSLT_FUNC_PI);
  3554. else if (IS_XSLT_NAME(node, "preserve-space"))
  3555. return(0);
  3556. } else if (*(node->name) == 's') {
  3557. if (IS_XSLT_NAME(node, "sort"))
  3558. return(XSLT_FUNC_SORT);
  3559. else if (IS_XSLT_NAME(node, "strip-space"))
  3560. return(0);
  3561. else if (IS_XSLT_NAME(node, "stylesheet"))
  3562. return(0);
  3563. } else if (node->name[0] == 't') {
  3564. if (IS_XSLT_NAME(node, "text"))
  3565. return(XSLT_FUNC_TEXT);
  3566. else if (IS_XSLT_NAME(node, "template"))
  3567. return(0);
  3568. else if (IS_XSLT_NAME(node, "transform"))
  3569. return(0);
  3570. } else if (*(node->name) == 'v') {
  3571. if (IS_XSLT_NAME(node, "value-of"))
  3572. return(XSLT_FUNC_VALUEOF);
  3573. else if (IS_XSLT_NAME(node, "variable"))
  3574. return(XSLT_FUNC_VARIABLE);
  3575. } else if (*(node->name) == 'w') {
  3576. if (IS_XSLT_NAME(node, "when"))
  3577. return(XSLT_FUNC_WHEN);
  3578. if (IS_XSLT_NAME(node, "with-param"))
  3579. return(XSLT_FUNC_WITHPARAM);
  3580. }
  3581. return(0);
  3582. }
  3583. /**
  3584. * xsltParseAnyXSLTElem:
  3585. *
  3586. * @cctxt: the compilation context
  3587. * @elem: the element node of the XSLT instruction
  3588. *
  3589. * Parses, validates the content models and compiles XSLT instructions.
  3590. *
  3591. * Returns 0 if everything's fine;
  3592. * -1 on API or internal errors.
  3593. */
  3594. int
  3595. xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
  3596. {
  3597. if ((cctxt == NULL) || (elem == NULL) ||
  3598. (elem->type != XML_ELEMENT_NODE))
  3599. return(-1);
  3600. elem->psvi = NULL;
  3601. if (! (IS_XSLT_ELEM_FAST(elem)))
  3602. return(-1);
  3603. /*
  3604. * Detection of handled content of extension instructions.
  3605. */
  3606. if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
  3607. cctxt->inode->extContentHandled = 1;
  3608. }
  3609. xsltCompilerNodePush(cctxt, elem);
  3610. /*
  3611. * URGENT TODO: Find a way to speed up this annoying redundant
  3612. * textual node-name and namespace comparison.
  3613. */
  3614. if (cctxt->inode->prev->curChildType != 0)
  3615. cctxt->inode->type = cctxt->inode->prev->curChildType;
  3616. else
  3617. cctxt->inode->type = xsltGetXSLTElementTypeByNode(cctxt, elem);
  3618. /*
  3619. * Update the in-scope namespaces if needed.
  3620. */
  3621. if (elem->nsDef != NULL)
  3622. cctxt->inode->inScopeNs =
  3623. xsltCompilerBuildInScopeNsList(cctxt, elem);
  3624. /*
  3625. * xsltStylePreCompute():
  3626. * This will compile the information found on the current
  3627. * element's attributes. NOTE that this won't process the
  3628. * children of the instruction.
  3629. */
  3630. xsltStylePreCompute(cctxt->style, elem);
  3631. /*
  3632. * TODO: How to react on errors in xsltStylePreCompute() ?
  3633. */
  3634. /*
  3635. * Validate the content model of the XSLT-element.
  3636. */
  3637. switch (cctxt->inode->type) {
  3638. case XSLT_FUNC_APPLYIMPORTS:
  3639. /* EMPTY */
  3640. goto empty_content;
  3641. case XSLT_FUNC_APPLYTEMPLATES:
  3642. /* <!-- Content: (xsl:sort | xsl:with-param)* --> */
  3643. goto apply_templates;
  3644. case XSLT_FUNC_ATTRIBUTE:
  3645. /* <!-- Content: template --> */
  3646. goto sequence_constructor;
  3647. case XSLT_FUNC_CALLTEMPLATE:
  3648. /* <!-- Content: xsl:with-param* --> */
  3649. goto call_template;
  3650. case XSLT_FUNC_CHOOSE:
  3651. /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */
  3652. goto choose;
  3653. case XSLT_FUNC_COMMENT:
  3654. /* <!-- Content: template --> */
  3655. goto sequence_constructor;
  3656. case XSLT_FUNC_COPY:
  3657. /* <!-- Content: template --> */
  3658. goto sequence_constructor;
  3659. case XSLT_FUNC_COPYOF:
  3660. /* EMPTY */
  3661. goto empty_content;
  3662. case XSLT_FUNC_DOCUMENT: /* Extra one */
  3663. /* ?? template ?? */
  3664. goto sequence_constructor;
  3665. case XSLT_FUNC_ELEMENT:
  3666. /* <!-- Content: template --> */
  3667. goto sequence_constructor;
  3668. case XSLT_FUNC_FALLBACK:
  3669. /* <!-- Content: template --> */
  3670. goto sequence_constructor;
  3671. case XSLT_FUNC_FOREACH:
  3672. /* <!-- Content: (xsl:sort*, template) --> */
  3673. goto for_each;
  3674. case XSLT_FUNC_IF:
  3675. /* <!-- Content: template --> */
  3676. goto sequence_constructor;
  3677. case XSLT_FUNC_OTHERWISE:
  3678. /* <!-- Content: template --> */
  3679. goto sequence_constructor;
  3680. case XSLT_FUNC_MESSAGE:
  3681. /* <!-- Content: template --> */
  3682. goto sequence_constructor;
  3683. case XSLT_FUNC_NUMBER:
  3684. /* EMPTY */
  3685. goto empty_content;
  3686. case XSLT_FUNC_PARAM:
  3687. /*
  3688. * Check for redefinition.
  3689. */
  3690. if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
  3691. xsltVarInfoPtr ivar = cctxt->ivar;
  3692. do {
  3693. if ((ivar->name ==
  3694. ((xsltStyleItemParamPtr) elem->psvi)->name) &&
  3695. (ivar->nsName ==
  3696. ((xsltStyleItemParamPtr) elem->psvi)->ns))
  3697. {
  3698. elem->psvi = NULL;
  3699. xsltTransformError(NULL, cctxt->style, elem,
  3700. "Redefinition of variable or parameter '%s'.\n",
  3701. ivar->name);
  3702. cctxt->style->errors++;
  3703. goto error;
  3704. }
  3705. ivar = ivar->prev;
  3706. } while (ivar != NULL);
  3707. }
  3708. /* <!-- Content: template --> */
  3709. goto sequence_constructor;
  3710. case XSLT_FUNC_PI:
  3711. /* <!-- Content: template --> */
  3712. goto sequence_constructor;
  3713. case XSLT_FUNC_SORT:
  3714. /* EMPTY */
  3715. goto empty_content;
  3716. case XSLT_FUNC_TEXT:
  3717. /* <!-- Content: #PCDATA --> */
  3718. goto text;
  3719. case XSLT_FUNC_VALUEOF:
  3720. /* EMPTY */
  3721. goto empty_content;
  3722. case XSLT_FUNC_VARIABLE:
  3723. /*
  3724. * Check for redefinition.
  3725. */
  3726. if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
  3727. xsltVarInfoPtr ivar = cctxt->ivar;
  3728. do {
  3729. if ((ivar->name ==
  3730. ((xsltStyleItemVariablePtr) elem->psvi)->name) &&
  3731. (ivar->nsName ==
  3732. ((xsltStyleItemVariablePtr) elem->psvi)->ns))
  3733. {
  3734. elem->psvi = NULL;
  3735. xsltTransformError(NULL, cctxt->style, elem,
  3736. "Redefinition of variable or parameter '%s'.\n",
  3737. ivar->name);
  3738. cctxt->style->errors++;
  3739. goto error;
  3740. }
  3741. ivar = ivar->prev;
  3742. } while (ivar != NULL);
  3743. }
  3744. /* <!-- Content: template --> */
  3745. goto sequence_constructor;
  3746. case XSLT_FUNC_WHEN:
  3747. /* <!-- Content: template --> */
  3748. goto sequence_constructor;
  3749. case XSLT_FUNC_WITHPARAM:
  3750. /* <!-- Content: template --> */
  3751. goto sequence_constructor;
  3752. default:
  3753. #ifdef WITH_XSLT_DEBUG_PARSING
  3754. xsltGenericDebug(xsltGenericDebugContext,
  3755. "xsltParseXSLTNode: Unhandled XSLT element '%s'.\n",
  3756. elem->name);
  3757. #endif
  3758. xsltTransformError(NULL, cctxt->style, elem,
  3759. "xsltParseXSLTNode: Internal error; "
  3760. "unhandled XSLT element '%s'.\n", elem->name);
  3761. cctxt->style->errors++;
  3762. goto internal_err;
  3763. }
  3764. apply_templates:
  3765. /* <!-- Content: (xsl:sort | xsl:with-param)* --> */
  3766. if (elem->children != NULL) {
  3767. xmlNodePtr child = elem->children;
  3768. do {
  3769. if (child->type == XML_ELEMENT_NODE) {
  3770. if (IS_XSLT_ELEM_FAST(child)) {
  3771. if (xmlStrEqual(child->name, BAD_CAST "with-param")) {
  3772. cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
  3773. xsltParseAnyXSLTElem(cctxt, child);
  3774. } else if (xmlStrEqual(child->name, BAD_CAST "sort")) {
  3775. cctxt->inode->curChildType = XSLT_FUNC_SORT;
  3776. xsltParseAnyXSLTElem(cctxt, child);
  3777. } else
  3778. xsltParseContentError(cctxt->style, child);
  3779. } else
  3780. xsltParseContentError(cctxt->style, child);
  3781. }
  3782. child = child->next;
  3783. } while (child != NULL);
  3784. }
  3785. goto exit;
  3786. call_template:
  3787. /* <!-- Content: xsl:with-param* --> */
  3788. if (elem->children != NULL) {
  3789. xmlNodePtr child = elem->children;
  3790. do {
  3791. if (child->type == XML_ELEMENT_NODE) {
  3792. if (IS_XSLT_ELEM_FAST(child)) {
  3793. xsltStyleType type;
  3794. type = xsltGetXSLTElementTypeByNode(cctxt, child);
  3795. if (type == XSLT_FUNC_WITHPARAM) {
  3796. cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
  3797. xsltParseAnyXSLTElem(cctxt, child);
  3798. } else {
  3799. xsltParseContentError(cctxt->style, child);
  3800. }
  3801. } else
  3802. xsltParseContentError(cctxt->style, child);
  3803. }
  3804. child = child->next;
  3805. } while (child != NULL);
  3806. }
  3807. goto exit;
  3808. text:
  3809. if (elem->children != NULL) {
  3810. xmlNodePtr child = elem->children;
  3811. do {
  3812. if ((child->type != XML_TEXT_NODE) &&
  3813. (child->type != XML_CDATA_SECTION_NODE))
  3814. {
  3815. xsltTransformError(NULL, cctxt->style, elem,
  3816. "The XSLT 'text' element must have only character "
  3817. "data as content.\n");
  3818. }
  3819. child = child->next;
  3820. } while (child != NULL);
  3821. }
  3822. goto exit;
  3823. empty_content:
  3824. if (elem->children != NULL) {
  3825. xmlNodePtr child = elem->children;
  3826. /*
  3827. * Relaxed behaviour: we will allow whitespace-only text-nodes.
  3828. */
  3829. do {
  3830. if (((child->type != XML_TEXT_NODE) &&
  3831. (child->type != XML_CDATA_SECTION_NODE)) ||
  3832. (! IS_BLANK_NODE(child)))
  3833. {
  3834. xsltTransformError(NULL, cctxt->style, elem,
  3835. "This XSLT element must have no content.\n");
  3836. cctxt->style->errors++;
  3837. break;
  3838. }
  3839. child = child->next;
  3840. } while (child != NULL);
  3841. }
  3842. goto exit;
  3843. choose:
  3844. /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */
  3845. /*
  3846. * TODO: text-nodes in between are *not* allowed in XSLT 1.0.
  3847. * The old behaviour did not check this.
  3848. * NOTE: In XSLT 2.0 they are stripped beforehand
  3849. * if whitespace-only (regardless of xml:space).
  3850. */
  3851. if (elem->children != NULL) {
  3852. xmlNodePtr child = elem->children;
  3853. int nbWhen = 0, nbOtherwise = 0, err = 0;
  3854. do {
  3855. if (child->type == XML_ELEMENT_NODE) {
  3856. if (IS_XSLT_ELEM_FAST(child)) {
  3857. xsltStyleType type;
  3858. type = xsltGetXSLTElementTypeByNode(cctxt, child);
  3859. if (type == XSLT_FUNC_WHEN) {
  3860. nbWhen++;
  3861. if (nbOtherwise) {
  3862. xsltParseContentError(cctxt->style, child);
  3863. err = 1;
  3864. break;
  3865. }
  3866. cctxt->inode->curChildType = XSLT_FUNC_WHEN;
  3867. xsltParseAnyXSLTElem(cctxt, child);
  3868. } else if (type == XSLT_FUNC_OTHERWISE) {
  3869. if (! nbWhen) {
  3870. xsltParseContentError(cctxt->style, child);
  3871. err = 1;
  3872. break;
  3873. }
  3874. if (nbOtherwise) {
  3875. xsltTransformError(NULL, cctxt->style, elem,
  3876. "The XSLT 'choose' element must not contain "
  3877. "more than one XSLT 'otherwise' element.\n");
  3878. cctxt->style->errors++;
  3879. err = 1;
  3880. break;
  3881. }
  3882. nbOtherwise++;
  3883. cctxt->inode->curChildType = XSLT_FUNC_OTHERWISE;
  3884. xsltParseAnyXSLTElem(cctxt, child);
  3885. } else
  3886. xsltParseContentError(cctxt->style, child);
  3887. } else
  3888. xsltParseContentError(cctxt->style, child);
  3889. }
  3890. /*
  3891. else
  3892. xsltParseContentError(cctxt, child);
  3893. */
  3894. child = child->next;
  3895. } while (child != NULL);
  3896. if ((! err) && (! nbWhen)) {
  3897. xsltTransformError(NULL, cctxt->style, elem,
  3898. "The XSLT element 'choose' must contain at least one "
  3899. "XSLT element 'when'.\n");
  3900. cctxt->style->errors++;
  3901. }
  3902. }
  3903. goto exit;
  3904. for_each:
  3905. /* <!-- Content: (xsl:sort*, template) --> */
  3906. /*
  3907. * NOTE: Text-nodes before xsl:sort are *not* allowed in XSLT 1.0.
  3908. * The old behaviour did not allow this, but it catched this
  3909. * only at transformation-time.
  3910. * In XSLT 2.0 they are stripped beforehand if whitespace-only
  3911. * (regardless of xml:space).
  3912. */
  3913. if (elem->children != NULL) {
  3914. xmlNodePtr child = elem->children;
  3915. /*
  3916. * Parse xsl:sort first.
  3917. */
  3918. do {
  3919. if ((child->type == XML_ELEMENT_NODE) &&
  3920. IS_XSLT_ELEM_FAST(child))
  3921. {
  3922. if (xsltGetXSLTElementTypeByNode(cctxt, child) ==
  3923. XSLT_FUNC_SORT)
  3924. {
  3925. cctxt->inode->curChildType = XSLT_FUNC_SORT;
  3926. xsltParseAnyXSLTElem(cctxt, child);
  3927. } else
  3928. break;
  3929. } else
  3930. break;
  3931. child = child->next;
  3932. } while (child != NULL);
  3933. /*
  3934. * Parse the sequece constructor.
  3935. */
  3936. if (child != NULL)
  3937. xsltParseSequenceConstructor(cctxt, child);
  3938. }
  3939. goto exit;
  3940. sequence_constructor:
  3941. /*
  3942. * Parse the sequence constructor.
  3943. */
  3944. if (elem->children != NULL)
  3945. xsltParseSequenceConstructor(cctxt, elem->children);
  3946. /*
  3947. * Register information for vars/params. Only needed if there
  3948. * are any following siblings.
  3949. */
  3950. if ((elem->next != NULL) &&
  3951. ((cctxt->inode->type == XSLT_FUNC_VARIABLE) ||
  3952. (cctxt->inode->type == XSLT_FUNC_PARAM)))
  3953. {
  3954. if ((elem->psvi != NULL) &&
  3955. (((xsltStyleBasicItemVariablePtr) elem->psvi)->name))
  3956. {
  3957. xsltCompilerVarInfoPush(cctxt, elem,
  3958. ((xsltStyleBasicItemVariablePtr) elem->psvi)->name,
  3959. ((xsltStyleBasicItemVariablePtr) elem->psvi)->ns);
  3960. }
  3961. }
  3962. error:
  3963. exit:
  3964. xsltCompilerNodePop(cctxt, elem);
  3965. return(0);
  3966. internal_err:
  3967. xsltCompilerNodePop(cctxt, elem);
  3968. return(-1);
  3969. }
  3970. /**
  3971. * xsltForwardsCompatUnkownItemCreate:
  3972. *
  3973. * @cctxt: the compilation context
  3974. *
  3975. * Creates a compiled representation of the unknown
  3976. * XSLT instruction.
  3977. *
  3978. * Returns the compiled representation.
  3979. */
  3980. static xsltStyleItemUknownPtr
  3981. xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)
  3982. {
  3983. xsltStyleItemUknownPtr item;
  3984. item = (xsltStyleItemUknownPtr) xmlMalloc(sizeof(xsltStyleItemUknown));
  3985. if (item == NULL) {
  3986. xsltTransformError(NULL, cctxt->style, NULL,
  3987. "Internal error in xsltForwardsCompatUnkownItemCreate(): "
  3988. "Failed to allocate memory.\n");
  3989. cctxt->style->errors++;
  3990. return(NULL);
  3991. }
  3992. memset(item, 0, sizeof(xsltStyleItemUknown));
  3993. item->type = XSLT_FUNC_UNKOWN_FORWARDS_COMPAT;
  3994. /*
  3995. * Store it in the stylesheet.
  3996. */
  3997. item->next = cctxt->style->preComps;
  3998. cctxt->style->preComps = (xsltElemPreCompPtr) item;
  3999. return(item);
  4000. }
  4001. /**
  4002. * xsltParseUnknownXSLTElem:
  4003. *
  4004. * @cctxt: the compilation context
  4005. * @node: the element of the unknown XSLT instruction
  4006. *
  4007. * Parses an unknown XSLT element.
  4008. * If forwards compatible mode is enabled this will allow
  4009. * such an unknown XSLT and; otherwise it is rejected.
  4010. *
  4011. * Returns 1 in the unknown XSLT instruction is rejected,
  4012. * 0 if everything's fine and
  4013. * -1 on API or internal errors.
  4014. */
  4015. static int
  4016. xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,
  4017. xmlNodePtr node)
  4018. {
  4019. if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
  4020. return(-1);
  4021. /*
  4022. * Detection of handled content of extension instructions.
  4023. */
  4024. if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
  4025. cctxt->inode->extContentHandled = 1;
  4026. }
  4027. if (cctxt->inode->forwardsCompat == 0) {
  4028. /*
  4029. * We are not in forwards-compatible mode, so raise an error.
  4030. */
  4031. xsltTransformError(NULL, cctxt->style, node,
  4032. "Unknown XSLT element '%s'.\n", node->name);
  4033. cctxt->style->errors++;
  4034. return(1);
  4035. }
  4036. /*
  4037. * Forwards-compatible mode.
  4038. * ------------------------
  4039. *
  4040. * Parse/compile xsl:fallback elements.
  4041. *
  4042. * QUESTION: Do we have to raise an error if there's no xsl:fallback?
  4043. * ANSWER: No, since in the stylesheet the fallback behaviour might
  4044. * also be provided by using the XSLT function "element-available".
  4045. */
  4046. if (cctxt->unknownItem == NULL) {
  4047. /*
  4048. * Create a singleton for all unknown XSLT instructions.
  4049. */
  4050. cctxt->unknownItem = xsltForwardsCompatUnkownItemCreate(cctxt);
  4051. if (cctxt->unknownItem == NULL) {
  4052. node->psvi = NULL;
  4053. return(-1);
  4054. }
  4055. }
  4056. node->psvi = cctxt->unknownItem;
  4057. if (node->children == NULL)
  4058. return(0);
  4059. else {
  4060. xmlNodePtr child = node->children;
  4061. xsltCompilerNodePush(cctxt, node);
  4062. /*
  4063. * Update the in-scope namespaces if needed.
  4064. */
  4065. if (node->nsDef != NULL)
  4066. cctxt->inode->inScopeNs =
  4067. xsltCompilerBuildInScopeNsList(cctxt, node);
  4068. /*
  4069. * Parse all xsl:fallback children.
  4070. */
  4071. do {
  4072. if ((child->type == XML_ELEMENT_NODE) &&
  4073. IS_XSLT_ELEM_FAST(child) &&
  4074. IS_XSLT_NAME(child, "fallback"))
  4075. {
  4076. cctxt->inode->curChildType = XSLT_FUNC_FALLBACK;
  4077. xsltParseAnyXSLTElem(cctxt, child);
  4078. }
  4079. child = child->next;
  4080. } while (child != NULL);
  4081. xsltCompilerNodePop(cctxt, node);
  4082. }
  4083. return(0);
  4084. }
  4085. /**
  4086. * xsltParseSequenceConstructor:
  4087. *
  4088. * @cctxt: the compilation context
  4089. * @cur: the start-node of the content to be parsed
  4090. *
  4091. * Parses a "template" content (or "sequence constructor" in XSLT 2.0 terms).
  4092. * This will additionally remove xsl:text elements from the tree.
  4093. */
  4094. void
  4095. xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
  4096. {
  4097. xsltStyleType type;
  4098. xmlNodePtr deleteNode = NULL;
  4099. if (cctxt == NULL) {
  4100. xmlGenericError(xmlGenericErrorContext,
  4101. "xsltParseSequenceConstructor: Bad arguments\n");
  4102. cctxt->style->errors++;
  4103. return;
  4104. }
  4105. /*
  4106. * Detection of handled content of extension instructions.
  4107. */
  4108. if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
  4109. cctxt->inode->extContentHandled = 1;
  4110. }
  4111. if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
  4112. return;
  4113. /*
  4114. * This is the content reffered to as a "template".
  4115. * E.g. an xsl:element has such content model:
  4116. * <xsl:element
  4117. * name = { qname }
  4118. * namespace = { uri-reference }
  4119. * use-attribute-sets = qnames>
  4120. * <!-- Content: template -->
  4121. *
  4122. * NOTE that in XSLT-2 the term "template" was abandoned due to
  4123. * confusion with xsl:template and the term "sequence constructor"
  4124. * was introduced instead.
  4125. *
  4126. * The following XSLT-instructions are allowed to appear:
  4127. * xsl:apply-templates, xsl:call-template, xsl:apply-imports,
  4128. * xsl:for-each, xsl:value-of, xsl:copy-of, xsl:number,
  4129. * xsl:choose, xsl:if, xsl:text, xsl:copy, xsl:variable,
  4130. * xsl:message, xsl:fallback,
  4131. * xsl:processing-instruction, xsl:comment, xsl:element
  4132. * xsl:attribute.
  4133. * Additional allowed content:
  4134. * 1) extension instructions
  4135. * 2) literal result elements
  4136. * 3) PCDATA
  4137. *
  4138. * NOTE that this content model does *not* allow xsl:param.
  4139. */
  4140. while (cur != NULL) {
  4141. if (deleteNode != NULL) {
  4142. #ifdef WITH_XSLT_DEBUG_BLANKS
  4143. xsltGenericDebug(xsltGenericDebugContext,
  4144. "xsltParseSequenceConstructor: removing xsl:text element\n");
  4145. #endif
  4146. xmlUnlinkNode(deleteNode);
  4147. xmlFreeNode(deleteNode);
  4148. deleteNode = NULL;
  4149. }
  4150. if (cur->type == XML_ELEMENT_NODE) {
  4151. if (cur->psvi == xsltXSLTTextMarker) {
  4152. /*
  4153. * xsl:text elements
  4154. * --------------------------------------------------------
  4155. */
  4156. xmlNodePtr tmp;
  4157. cur->psvi = NULL;
  4158. /*
  4159. * Mark the xsl:text element for later deletion.
  4160. */
  4161. deleteNode = cur;
  4162. /*
  4163. * Validate content.
  4164. */
  4165. tmp = cur->children;
  4166. if (tmp) {
  4167. /*
  4168. * We don't expect more than one text-node in the
  4169. * content, since we already merged adjacent
  4170. * text/CDATA-nodes and eliminated PI/comment-nodes.
  4171. */
  4172. if ((tmp->type == XML_TEXT_NODE) ||
  4173. (tmp->next == NULL))
  4174. {
  4175. /*
  4176. * Leave the contained text-node in the tree.
  4177. */
  4178. xmlUnlinkNode(tmp);
  4179. xmlAddPrevSibling(cur, tmp);
  4180. } else {
  4181. tmp = NULL;
  4182. xsltTransformError(NULL, cctxt->style, cur,
  4183. "Element 'xsl:text': Invalid type "
  4184. "of node found in content.\n");
  4185. cctxt->style->errors++;
  4186. }
  4187. }
  4188. if (cur->properties) {
  4189. xmlAttrPtr attr;
  4190. /*
  4191. * TODO: We need to report errors for
  4192. * invalid attrs.
  4193. */
  4194. attr = cur->properties;
  4195. do {
  4196. if ((attr->ns == NULL) &&
  4197. (attr->name != NULL) &&
  4198. (attr->name[0] == 'd') &&
  4199. xmlStrEqual(attr->name,
  4200. BAD_CAST "disable-output-escaping"))
  4201. {
  4202. /*
  4203. * Attr "disable-output-escaping".
  4204. * XSLT-2: This attribute is deprecated.
  4205. */
  4206. if ((attr->children != NULL) &&
  4207. xmlStrEqual(attr->children->content,
  4208. BAD_CAST "yes"))
  4209. {
  4210. /*
  4211. * Disable output escaping for this
  4212. * text node.
  4213. */
  4214. if (tmp)
  4215. tmp->name = xmlStringTextNoenc;
  4216. } else if ((attr->children == NULL) ||
  4217. (attr->children->content == NULL) ||
  4218. (!xmlStrEqual(attr->children->content,
  4219. BAD_CAST "no")))
  4220. {
  4221. xsltTransformError(NULL, cctxt->style,
  4222. cur,
  4223. "Attribute 'disable-output-escaping': "
  4224. "Invalid value. Expected is "
  4225. "'yes' or 'no'.\n");
  4226. cctxt->style->errors++;
  4227. }
  4228. break;
  4229. }
  4230. attr = attr->next;
  4231. } while (attr != NULL);
  4232. }
  4233. } else if (IS_XSLT_ELEM_FAST(cur)) {
  4234. /*
  4235. * TODO: Using the XSLT-marker is still not stable yet.
  4236. */
  4237. /* if (cur->psvi == xsltXSLTElemMarker) { */
  4238. /*
  4239. * XSLT instructions
  4240. * --------------------------------------------------------
  4241. */
  4242. cur->psvi = NULL;
  4243. type = xsltGetXSLTElementTypeByNode(cctxt, cur);
  4244. switch (type) {
  4245. case XSLT_FUNC_APPLYIMPORTS:
  4246. case XSLT_FUNC_APPLYTEMPLATES:
  4247. case XSLT_FUNC_ATTRIBUTE:
  4248. case XSLT_FUNC_CALLTEMPLATE:
  4249. case XSLT_FUNC_CHOOSE:
  4250. case XSLT_FUNC_COMMENT:
  4251. case XSLT_FUNC_COPY:
  4252. case XSLT_FUNC_COPYOF:
  4253. case XSLT_FUNC_DOCUMENT: /* Extra one */
  4254. case XSLT_FUNC_ELEMENT:
  4255. case XSLT_FUNC_FALLBACK:
  4256. case XSLT_FUNC_FOREACH:
  4257. case XSLT_FUNC_IF:
  4258. case XSLT_FUNC_MESSAGE:
  4259. case XSLT_FUNC_NUMBER:
  4260. case XSLT_FUNC_PI:
  4261. case XSLT_FUNC_TEXT:
  4262. case XSLT_FUNC_VALUEOF:
  4263. case XSLT_FUNC_VARIABLE:
  4264. /*
  4265. * Parse the XSLT element.
  4266. */
  4267. cctxt->inode->curChildType = type;
  4268. xsltParseAnyXSLTElem(cctxt, cur);
  4269. break;
  4270. default:
  4271. xsltParseUnknownXSLTElem(cctxt, cur);
  4272. cur = cur->next;
  4273. continue;
  4274. }
  4275. } else {
  4276. /*
  4277. * Non-XSLT elements
  4278. * -----------------
  4279. */
  4280. xsltCompilerNodePush(cctxt, cur);
  4281. /*
  4282. * Update the in-scope namespaces if needed.
  4283. */
  4284. if (cur->nsDef != NULL)
  4285. cctxt->inode->inScopeNs =
  4286. xsltCompilerBuildInScopeNsList(cctxt, cur);
  4287. /*
  4288. * The current element is either a literal result element
  4289. * or an extension instruction.
  4290. *
  4291. * Process attr "xsl:extension-element-prefixes".
  4292. * FUTURE TODO: IIRC in XSLT 2.0 this attribute must be
  4293. * processed by the implementor of the extension function;
  4294. * i.e., it won't be handled by the XSLT processor.
  4295. */
  4296. /* SPEC 1.0:
  4297. * "exclude-result-prefixes" is only allowed on literal
  4298. * result elements and "xsl:exclude-result-prefixes"
  4299. * on xsl:stylesheet/xsl:transform.
  4300. * SPEC 2.0:
  4301. * "There are a number of standard attributes
  4302. * that may appear on any XSLT element: specifically
  4303. * version, exclude-result-prefixes,
  4304. * extension-element-prefixes, xpath-default-namespace,
  4305. * default-collation, and use-when."
  4306. *
  4307. * SPEC 2.0:
  4308. * For literal result elements:
  4309. * "xsl:version, xsl:exclude-result-prefixes,
  4310. * xsl:extension-element-prefixes,
  4311. * xsl:xpath-default-namespace,
  4312. * xsl:default-collation, or xsl:use-when."
  4313. */
  4314. if (cur->properties)
  4315. cctxt->inode->extElemNs =
  4316. xsltParseExtElemPrefixes(cctxt,
  4317. cur, cctxt->inode->extElemNs,
  4318. XSLT_ELEMENT_CATEGORY_LRE);
  4319. /*
  4320. * Eval if we have an extension instruction here.
  4321. */
  4322. if ((cur->ns != NULL) &&
  4323. (cctxt->inode->extElemNs != NULL) &&
  4324. (xsltCheckExtPrefix(cctxt->style, cur->ns->href) == 1))
  4325. {
  4326. /*
  4327. * Extension instructions
  4328. * ----------------------------------------------------
  4329. * Mark the node information.
  4330. */
  4331. cctxt->inode->category = XSLT_ELEMENT_CATEGORY_EXTENSION;
  4332. cctxt->inode->extContentHandled = 0;
  4333. if (cur->psvi != NULL) {
  4334. cur->psvi = NULL;
  4335. /*
  4336. * TODO: Temporary sanity check.
  4337. */
  4338. xsltTransformError(NULL, cctxt->style, cur,
  4339. "Internal error in xsltParseSequenceConstructor(): "
  4340. "Occupied PSVI field.\n");
  4341. cctxt->style->errors++;
  4342. cur = cur->next;
  4343. continue;
  4344. }
  4345. cur->psvi = (void *)
  4346. xsltPreComputeExtModuleElement(cctxt->style, cur);
  4347. if (cur->psvi == NULL) {
  4348. /*
  4349. * OLD COMMENT: "Unknown element, maybe registered
  4350. * at the context level. Mark it for later
  4351. * recognition."
  4352. * QUESTION: What does the xsltExtMarker mean?
  4353. * ANSWER: It is used in
  4354. * xsltApplySequenceConstructor() at
  4355. * transformation-time to look out for extension
  4356. * registered in the transformation context.
  4357. */
  4358. cur->psvi = (void *) xsltExtMarker;
  4359. }
  4360. /*
  4361. * BIG NOTE: Now the ugly part. In previous versions
  4362. * of Libxslt (until 1.1.16), all the content of an
  4363. * extension instruction was processed and compiled without
  4364. * the need of the extension-author to explicitely call
  4365. * such a processing;.We now need to mimic this old
  4366. * behaviour in order to avoid breaking old code
  4367. * on the extension-author's side.
  4368. * The mechanism:
  4369. * 1) If the author does *not* set the
  4370. * compile-time-flag @extContentHandled, then we'll
  4371. * parse the content assuming that it's a "template"
  4372. * (or "sequence constructor in XSLT 2.0 terms).
  4373. * NOTE: If the extension is registered at
  4374. * transformation-time only, then there's no way of
  4375. * knowing that content shall be valid, and we'll
  4376. * process the content the same way.
  4377. * 2) If the author *does* set the flag, then we'll assume
  4378. * that the author has handled the parsing him/herself
  4379. * (e.g. called xsltParseSequenceConstructor(), etc.
  4380. * explicitely in his/her code).
  4381. */
  4382. if ((cur->children != NULL) &&
  4383. (cctxt->inode->extContentHandled == 0))
  4384. {
  4385. /*
  4386. * Default parsing of the content using the
  4387. * sequence-constructor model.
  4388. */
  4389. xsltParseSequenceConstructor(cctxt, cur->children);
  4390. }
  4391. } else {
  4392. /*
  4393. * Literal result element
  4394. * ----------------------------------------------------
  4395. * Allowed XSLT attributes:
  4396. * xsl:extension-element-prefixes CDATA #IMPLIED
  4397. * xsl:exclude-result-prefixes CDATA #IMPLIED
  4398. * TODO: xsl:use-attribute-sets %qnames; #IMPLIED
  4399. * xsl:version NMTOKEN #IMPLIED
  4400. */
  4401. cur->psvi = NULL;
  4402. cctxt->inode->category = XSLT_ELEMENT_CATEGORY_LRE;
  4403. if (cur->properties != NULL) {
  4404. xmlAttrPtr attr = cur->properties;
  4405. /*
  4406. * Attribute "xsl:exclude-result-prefixes".
  4407. */
  4408. cctxt->inode->exclResultNs =
  4409. xsltParseExclResultPrefixes(cctxt, cur,
  4410. cctxt->inode->exclResultNs,
  4411. XSLT_ELEMENT_CATEGORY_LRE);
  4412. /*
  4413. * Attribute "xsl:version".
  4414. */
  4415. xsltParseAttrXSLTVersion(cctxt, cur,
  4416. XSLT_ELEMENT_CATEGORY_LRE);
  4417. /*
  4418. * Report invalid XSLT attributes.
  4419. * For XSLT 1.0 only xsl:use-attribute-sets is allowed
  4420. * next to xsl:version, xsl:exclude-result-prefixes and
  4421. * xsl:extension-element-prefixes.
  4422. *
  4423. * Mark all XSLT attributes, in order to skip such
  4424. * attributes when instantiating the LRE.
  4425. */
  4426. do {
  4427. if ((attr->psvi != xsltXSLTAttrMarker) &&
  4428. IS_XSLT_ATTR_FAST(attr))
  4429. {
  4430. if (! xmlStrEqual(attr->name,
  4431. BAD_CAST "use-attribute-sets"))
  4432. {
  4433. xsltTransformError(NULL, cctxt->style,
  4434. cur,
  4435. "Unknown XSLT attribute '%s'.\n",
  4436. attr->name);
  4437. cctxt->style->errors++;
  4438. } else {
  4439. /*
  4440. * XSLT attr marker.
  4441. */
  4442. attr->psvi = (void *) xsltXSLTAttrMarker;
  4443. }
  4444. }
  4445. attr = attr->next;
  4446. } while (attr != NULL);
  4447. }
  4448. /*
  4449. * Create/reuse info for the literal result element.
  4450. */
  4451. if (cctxt->inode->nsChanged)
  4452. xsltLREInfoCreate(cctxt, cur, 1);
  4453. cur->psvi = cctxt->inode->litResElemInfo;
  4454. /*
  4455. * Apply ns-aliasing on the element and on its attributes.
  4456. */
  4457. if (cctxt->hasNsAliases)
  4458. xsltLREBuildEffectiveNs(cctxt, cur);
  4459. /*
  4460. * Compile attribute value templates (AVT).
  4461. */
  4462. if (cur->properties) {
  4463. xmlAttrPtr attr = cur->properties;
  4464. while (attr != NULL) {
  4465. xsltCompileAttr(cctxt->style, attr);
  4466. attr = attr->next;
  4467. }
  4468. }
  4469. /*
  4470. * Parse the content, which is defined to be a "template"
  4471. * (or "sequence constructor" in XSLT 2.0 terms).
  4472. */
  4473. if (cur->children != NULL) {
  4474. xsltParseSequenceConstructor(cctxt, cur->children);
  4475. }
  4476. }
  4477. /*
  4478. * Leave the non-XSLT element.
  4479. */
  4480. xsltCompilerNodePop(cctxt, cur);
  4481. }
  4482. }
  4483. cur = cur->next;
  4484. }
  4485. if (deleteNode != NULL) {
  4486. #ifdef WITH_XSLT_DEBUG_BLANKS
  4487. xsltGenericDebug(xsltGenericDebugContext,
  4488. "xsltParseSequenceConstructor: removing xsl:text element\n");
  4489. #endif
  4490. xmlUnlinkNode(deleteNode);
  4491. xmlFreeNode(deleteNode);
  4492. deleteNode = NULL;
  4493. }
  4494. }
  4495. /**
  4496. * xsltParseTemplateContent:
  4497. * @style: the XSLT stylesheet
  4498. * @templ: the node containing the content to be parsed
  4499. *
  4500. * Parses and compiles the content-model of an xsl:template element.
  4501. * Note that this is *not* the "template" content model (or "sequence
  4502. * constructor" in XSLT 2.0); it it allows addional xsl:param
  4503. * elements as immediate children of @templ.
  4504. *
  4505. * Called by:
  4506. * exsltFuncFunctionComp() (EXSLT, functions.c)
  4507. * So this is intended to be called from extension functions.
  4508. */
  4509. void
  4510. xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
  4511. if ((style == NULL) || (templ == NULL) ||
  4512. (templ->type == XML_NAMESPACE_DECL))
  4513. return;
  4514. /*
  4515. * Detection of handled content of extension instructions.
  4516. */
  4517. if (XSLT_CCTXT(style)->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
  4518. XSLT_CCTXT(style)->inode->extContentHandled = 1;
  4519. }
  4520. if (templ->children != NULL) {
  4521. xmlNodePtr child = templ->children;
  4522. /*
  4523. * Process xsl:param elements, which can only occur as the
  4524. * immediate children of xsl:template (well, and of any
  4525. * user-defined extension instruction if needed).
  4526. */
  4527. do {
  4528. if ((child->type == XML_ELEMENT_NODE) &&
  4529. IS_XSLT_ELEM_FAST(child) &&
  4530. IS_XSLT_NAME(child, "param"))
  4531. {
  4532. XSLT_CCTXT(style)->inode->curChildType = XSLT_FUNC_PARAM;
  4533. xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
  4534. } else
  4535. break;
  4536. child = child->next;
  4537. } while (child != NULL);
  4538. /*
  4539. * Parse the content and register the pattern.
  4540. */
  4541. xsltParseSequenceConstructor(XSLT_CCTXT(style), child);
  4542. }
  4543. }
  4544. #else /* XSLT_REFACTORED */
  4545. /**
  4546. * xsltParseTemplateContent:
  4547. * @style: the XSLT stylesheet
  4548. * @templ: the container node (can be a document for literal results)
  4549. *
  4550. * parse a template content-model
  4551. * Clean-up the template content from unwanted ignorable blank nodes
  4552. * and process xslt:text
  4553. */
  4554. void
  4555. xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
  4556. xmlNodePtr cur, delete;
  4557. if ((style == NULL) || (templ == NULL) ||
  4558. (templ->type == XML_NAMESPACE_DECL)) return;
  4559. /*
  4560. * This content comes from the stylesheet
  4561. * For stylesheets, the set of whitespace-preserving
  4562. * element names consists of just xsl:text.
  4563. */
  4564. cur = templ->children;
  4565. delete = NULL;
  4566. while (cur != NULL) {
  4567. if (delete != NULL) {
  4568. #ifdef WITH_XSLT_DEBUG_BLANKS
  4569. xsltGenericDebug(xsltGenericDebugContext,
  4570. "xsltParseTemplateContent: removing text\n");
  4571. #endif
  4572. xmlUnlinkNode(delete);
  4573. xmlFreeNode(delete);
  4574. delete = NULL;
  4575. }
  4576. if (IS_XSLT_ELEM(cur)) {
  4577. xsltStylePreCompute(style, cur);
  4578. if (IS_XSLT_NAME(cur, "text")) {
  4579. /*
  4580. * TODO: Processing of xsl:text should be moved to
  4581. * xsltPreprocessStylesheet(), since otherwise this
  4582. * will be performed for every multiply included
  4583. * stylesheet; i.e. this here is not skipped with
  4584. * the use of the style->nopreproc flag.
  4585. */
  4586. if (cur->children != NULL) {
  4587. xmlChar *prop;
  4588. xmlNodePtr text = cur->children, next;
  4589. int noesc = 0;
  4590. prop = xmlGetNsProp(cur,
  4591. (const xmlChar *)"disable-output-escaping",
  4592. NULL);
  4593. if (prop != NULL) {
  4594. #ifdef WITH_XSLT_DEBUG_PARSING
  4595. xsltGenericDebug(xsltGenericDebugContext,
  4596. "Disable escaping: %s\n", text->content);
  4597. #endif
  4598. if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
  4599. noesc = 1;
  4600. } else if (!xmlStrEqual(prop,
  4601. (const xmlChar *)"no")){
  4602. xsltTransformError(NULL, style, cur,
  4603. "xsl:text: disable-output-escaping allows only yes or no\n");
  4604. style->warnings++;
  4605. }
  4606. xmlFree(prop);
  4607. }
  4608. while (text != NULL) {
  4609. if (text->type == XML_COMMENT_NODE) {
  4610. text = text->next;
  4611. continue;
  4612. }
  4613. if ((text->type != XML_TEXT_NODE) &&
  4614. (text->type != XML_CDATA_SECTION_NODE)) {
  4615. xsltTransformError(NULL, style, cur,
  4616. "xsltParseTemplateContent: xslt:text content problem\n");
  4617. style->errors++;
  4618. break;
  4619. }
  4620. if ((noesc) && (text->type != XML_CDATA_SECTION_NODE))
  4621. text->name = xmlStringTextNoenc;
  4622. text = text->next;
  4623. }
  4624. /*
  4625. * replace xsl:text by the list of childs
  4626. */
  4627. if (text == NULL) {
  4628. text = cur->children;
  4629. while (text != NULL) {
  4630. if ((style->internalized) &&
  4631. (text->content != NULL) &&
  4632. (!xmlDictOwns(style->dict, text->content))) {
  4633. /*
  4634. * internalize the text string
  4635. */
  4636. if (text->doc->dict != NULL) {
  4637. const xmlChar *tmp;
  4638. tmp = xmlDictLookup(text->doc->dict,
  4639. text->content, -1);
  4640. if (tmp != text->content) {
  4641. xmlNodeSetContent(text, NULL);
  4642. text->content = (xmlChar *) tmp;
  4643. }
  4644. }
  4645. }
  4646. next = text->next;
  4647. xmlUnlinkNode(text);
  4648. xmlAddPrevSibling(cur, text);
  4649. text = next;
  4650. }
  4651. }
  4652. }
  4653. delete = cur;
  4654. goto skip_children;
  4655. }
  4656. }
  4657. else if ((cur->ns != NULL) && (style->nsDefs != NULL) &&
  4658. (xsltCheckExtPrefix(style, cur->ns->prefix)))
  4659. {
  4660. /*
  4661. * okay this is an extension element compile it too
  4662. */
  4663. xsltStylePreCompute(style, cur);
  4664. }
  4665. else if (cur->type == XML_ELEMENT_NODE)
  4666. {
  4667. /*
  4668. * This is an element which will be output as part of the
  4669. * template exectution, precompile AVT if found.
  4670. */
  4671. if ((cur->ns == NULL) && (style->defaultAlias != NULL)) {
  4672. cur->ns = xmlSearchNsByHref(cur->doc, cur,
  4673. style->defaultAlias);
  4674. }
  4675. if (cur->properties != NULL) {
  4676. xmlAttrPtr attr = cur->properties;
  4677. while (attr != NULL) {
  4678. xsltCompileAttr(style, attr);
  4679. attr = attr->next;
  4680. }
  4681. }
  4682. }
  4683. /*
  4684. * Skip to next node
  4685. */
  4686. if (cur->children != NULL) {
  4687. if (cur->children->type != XML_ENTITY_DECL) {
  4688. cur = cur->children;
  4689. continue;
  4690. }
  4691. }
  4692. skip_children:
  4693. if (cur->next != NULL) {
  4694. cur = cur->next;
  4695. continue;
  4696. }
  4697. do {
  4698. cur = cur->parent;
  4699. if (cur == NULL)
  4700. break;
  4701. if (cur == templ) {
  4702. cur = NULL;
  4703. break;
  4704. }
  4705. if (cur->next != NULL) {
  4706. cur = cur->next;
  4707. break;
  4708. }
  4709. } while (cur != NULL);
  4710. }
  4711. if (delete != NULL) {
  4712. #ifdef WITH_XSLT_DEBUG_PARSING
  4713. xsltGenericDebug(xsltGenericDebugContext,
  4714. "xsltParseTemplateContent: removing text\n");
  4715. #endif
  4716. xmlUnlinkNode(delete);
  4717. xmlFreeNode(delete);
  4718. delete = NULL;
  4719. }
  4720. /*
  4721. * Skip the first params
  4722. */
  4723. cur = templ->children;
  4724. while (cur != NULL) {
  4725. if ((IS_XSLT_ELEM(cur)) && (!(IS_XSLT_NAME(cur, "param"))))
  4726. break;
  4727. cur = cur->next;
  4728. }
  4729. /*
  4730. * Browse the remainder of the template
  4731. */
  4732. while (cur != NULL) {
  4733. if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "param"))) {
  4734. xmlNodePtr param = cur;
  4735. xsltTransformError(NULL, style, cur,
  4736. "xsltParseTemplateContent: ignoring misplaced param element\n");
  4737. if (style != NULL) style->warnings++;
  4738. cur = cur->next;
  4739. xmlUnlinkNode(param);
  4740. xmlFreeNode(param);
  4741. } else
  4742. break;
  4743. }
  4744. }
  4745. #endif /* else XSLT_REFACTORED */
  4746. /**
  4747. * xsltParseStylesheetKey:
  4748. * @style: the XSLT stylesheet
  4749. * @key: the "key" element
  4750. *
  4751. * <!-- Category: top-level-element -->
  4752. * <xsl:key name = qname, match = pattern, use = expression />
  4753. *
  4754. * parse an XSLT stylesheet key definition and register it
  4755. */
  4756. static void
  4757. xsltParseStylesheetKey(xsltStylesheetPtr style, xmlNodePtr key) {
  4758. xmlChar *prop = NULL;
  4759. xmlChar *use = NULL;
  4760. xmlChar *match = NULL;
  4761. xmlChar *name = NULL;
  4762. xmlChar *nameURI = NULL;
  4763. if ((style == NULL) || (key == NULL) || (key->type != XML_ELEMENT_NODE))
  4764. return;
  4765. /*
  4766. * Get arguments
  4767. */
  4768. prop = xmlGetNsProp(key, (const xmlChar *)"name", NULL);
  4769. if (prop != NULL) {
  4770. const xmlChar *URI;
  4771. /*
  4772. * TODO: Don't use xsltGetQNameURI().
  4773. */
  4774. URI = xsltGetQNameURI(key, &prop);
  4775. if (prop == NULL) {
  4776. if (style != NULL) style->errors++;
  4777. goto error;
  4778. } else {
  4779. name = prop;
  4780. if (URI != NULL)
  4781. nameURI = xmlStrdup(URI);
  4782. }
  4783. #ifdef WITH_XSLT_DEBUG_PARSING
  4784. xsltGenericDebug(xsltGenericDebugContext,
  4785. "xsltParseStylesheetKey: name %s\n", name);
  4786. #endif
  4787. } else {
  4788. xsltTransformError(NULL, style, key,
  4789. "xsl:key : error missing name\n");
  4790. if (style != NULL) style->errors++;
  4791. goto error;
  4792. }
  4793. match = xmlGetNsProp(key, (const xmlChar *)"match", NULL);
  4794. if (match == NULL) {
  4795. xsltTransformError(NULL, style, key,
  4796. "xsl:key : error missing match\n");
  4797. if (style != NULL) style->errors++;
  4798. goto error;
  4799. }
  4800. use = xmlGetNsProp(key, (const xmlChar *)"use", NULL);
  4801. if (use == NULL) {
  4802. xsltTransformError(NULL, style, key,
  4803. "xsl:key : error missing use\n");
  4804. if (style != NULL) style->errors++;
  4805. goto error;
  4806. }
  4807. /*
  4808. * register the keys
  4809. */
  4810. xsltAddKey(style, name, nameURI, match, use, key);
  4811. error:
  4812. if (use != NULL)
  4813. xmlFree(use);
  4814. if (match != NULL)
  4815. xmlFree(match);
  4816. if (name != NULL)
  4817. xmlFree(name);
  4818. if (nameURI != NULL)
  4819. xmlFree(nameURI);
  4820. if (key->children != NULL) {
  4821. xsltParseContentError(style, key->children);
  4822. }
  4823. }
  4824. #ifdef XSLT_REFACTORED
  4825. /**
  4826. * xsltParseXSLTTemplate:
  4827. * @style: the XSLT stylesheet
  4828. * @template: the "template" element
  4829. *
  4830. * parse an XSLT stylesheet template building the associated structures
  4831. * TODO: Is @style ever expected to be NULL?
  4832. *
  4833. * Called from:
  4834. * xsltParseXSLTStylesheet()
  4835. * xsltParseStylesheetTop()
  4836. */
  4837. static void
  4838. xsltParseXSLTTemplate(xsltCompilerCtxtPtr cctxt, xmlNodePtr templNode) {
  4839. xsltTemplatePtr templ;
  4840. xmlChar *prop;
  4841. double priority;
  4842. if ((cctxt == NULL) || (templNode == NULL) ||
  4843. (templNode->type != XML_ELEMENT_NODE))
  4844. return;
  4845. /*
  4846. * Create and link the structure
  4847. */
  4848. templ = xsltNewTemplate();
  4849. if (templ == NULL)
  4850. return;
  4851. xsltCompilerNodePush(cctxt, templNode);
  4852. if (templNode->nsDef != NULL)
  4853. cctxt->inode->inScopeNs =
  4854. xsltCompilerBuildInScopeNsList(cctxt, templNode);
  4855. templ->next = cctxt->style->templates;
  4856. cctxt->style->templates = templ;
  4857. templ->style = cctxt->style;
  4858. /*
  4859. * Attribute "mode".
  4860. */
  4861. prop = xmlGetNsProp(templNode, (const xmlChar *)"mode", NULL);
  4862. if (prop != NULL) {
  4863. const xmlChar *modeURI;
  4864. /*
  4865. * TODO: We need a standardized function for extraction
  4866. * of namespace names and local names from QNames.
  4867. * Don't use xsltGetQNameURI() as it cannot channe�
  4868. * reports through the context.
  4869. */
  4870. modeURI = xsltGetQNameURI(templNode, &prop);
  4871. if (prop == NULL) {
  4872. cctxt->style->errors++;
  4873. goto error;
  4874. }
  4875. templ->mode = xmlDictLookup(cctxt->style->dict, prop, -1);
  4876. xmlFree(prop);
  4877. prop = NULL;
  4878. if (xmlValidateNCName(templ->mode, 0)) {
  4879. xsltTransformError(NULL, cctxt->style, templNode,
  4880. "xsl:template: Attribute 'mode': The local part '%s' "
  4881. "of the value is not a valid NCName.\n", templ->name);
  4882. cctxt->style->errors++;
  4883. goto error;
  4884. }
  4885. if (modeURI != NULL)
  4886. templ->modeURI = xmlDictLookup(cctxt->style->dict, modeURI, -1);
  4887. #ifdef WITH_XSLT_DEBUG_PARSING
  4888. xsltGenericDebug(xsltGenericDebugContext,
  4889. "xsltParseXSLTTemplate: mode %s\n", templ->mode);
  4890. #endif
  4891. }
  4892. /*
  4893. * Attribute "match".
  4894. */
  4895. prop = xmlGetNsProp(templNode, (const xmlChar *)"match", NULL);
  4896. if (prop != NULL) {
  4897. templ->match = prop;
  4898. prop = NULL;
  4899. }
  4900. /*
  4901. * Attribute "priority".
  4902. */
  4903. prop = xmlGetNsProp(templNode, (const xmlChar *)"priority", NULL);
  4904. if (prop != NULL) {
  4905. priority = xmlXPathStringEvalNumber(prop);
  4906. templ->priority = (float) priority;
  4907. xmlFree(prop);
  4908. prop = NULL;
  4909. }
  4910. /*
  4911. * Attribute "name".
  4912. */
  4913. prop = xmlGetNsProp(templNode, (const xmlChar *)"name", NULL);
  4914. if (prop != NULL) {
  4915. const xmlChar *nameURI;
  4916. xsltTemplatePtr curTempl;
  4917. /*
  4918. * TODO: Don't use xsltGetQNameURI().
  4919. */
  4920. nameURI = xsltGetQNameURI(templNode, &prop);
  4921. if (prop == NULL) {
  4922. cctxt->style->errors++;
  4923. goto error;
  4924. }
  4925. templ->name = xmlDictLookup(cctxt->style->dict, prop, -1);
  4926. xmlFree(prop);
  4927. prop = NULL;
  4928. if (xmlValidateNCName(templ->name, 0)) {
  4929. xsltTransformError(NULL, cctxt->style, templNode,
  4930. "xsl:template: Attribute 'name': The local part '%s' of "
  4931. "the value is not a valid NCName.\n", templ->name);
  4932. cctxt->style->errors++;
  4933. goto error;
  4934. }
  4935. if (nameURI != NULL)
  4936. templ->nameURI = xmlDictLookup(cctxt->style->dict, nameURI, -1);
  4937. curTempl = templ->next;
  4938. while (curTempl != NULL) {
  4939. if ((nameURI != NULL && xmlStrEqual(curTempl->name, templ->name) &&
  4940. xmlStrEqual(curTempl->nameURI, nameURI) ) ||
  4941. (nameURI == NULL && curTempl->nameURI == NULL &&
  4942. xmlStrEqual(curTempl->name, templ->name)))
  4943. {
  4944. xsltTransformError(NULL, cctxt->style, templNode,
  4945. "xsl:template: error duplicate name '%s'\n", templ->name);
  4946. cctxt->style->errors++;
  4947. goto error;
  4948. }
  4949. curTempl = curTempl->next;
  4950. }
  4951. }
  4952. if (templNode->children != NULL) {
  4953. xsltParseTemplateContent(cctxt->style, templNode);
  4954. /*
  4955. * MAYBE TODO: Custom behaviour: In order to stay compatible with
  4956. * Xalan and MSXML(.NET), we could allow whitespace
  4957. * to appear before an xml:param element; this whitespace
  4958. * will additionally become part of the "template".
  4959. * NOTE that this is totally deviates from the spec, but
  4960. * is the de facto behaviour of Xalan and MSXML(.NET).
  4961. * Personally I wouldn't allow this, since if we have:
  4962. * <xsl:template ...xml:space="preserve">
  4963. * <xsl:param name="foo"/>
  4964. * <xsl:param name="bar"/>
  4965. * <xsl:param name="zoo"/>
  4966. * ... the whitespace between every xsl:param would be
  4967. * added to the result tree.
  4968. */
  4969. }
  4970. templ->elem = templNode;
  4971. templ->content = templNode->children;
  4972. xsltAddTemplate(cctxt->style, templ, templ->mode, templ->modeURI);
  4973. error:
  4974. xsltCompilerNodePop(cctxt, templNode);
  4975. return;
  4976. }
  4977. #else /* XSLT_REFACTORED */
  4978. /**
  4979. * xsltParseStylesheetTemplate:
  4980. * @style: the XSLT stylesheet
  4981. * @template: the "template" element
  4982. *
  4983. * parse an XSLT stylesheet template building the associated structures
  4984. */
  4985. static void
  4986. xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
  4987. xsltTemplatePtr ret;
  4988. xmlChar *prop;
  4989. xmlChar *mode = NULL;
  4990. xmlChar *modeURI = NULL;
  4991. double priority;
  4992. if ((style == NULL) || (template == NULL) ||
  4993. (template->type != XML_ELEMENT_NODE))
  4994. return;
  4995. /*
  4996. * Create and link the structure
  4997. */
  4998. ret = xsltNewTemplate();
  4999. if (ret == NULL)
  5000. return;
  5001. ret->next = style->templates;
  5002. style->templates = ret;
  5003. ret->style = style;
  5004. /*
  5005. * Get inherited namespaces
  5006. */
  5007. /*
  5008. * TODO: Apply the optimized in-scope-namespace mechanism
  5009. * as for the other XSLT instructions.
  5010. */
  5011. xsltGetInheritedNsList(style, ret, template);
  5012. /*
  5013. * Get arguments
  5014. */
  5015. prop = xmlGetNsProp(template, (const xmlChar *)"mode", NULL);
  5016. if (prop != NULL) {
  5017. const xmlChar *URI;
  5018. /*
  5019. * TODO: Don't use xsltGetQNameURI().
  5020. */
  5021. URI = xsltGetQNameURI(template, &prop);
  5022. if (prop == NULL) {
  5023. if (style != NULL) style->errors++;
  5024. goto error;
  5025. } else {
  5026. mode = prop;
  5027. if (URI != NULL)
  5028. modeURI = xmlStrdup(URI);
  5029. }
  5030. ret->mode = xmlDictLookup(style->dict, mode, -1);
  5031. ret->modeURI = xmlDictLookup(style->dict, modeURI, -1);
  5032. #ifdef WITH_XSLT_DEBUG_PARSING
  5033. xsltGenericDebug(xsltGenericDebugContext,
  5034. "xsltParseStylesheetTemplate: mode %s\n", mode);
  5035. #endif
  5036. if (mode != NULL) xmlFree(mode);
  5037. if (modeURI != NULL) xmlFree(modeURI);
  5038. }
  5039. prop = xmlGetNsProp(template, (const xmlChar *)"match", NULL);
  5040. if (prop != NULL) {
  5041. if (ret->match != NULL) xmlFree(ret->match);
  5042. ret->match = prop;
  5043. }
  5044. prop = xmlGetNsProp(template, (const xmlChar *)"priority", NULL);
  5045. if (prop != NULL) {
  5046. priority = xmlXPathStringEvalNumber(prop);
  5047. ret->priority = (float) priority;
  5048. xmlFree(prop);
  5049. }
  5050. prop = xmlGetNsProp(template, (const xmlChar *)"name", NULL);
  5051. if (prop != NULL) {
  5052. const xmlChar *URI;
  5053. /*
  5054. * TODO: Don't use xsltGetQNameURI().
  5055. */
  5056. URI = xsltGetQNameURI(template, &prop);
  5057. if (prop == NULL) {
  5058. if (style != NULL) style->errors++;
  5059. goto error;
  5060. } else {
  5061. if (xmlValidateNCName(prop,0)) {
  5062. xsltTransformError(NULL, style, template,
  5063. "xsl:template : error invalid name '%s'\n", prop);
  5064. if (style != NULL) style->errors++;
  5065. xmlFree(prop);
  5066. goto error;
  5067. }
  5068. ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1);
  5069. xmlFree(prop);
  5070. prop = NULL;
  5071. if (URI != NULL)
  5072. ret->nameURI = xmlDictLookup(style->dict, BAD_CAST URI, -1);
  5073. else
  5074. ret->nameURI = NULL;
  5075. }
  5076. }
  5077. /*
  5078. * parse the content and register the pattern
  5079. */
  5080. xsltParseTemplateContent(style, template);
  5081. ret->elem = template;
  5082. ret->content = template->children;
  5083. xsltAddTemplate(style, ret, ret->mode, ret->modeURI);
  5084. error:
  5085. return;
  5086. }
  5087. #endif /* else XSLT_REFACTORED */
  5088. #ifdef XSLT_REFACTORED
  5089. /**
  5090. * xsltIncludeComp:
  5091. * @cctxt: the compilation context
  5092. * @node: the xsl:include node
  5093. *
  5094. * Process the xslt include node on the source node
  5095. */
  5096. static xsltStyleItemIncludePtr
  5097. xsltCompileXSLTIncludeElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node) {
  5098. xsltStyleItemIncludePtr item;
  5099. if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
  5100. return(NULL);
  5101. node->psvi = NULL;
  5102. item = (xsltStyleItemIncludePtr) xmlMalloc(sizeof(xsltStyleItemInclude));
  5103. if (item == NULL) {
  5104. xsltTransformError(NULL, cctxt->style, node,
  5105. "xsltIncludeComp : malloc failed\n");
  5106. cctxt->style->errors++;
  5107. return(NULL);
  5108. }
  5109. memset(item, 0, sizeof(xsltStyleItemInclude));
  5110. node->psvi = item;
  5111. item->inst = node;
  5112. item->type = XSLT_FUNC_INCLUDE;
  5113. item->next = cctxt->style->preComps;
  5114. cctxt->style->preComps = (xsltElemPreCompPtr) item;
  5115. return(item);
  5116. }
  5117. /**
  5118. * xsltParseFindTopLevelElem:
  5119. */
  5120. static int
  5121. xsltParseFindTopLevelElem(xsltCompilerCtxtPtr cctxt,
  5122. xmlNodePtr cur,
  5123. const xmlChar *name,
  5124. const xmlChar *namespaceURI,
  5125. int breakOnOtherElem,
  5126. xmlNodePtr *resultNode)
  5127. {
  5128. if (name == NULL)
  5129. return(-1);
  5130. *resultNode = NULL;
  5131. while (cur != NULL) {
  5132. if (cur->type == XML_ELEMENT_NODE) {
  5133. if ((cur->ns != NULL) && (cur->name != NULL)) {
  5134. if ((*(cur->name) == *name) &&
  5135. xmlStrEqual(cur->name, name) &&
  5136. xmlStrEqual(cur->ns->href, namespaceURI))
  5137. {
  5138. *resultNode = cur;
  5139. return(1);
  5140. }
  5141. }
  5142. if (breakOnOtherElem)
  5143. break;
  5144. }
  5145. cur = cur->next;
  5146. }
  5147. *resultNode = cur;
  5148. return(0);
  5149. }
  5150. static int
  5151. xsltParseTopLevelXSLTElem(xsltCompilerCtxtPtr cctxt,
  5152. xmlNodePtr node,
  5153. xsltStyleType type)
  5154. {
  5155. int ret = 0;
  5156. /*
  5157. * TODO: The reason why this function exists:
  5158. * due to historical reasons some of the
  5159. * top-level declarations are processed by functions
  5160. * in other files. Since we need still to set
  5161. * up the node-info and generate information like
  5162. * in-scope namespaces, this is a wrapper around
  5163. * those old parsing functions.
  5164. */
  5165. xsltCompilerNodePush(cctxt, node);
  5166. if (node->nsDef != NULL)
  5167. cctxt->inode->inScopeNs =
  5168. xsltCompilerBuildInScopeNsList(cctxt, node);
  5169. cctxt->inode->type = type;
  5170. switch (type) {
  5171. case XSLT_FUNC_INCLUDE:
  5172. {
  5173. int oldIsInclude;
  5174. if (xsltCompileXSLTIncludeElem(cctxt, node) == NULL)
  5175. goto exit;
  5176. /*
  5177. * Mark this stylesheet tree as being currently included.
  5178. */
  5179. oldIsInclude = cctxt->isInclude;
  5180. cctxt->isInclude = 1;
  5181. if (xsltParseStylesheetInclude(cctxt->style, node) != 0) {
  5182. cctxt->style->errors++;
  5183. }
  5184. cctxt->isInclude = oldIsInclude;
  5185. }
  5186. break;
  5187. case XSLT_FUNC_PARAM:
  5188. xsltStylePreCompute(cctxt->style, node);
  5189. xsltParseGlobalParam(cctxt->style, node);
  5190. break;
  5191. case XSLT_FUNC_VARIABLE:
  5192. xsltStylePreCompute(cctxt->style, node);
  5193. xsltParseGlobalVariable(cctxt->style, node);
  5194. break;
  5195. case XSLT_FUNC_ATTRSET:
  5196. xsltParseStylesheetAttributeSet(cctxt->style, node);
  5197. break;
  5198. default:
  5199. xsltTransformError(NULL, cctxt->style, node,
  5200. "Internal error: (xsltParseTopLevelXSLTElem) "
  5201. "Cannot handle this top-level declaration.\n");
  5202. cctxt->style->errors++;
  5203. ret = -1;
  5204. }
  5205. exit:
  5206. xsltCompilerNodePop(cctxt, node);
  5207. return(ret);
  5208. }
  5209. #if 0
  5210. static int
  5211. xsltParseRemoveWhitespace(xmlNodePtr node)
  5212. {
  5213. if ((node == NULL) || (node->children == NULL))
  5214. return(0);
  5215. else {
  5216. xmlNodePtr delNode = NULL, child = node->children;
  5217. do {
  5218. if (delNode) {
  5219. xmlUnlinkNode(delNode);
  5220. xmlFreeNode(delNode);
  5221. delNode = NULL;
  5222. }
  5223. if (((child->type == XML_TEXT_NODE) ||
  5224. (child->type == XML_CDATA_SECTION_NODE)) &&
  5225. (IS_BLANK_NODE(child)))
  5226. delNode = child;
  5227. child = child->next;
  5228. } while (child != NULL);
  5229. if (delNode) {
  5230. xmlUnlinkNode(delNode);
  5231. xmlFreeNode(delNode);
  5232. delNode = NULL;
  5233. }
  5234. }
  5235. return(0);
  5236. }
  5237. #endif
  5238. static int
  5239. xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
  5240. {
  5241. #ifdef WITH_XSLT_DEBUG_PARSING
  5242. int templates = 0;
  5243. #endif
  5244. xmlNodePtr cur, start = NULL;
  5245. xsltStylesheetPtr style;
  5246. if ((cctxt == NULL) || (node == NULL) ||
  5247. (node->type != XML_ELEMENT_NODE))
  5248. return(-1);
  5249. style = cctxt->style;
  5250. /*
  5251. * At this stage all import declarations of all stylesheet modules
  5252. * with the same stylesheet level have been processed.
  5253. * Now we can safely parse the rest of the declarations.
  5254. */
  5255. if (IS_XSLT_ELEM_FAST(node) && IS_XSLT_NAME(node, "include"))
  5256. {
  5257. xsltDocumentPtr include;
  5258. /*
  5259. * URGENT TODO: Make this work with simplified stylesheets!
  5260. * I.e., when we won't find an xsl:stylesheet element.
  5261. */
  5262. /*
  5263. * This is as include declaration.
  5264. */
  5265. include = ((xsltStyleItemIncludePtr) node->psvi)->include;
  5266. if (include == NULL) {
  5267. /* TODO: raise error? */
  5268. return(-1);
  5269. }
  5270. /*
  5271. * TODO: Actually an xsl:include should locate an embedded
  5272. * stylesheet as well; so the document-element won't always
  5273. * be the element where the actual stylesheet is rooted at.
  5274. * But such embedded stylesheets are not supported by Libxslt yet.
  5275. */
  5276. node = xmlDocGetRootElement(include->doc);
  5277. if (node == NULL) {
  5278. return(-1);
  5279. }
  5280. }
  5281. if (node->children == NULL)
  5282. return(0);
  5283. /*
  5284. * Push the xsl:stylesheet/xsl:transform element.
  5285. */
  5286. xsltCompilerNodePush(cctxt, node);
  5287. cctxt->inode->isRoot = 1;
  5288. cctxt->inode->nsChanged = 0;
  5289. /*
  5290. * Start with the naked dummy info for literal result elements.
  5291. */
  5292. cctxt->inode->litResElemInfo = cctxt->inodeList->litResElemInfo;
  5293. /*
  5294. * In every case, we need to have
  5295. * the in-scope namespaces of the element, where the
  5296. * stylesheet is rooted at, regardless if it's an XSLT
  5297. * instruction or a literal result instruction (or if
  5298. * this is an embedded stylesheet).
  5299. */
  5300. cctxt->inode->inScopeNs =
  5301. xsltCompilerBuildInScopeNsList(cctxt, node);
  5302. /*
  5303. * Process attributes of xsl:stylesheet/xsl:transform.
  5304. * --------------------------------------------------
  5305. * Allowed are:
  5306. * id = id
  5307. * extension-element-prefixes = tokens
  5308. * exclude-result-prefixes = tokens
  5309. * version = number (mandatory)
  5310. */
  5311. if (xsltParseAttrXSLTVersion(cctxt, node,
  5312. XSLT_ELEMENT_CATEGORY_XSLT) == 0)
  5313. {
  5314. /*
  5315. * Attribute "version".
  5316. * XSLT 1.0: "An xsl:stylesheet element *must* have a version
  5317. * attribute, indicating the version of XSLT that the
  5318. * stylesheet requires".
  5319. * The root element of a simplified stylesheet must also have
  5320. * this attribute.
  5321. */
  5322. #ifdef XSLT_REFACTORED_MANDATORY_VERSION
  5323. if (isXsltElem)
  5324. xsltTransformError(NULL, cctxt->style, node,
  5325. "The attribute 'version' is missing.\n");
  5326. cctxt->style->errors++;
  5327. #else
  5328. /* OLD behaviour. */
  5329. xsltTransformError(NULL, cctxt->style, node,
  5330. "xsl:version is missing: document may not be a stylesheet\n");
  5331. cctxt->style->warnings++;
  5332. #endif
  5333. }
  5334. /*
  5335. * The namespaces declared by the attributes
  5336. * "extension-element-prefixes" and
  5337. * "exclude-result-prefixes" are local to *this*
  5338. * stylesheet tree; i.e., they are *not* visible to
  5339. * other stylesheet-modules, whether imported or included.
  5340. *
  5341. * Attribute "extension-element-prefixes".
  5342. */
  5343. cctxt->inode->extElemNs =
  5344. xsltParseExtElemPrefixes(cctxt, node, NULL,
  5345. XSLT_ELEMENT_CATEGORY_XSLT);
  5346. /*
  5347. * Attribute "exclude-result-prefixes".
  5348. */
  5349. cctxt->inode->exclResultNs =
  5350. xsltParseExclResultPrefixes(cctxt, node, NULL,
  5351. XSLT_ELEMENT_CATEGORY_XSLT);
  5352. /*
  5353. * Create/reuse info for the literal result element.
  5354. */
  5355. if (cctxt->inode->nsChanged)
  5356. xsltLREInfoCreate(cctxt, node, 0);
  5357. /*
  5358. * Processed top-level elements:
  5359. * ----------------------------
  5360. * xsl:variable, xsl:param (QName, in-scope ns,
  5361. * expression (vars allowed))
  5362. * xsl:attribute-set (QName, in-scope ns)
  5363. * xsl:strip-space, xsl:preserve-space (XPath NameTests,
  5364. * in-scope ns)
  5365. * I *think* global scope, merge with includes
  5366. * xsl:output (QName, in-scope ns)
  5367. * xsl:key (QName, in-scope ns, pattern,
  5368. * expression (vars *not* allowed))
  5369. * xsl:decimal-format (QName, needs in-scope ns)
  5370. * xsl:namespace-alias (in-scope ns)
  5371. * global scope, merge with includes
  5372. * xsl:template (last, QName, pattern)
  5373. *
  5374. * (whitespace-only text-nodes have *not* been removed
  5375. * yet; this will be done in xsltParseSequenceConstructor)
  5376. *
  5377. * Report misplaced child-nodes first.
  5378. */
  5379. cur = node->children;
  5380. while (cur != NULL) {
  5381. if (cur->type == XML_TEXT_NODE) {
  5382. xsltTransformError(NULL, style, cur,
  5383. "Misplaced text node (content: '%s').\n",
  5384. (cur->content != NULL) ? cur->content : BAD_CAST "");
  5385. style->errors++;
  5386. } else if (cur->type != XML_ELEMENT_NODE) {
  5387. xsltTransformError(NULL, style, cur, "Misplaced node.\n");
  5388. style->errors++;
  5389. }
  5390. cur = cur->next;
  5391. }
  5392. /*
  5393. * Skip xsl:import elements; they have been processed
  5394. * already.
  5395. */
  5396. cur = node->children;
  5397. while ((cur != NULL) && xsltParseFindTopLevelElem(cctxt, cur,
  5398. BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)
  5399. cur = cur->next;
  5400. if (cur == NULL)
  5401. goto exit;
  5402. start = cur;
  5403. /*
  5404. * Process all top-level xsl:param elements.
  5405. */
  5406. while ((cur != NULL) &&
  5407. xsltParseFindTopLevelElem(cctxt, cur,
  5408. BAD_CAST "param", XSLT_NAMESPACE, 0, &cur) == 1)
  5409. {
  5410. xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_PARAM);
  5411. cur = cur->next;
  5412. }
  5413. /*
  5414. * Process all top-level xsl:variable elements.
  5415. */
  5416. cur = start;
  5417. while ((cur != NULL) &&
  5418. xsltParseFindTopLevelElem(cctxt, cur,
  5419. BAD_CAST "variable", XSLT_NAMESPACE, 0, &cur) == 1)
  5420. {
  5421. xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_VARIABLE);
  5422. cur = cur->next;
  5423. }
  5424. /*
  5425. * Process all the rest of top-level elements.
  5426. */
  5427. cur = start;
  5428. while (cur != NULL) {
  5429. /*
  5430. * Process element nodes.
  5431. */
  5432. if (cur->type == XML_ELEMENT_NODE) {
  5433. if (cur->ns == NULL) {
  5434. xsltTransformError(NULL, style, cur,
  5435. "Unexpected top-level element in no namespace.\n");
  5436. style->errors++;
  5437. cur = cur->next;
  5438. continue;
  5439. }
  5440. /*
  5441. * Process all XSLT elements.
  5442. */
  5443. if (IS_XSLT_ELEM_FAST(cur)) {
  5444. /*
  5445. * xsl:import is only allowed at the beginning.
  5446. */
  5447. if (IS_XSLT_NAME(cur, "import")) {
  5448. xsltTransformError(NULL, style, cur,
  5449. "Misplaced xsl:import element.\n");
  5450. style->errors++;
  5451. cur = cur->next;
  5452. continue;
  5453. }
  5454. /*
  5455. * TODO: Change the return type of the parsing functions
  5456. * to int.
  5457. */
  5458. if (IS_XSLT_NAME(cur, "template")) {
  5459. #ifdef WITH_XSLT_DEBUG_PARSING
  5460. templates++;
  5461. #endif
  5462. /*
  5463. * TODO: Is the position of xsl:template in the
  5464. * tree significant? If not it would be easier to
  5465. * parse them at a later stage.
  5466. */
  5467. xsltParseXSLTTemplate(cctxt, cur);
  5468. } else if (IS_XSLT_NAME(cur, "variable")) {
  5469. /* NOP; done already */
  5470. } else if (IS_XSLT_NAME(cur, "param")) {
  5471. /* NOP; done already */
  5472. } else if (IS_XSLT_NAME(cur, "include")) {
  5473. if (cur->psvi != NULL)
  5474. xsltParseXSLTStylesheetElemCore(cctxt, cur);
  5475. else {
  5476. xsltTransformError(NULL, style, cur,
  5477. "Internal error: "
  5478. "(xsltParseXSLTStylesheetElemCore) "
  5479. "The xsl:include element was not compiled.\n");
  5480. style->errors++;
  5481. }
  5482. } else if (IS_XSLT_NAME(cur, "strip-space")) {
  5483. /* No node info needed. */
  5484. xsltParseStylesheetStripSpace(style, cur);
  5485. } else if (IS_XSLT_NAME(cur, "preserve-space")) {
  5486. /* No node info needed. */
  5487. xsltParseStylesheetPreserveSpace(style, cur);
  5488. } else if (IS_XSLT_NAME(cur, "output")) {
  5489. /* No node-info needed. */
  5490. xsltParseStylesheetOutput(style, cur);
  5491. } else if (IS_XSLT_NAME(cur, "key")) {
  5492. /* TODO: node-info needed for expressions ? */
  5493. xsltParseStylesheetKey(style, cur);
  5494. } else if (IS_XSLT_NAME(cur, "decimal-format")) {
  5495. /* No node-info needed. */
  5496. xsltParseStylesheetDecimalFormat(style, cur);
  5497. } else if (IS_XSLT_NAME(cur, "attribute-set")) {
  5498. xsltParseTopLevelXSLTElem(cctxt, cur,
  5499. XSLT_FUNC_ATTRSET);
  5500. } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
  5501. /* NOP; done already */
  5502. } else {
  5503. if (cctxt->inode->forwardsCompat) {
  5504. /*
  5505. * Forwards-compatible mode:
  5506. *
  5507. * XSLT-1: "if it is a top-level element and
  5508. * XSLT 1.0 does not allow such elements as top-level
  5509. * elements, then the element must be ignored along
  5510. * with its content;"
  5511. */
  5512. /*
  5513. * TODO: I don't think we should generate a warning.
  5514. */
  5515. xsltTransformError(NULL, style, cur,
  5516. "Forwards-compatible mode: Ignoring unknown XSLT "
  5517. "element '%s'.\n", cur->name);
  5518. style->warnings++;
  5519. } else {
  5520. xsltTransformError(NULL, style, cur,
  5521. "Unknown XSLT element '%s'.\n", cur->name);
  5522. style->errors++;
  5523. }
  5524. }
  5525. } else {
  5526. xsltTopLevelFunction function;
  5527. /*
  5528. * Process non-XSLT elements, which are in a
  5529. * non-NULL namespace.
  5530. */
  5531. /*
  5532. * QUESTION: What does xsltExtModuleTopLevelLookup()
  5533. * do exactly?
  5534. */
  5535. function = xsltExtModuleTopLevelLookup(cur->name,
  5536. cur->ns->href);
  5537. if (function != NULL)
  5538. function(style, cur);
  5539. #ifdef WITH_XSLT_DEBUG_PARSING
  5540. xsltGenericDebug(xsltGenericDebugContext,
  5541. "xsltParseXSLTStylesheetElemCore : User-defined "
  5542. "data element '%s'.\n", cur->name);
  5543. #endif
  5544. }
  5545. }
  5546. cur = cur->next;
  5547. }
  5548. exit:
  5549. #ifdef WITH_XSLT_DEBUG_PARSING
  5550. xsltGenericDebug(xsltGenericDebugContext,
  5551. "### END of parsing top-level elements of doc '%s'.\n",
  5552. node->doc->URL);
  5553. xsltGenericDebug(xsltGenericDebugContext,
  5554. "### Templates: %d\n", templates);
  5555. #ifdef XSLT_REFACTORED
  5556. xsltGenericDebug(xsltGenericDebugContext,
  5557. "### Max inodes: %d\n", cctxt->maxNodeInfos);
  5558. xsltGenericDebug(xsltGenericDebugContext,
  5559. "### Max LREs : %d\n", cctxt->maxLREs);
  5560. #endif /* XSLT_REFACTORED */
  5561. #endif /* WITH_XSLT_DEBUG_PARSING */
  5562. xsltCompilerNodePop(cctxt, node);
  5563. return(0);
  5564. }
  5565. /**
  5566. * xsltParseXSLTStylesheet:
  5567. * @cctxt: the compiler context
  5568. * @node: the xsl:stylesheet/xsl:transform element-node
  5569. *
  5570. * Parses the xsl:stylesheet and xsl:transform element.
  5571. *
  5572. * <xsl:stylesheet
  5573. * id = id
  5574. * extension-element-prefixes = tokens
  5575. * exclude-result-prefixes = tokens
  5576. * version = number>
  5577. * <!-- Content: (xsl:import*, top-level-elements) -->
  5578. * </xsl:stylesheet>
  5579. *
  5580. * BIG TODO: The xsl:include stuff.
  5581. *
  5582. * Called by xsltParseStylesheetTree()
  5583. *
  5584. * Returns 0 on success, a positive result on errors and
  5585. * -1 on API or internal errors.
  5586. */
  5587. static int
  5588. xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
  5589. {
  5590. xmlNodePtr cur, start;
  5591. if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
  5592. return(-1);
  5593. if (node->children == NULL)
  5594. goto exit;
  5595. /*
  5596. * Process top-level elements:
  5597. * xsl:import (must be first)
  5598. * xsl:include (this is just a pre-processing)
  5599. */
  5600. cur = node->children;
  5601. /*
  5602. * Process xsl:import elements.
  5603. * XSLT 1.0: "The xsl:import element children must precede all
  5604. * other element children of an xsl:stylesheet element,
  5605. * including any xsl:include element children."
  5606. */
  5607. while ((cur != NULL) &&
  5608. xsltParseFindTopLevelElem(cctxt, cur,
  5609. BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)
  5610. {
  5611. if (xsltParseStylesheetImport(cctxt->style, cur) != 0) {
  5612. cctxt->style->errors++;
  5613. }
  5614. cur = cur->next;
  5615. }
  5616. if (cur == NULL)
  5617. goto exit;
  5618. start = cur;
  5619. /*
  5620. * Pre-process all xsl:include elements.
  5621. */
  5622. cur = start;
  5623. while ((cur != NULL) &&
  5624. xsltParseFindTopLevelElem(cctxt, cur,
  5625. BAD_CAST "include", XSLT_NAMESPACE, 0, &cur) == 1)
  5626. {
  5627. xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_INCLUDE);
  5628. cur = cur->next;
  5629. }
  5630. /*
  5631. * Pre-process all xsl:namespace-alias elements.
  5632. * URGENT TODO: This won't work correctly: the order of included
  5633. * aliases and aliases defined here is significant.
  5634. */
  5635. cur = start;
  5636. while ((cur != NULL) &&
  5637. xsltParseFindTopLevelElem(cctxt, cur,
  5638. BAD_CAST "namespace-alias", XSLT_NAMESPACE, 0, &cur) == 1)
  5639. {
  5640. xsltNamespaceAlias(cctxt->style, cur);
  5641. cur = cur->next;
  5642. }
  5643. if (cctxt->isInclude) {
  5644. /*
  5645. * If this stylesheet is intended for inclusion, then
  5646. * we will process only imports and includes.
  5647. */
  5648. goto exit;
  5649. }
  5650. /*
  5651. * Now parse the rest of the top-level elements.
  5652. */
  5653. xsltParseXSLTStylesheetElemCore(cctxt, node);
  5654. exit:
  5655. return(0);
  5656. }
  5657. #else /* XSLT_REFACTORED */
  5658. /**
  5659. * xsltParseStylesheetTop:
  5660. * @style: the XSLT stylesheet
  5661. * @top: the top level "stylesheet" or "transform" element
  5662. *
  5663. * scan the top level elements of an XSL stylesheet
  5664. */
  5665. static void
  5666. xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
  5667. xmlNodePtr cur;
  5668. xmlChar *prop;
  5669. #ifdef WITH_XSLT_DEBUG_PARSING
  5670. int templates = 0;
  5671. #endif
  5672. if ((top == NULL) || (top->type != XML_ELEMENT_NODE))
  5673. return;
  5674. prop = xmlGetNsProp(top, (const xmlChar *)"version", NULL);
  5675. if (prop == NULL) {
  5676. xsltTransformError(NULL, style, top,
  5677. "xsl:version is missing: document may not be a stylesheet\n");
  5678. if (style != NULL) style->warnings++;
  5679. } else {
  5680. if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
  5681. (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
  5682. xsltTransformError(NULL, style, top,
  5683. "xsl:version: only 1.1 features are supported\n");
  5684. if (style != NULL) {
  5685. style->forwards_compatible = 1;
  5686. style->warnings++;
  5687. }
  5688. }
  5689. xmlFree(prop);
  5690. }
  5691. /*
  5692. * process xsl:import elements
  5693. */
  5694. cur = top->children;
  5695. while (cur != NULL) {
  5696. if (IS_BLANK_NODE(cur)) {
  5697. cur = cur->next;
  5698. continue;
  5699. }
  5700. if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "import")) {
  5701. if (xsltParseStylesheetImport(style, cur) != 0)
  5702. if (style != NULL) style->errors++;
  5703. } else
  5704. break;
  5705. cur = cur->next;
  5706. }
  5707. /*
  5708. * process other top-level elements
  5709. */
  5710. while (cur != NULL) {
  5711. if (IS_BLANK_NODE(cur)) {
  5712. cur = cur->next;
  5713. continue;
  5714. }
  5715. if (cur->type == XML_TEXT_NODE) {
  5716. if (cur->content != NULL) {
  5717. xsltTransformError(NULL, style, cur,
  5718. "misplaced text node: '%s'\n", cur->content);
  5719. }
  5720. if (style != NULL) style->errors++;
  5721. cur = cur->next;
  5722. continue;
  5723. }
  5724. if ((cur->type == XML_ELEMENT_NODE) && (cur->ns == NULL)) {
  5725. xsltGenericError(xsltGenericErrorContext,
  5726. "Found a top-level element %s with null namespace URI\n",
  5727. cur->name);
  5728. if (style != NULL) style->errors++;
  5729. cur = cur->next;
  5730. continue;
  5731. }
  5732. if ((cur->type == XML_ELEMENT_NODE) && (!(IS_XSLT_ELEM(cur)))) {
  5733. xsltTopLevelFunction function;
  5734. function = xsltExtModuleTopLevelLookup(cur->name,
  5735. cur->ns->href);
  5736. if (function != NULL)
  5737. function(style, cur);
  5738. #ifdef WITH_XSLT_DEBUG_PARSING
  5739. xsltGenericDebug(xsltGenericDebugContext,
  5740. "xsltParseStylesheetTop : found foreign element %s\n",
  5741. cur->name);
  5742. #endif
  5743. cur = cur->next;
  5744. continue;
  5745. }
  5746. if (IS_XSLT_NAME(cur, "import")) {
  5747. xsltTransformError(NULL, style, cur,
  5748. "xsltParseStylesheetTop: ignoring misplaced import element\n");
  5749. if (style != NULL) style->errors++;
  5750. } else if (IS_XSLT_NAME(cur, "include")) {
  5751. if (xsltParseStylesheetInclude(style, cur) != 0)
  5752. if (style != NULL) style->errors++;
  5753. } else if (IS_XSLT_NAME(cur, "strip-space")) {
  5754. xsltParseStylesheetStripSpace(style, cur);
  5755. } else if (IS_XSLT_NAME(cur, "preserve-space")) {
  5756. xsltParseStylesheetPreserveSpace(style, cur);
  5757. } else if (IS_XSLT_NAME(cur, "output")) {
  5758. xsltParseStylesheetOutput(style, cur);
  5759. } else if (IS_XSLT_NAME(cur, "key")) {
  5760. xsltParseStylesheetKey(style, cur);
  5761. } else if (IS_XSLT_NAME(cur, "decimal-format")) {
  5762. xsltParseStylesheetDecimalFormat(style, cur);
  5763. } else if (IS_XSLT_NAME(cur, "attribute-set")) {
  5764. xsltParseStylesheetAttributeSet(style, cur);
  5765. } else if (IS_XSLT_NAME(cur, "variable")) {
  5766. xsltParseGlobalVariable(style, cur);
  5767. } else if (IS_XSLT_NAME(cur, "param")) {
  5768. xsltParseGlobalParam(style, cur);
  5769. } else if (IS_XSLT_NAME(cur, "template")) {
  5770. #ifdef WITH_XSLT_DEBUG_PARSING
  5771. templates++;
  5772. #endif
  5773. xsltParseStylesheetTemplate(style, cur);
  5774. } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
  5775. xsltNamespaceAlias(style, cur);
  5776. } else {
  5777. if ((style != NULL) && (style->forwards_compatible == 0)) {
  5778. xsltTransformError(NULL, style, cur,
  5779. "xsltParseStylesheetTop: unknown %s element\n",
  5780. cur->name);
  5781. if (style != NULL) style->errors++;
  5782. }
  5783. }
  5784. cur = cur->next;
  5785. }
  5786. #ifdef WITH_XSLT_DEBUG_PARSING
  5787. xsltGenericDebug(xsltGenericDebugContext,
  5788. "parsed %d templates\n", templates);
  5789. #endif
  5790. }
  5791. #endif /* else of XSLT_REFACTORED */
  5792. #ifdef XSLT_REFACTORED
  5793. /**
  5794. * xsltParseSimplifiedStylesheetTree:
  5795. *
  5796. * @style: the stylesheet (TODO: Change this to the compiler context)
  5797. * @doc: the document containing the stylesheet.
  5798. * @node: the node where the stylesheet is rooted at
  5799. *
  5800. * Returns 0 in case of success, a positive result if an error occurred
  5801. * and -1 on API and internal errors.
  5802. */
  5803. static int
  5804. xsltParseSimplifiedStylesheetTree(xsltCompilerCtxtPtr cctxt,
  5805. xmlDocPtr doc,
  5806. xmlNodePtr node)
  5807. {
  5808. xsltTemplatePtr templ;
  5809. if ((cctxt == NULL) || (node == NULL))
  5810. return(-1);
  5811. if (xsltParseAttrXSLTVersion(cctxt, node, 0) == XSLT_ELEMENT_CATEGORY_LRE)
  5812. {
  5813. /*
  5814. * TODO: Adjust report, since this might be an
  5815. * embedded stylesheet.
  5816. */
  5817. xsltTransformError(NULL, cctxt->style, node,
  5818. "The attribute 'xsl:version' is missing; cannot identify "
  5819. "this document as an XSLT stylesheet document.\n");
  5820. cctxt->style->errors++;
  5821. return(1);
  5822. }
  5823. #ifdef WITH_XSLT_DEBUG_PARSING
  5824. xsltGenericDebug(xsltGenericDebugContext,
  5825. "xsltParseSimplifiedStylesheetTree: document is stylesheet\n");
  5826. #endif
  5827. /*
  5828. * Create and link the template
  5829. */
  5830. templ = xsltNewTemplate();
  5831. if (templ == NULL) {
  5832. return(-1);
  5833. }
  5834. templ->next = cctxt->style->templates;
  5835. cctxt->style->templates = templ;
  5836. templ->match = xmlStrdup(BAD_CAST "/");
  5837. /*
  5838. * Note that we push the document-node in this special case.
  5839. */
  5840. xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);
  5841. /*
  5842. * In every case, we need to have
  5843. * the in-scope namespaces of the element, where the
  5844. * stylesheet is rooted at, regardless if it's an XSLT
  5845. * instruction or a literal result instruction (or if
  5846. * this is an embedded stylesheet).
  5847. */
  5848. cctxt->inode->inScopeNs =
  5849. xsltCompilerBuildInScopeNsList(cctxt, node);
  5850. /*
  5851. * Parse the content and register the match-pattern.
  5852. */
  5853. xsltParseSequenceConstructor(cctxt, node);
  5854. xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);
  5855. templ->elem = (xmlNodePtr) doc;
  5856. templ->content = node;
  5857. xsltAddTemplate(cctxt->style, templ, NULL, NULL);
  5858. cctxt->style->literal_result = 1;
  5859. return(0);
  5860. }
  5861. #ifdef XSLT_REFACTORED_XSLT_NSCOMP
  5862. /**
  5863. * xsltRestoreDocumentNamespaces:
  5864. * @ns: map of namespaces
  5865. * @doc: the document
  5866. *
  5867. * Restore the namespaces for the document
  5868. *
  5869. * Returns 0 in case of success, -1 in case of failure
  5870. */
  5871. int
  5872. xsltRestoreDocumentNamespaces(xsltNsMapPtr ns, xmlDocPtr doc)
  5873. {
  5874. if (doc == NULL)
  5875. return(-1);
  5876. /*
  5877. * Revert the changes we have applied to the namespace-URIs of
  5878. * ns-decls.
  5879. */
  5880. while (ns != NULL) {
  5881. if ((ns->doc == doc) && (ns->ns != NULL)) {
  5882. ns->ns->href = ns->origNsName;
  5883. ns->origNsName = NULL;
  5884. ns->ns = NULL;
  5885. }
  5886. ns = ns->next;
  5887. }
  5888. return(0);
  5889. }
  5890. #endif /* XSLT_REFACTORED_XSLT_NSCOMP */
  5891. /**
  5892. * xsltParseStylesheetProcess:
  5893. * @style: the XSLT stylesheet (the current stylesheet-level)
  5894. * @doc: and xmlDoc parsed XML
  5895. *
  5896. * Parses an XSLT stylesheet, adding the associated structures.
  5897. * Called by:
  5898. * xsltParseStylesheetImportedDoc() (xslt.c)
  5899. * xsltParseStylesheetInclude() (imports.c)
  5900. *
  5901. * Returns the value of the @style parameter if everything
  5902. * went right, NULL if something went amiss.
  5903. */
  5904. xsltStylesheetPtr
  5905. xsltParseStylesheetProcess(xsltStylesheetPtr style, xmlDocPtr doc)
  5906. {
  5907. xsltCompilerCtxtPtr cctxt;
  5908. xmlNodePtr cur;
  5909. int oldIsSimplifiedStylesheet;
  5910. xsltInitGlobals();
  5911. if ((style == NULL) || (doc == NULL))
  5912. return(NULL);
  5913. cctxt = XSLT_CCTXT(style);
  5914. cur = xmlDocGetRootElement(doc);
  5915. if (cur == NULL) {
  5916. xsltTransformError(NULL, style, (xmlNodePtr) doc,
  5917. "xsltParseStylesheetProcess : empty stylesheet\n");
  5918. return(NULL);
  5919. }
  5920. oldIsSimplifiedStylesheet = cctxt->simplified;
  5921. if ((IS_XSLT_ELEM(cur)) &&
  5922. ((IS_XSLT_NAME(cur, "stylesheet")) ||
  5923. (IS_XSLT_NAME(cur, "transform")))) {
  5924. #ifdef WITH_XSLT_DEBUG_PARSING
  5925. xsltGenericDebug(xsltGenericDebugContext,
  5926. "xsltParseStylesheetProcess : found stylesheet\n");
  5927. #endif
  5928. cctxt->simplified = 0;
  5929. style->literal_result = 0;
  5930. } else {
  5931. cctxt->simplified = 1;
  5932. style->literal_result = 1;
  5933. }
  5934. /*
  5935. * Pre-process the stylesheet if not already done before.
  5936. * This will remove PIs and comments, merge adjacent
  5937. * text nodes, internalize strings, etc.
  5938. */
  5939. if (! style->nopreproc)
  5940. xsltParsePreprocessStylesheetTree(cctxt, cur);
  5941. /*
  5942. * Parse and compile the stylesheet.
  5943. */
  5944. if (style->literal_result == 0) {
  5945. if (xsltParseXSLTStylesheetElem(cctxt, cur) != 0)
  5946. return(NULL);
  5947. } else {
  5948. if (xsltParseSimplifiedStylesheetTree(cctxt, doc, cur) != 0)
  5949. return(NULL);
  5950. }
  5951. cctxt->simplified = oldIsSimplifiedStylesheet;
  5952. return(style);
  5953. }
  5954. #else /* XSLT_REFACTORED */
  5955. /**
  5956. * xsltParseStylesheetProcess:
  5957. * @ret: the XSLT stylesheet (the current stylesheet-level)
  5958. * @doc: and xmlDoc parsed XML
  5959. *
  5960. * Parses an XSLT stylesheet, adding the associated structures.
  5961. * Called by:
  5962. * xsltParseStylesheetImportedDoc() (xslt.c)
  5963. * xsltParseStylesheetInclude() (imports.c)
  5964. *
  5965. * Returns the value of the @style parameter if everything
  5966. * went right, NULL if something went amiss.
  5967. */
  5968. xsltStylesheetPtr
  5969. xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
  5970. xmlNodePtr cur;
  5971. xsltInitGlobals();
  5972. if (doc == NULL)
  5973. return(NULL);
  5974. if (ret == NULL)
  5975. return(ret);
  5976. /*
  5977. * First steps, remove blank nodes,
  5978. * locate the xsl:stylesheet element and the
  5979. * namespace declaration.
  5980. */
  5981. cur = xmlDocGetRootElement(doc);
  5982. if (cur == NULL) {
  5983. xsltTransformError(NULL, ret, (xmlNodePtr) doc,
  5984. "xsltParseStylesheetProcess : empty stylesheet\n");
  5985. return(NULL);
  5986. }
  5987. if ((IS_XSLT_ELEM(cur)) &&
  5988. ((IS_XSLT_NAME(cur, "stylesheet")) ||
  5989. (IS_XSLT_NAME(cur, "transform")))) {
  5990. #ifdef WITH_XSLT_DEBUG_PARSING
  5991. xsltGenericDebug(xsltGenericDebugContext,
  5992. "xsltParseStylesheetProcess : found stylesheet\n");
  5993. #endif
  5994. ret->literal_result = 0;
  5995. xsltParseStylesheetExcludePrefix(ret, cur, 1);
  5996. xsltParseStylesheetExtPrefix(ret, cur, 1);
  5997. } else {
  5998. xsltParseStylesheetExcludePrefix(ret, cur, 0);
  5999. xsltParseStylesheetExtPrefix(ret, cur, 0);
  6000. ret->literal_result = 1;
  6001. }
  6002. if (!ret->nopreproc) {
  6003. xsltPreprocessStylesheet(ret, cur);
  6004. }
  6005. if (ret->literal_result == 0) {
  6006. xsltParseStylesheetTop(ret, cur);
  6007. } else {
  6008. xmlChar *prop;
  6009. xsltTemplatePtr template;
  6010. /*
  6011. * the document itself might be the template, check xsl:version
  6012. */
  6013. prop = xmlGetNsProp(cur, (const xmlChar *)"version", XSLT_NAMESPACE);
  6014. if (prop == NULL) {
  6015. xsltTransformError(NULL, ret, cur,
  6016. "xsltParseStylesheetProcess : document is not a stylesheet\n");
  6017. return(NULL);
  6018. }
  6019. #ifdef WITH_XSLT_DEBUG_PARSING
  6020. xsltGenericDebug(xsltGenericDebugContext,
  6021. "xsltParseStylesheetProcess : document is stylesheet\n");
  6022. #endif
  6023. if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
  6024. (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
  6025. xsltTransformError(NULL, ret, cur,
  6026. "xsl:version: only 1.1 features are supported\n");
  6027. ret->forwards_compatible = 1;
  6028. ret->warnings++;
  6029. }
  6030. xmlFree(prop);
  6031. /*
  6032. * Create and link the template
  6033. */
  6034. template = xsltNewTemplate();
  6035. if (template == NULL) {
  6036. return(NULL);
  6037. }
  6038. template->next = ret->templates;
  6039. ret->templates = template;
  6040. template->match = xmlStrdup((const xmlChar *)"/");
  6041. /*
  6042. * parse the content and register the pattern
  6043. */
  6044. xsltParseTemplateContent(ret, (xmlNodePtr) doc);
  6045. template->elem = (xmlNodePtr) doc;
  6046. template->content = doc->children;
  6047. xsltAddTemplate(ret, template, NULL, NULL);
  6048. ret->literal_result = 1;
  6049. }
  6050. return(ret);
  6051. }
  6052. #endif /* else of XSLT_REFACTORED */
  6053. /**
  6054. * xsltParseStylesheetImportedDoc:
  6055. * @doc: an xmlDoc parsed XML
  6056. * @parentStyle: pointer to the parent stylesheet (if it exists)
  6057. *
  6058. * parse an XSLT stylesheet building the associated structures
  6059. * except the processing not needed for imported documents.
  6060. *
  6061. * Returns a new XSLT stylesheet structure.
  6062. */
  6063. xsltStylesheetPtr
  6064. xsltParseStylesheetImportedDoc(xmlDocPtr doc,
  6065. xsltStylesheetPtr parentStyle) {
  6066. xsltStylesheetPtr retStyle;
  6067. if (doc == NULL)
  6068. return(NULL);
  6069. retStyle = xsltNewStylesheetInternal(parentStyle);
  6070. if (retStyle == NULL)
  6071. return(NULL);
  6072. if (xsltParseStylesheetUser(retStyle, doc) != 0) {
  6073. xsltFreeStylesheet(retStyle);
  6074. return(NULL);
  6075. }
  6076. return(retStyle);
  6077. }
  6078. /**
  6079. * xsltParseStylesheetUser:
  6080. * @style: pointer to the stylesheet
  6081. * @doc: an xmlDoc parsed XML
  6082. *
  6083. * Parse an XSLT stylesheet with a user-provided stylesheet struct.
  6084. *
  6085. * Returns 0 if successful, -1 in case of error.
  6086. */
  6087. int
  6088. xsltParseStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc) {
  6089. if ((style == NULL) || (doc == NULL))
  6090. return(-1);
  6091. /*
  6092. * Adjust the string dict.
  6093. */
  6094. if (doc->dict != NULL) {
  6095. xmlDictFree(style->dict);
  6096. style->dict = doc->dict;
  6097. #ifdef WITH_XSLT_DEBUG
  6098. xsltGenericDebug(xsltGenericDebugContext,
  6099. "reusing dictionary from %s for stylesheet\n",
  6100. doc->URL);
  6101. #endif
  6102. xmlDictReference(style->dict);
  6103. }
  6104. /*
  6105. * TODO: Eliminate xsltGatherNamespaces(); we must not restrict
  6106. * the stylesheet to containt distinct namespace prefixes.
  6107. */
  6108. xsltGatherNamespaces(style);
  6109. #ifdef XSLT_REFACTORED
  6110. {
  6111. xsltCompilerCtxtPtr cctxt;
  6112. xsltStylesheetPtr oldCurSheet;
  6113. if (style->parent == NULL) {
  6114. xsltPrincipalStylesheetDataPtr principalData;
  6115. /*
  6116. * Create extra data for the principal stylesheet.
  6117. */
  6118. principalData = xsltNewPrincipalStylesheetData();
  6119. if (principalData == NULL) {
  6120. return(-1);
  6121. }
  6122. style->principalData = principalData;
  6123. /*
  6124. * Create the compilation context
  6125. * ------------------------------
  6126. * (only once; for the principal stylesheet).
  6127. * This is currently the only function where the
  6128. * compilation context is created.
  6129. */
  6130. cctxt = xsltCompilationCtxtCreate(style);
  6131. if (cctxt == NULL) {
  6132. return(-1);
  6133. }
  6134. style->compCtxt = (void *) cctxt;
  6135. cctxt->style = style;
  6136. cctxt->dict = style->dict;
  6137. cctxt->psData = principalData;
  6138. /*
  6139. * Push initial dummy node info.
  6140. */
  6141. cctxt->depth = -1;
  6142. xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);
  6143. } else {
  6144. /*
  6145. * Imported stylesheet.
  6146. */
  6147. cctxt = style->parent->compCtxt;
  6148. style->compCtxt = cctxt;
  6149. }
  6150. /*
  6151. * Save the old and set the current stylesheet structure in the
  6152. * compilation context.
  6153. */
  6154. oldCurSheet = cctxt->style;
  6155. cctxt->style = style;
  6156. style->doc = doc;
  6157. xsltParseStylesheetProcess(style, doc);
  6158. cctxt->style = oldCurSheet;
  6159. if (style->parent == NULL) {
  6160. /*
  6161. * Pop the initial dummy node info.
  6162. */
  6163. xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);
  6164. } else {
  6165. /*
  6166. * Clear the compilation context of imported
  6167. * stylesheets.
  6168. * TODO: really?
  6169. */
  6170. /* style->compCtxt = NULL; */
  6171. }
  6172. #ifdef XSLT_REFACTORED_XSLT_NSCOMP
  6173. if (style->errors != 0) {
  6174. /*
  6175. * Restore all changes made to namespace URIs of ns-decls.
  6176. */
  6177. if (cctxt->psData->nsMap)
  6178. xsltRestoreDocumentNamespaces(cctxt->psData->nsMap, doc);
  6179. }
  6180. #endif
  6181. if (style->parent == NULL) {
  6182. xsltCompilationCtxtFree(style->compCtxt);
  6183. style->compCtxt = NULL;
  6184. }
  6185. }
  6186. #else /* XSLT_REFACTORED */
  6187. /*
  6188. * Old behaviour.
  6189. */
  6190. style->doc = doc;
  6191. if (xsltParseStylesheetProcess(style, doc) == NULL) {
  6192. style->doc = NULL;
  6193. return(-1);
  6194. }
  6195. #endif /* else of XSLT_REFACTORED */
  6196. if (style->errors != 0) {
  6197. /*
  6198. * Detach the doc from the stylesheet; otherwise the doc
  6199. * will be freed in xsltFreeStylesheet().
  6200. */
  6201. style->doc = NULL;
  6202. /*
  6203. * Cleanup the doc if its the main stylesheet.
  6204. */
  6205. if (style->parent == NULL)
  6206. xsltCleanupStylesheetTree(doc, xmlDocGetRootElement(doc));
  6207. return(-1);
  6208. }
  6209. if (style->parent == NULL)
  6210. xsltResolveStylesheetAttributeSet(style);
  6211. return(0);
  6212. }
  6213. /**
  6214. * xsltParseStylesheetDoc:
  6215. * @doc: and xmlDoc parsed XML
  6216. *
  6217. * parse an XSLT stylesheet, building the associated structures. doc
  6218. * is kept as a reference within the returned stylesheet, so changes
  6219. * to doc after the parsing will be reflected when the stylesheet
  6220. * is applied, and the doc is automatically freed when the
  6221. * stylesheet is closed.
  6222. *
  6223. * Returns a new XSLT stylesheet structure.
  6224. */
  6225. xsltStylesheetPtr
  6226. xsltParseStylesheetDoc(xmlDocPtr doc) {
  6227. xsltInitGlobals();
  6228. return(xsltParseStylesheetImportedDoc(doc, NULL));
  6229. }
  6230. /**
  6231. * xsltParseStylesheetFile:
  6232. * @filename: the filename/URL to the stylesheet
  6233. *
  6234. * Load and parse an XSLT stylesheet
  6235. *
  6236. * Returns a new XSLT stylesheet structure.
  6237. */
  6238. xsltStylesheetPtr
  6239. xsltParseStylesheetFile(const xmlChar* filename) {
  6240. xsltSecurityPrefsPtr sec;
  6241. xsltStylesheetPtr ret;
  6242. xmlDocPtr doc;
  6243. xsltInitGlobals();
  6244. if (filename == NULL)
  6245. return(NULL);
  6246. #ifdef WITH_XSLT_DEBUG_PARSING
  6247. xsltGenericDebug(xsltGenericDebugContext,
  6248. "xsltParseStylesheetFile : parse %s\n", filename);
  6249. #endif
  6250. /*
  6251. * Security framework check
  6252. */
  6253. sec = xsltGetDefaultSecurityPrefs();
  6254. if (sec != NULL) {
  6255. int res;
  6256. res = xsltCheckRead(sec, NULL, filename);
  6257. if (res <= 0) {
  6258. if (res == 0)
  6259. xsltTransformError(NULL, NULL, NULL,
  6260. "xsltParseStylesheetFile: read rights for %s denied\n",
  6261. filename);
  6262. return(NULL);
  6263. }
  6264. }
  6265. doc = xsltDocDefaultLoader(filename, NULL, XSLT_PARSE_OPTIONS,
  6266. NULL, XSLT_LOAD_START);
  6267. if (doc == NULL) {
  6268. xsltTransformError(NULL, NULL, NULL,
  6269. "xsltParseStylesheetFile : cannot parse %s\n", filename);
  6270. return(NULL);
  6271. }
  6272. ret = xsltParseStylesheetDoc(doc);
  6273. if (ret == NULL) {
  6274. xmlFreeDoc(doc);
  6275. return(NULL);
  6276. }
  6277. return(ret);
  6278. }
  6279. /************************************************************************
  6280. * *
  6281. * Handling of Stylesheet PI *
  6282. * *
  6283. ************************************************************************/
  6284. #define CUR (*cur)
  6285. #define SKIP(val) cur += (val)
  6286. #define NXT(val) cur[(val)]
  6287. #define SKIP_BLANKS \
  6288. while (IS_BLANK(CUR)) NEXT
  6289. #define NEXT ((*cur) ? cur++ : cur)
  6290. /**
  6291. * xsltParseStylesheetPI:
  6292. * @value: the value of the PI
  6293. *
  6294. * This function checks that the type is text/xml and extracts
  6295. * the URI-Reference for the stylesheet
  6296. *
  6297. * Returns the URI-Reference for the stylesheet or NULL (it need to
  6298. * be freed by the caller)
  6299. */
  6300. static xmlChar *
  6301. xsltParseStylesheetPI(const xmlChar *value) {
  6302. const xmlChar *cur;
  6303. const xmlChar *start;
  6304. xmlChar *val;
  6305. xmlChar tmp;
  6306. xmlChar *href = NULL;
  6307. int isXml = 0;
  6308. if (value == NULL)
  6309. return(NULL);
  6310. cur = value;
  6311. while (CUR != 0) {
  6312. SKIP_BLANKS;
  6313. if ((CUR == 't') && (NXT(1) == 'y') && (NXT(2) == 'p') &&
  6314. (NXT(3) == 'e')) {
  6315. SKIP(4);
  6316. SKIP_BLANKS;
  6317. if (CUR != '=')
  6318. continue;
  6319. NEXT;
  6320. if ((CUR != '\'') && (CUR != '"'))
  6321. continue;
  6322. tmp = CUR;
  6323. NEXT;
  6324. start = cur;
  6325. while ((CUR != 0) && (CUR != tmp))
  6326. NEXT;
  6327. if (CUR != tmp)
  6328. continue;
  6329. val = xmlStrndup(start, cur - start);
  6330. NEXT;
  6331. if (val == NULL)
  6332. return(NULL);
  6333. if ((xmlStrcasecmp(val, BAD_CAST "text/xml")) &&
  6334. (xmlStrcasecmp(val, BAD_CAST "text/xsl"))) {
  6335. xmlFree(val);
  6336. break;
  6337. }
  6338. isXml = 1;
  6339. xmlFree(val);
  6340. } else if ((CUR == 'h') && (NXT(1) == 'r') && (NXT(2) == 'e') &&
  6341. (NXT(3) == 'f')) {
  6342. SKIP(4);
  6343. SKIP_BLANKS;
  6344. if (CUR != '=')
  6345. continue;
  6346. NEXT;
  6347. if ((CUR != '\'') && (CUR != '"'))
  6348. continue;
  6349. tmp = CUR;
  6350. NEXT;
  6351. start = cur;
  6352. while ((CUR != 0) && (CUR != tmp))
  6353. NEXT;
  6354. if (CUR != tmp)
  6355. continue;
  6356. if (href == NULL)
  6357. href = xmlStrndup(start, cur - start);
  6358. NEXT;
  6359. } else {
  6360. while ((CUR != 0) && (!IS_BLANK(CUR)))
  6361. NEXT;
  6362. }
  6363. }
  6364. if (!isXml) {
  6365. if (href != NULL)
  6366. xmlFree(href);
  6367. href = NULL;
  6368. }
  6369. return(href);
  6370. }
  6371. /**
  6372. * xsltLoadStylesheetPI:
  6373. * @doc: a document to process
  6374. *
  6375. * This function tries to locate the stylesheet PI in the given document
  6376. * If found, and if contained within the document, it will extract
  6377. * that subtree to build the stylesheet to process @doc (doc itself will
  6378. * be modified). If found but referencing an external document it will
  6379. * attempt to load it and generate a stylesheet from it. In both cases,
  6380. * the resulting stylesheet and the document need to be freed once the
  6381. * transformation is done.
  6382. *
  6383. * Returns a new XSLT stylesheet structure or NULL if not found.
  6384. */
  6385. xsltStylesheetPtr
  6386. xsltLoadStylesheetPI(xmlDocPtr doc) {
  6387. xmlNodePtr child;
  6388. xsltStylesheetPtr ret = NULL;
  6389. xmlChar *href = NULL;
  6390. xmlURIPtr URI;
  6391. xsltInitGlobals();
  6392. if (doc == NULL)
  6393. return(NULL);
  6394. /*
  6395. * Find the text/xml stylesheet PI id any before the root
  6396. */
  6397. child = doc->children;
  6398. while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) {
  6399. if ((child->type == XML_PI_NODE) &&
  6400. (xmlStrEqual(child->name, BAD_CAST "xml-stylesheet"))) {
  6401. href = xsltParseStylesheetPI(child->content);
  6402. if (href != NULL)
  6403. break;
  6404. }
  6405. child = child->next;
  6406. }
  6407. /*
  6408. * If found check the href to select processing
  6409. */
  6410. if (href != NULL) {
  6411. #ifdef WITH_XSLT_DEBUG_PARSING
  6412. xsltGenericDebug(xsltGenericDebugContext,
  6413. "xsltLoadStylesheetPI : found PI href=%s\n", href);
  6414. #endif
  6415. URI = xmlParseURI((const char *) href);
  6416. if (URI == NULL) {
  6417. xsltTransformError(NULL, NULL, child,
  6418. "xml-stylesheet : href %s is not valid\n", href);
  6419. xmlFree(href);
  6420. return(NULL);
  6421. }
  6422. if ((URI->fragment != NULL) && (URI->scheme == NULL) &&
  6423. (URI->opaque == NULL) && (URI->authority == NULL) &&
  6424. (URI->server == NULL) && (URI->user == NULL) &&
  6425. (URI->path == NULL) && (URI->query == NULL)) {
  6426. xmlAttrPtr ID;
  6427. #ifdef WITH_XSLT_DEBUG_PARSING
  6428. xsltGenericDebug(xsltGenericDebugContext,
  6429. "xsltLoadStylesheetPI : Reference to ID %s\n", href);
  6430. #endif
  6431. if (URI->fragment[0] == '#')
  6432. ID = xmlGetID(doc, (const xmlChar *) &(URI->fragment[1]));
  6433. else
  6434. ID = xmlGetID(doc, (const xmlChar *) URI->fragment);
  6435. if (ID == NULL) {
  6436. xsltTransformError(NULL, NULL, child,
  6437. "xml-stylesheet : no ID %s found\n", URI->fragment);
  6438. } else {
  6439. xmlDocPtr fake;
  6440. xmlNodePtr subtree, newtree;
  6441. xmlNsPtr ns;
  6442. #ifdef WITH_XSLT_DEBUG
  6443. xsltGenericDebug(xsltGenericDebugContext,
  6444. "creating new document from %s for embedded stylesheet\n",
  6445. doc->URL);
  6446. #endif
  6447. /*
  6448. * move the subtree in a new document passed to
  6449. * the stylesheet analyzer
  6450. */
  6451. subtree = ID->parent;
  6452. fake = xmlNewDoc(NULL);
  6453. if (fake != NULL) {
  6454. /*
  6455. * Should the dictionary still be shared even though
  6456. * the nodes are being copied rather than moved?
  6457. */
  6458. fake->dict = doc->dict;
  6459. xmlDictReference(doc->dict);
  6460. #ifdef WITH_XSLT_DEBUG
  6461. xsltGenericDebug(xsltGenericDebugContext,
  6462. "reusing dictionary from %s for embedded stylesheet\n",
  6463. doc->URL);
  6464. #endif
  6465. newtree = xmlDocCopyNode(subtree, fake, 1);
  6466. fake->URL = xmlNodeGetBase(doc, subtree->parent);
  6467. #ifdef WITH_XSLT_DEBUG
  6468. xsltGenericDebug(xsltGenericDebugContext,
  6469. "set base URI for embedded stylesheet as %s\n",
  6470. fake->URL);
  6471. #endif
  6472. /*
  6473. * Add all namespaces in scope of embedded stylesheet to
  6474. * root element of newly created stylesheet document
  6475. */
  6476. while ((subtree = subtree->parent) != (xmlNodePtr)doc) {
  6477. for (ns = subtree->ns; ns; ns = ns->next) {
  6478. xmlNewNs(newtree, ns->href, ns->prefix);
  6479. }
  6480. }
  6481. xmlAddChild((xmlNodePtr)fake, newtree);
  6482. ret = xsltParseStylesheetDoc(fake);
  6483. if (ret == NULL)
  6484. xmlFreeDoc(fake);
  6485. }
  6486. }
  6487. } else {
  6488. xmlChar *URL, *base;
  6489. /*
  6490. * Reference to an external stylesheet
  6491. */
  6492. base = xmlNodeGetBase(doc, (xmlNodePtr) doc);
  6493. URL = xmlBuildURI(href, base);
  6494. if (URL != NULL) {
  6495. #ifdef WITH_XSLT_DEBUG_PARSING
  6496. xsltGenericDebug(xsltGenericDebugContext,
  6497. "xsltLoadStylesheetPI : fetching %s\n", URL);
  6498. #endif
  6499. ret = xsltParseStylesheetFile(URL);
  6500. xmlFree(URL);
  6501. } else {
  6502. #ifdef WITH_XSLT_DEBUG_PARSING
  6503. xsltGenericDebug(xsltGenericDebugContext,
  6504. "xsltLoadStylesheetPI : fetching %s\n", href);
  6505. #endif
  6506. ret = xsltParseStylesheetFile(href);
  6507. }
  6508. if (base != NULL)
  6509. xmlFree(base);
  6510. }
  6511. xmlFreeURI(URI);
  6512. xmlFree(href);
  6513. }
  6514. return(ret);
  6515. }