preproc.c 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376
  1. /*
  2. * preproc.c: Preprocessing of style operations
  3. *
  4. * References:
  5. * http://www.w3.org/TR/1999/REC-xslt-19991116
  6. *
  7. * Michael Kay "XSLT Programmer's Reference" pp 637-643
  8. * Writing Multiple Output Files
  9. *
  10. * XSLT-1.1 Working Draft
  11. * http://www.w3.org/TR/xslt11#multiple-output
  12. *
  13. * See Copyright for the status of this software.
  14. *
  15. * daniel@veillard.com
  16. */
  17. #define IN_LIBXSLT
  18. #include "libxslt.h"
  19. #include <string.h>
  20. #include <libxml/xmlmemory.h>
  21. #include <libxml/parser.h>
  22. #include <libxml/tree.h>
  23. #include <libxml/valid.h>
  24. #include <libxml/hash.h>
  25. #include <libxml/uri.h>
  26. #include <libxml/encoding.h>
  27. #include <libxml/xmlerror.h>
  28. #include "xslt.h"
  29. #include "xsltutils.h"
  30. #include "xsltInternals.h"
  31. #include "transform.h"
  32. #include "templates.h"
  33. #include "variables.h"
  34. #include "numbersInternals.h"
  35. #include "preproc.h"
  36. #include "extra.h"
  37. #include "imports.h"
  38. #include "extensions.h"
  39. #include "pattern.h"
  40. #ifdef WITH_XSLT_DEBUG
  41. #define WITH_XSLT_DEBUG_PREPROC
  42. #endif
  43. const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element";
  44. /************************************************************************
  45. * *
  46. * Grammar checks *
  47. * *
  48. ************************************************************************/
  49. #ifdef XSLT_REFACTORED
  50. /*
  51. * Grammar checks are now performed in xslt.c.
  52. */
  53. #else
  54. /**
  55. * xsltCheckTopLevelElement:
  56. * @style: the XSLT stylesheet
  57. * @inst: the XSLT instruction
  58. * @err: raise an error or not
  59. *
  60. * Check that the instruction is instanciated as a top level element.
  61. *
  62. * Returns -1 in case of error, 0 if failed and 1 in case of success
  63. */
  64. static int
  65. xsltCheckTopLevelElement(xsltStylesheetPtr style, xmlNodePtr inst, int err) {
  66. xmlNodePtr parent;
  67. if ((style == NULL) || (inst == NULL) || (inst->ns == NULL))
  68. return(-1);
  69. parent = inst->parent;
  70. if (parent == NULL) {
  71. if (err) {
  72. xsltTransformError(NULL, style, inst,
  73. "internal problem: element has no parent\n");
  74. style->errors++;
  75. }
  76. return(0);
  77. }
  78. if ((parent->ns == NULL) || (parent->type != XML_ELEMENT_NODE) ||
  79. ((parent->ns != inst->ns) &&
  80. (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
  81. ((!xmlStrEqual(parent->name, BAD_CAST "stylesheet")) &&
  82. (!xmlStrEqual(parent->name, BAD_CAST "transform")))) {
  83. if (err) {
  84. xsltTransformError(NULL, style, inst,
  85. "element %s only allowed as child of stylesheet\n",
  86. inst->name);
  87. style->errors++;
  88. }
  89. return(0);
  90. }
  91. return(1);
  92. }
  93. /**
  94. * xsltCheckInstructionElement:
  95. * @style: the XSLT stylesheet
  96. * @inst: the XSLT instruction
  97. *
  98. * Check that the instruction is instanciated as an instruction element.
  99. */
  100. static void
  101. xsltCheckInstructionElement(xsltStylesheetPtr style, xmlNodePtr inst) {
  102. xmlNodePtr parent;
  103. int has_ext;
  104. if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||
  105. (style->literal_result))
  106. return;
  107. has_ext = (style->extInfos != NULL);
  108. parent = inst->parent;
  109. if (parent == NULL) {
  110. xsltTransformError(NULL, style, inst,
  111. "internal problem: element has no parent\n");
  112. style->errors++;
  113. return;
  114. }
  115. while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {
  116. if (((parent->ns == inst->ns) ||
  117. ((parent->ns != NULL) &&
  118. (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&
  119. ((xmlStrEqual(parent->name, BAD_CAST "template")) ||
  120. (xmlStrEqual(parent->name, BAD_CAST "param")) ||
  121. (xmlStrEqual(parent->name, BAD_CAST "attribute")) ||
  122. (xmlStrEqual(parent->name, BAD_CAST "variable")))) {
  123. return;
  124. }
  125. /*
  126. * if we are within an extension element all bets are off
  127. * about the semantic there e.g. xsl:param within func:function
  128. */
  129. if ((has_ext) && (parent->ns != NULL) &&
  130. (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))
  131. return;
  132. parent = parent->parent;
  133. }
  134. xsltTransformError(NULL, style, inst,
  135. "element %s only allowed within a template, variable or param\n",
  136. inst->name);
  137. style->errors++;
  138. }
  139. /**
  140. * xsltCheckParentElement:
  141. * @style: the XSLT stylesheet
  142. * @inst: the XSLT instruction
  143. * @allow1: allowed parent1
  144. * @allow2: allowed parent2
  145. *
  146. * Check that the instruction is instanciated as the childre of one of the
  147. * possible parents.
  148. */
  149. static void
  150. xsltCheckParentElement(xsltStylesheetPtr style, xmlNodePtr inst,
  151. const xmlChar *allow1, const xmlChar *allow2) {
  152. xmlNodePtr parent;
  153. if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||
  154. (style->literal_result))
  155. return;
  156. parent = inst->parent;
  157. if (parent == NULL) {
  158. xsltTransformError(NULL, style, inst,
  159. "internal problem: element has no parent\n");
  160. style->errors++;
  161. return;
  162. }
  163. if (((parent->ns == inst->ns) ||
  164. ((parent->ns != NULL) &&
  165. (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&
  166. ((xmlStrEqual(parent->name, allow1)) ||
  167. (xmlStrEqual(parent->name, allow2)))) {
  168. return;
  169. }
  170. if (style->extInfos != NULL) {
  171. while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {
  172. /*
  173. * if we are within an extension element all bets are off
  174. * about the semantic there e.g. xsl:param within func:function
  175. */
  176. if ((parent->ns != NULL) &&
  177. (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))
  178. return;
  179. parent = parent->parent;
  180. }
  181. }
  182. xsltTransformError(NULL, style, inst,
  183. "element %s is not allowed within that context\n",
  184. inst->name);
  185. style->errors++;
  186. }
  187. #endif
  188. /************************************************************************
  189. * *
  190. * handling of precomputed data *
  191. * *
  192. ************************************************************************/
  193. /**
  194. * xsltNewStylePreComp:
  195. * @style: the XSLT stylesheet
  196. * @type: the construct type
  197. *
  198. * Create a new XSLT Style precomputed block
  199. *
  200. * Returns the newly allocated specialized structure
  201. * or NULL in case of error
  202. */
  203. static xsltStylePreCompPtr
  204. xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) {
  205. xsltStylePreCompPtr cur;
  206. #ifdef XSLT_REFACTORED
  207. size_t size;
  208. #endif
  209. if (style == NULL)
  210. return(NULL);
  211. #ifdef XSLT_REFACTORED
  212. /*
  213. * URGENT TODO: Use specialized factory functions in order
  214. * to avoid this ugliness.
  215. */
  216. switch (type) {
  217. case XSLT_FUNC_COPY:
  218. size = sizeof(xsltStyleItemCopy); break;
  219. case XSLT_FUNC_SORT:
  220. size = sizeof(xsltStyleItemSort); break;
  221. case XSLT_FUNC_TEXT:
  222. size = sizeof(xsltStyleItemText); break;
  223. case XSLT_FUNC_ELEMENT:
  224. size = sizeof(xsltStyleItemElement); break;
  225. case XSLT_FUNC_ATTRIBUTE:
  226. size = sizeof(xsltStyleItemAttribute); break;
  227. case XSLT_FUNC_COMMENT:
  228. size = sizeof(xsltStyleItemComment); break;
  229. case XSLT_FUNC_PI:
  230. size = sizeof(xsltStyleItemPI); break;
  231. case XSLT_FUNC_COPYOF:
  232. size = sizeof(xsltStyleItemCopyOf); break;
  233. case XSLT_FUNC_VALUEOF:
  234. size = sizeof(xsltStyleItemValueOf); break;;
  235. case XSLT_FUNC_NUMBER:
  236. size = sizeof(xsltStyleItemNumber); break;
  237. case XSLT_FUNC_APPLYIMPORTS:
  238. size = sizeof(xsltStyleItemApplyImports); break;
  239. case XSLT_FUNC_CALLTEMPLATE:
  240. size = sizeof(xsltStyleItemCallTemplate); break;
  241. case XSLT_FUNC_APPLYTEMPLATES:
  242. size = sizeof(xsltStyleItemApplyTemplates); break;
  243. case XSLT_FUNC_CHOOSE:
  244. size = sizeof(xsltStyleItemChoose); break;
  245. case XSLT_FUNC_IF:
  246. size = sizeof(xsltStyleItemIf); break;
  247. case XSLT_FUNC_FOREACH:
  248. size = sizeof(xsltStyleItemForEach); break;
  249. case XSLT_FUNC_DOCUMENT:
  250. size = sizeof(xsltStyleItemDocument); break;
  251. case XSLT_FUNC_WITHPARAM:
  252. size = sizeof(xsltStyleItemWithParam); break;
  253. case XSLT_FUNC_PARAM:
  254. size = sizeof(xsltStyleItemParam); break;
  255. case XSLT_FUNC_VARIABLE:
  256. size = sizeof(xsltStyleItemVariable); break;
  257. case XSLT_FUNC_WHEN:
  258. size = sizeof(xsltStyleItemWhen); break;
  259. case XSLT_FUNC_OTHERWISE:
  260. size = sizeof(xsltStyleItemOtherwise); break;
  261. default:
  262. xsltTransformError(NULL, style, NULL,
  263. "xsltNewStylePreComp : invalid type %d\n", type);
  264. style->errors++;
  265. return(NULL);
  266. }
  267. /*
  268. * Create the structure.
  269. */
  270. cur = (xsltStylePreCompPtr) xmlMalloc(size);
  271. if (cur == NULL) {
  272. xsltTransformError(NULL, style, NULL,
  273. "xsltNewStylePreComp : malloc failed\n");
  274. style->errors++;
  275. return(NULL);
  276. }
  277. memset(cur, 0, size);
  278. #else /* XSLT_REFACTORED */
  279. /*
  280. * Old behaviour.
  281. */
  282. cur = (xsltStylePreCompPtr) xmlMalloc(sizeof(xsltStylePreComp));
  283. if (cur == NULL) {
  284. xsltTransformError(NULL, style, NULL,
  285. "xsltNewStylePreComp : malloc failed\n");
  286. style->errors++;
  287. return(NULL);
  288. }
  289. memset(cur, 0, sizeof(xsltStylePreComp));
  290. #endif /* XSLT_REFACTORED */
  291. /*
  292. * URGENT TODO: Better to move this to spezialized factory functions.
  293. */
  294. cur->type = type;
  295. switch (cur->type) {
  296. case XSLT_FUNC_COPY:
  297. cur->func = xsltCopy;break;
  298. case XSLT_FUNC_SORT:
  299. cur->func = xsltSort;break;
  300. case XSLT_FUNC_TEXT:
  301. cur->func = xsltText;break;
  302. case XSLT_FUNC_ELEMENT:
  303. cur->func = xsltElement;break;
  304. case XSLT_FUNC_ATTRIBUTE:
  305. cur->func = xsltAttribute;break;
  306. case XSLT_FUNC_COMMENT:
  307. cur->func = xsltComment;break;
  308. case XSLT_FUNC_PI:
  309. cur->func = xsltProcessingInstruction;
  310. break;
  311. case XSLT_FUNC_COPYOF:
  312. cur->func = xsltCopyOf;break;
  313. case XSLT_FUNC_VALUEOF:
  314. cur->func = xsltValueOf;break;
  315. case XSLT_FUNC_NUMBER:
  316. cur->func = xsltNumber;break;
  317. case XSLT_FUNC_APPLYIMPORTS:
  318. cur->func = xsltApplyImports;break;
  319. case XSLT_FUNC_CALLTEMPLATE:
  320. cur->func = xsltCallTemplate;break;
  321. case XSLT_FUNC_APPLYTEMPLATES:
  322. cur->func = xsltApplyTemplates;break;
  323. case XSLT_FUNC_CHOOSE:
  324. cur->func = xsltChoose;break;
  325. case XSLT_FUNC_IF:
  326. cur->func = xsltIf;break;
  327. case XSLT_FUNC_FOREACH:
  328. cur->func = xsltForEach;break;
  329. case XSLT_FUNC_DOCUMENT:
  330. cur->func = xsltDocumentElem;break;
  331. case XSLT_FUNC_WITHPARAM:
  332. case XSLT_FUNC_PARAM:
  333. case XSLT_FUNC_VARIABLE:
  334. case XSLT_FUNC_WHEN:
  335. break;
  336. default:
  337. if (cur->func == NULL) {
  338. xsltTransformError(NULL, style, NULL,
  339. "xsltNewStylePreComp : no function for type %d\n", type);
  340. style->errors++;
  341. }
  342. }
  343. cur->next = style->preComps;
  344. style->preComps = (xsltElemPreCompPtr) cur;
  345. return(cur);
  346. }
  347. /**
  348. * xsltFreeStylePreComp:
  349. * @comp: an XSLT Style precomputed block
  350. *
  351. * Free up the memory allocated by @comp
  352. */
  353. static void
  354. xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
  355. if (comp == NULL)
  356. return;
  357. #ifdef XSLT_REFACTORED
  358. /*
  359. * URGENT TODO: Implement destructors.
  360. */
  361. switch (comp->type) {
  362. case XSLT_FUNC_LITERAL_RESULT_ELEMENT:
  363. break;
  364. case XSLT_FUNC_COPY:
  365. break;
  366. case XSLT_FUNC_SORT: {
  367. xsltStyleItemSortPtr item = (xsltStyleItemSortPtr) comp;
  368. if (item->locale != (xsltLocale)0)
  369. xsltFreeLocale(item->locale);
  370. if (item->comp != NULL)
  371. xmlXPathFreeCompExpr(item->comp);
  372. }
  373. break;
  374. case XSLT_FUNC_TEXT:
  375. break;
  376. case XSLT_FUNC_ELEMENT:
  377. break;
  378. case XSLT_FUNC_ATTRIBUTE:
  379. break;
  380. case XSLT_FUNC_COMMENT:
  381. break;
  382. case XSLT_FUNC_PI:
  383. break;
  384. case XSLT_FUNC_COPYOF: {
  385. xsltStyleItemCopyOfPtr item = (xsltStyleItemCopyOfPtr) comp;
  386. if (item->comp != NULL)
  387. xmlXPathFreeCompExpr(item->comp);
  388. }
  389. break;
  390. case XSLT_FUNC_VALUEOF: {
  391. xsltStyleItemValueOfPtr item = (xsltStyleItemValueOfPtr) comp;
  392. if (item->comp != NULL)
  393. xmlXPathFreeCompExpr(item->comp);
  394. }
  395. break;
  396. case XSLT_FUNC_NUMBER: {
  397. xsltStyleItemNumberPtr item = (xsltStyleItemNumberPtr) comp;
  398. if (item->numdata.countPat != NULL)
  399. xsltFreeCompMatchList(item->numdata.countPat);
  400. if (item->numdata.fromPat != NULL)
  401. xsltFreeCompMatchList(item->numdata.fromPat);
  402. }
  403. break;
  404. case XSLT_FUNC_APPLYIMPORTS:
  405. break;
  406. case XSLT_FUNC_CALLTEMPLATE:
  407. break;
  408. case XSLT_FUNC_APPLYTEMPLATES: {
  409. xsltStyleItemApplyTemplatesPtr item =
  410. (xsltStyleItemApplyTemplatesPtr) comp;
  411. if (item->comp != NULL)
  412. xmlXPathFreeCompExpr(item->comp);
  413. }
  414. break;
  415. case XSLT_FUNC_CHOOSE:
  416. break;
  417. case XSLT_FUNC_IF: {
  418. xsltStyleItemIfPtr item = (xsltStyleItemIfPtr) comp;
  419. if (item->comp != NULL)
  420. xmlXPathFreeCompExpr(item->comp);
  421. }
  422. break;
  423. case XSLT_FUNC_FOREACH: {
  424. xsltStyleItemForEachPtr item =
  425. (xsltStyleItemForEachPtr) comp;
  426. if (item->comp != NULL)
  427. xmlXPathFreeCompExpr(item->comp);
  428. }
  429. break;
  430. case XSLT_FUNC_DOCUMENT:
  431. break;
  432. case XSLT_FUNC_WITHPARAM: {
  433. xsltStyleItemWithParamPtr item =
  434. (xsltStyleItemWithParamPtr) comp;
  435. if (item->comp != NULL)
  436. xmlXPathFreeCompExpr(item->comp);
  437. }
  438. break;
  439. case XSLT_FUNC_PARAM: {
  440. xsltStyleItemParamPtr item =
  441. (xsltStyleItemParamPtr) comp;
  442. if (item->comp != NULL)
  443. xmlXPathFreeCompExpr(item->comp);
  444. }
  445. break;
  446. case XSLT_FUNC_VARIABLE: {
  447. xsltStyleItemVariablePtr item =
  448. (xsltStyleItemVariablePtr) comp;
  449. if (item->comp != NULL)
  450. xmlXPathFreeCompExpr(item->comp);
  451. }
  452. break;
  453. case XSLT_FUNC_WHEN: {
  454. xsltStyleItemWhenPtr item =
  455. (xsltStyleItemWhenPtr) comp;
  456. if (item->comp != NULL)
  457. xmlXPathFreeCompExpr(item->comp);
  458. }
  459. break;
  460. case XSLT_FUNC_OTHERWISE:
  461. case XSLT_FUNC_FALLBACK:
  462. case XSLT_FUNC_MESSAGE:
  463. case XSLT_FUNC_INCLUDE:
  464. case XSLT_FUNC_ATTRSET:
  465. break;
  466. default:
  467. /* TODO: Raise error. */
  468. break;
  469. }
  470. #else
  471. if (comp->locale != (xsltLocale)0)
  472. xsltFreeLocale(comp->locale);
  473. if (comp->comp != NULL)
  474. xmlXPathFreeCompExpr(comp->comp);
  475. if (comp->numdata.countPat != NULL)
  476. xsltFreeCompMatchList(comp->numdata.countPat);
  477. if (comp->numdata.fromPat != NULL)
  478. xsltFreeCompMatchList(comp->numdata.fromPat);
  479. if (comp->nsList != NULL)
  480. xmlFree(comp->nsList);
  481. #endif
  482. xmlFree(comp);
  483. }
  484. /************************************************************************
  485. * *
  486. * XSLT-1.1 extensions *
  487. * *
  488. ************************************************************************/
  489. /**
  490. * xsltDocumentComp:
  491. * @style: the XSLT stylesheet
  492. * @inst: the instruction in the stylesheet
  493. * @function: unused
  494. *
  495. * Pre process an XSLT-1.1 document element
  496. *
  497. * Returns a precompiled data structure for the element
  498. */
  499. xsltElemPreCompPtr
  500. xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
  501. xsltTransformFunction function ATTRIBUTE_UNUSED) {
  502. #ifdef XSLT_REFACTORED
  503. xsltStyleItemDocumentPtr comp;
  504. #else
  505. xsltStylePreCompPtr comp;
  506. #endif
  507. const xmlChar *filename = NULL;
  508. /*
  509. * As of 2006-03-30, this function is currently defined in Libxslt
  510. * to be used for:
  511. * (in libxslt/extra.c)
  512. * "output" in XSLT_SAXON_NAMESPACE
  513. * "write" XSLT_XALAN_NAMESPACE
  514. * "document" XSLT_XT_NAMESPACE
  515. * "document" XSLT_NAMESPACE (from the abandoned old working
  516. * draft of XSLT 1.1)
  517. * (in libexslt/common.c)
  518. * "document" in EXSLT_COMMON_NAMESPACE
  519. */
  520. #ifdef XSLT_REFACTORED
  521. comp = (xsltStyleItemDocumentPtr)
  522. xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
  523. #else
  524. comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
  525. #endif
  526. if (comp == NULL)
  527. return (NULL);
  528. comp->inst = inst;
  529. comp->ver11 = 0;
  530. if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {
  531. #ifdef WITH_XSLT_DEBUG_EXTRA
  532. xsltGenericDebug(xsltGenericDebugContext,
  533. "Found saxon:output extension\n");
  534. #endif
  535. /*
  536. * The element "output" is in the namespace XSLT_SAXON_NAMESPACE
  537. * (http://icl.com/saxon)
  538. * The @file is in no namespace; it is an AVT.
  539. * (http://www.computerwizards.com/saxon/doc/extensions.html#saxon:output)
  540. *
  541. * TODO: Do we need not to check the namespace here?
  542. */
  543. filename = xsltEvalStaticAttrValueTemplate(style, inst,
  544. (const xmlChar *)"file",
  545. NULL, &comp->has_filename);
  546. } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {
  547. #ifdef WITH_XSLT_DEBUG_EXTRA
  548. xsltGenericDebug(xsltGenericDebugContext,
  549. "Found xalan:write extension\n");
  550. #endif
  551. /* the filename need to be interpreted */
  552. /*
  553. * TODO: Is "filename need to be interpreted" meant to be a todo?
  554. * Where will be the filename of xalan:write be processed?
  555. *
  556. * TODO: Do we need not to check the namespace here?
  557. * The extension ns is "http://xml.apache.org/xalan/redirect".
  558. * See http://xml.apache.org/xalan-j/extensionslib.html.
  559. */
  560. } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {
  561. if (inst->ns != NULL) {
  562. if (xmlStrEqual(inst->ns->href, XSLT_NAMESPACE)) {
  563. /*
  564. * Mark the instruction as being of
  565. * XSLT version 1.1 (abandoned).
  566. */
  567. comp->ver11 = 1;
  568. #ifdef WITH_XSLT_DEBUG_EXTRA
  569. xsltGenericDebug(xsltGenericDebugContext,
  570. "Found xslt11:document construct\n");
  571. #endif
  572. } else {
  573. if (xmlStrEqual(inst->ns->href,
  574. (const xmlChar *)"http://exslt.org/common")) {
  575. /* EXSLT. */
  576. #ifdef WITH_XSLT_DEBUG_EXTRA
  577. xsltGenericDebug(xsltGenericDebugContext,
  578. "Found exslt:document extension\n");
  579. #endif
  580. } else if (xmlStrEqual(inst->ns->href, XSLT_XT_NAMESPACE)) {
  581. /* James Clark's XT. */
  582. #ifdef WITH_XSLT_DEBUG_EXTRA
  583. xsltGenericDebug(xsltGenericDebugContext,
  584. "Found xt:document extension\n");
  585. #endif
  586. }
  587. }
  588. }
  589. /*
  590. * The element "document" is used in conjunction with the
  591. * following namespaces:
  592. *
  593. * 1) XSLT_NAMESPACE (http://www.w3.org/1999/XSL/Transform version 1.1)
  594. * <!ELEMENT xsl:document %template;>
  595. * <!ATTLIST xsl:document
  596. * href %avt; #REQUIRED
  597. * @href is an AVT
  598. * IMPORTANT: xsl:document was in the abandoned XSLT 1.1 draft,
  599. * it was removed and isn't available in XSLT 1.1 anymore.
  600. * In XSLT 2.0 it was renamed to xsl:result-document.
  601. *
  602. * All other attributes are identical to the attributes
  603. * on xsl:output
  604. *
  605. * 2) EXSLT_COMMON_NAMESPACE (http://exslt.org/common)
  606. * <exsl:document
  607. * href = { uri-reference }
  608. * TODO: is @href is an AVT?
  609. *
  610. * 3) XSLT_XT_NAMESPACE (http://www.jclark.com/xt)
  611. * Example: <xt:document method="xml" href="myFile.xml">
  612. * TODO: is @href is an AVT?
  613. *
  614. * In all cases @href is in no namespace.
  615. */
  616. filename = xsltEvalStaticAttrValueTemplate(style, inst,
  617. (const xmlChar *)"href", NULL, &comp->has_filename);
  618. }
  619. if (!comp->has_filename) {
  620. goto error;
  621. }
  622. comp->filename = filename;
  623. error:
  624. return ((xsltElemPreCompPtr) comp);
  625. }
  626. /************************************************************************
  627. * *
  628. * Most of the XSLT-1.0 transformations *
  629. * *
  630. ************************************************************************/
  631. /**
  632. * xsltSortComp:
  633. * @style: the XSLT stylesheet
  634. * @inst: the xslt sort node
  635. *
  636. * Process the xslt sort node on the source node
  637. */
  638. static void
  639. xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  640. #ifdef XSLT_REFACTORED
  641. xsltStyleItemSortPtr comp;
  642. #else
  643. xsltStylePreCompPtr comp;
  644. #endif
  645. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  646. return;
  647. #ifdef XSLT_REFACTORED
  648. comp = (xsltStyleItemSortPtr) xsltNewStylePreComp(style, XSLT_FUNC_SORT);
  649. #else
  650. comp = xsltNewStylePreComp(style, XSLT_FUNC_SORT);
  651. #endif
  652. if (comp == NULL)
  653. return;
  654. inst->psvi = comp;
  655. comp->inst = inst;
  656. comp->stype = xsltEvalStaticAttrValueTemplate(style, inst,
  657. (const xmlChar *)"data-type",
  658. NULL, &comp->has_stype);
  659. if (comp->stype != NULL) {
  660. if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
  661. comp->number = 0;
  662. else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
  663. comp->number = 1;
  664. else {
  665. xsltTransformError(NULL, style, inst,
  666. "xsltSortComp: no support for data-type = %s\n", comp->stype);
  667. comp->number = 0; /* use default */
  668. if (style != NULL) style->warnings++;
  669. }
  670. }
  671. comp->order = xsltEvalStaticAttrValueTemplate(style, inst,
  672. (const xmlChar *)"order",
  673. NULL, &comp->has_order);
  674. if (comp->order != NULL) {
  675. if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
  676. comp->descending = 0;
  677. else if (xmlStrEqual(comp->order, (const xmlChar *) "descending"))
  678. comp->descending = 1;
  679. else {
  680. xsltTransformError(NULL, style, inst,
  681. "xsltSortComp: invalid value %s for order\n", comp->order);
  682. comp->descending = 0; /* use default */
  683. if (style != NULL) style->warnings++;
  684. }
  685. }
  686. comp->case_order = xsltEvalStaticAttrValueTemplate(style, inst,
  687. (const xmlChar *)"case-order",
  688. NULL, &comp->has_use);
  689. if (comp->case_order != NULL) {
  690. if (xmlStrEqual(comp->case_order, (const xmlChar *) "upper-first"))
  691. comp->lower_first = 0;
  692. else if (xmlStrEqual(comp->case_order, (const xmlChar *) "lower-first"))
  693. comp->lower_first = 1;
  694. else {
  695. xsltTransformError(NULL, style, inst,
  696. "xsltSortComp: invalid value %s for order\n", comp->order);
  697. comp->lower_first = 0; /* use default */
  698. if (style != NULL) style->warnings++;
  699. }
  700. }
  701. comp->lang = xsltEvalStaticAttrValueTemplate(style, inst,
  702. (const xmlChar *)"lang",
  703. NULL, &comp->has_lang);
  704. if (comp->lang != NULL) {
  705. comp->locale = xsltNewLocale(comp->lang);
  706. }
  707. else {
  708. comp->locale = (xsltLocale)0;
  709. }
  710. comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE);
  711. if (comp->select == NULL) {
  712. /*
  713. * The default value of the select attribute is ., which will
  714. * cause the string-value of the current node to be used as
  715. * the sort key.
  716. */
  717. comp->select = xmlDictLookup(style->dict, BAD_CAST ".", 1);
  718. }
  719. comp->comp = xsltXPathCompile(style, comp->select);
  720. if (comp->comp == NULL) {
  721. xsltTransformError(NULL, style, inst,
  722. "xsltSortComp: could not compile select expression '%s'\n",
  723. comp->select);
  724. if (style != NULL) style->errors++;
  725. }
  726. if (inst->children != NULL) {
  727. xsltTransformError(NULL, style, inst,
  728. "xsl:sort : is not empty\n");
  729. if (style != NULL) style->errors++;
  730. }
  731. }
  732. /**
  733. * xsltCopyComp:
  734. * @style: the XSLT stylesheet
  735. * @inst: the xslt copy node
  736. *
  737. * Process the xslt copy node on the source node
  738. */
  739. static void
  740. xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  741. #ifdef XSLT_REFACTORED
  742. xsltStyleItemCopyPtr comp;
  743. #else
  744. xsltStylePreCompPtr comp;
  745. #endif
  746. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  747. return;
  748. #ifdef XSLT_REFACTORED
  749. comp = (xsltStyleItemCopyPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPY);
  750. #else
  751. comp = xsltNewStylePreComp(style, XSLT_FUNC_COPY);
  752. #endif
  753. if (comp == NULL)
  754. return;
  755. inst->psvi = comp;
  756. comp->inst = inst;
  757. comp->use = xsltGetCNsProp(style, inst, (const xmlChar *)"use-attribute-sets",
  758. XSLT_NAMESPACE);
  759. if (comp->use == NULL)
  760. comp->has_use = 0;
  761. else
  762. comp->has_use = 1;
  763. }
  764. #ifdef XSLT_REFACTORED
  765. /* Enable if ever needed for xsl:text. */
  766. #else
  767. /**
  768. * xsltTextComp:
  769. * @style: an XSLT compiled stylesheet
  770. * @inst: the xslt text node
  771. *
  772. * TODO: This function is obsolete, since xsl:text won't
  773. * be compiled, but removed from the tree.
  774. *
  775. * Process the xslt text node on the source node
  776. */
  777. static void
  778. xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  779. #ifdef XSLT_REFACTORED
  780. xsltStyleItemTextPtr comp;
  781. #else
  782. xsltStylePreCompPtr comp;
  783. #endif
  784. const xmlChar *prop;
  785. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  786. return;
  787. #ifdef XSLT_REFACTORED
  788. comp = (xsltStyleItemTextPtr) xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
  789. #else
  790. comp = xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
  791. #endif
  792. if (comp == NULL)
  793. return;
  794. inst->psvi = comp;
  795. comp->inst = inst;
  796. comp->noescape = 0;
  797. prop = xsltGetCNsProp(style, inst,
  798. (const xmlChar *)"disable-output-escaping",
  799. XSLT_NAMESPACE);
  800. if (prop != NULL) {
  801. if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
  802. comp->noescape = 1;
  803. } else if (!xmlStrEqual(prop,
  804. (const xmlChar *)"no")){
  805. xsltTransformError(NULL, style, inst,
  806. "xsl:text: disable-output-escaping allows only yes or no\n");
  807. if (style != NULL) style->warnings++;
  808. }
  809. }
  810. }
  811. #endif /* else of XSLT_REFACTORED */
  812. /**
  813. * xsltElementComp:
  814. * @style: an XSLT compiled stylesheet
  815. * @inst: the xslt element node
  816. *
  817. * Process the xslt element node on the source node
  818. */
  819. static void
  820. xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  821. #ifdef XSLT_REFACTORED
  822. xsltStyleItemElementPtr comp;
  823. #else
  824. xsltStylePreCompPtr comp;
  825. #endif
  826. /*
  827. * <xsl:element
  828. * name = { qname }
  829. * namespace = { uri-reference }
  830. * use-attribute-sets = qnames>
  831. * <!-- Content: template -->
  832. * </xsl:element>
  833. */
  834. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  835. return;
  836. #ifdef XSLT_REFACTORED
  837. comp = (xsltStyleItemElementPtr) xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
  838. #else
  839. comp = xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
  840. #endif
  841. if (comp == NULL)
  842. return;
  843. inst->psvi = comp;
  844. comp->inst = inst;
  845. /*
  846. * Attribute "name".
  847. */
  848. /*
  849. * TODO: Precompile the AVT. See bug #344894.
  850. */
  851. comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
  852. (const xmlChar *)"name", NULL, &comp->has_name);
  853. if (! comp->has_name) {
  854. xsltTransformError(NULL, style, inst,
  855. "xsl:element: The attribute 'name' is missing.\n");
  856. style->errors++;
  857. goto error;
  858. }
  859. /*
  860. * Attribute "namespace".
  861. */
  862. /*
  863. * TODO: Precompile the AVT. See bug #344894.
  864. */
  865. comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
  866. (const xmlChar *)"namespace", NULL, &comp->has_ns);
  867. if (comp->name != NULL) {
  868. if (xmlValidateQName(comp->name, 0)) {
  869. xsltTransformError(NULL, style, inst,
  870. "xsl:element: The value '%s' of the attribute 'name' is "
  871. "not a valid QName.\n", comp->name);
  872. style->errors++;
  873. } else {
  874. const xmlChar *prefix = NULL, *name;
  875. name = xsltSplitQName(style->dict, comp->name, &prefix);
  876. if (comp->has_ns == 0) {
  877. xmlNsPtr ns;
  878. /*
  879. * SPEC XSLT 1.0:
  880. * "If the namespace attribute is not present, then the QName is
  881. * expanded into an expanded-name using the namespace declarations
  882. * in effect for the xsl:element element, including any default
  883. * namespace declaration.
  884. */
  885. ns = xmlSearchNs(inst->doc, inst, prefix);
  886. if (ns != NULL) {
  887. comp->ns = xmlDictLookup(style->dict, ns->href, -1);
  888. comp->has_ns = 1;
  889. #ifdef XSLT_REFACTORED
  890. comp->nsPrefix = prefix;
  891. comp->name = name;
  892. #else
  893. (void)name; /* Suppress unused variable warning. */
  894. #endif
  895. } else if (prefix != NULL) {
  896. xsltTransformError(NULL, style, inst,
  897. "xsl:element: The prefixed QName '%s' "
  898. "has no namespace binding in scope in the "
  899. "stylesheet; this is an error, since the namespace was "
  900. "not specified by the instruction itself.\n", comp->name);
  901. style->errors++;
  902. }
  903. }
  904. if ((prefix != NULL) &&
  905. (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))
  906. {
  907. /*
  908. * Mark is to be skipped.
  909. */
  910. comp->has_name = 0;
  911. }
  912. }
  913. }
  914. /*
  915. * Attribute "use-attribute-sets",
  916. */
  917. comp->use = xsltEvalStaticAttrValueTemplate(style, inst,
  918. (const xmlChar *)"use-attribute-sets",
  919. NULL, &comp->has_use);
  920. error:
  921. return;
  922. }
  923. /**
  924. * xsltAttributeComp:
  925. * @style: an XSLT compiled stylesheet
  926. * @inst: the xslt attribute node
  927. *
  928. * Process the xslt attribute node on the source node
  929. */
  930. static void
  931. xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  932. #ifdef XSLT_REFACTORED
  933. xsltStyleItemAttributePtr comp;
  934. #else
  935. xsltStylePreCompPtr comp;
  936. #endif
  937. /*
  938. * <xsl:attribute
  939. * name = { qname }
  940. * namespace = { uri-reference }>
  941. * <!-- Content: template -->
  942. * </xsl:attribute>
  943. */
  944. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  945. return;
  946. #ifdef XSLT_REFACTORED
  947. comp = (xsltStyleItemAttributePtr) xsltNewStylePreComp(style,
  948. XSLT_FUNC_ATTRIBUTE);
  949. #else
  950. comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE);
  951. #endif
  952. if (comp == NULL)
  953. return;
  954. inst->psvi = comp;
  955. comp->inst = inst;
  956. /*
  957. * Attribute "name".
  958. */
  959. /*
  960. * TODO: Precompile the AVT. See bug #344894.
  961. */
  962. comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
  963. (const xmlChar *)"name",
  964. NULL, &comp->has_name);
  965. if (! comp->has_name) {
  966. xsltTransformError(NULL, style, inst,
  967. "XSLT-attribute: The attribute 'name' is missing.\n");
  968. style->errors++;
  969. return;
  970. }
  971. /*
  972. * Attribute "namespace".
  973. */
  974. /*
  975. * TODO: Precompile the AVT. See bug #344894.
  976. */
  977. comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
  978. (const xmlChar *)"namespace",
  979. NULL, &comp->has_ns);
  980. if (comp->name != NULL) {
  981. if (xmlValidateQName(comp->name, 0)) {
  982. xsltTransformError(NULL, style, inst,
  983. "xsl:attribute: The value '%s' of the attribute 'name' is "
  984. "not a valid QName.\n", comp->name);
  985. style->errors++;
  986. } else if (xmlStrEqual(comp->name, BAD_CAST "xmlns")) {
  987. xsltTransformError(NULL, style, inst,
  988. "xsl:attribute: The attribute name 'xmlns' is not allowed.\n");
  989. style->errors++;
  990. } else {
  991. const xmlChar *prefix = NULL, *name;
  992. name = xsltSplitQName(style->dict, comp->name, &prefix);
  993. if (prefix != NULL) {
  994. if (comp->has_ns == 0) {
  995. xmlNsPtr ns;
  996. /*
  997. * SPEC XSLT 1.0:
  998. * "If the namespace attribute is not present, then the
  999. * QName is expanded into an expanded-name using the
  1000. * namespace declarations in effect for the xsl:element
  1001. * element, including any default namespace declaration.
  1002. */
  1003. ns = xmlSearchNs(inst->doc, inst, prefix);
  1004. if (ns != NULL) {
  1005. comp->ns = xmlDictLookup(style->dict, ns->href, -1);
  1006. comp->has_ns = 1;
  1007. #ifdef XSLT_REFACTORED
  1008. comp->nsPrefix = prefix;
  1009. comp->name = name;
  1010. #else
  1011. (void)name; /* Suppress unused variable warning. */
  1012. #endif
  1013. } else {
  1014. xsltTransformError(NULL, style, inst,
  1015. "xsl:attribute: The prefixed QName '%s' "
  1016. "has no namespace binding in scope in the "
  1017. "stylesheet; this is an error, since the "
  1018. "namespace was not specified by the instruction "
  1019. "itself.\n", comp->name);
  1020. style->errors++;
  1021. }
  1022. }
  1023. }
  1024. }
  1025. }
  1026. }
  1027. /**
  1028. * xsltCommentComp:
  1029. * @style: an XSLT compiled stylesheet
  1030. * @inst: the xslt comment node
  1031. *
  1032. * Process the xslt comment node on the source node
  1033. */
  1034. static void
  1035. xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1036. #ifdef XSLT_REFACTORED
  1037. xsltStyleItemCommentPtr comp;
  1038. #else
  1039. xsltStylePreCompPtr comp;
  1040. #endif
  1041. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1042. return;
  1043. #ifdef XSLT_REFACTORED
  1044. comp = (xsltStyleItemCommentPtr) xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
  1045. #else
  1046. comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
  1047. #endif
  1048. if (comp == NULL)
  1049. return;
  1050. inst->psvi = comp;
  1051. comp->inst = inst;
  1052. }
  1053. /**
  1054. * xsltProcessingInstructionComp:
  1055. * @style: an XSLT compiled stylesheet
  1056. * @inst: the xslt processing-instruction node
  1057. *
  1058. * Process the xslt processing-instruction node on the source node
  1059. */
  1060. static void
  1061. xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1062. #ifdef XSLT_REFACTORED
  1063. xsltStyleItemPIPtr comp;
  1064. #else
  1065. xsltStylePreCompPtr comp;
  1066. #endif
  1067. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1068. return;
  1069. #ifdef XSLT_REFACTORED
  1070. comp = (xsltStyleItemPIPtr) xsltNewStylePreComp(style, XSLT_FUNC_PI);
  1071. #else
  1072. comp = xsltNewStylePreComp(style, XSLT_FUNC_PI);
  1073. #endif
  1074. if (comp == NULL)
  1075. return;
  1076. inst->psvi = comp;
  1077. comp->inst = inst;
  1078. comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
  1079. (const xmlChar *)"name",
  1080. XSLT_NAMESPACE, &comp->has_name);
  1081. }
  1082. /**
  1083. * xsltCopyOfComp:
  1084. * @style: an XSLT compiled stylesheet
  1085. * @inst: the xslt copy-of node
  1086. *
  1087. * Process the xslt copy-of node on the source node
  1088. */
  1089. static void
  1090. xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1091. #ifdef XSLT_REFACTORED
  1092. xsltStyleItemCopyOfPtr comp;
  1093. #else
  1094. xsltStylePreCompPtr comp;
  1095. #endif
  1096. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1097. return;
  1098. #ifdef XSLT_REFACTORED
  1099. comp = (xsltStyleItemCopyOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
  1100. #else
  1101. comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
  1102. #endif
  1103. if (comp == NULL)
  1104. return;
  1105. inst->psvi = comp;
  1106. comp->inst = inst;
  1107. comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
  1108. XSLT_NAMESPACE);
  1109. if (comp->select == NULL) {
  1110. xsltTransformError(NULL, style, inst,
  1111. "xsl:copy-of : select is missing\n");
  1112. if (style != NULL) style->errors++;
  1113. return;
  1114. }
  1115. comp->comp = xsltXPathCompile(style, comp->select);
  1116. if (comp->comp == NULL) {
  1117. xsltTransformError(NULL, style, inst,
  1118. "xsl:copy-of : could not compile select expression '%s'\n",
  1119. comp->select);
  1120. if (style != NULL) style->errors++;
  1121. }
  1122. }
  1123. /**
  1124. * xsltValueOfComp:
  1125. * @style: an XSLT compiled stylesheet
  1126. * @inst: the xslt value-of node
  1127. *
  1128. * Process the xslt value-of node on the source node
  1129. */
  1130. static void
  1131. xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1132. #ifdef XSLT_REFACTORED
  1133. xsltStyleItemValueOfPtr comp;
  1134. #else
  1135. xsltStylePreCompPtr comp;
  1136. #endif
  1137. const xmlChar *prop;
  1138. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1139. return;
  1140. #ifdef XSLT_REFACTORED
  1141. comp = (xsltStyleItemValueOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
  1142. #else
  1143. comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
  1144. #endif
  1145. if (comp == NULL)
  1146. return;
  1147. inst->psvi = comp;
  1148. comp->inst = inst;
  1149. prop = xsltGetCNsProp(style, inst,
  1150. (const xmlChar *)"disable-output-escaping",
  1151. XSLT_NAMESPACE);
  1152. if (prop != NULL) {
  1153. if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
  1154. comp->noescape = 1;
  1155. } else if (!xmlStrEqual(prop,
  1156. (const xmlChar *)"no")){
  1157. xsltTransformError(NULL, style, inst,
  1158. "xsl:value-of : disable-output-escaping allows only yes or no\n");
  1159. if (style != NULL) style->warnings++;
  1160. }
  1161. }
  1162. comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
  1163. XSLT_NAMESPACE);
  1164. if (comp->select == NULL) {
  1165. xsltTransformError(NULL, style, inst,
  1166. "xsl:value-of : select is missing\n");
  1167. if (style != NULL) style->errors++;
  1168. return;
  1169. }
  1170. comp->comp = xsltXPathCompile(style, comp->select);
  1171. if (comp->comp == NULL) {
  1172. xsltTransformError(NULL, style, inst,
  1173. "xsl:value-of : could not compile select expression '%s'\n",
  1174. comp->select);
  1175. if (style != NULL) style->errors++;
  1176. }
  1177. }
  1178. static void
  1179. xsltGetQNameProperty(xsltStylesheetPtr style, xmlNodePtr inst,
  1180. const xmlChar *propName,
  1181. int mandatory,
  1182. int *hasProp, const xmlChar **nsName,
  1183. const xmlChar** localName)
  1184. {
  1185. const xmlChar *prop;
  1186. if (nsName)
  1187. *nsName = NULL;
  1188. if (localName)
  1189. *localName = NULL;
  1190. if (hasProp)
  1191. *hasProp = 0;
  1192. prop = xsltGetCNsProp(style, inst, propName, XSLT_NAMESPACE);
  1193. if (prop == NULL) {
  1194. if (mandatory) {
  1195. xsltTransformError(NULL, style, inst,
  1196. "The attribute '%s' is missing.\n", propName);
  1197. style->errors++;
  1198. return;
  1199. }
  1200. } else {
  1201. const xmlChar *URI;
  1202. if (xmlValidateQName(prop, 0)) {
  1203. xsltTransformError(NULL, style, inst,
  1204. "The value '%s' of the attribute "
  1205. "'%s' is not a valid QName.\n", prop, propName);
  1206. style->errors++;
  1207. return;
  1208. } else {
  1209. /*
  1210. * @prop will be in the string dict afterwards, @URI not.
  1211. */
  1212. URI = xsltGetQNameURI2(style, inst, &prop);
  1213. if (prop == NULL) {
  1214. style->errors++;
  1215. } else {
  1216. if (localName)
  1217. *localName = prop;
  1218. if (hasProp)
  1219. *hasProp = 1;
  1220. if (URI != NULL) {
  1221. /*
  1222. * Fixes bug #308441: Put the ns-name in the dict
  1223. * in order to pointer compare names during XPath's
  1224. * variable lookup.
  1225. */
  1226. if (nsName)
  1227. *nsName = xmlDictLookup(style->dict, URI, -1);
  1228. /* comp->has_ns = 1; */
  1229. }
  1230. }
  1231. }
  1232. }
  1233. return;
  1234. }
  1235. /**
  1236. * xsltWithParamComp:
  1237. * @style: an XSLT compiled stylesheet
  1238. * @inst: the xslt with-param node
  1239. *
  1240. * Process the xslt with-param node on the source node
  1241. * Allowed parents: xsl:call-template, xsl:apply-templates.
  1242. * <xsl:with-param
  1243. * name = qname
  1244. * select = expression>
  1245. * <!-- Content: template -->
  1246. * </xsl:with-param>
  1247. */
  1248. static void
  1249. xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1250. #ifdef XSLT_REFACTORED
  1251. xsltStyleItemWithParamPtr comp;
  1252. #else
  1253. xsltStylePreCompPtr comp;
  1254. #endif
  1255. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1256. return;
  1257. #ifdef XSLT_REFACTORED
  1258. comp = (xsltStyleItemWithParamPtr) xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
  1259. #else
  1260. comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
  1261. #endif
  1262. if (comp == NULL)
  1263. return;
  1264. inst->psvi = comp;
  1265. comp->inst = inst;
  1266. /*
  1267. * Attribute "name".
  1268. */
  1269. xsltGetQNameProperty(style, inst, BAD_CAST "name",
  1270. 1, &(comp->has_name), &(comp->ns), &(comp->name));
  1271. if (comp->ns)
  1272. comp->has_ns = 1;
  1273. /*
  1274. * Attribute "select".
  1275. */
  1276. comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
  1277. XSLT_NAMESPACE);
  1278. if (comp->select != NULL) {
  1279. comp->comp = xsltXPathCompile(style, comp->select);
  1280. if (comp->comp == NULL) {
  1281. xsltTransformError(NULL, style, inst,
  1282. "XSLT-with-param: Failed to compile select "
  1283. "expression '%s'\n", comp->select);
  1284. style->errors++;
  1285. }
  1286. if (inst->children != NULL) {
  1287. xsltTransformError(NULL, style, inst,
  1288. "XSLT-with-param: The content should be empty since "
  1289. "the attribute select is present.\n");
  1290. style->warnings++;
  1291. }
  1292. }
  1293. }
  1294. /**
  1295. * xsltNumberComp:
  1296. * @style: an XSLT compiled stylesheet
  1297. * @cur: the xslt number node
  1298. *
  1299. * Process the xslt number node on the source node
  1300. */
  1301. static void
  1302. xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
  1303. #ifdef XSLT_REFACTORED
  1304. xsltStyleItemNumberPtr comp;
  1305. #else
  1306. xsltStylePreCompPtr comp;
  1307. #endif
  1308. const xmlChar *prop;
  1309. if ((style == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE))
  1310. return;
  1311. #ifdef XSLT_REFACTORED
  1312. comp = (xsltStyleItemNumberPtr) xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
  1313. #else
  1314. comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
  1315. #endif
  1316. if (comp == NULL)
  1317. return;
  1318. cur->psvi = comp;
  1319. comp->numdata.doc = cur->doc;
  1320. comp->numdata.node = cur;
  1321. comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",
  1322. XSLT_NAMESPACE);
  1323. prop = xsltEvalStaticAttrValueTemplate(style, cur,
  1324. (const xmlChar *)"format",
  1325. XSLT_NAMESPACE, &comp->numdata.has_format);
  1326. if (comp->numdata.has_format == 0) {
  1327. comp->numdata.format = xmlDictLookup(style->dict, BAD_CAST "" , 0);
  1328. } else {
  1329. comp->numdata.format = prop;
  1330. }
  1331. comp->numdata.count = xsltGetCNsProp(style, cur, (const xmlChar *)"count",
  1332. XSLT_NAMESPACE);
  1333. comp->numdata.from = xsltGetCNsProp(style, cur, (const xmlChar *)"from",
  1334. XSLT_NAMESPACE);
  1335. prop = xsltGetCNsProp(style, cur, (const xmlChar *)"count", XSLT_NAMESPACE);
  1336. if (prop != NULL) {
  1337. comp->numdata.countPat = xsltCompilePattern(prop, cur->doc, cur, style,
  1338. NULL);
  1339. }
  1340. prop = xsltGetCNsProp(style, cur, (const xmlChar *)"from", XSLT_NAMESPACE);
  1341. if (prop != NULL) {
  1342. comp->numdata.fromPat = xsltCompilePattern(prop, cur->doc, cur, style,
  1343. NULL);
  1344. }
  1345. prop = xsltGetCNsProp(style, cur, (const xmlChar *)"level", XSLT_NAMESPACE);
  1346. if (prop != NULL) {
  1347. if (xmlStrEqual(prop, BAD_CAST("single")) ||
  1348. xmlStrEqual(prop, BAD_CAST("multiple")) ||
  1349. xmlStrEqual(prop, BAD_CAST("any"))) {
  1350. comp->numdata.level = prop;
  1351. } else {
  1352. xsltTransformError(NULL, style, cur,
  1353. "xsl:number : invalid value %s for level\n", prop);
  1354. if (style != NULL) style->warnings++;
  1355. }
  1356. }
  1357. prop = xsltGetCNsProp(style, cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
  1358. if (prop != NULL) {
  1359. xsltTransformError(NULL, style, cur,
  1360. "xsl:number : lang attribute not implemented\n");
  1361. XSLT_TODO; /* xsl:number lang attribute */
  1362. }
  1363. prop = xsltGetCNsProp(style, cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
  1364. if (prop != NULL) {
  1365. if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {
  1366. xsltTransformError(NULL, style, cur,
  1367. "xsl:number : letter-value 'alphabetic' not implemented\n");
  1368. if (style != NULL) style->warnings++;
  1369. XSLT_TODO; /* xsl:number letter-value attribute alphabetic */
  1370. } else if (xmlStrEqual(prop, BAD_CAST("traditional"))) {
  1371. xsltTransformError(NULL, style, cur,
  1372. "xsl:number : letter-value 'traditional' not implemented\n");
  1373. if (style != NULL) style->warnings++;
  1374. XSLT_TODO; /* xsl:number letter-value attribute traditional */
  1375. } else {
  1376. xsltTransformError(NULL, style, cur,
  1377. "xsl:number : invalid value %s for letter-value\n", prop);
  1378. if (style != NULL) style->warnings++;
  1379. }
  1380. }
  1381. prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-separator",
  1382. XSLT_NAMESPACE);
  1383. if (prop != NULL) {
  1384. comp->numdata.groupingCharacterLen = xmlStrlen(prop);
  1385. comp->numdata.groupingCharacter =
  1386. xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));
  1387. }
  1388. prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);
  1389. if (prop != NULL) {
  1390. sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup);
  1391. } else {
  1392. comp->numdata.groupingCharacter = 0;
  1393. }
  1394. /* Set default values */
  1395. if (comp->numdata.value == NULL) {
  1396. if (comp->numdata.level == NULL) {
  1397. comp->numdata.level = xmlDictLookup(style->dict,
  1398. BAD_CAST"single", 6);
  1399. }
  1400. }
  1401. }
  1402. /**
  1403. * xsltApplyImportsComp:
  1404. * @style: an XSLT compiled stylesheet
  1405. * @inst: the xslt apply-imports node
  1406. *
  1407. * Process the xslt apply-imports node on the source node
  1408. */
  1409. static void
  1410. xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1411. #ifdef XSLT_REFACTORED
  1412. xsltStyleItemApplyImportsPtr comp;
  1413. #else
  1414. xsltStylePreCompPtr comp;
  1415. #endif
  1416. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1417. return;
  1418. #ifdef XSLT_REFACTORED
  1419. comp = (xsltStyleItemApplyImportsPtr) xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
  1420. #else
  1421. comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
  1422. #endif
  1423. if (comp == NULL)
  1424. return;
  1425. inst->psvi = comp;
  1426. comp->inst = inst;
  1427. }
  1428. /**
  1429. * xsltCallTemplateComp:
  1430. * @style: an XSLT compiled stylesheet
  1431. * @inst: the xslt call-template node
  1432. *
  1433. * Process the xslt call-template node on the source node
  1434. */
  1435. static void
  1436. xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1437. #ifdef XSLT_REFACTORED
  1438. xsltStyleItemCallTemplatePtr comp;
  1439. #else
  1440. xsltStylePreCompPtr comp;
  1441. #endif
  1442. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1443. return;
  1444. #ifdef XSLT_REFACTORED
  1445. comp = (xsltStyleItemCallTemplatePtr)
  1446. xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
  1447. #else
  1448. comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
  1449. #endif
  1450. if (comp == NULL)
  1451. return;
  1452. inst->psvi = comp;
  1453. comp->inst = inst;
  1454. /*
  1455. * Attribute "name".
  1456. */
  1457. xsltGetQNameProperty(style, inst, BAD_CAST "name",
  1458. 1, &(comp->has_name), &(comp->ns), &(comp->name));
  1459. if (comp->ns)
  1460. comp->has_ns = 1;
  1461. }
  1462. /**
  1463. * xsltApplyTemplatesComp:
  1464. * @style: an XSLT compiled stylesheet
  1465. * @inst: the apply-templates node
  1466. *
  1467. * Process the apply-templates node on the source node
  1468. */
  1469. static void
  1470. xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1471. #ifdef XSLT_REFACTORED
  1472. xsltStyleItemApplyTemplatesPtr comp;
  1473. #else
  1474. xsltStylePreCompPtr comp;
  1475. #endif
  1476. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1477. return;
  1478. #ifdef XSLT_REFACTORED
  1479. comp = (xsltStyleItemApplyTemplatesPtr)
  1480. xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
  1481. #else
  1482. comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
  1483. #endif
  1484. if (comp == NULL)
  1485. return;
  1486. inst->psvi = comp;
  1487. comp->inst = inst;
  1488. /*
  1489. * Attribute "mode".
  1490. */
  1491. xsltGetQNameProperty(style, inst, BAD_CAST "mode",
  1492. 0, NULL, &(comp->modeURI), &(comp->mode));
  1493. /*
  1494. * Attribute "select".
  1495. */
  1496. comp->select = xsltGetCNsProp(style, inst, BAD_CAST "select",
  1497. XSLT_NAMESPACE);
  1498. if (comp->select != NULL) {
  1499. comp->comp = xsltXPathCompile(style, comp->select);
  1500. if (comp->comp == NULL) {
  1501. xsltTransformError(NULL, style, inst,
  1502. "XSLT-apply-templates: could not compile select "
  1503. "expression '%s'\n", comp->select);
  1504. style->errors++;
  1505. }
  1506. }
  1507. /* TODO: handle (or skip) the xsl:sort and xsl:with-param */
  1508. }
  1509. /**
  1510. * xsltChooseComp:
  1511. * @style: an XSLT compiled stylesheet
  1512. * @inst: the xslt choose node
  1513. *
  1514. * Process the xslt choose node on the source node
  1515. */
  1516. static void
  1517. xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1518. #ifdef XSLT_REFACTORED
  1519. xsltStyleItemChoosePtr comp;
  1520. #else
  1521. xsltStylePreCompPtr comp;
  1522. #endif
  1523. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1524. return;
  1525. #ifdef XSLT_REFACTORED
  1526. comp = (xsltStyleItemChoosePtr)
  1527. xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
  1528. #else
  1529. comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
  1530. #endif
  1531. if (comp == NULL)
  1532. return;
  1533. inst->psvi = comp;
  1534. comp->inst = inst;
  1535. }
  1536. /**
  1537. * xsltIfComp:
  1538. * @style: an XSLT compiled stylesheet
  1539. * @inst: the xslt if node
  1540. *
  1541. * Process the xslt if node on the source node
  1542. */
  1543. static void
  1544. xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1545. #ifdef XSLT_REFACTORED
  1546. xsltStyleItemIfPtr comp;
  1547. #else
  1548. xsltStylePreCompPtr comp;
  1549. #endif
  1550. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1551. return;
  1552. #ifdef XSLT_REFACTORED
  1553. comp = (xsltStyleItemIfPtr)
  1554. xsltNewStylePreComp(style, XSLT_FUNC_IF);
  1555. #else
  1556. comp = xsltNewStylePreComp(style, XSLT_FUNC_IF);
  1557. #endif
  1558. if (comp == NULL)
  1559. return;
  1560. inst->psvi = comp;
  1561. comp->inst = inst;
  1562. comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
  1563. if (comp->test == NULL) {
  1564. xsltTransformError(NULL, style, inst,
  1565. "xsl:if : test is not defined\n");
  1566. if (style != NULL) style->errors++;
  1567. return;
  1568. }
  1569. comp->comp = xsltXPathCompile(style, comp->test);
  1570. if (comp->comp == NULL) {
  1571. xsltTransformError(NULL, style, inst,
  1572. "xsl:if : could not compile test expression '%s'\n",
  1573. comp->test);
  1574. if (style != NULL) style->errors++;
  1575. }
  1576. }
  1577. /**
  1578. * xsltWhenComp:
  1579. * @style: an XSLT compiled stylesheet
  1580. * @inst: the xslt if node
  1581. *
  1582. * Process the xslt if node on the source node
  1583. */
  1584. static void
  1585. xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1586. #ifdef XSLT_REFACTORED
  1587. xsltStyleItemWhenPtr comp;
  1588. #else
  1589. xsltStylePreCompPtr comp;
  1590. #endif
  1591. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1592. return;
  1593. #ifdef XSLT_REFACTORED
  1594. comp = (xsltStyleItemWhenPtr)
  1595. xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
  1596. #else
  1597. comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
  1598. #endif
  1599. if (comp == NULL)
  1600. return;
  1601. inst->psvi = comp;
  1602. comp->inst = inst;
  1603. comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
  1604. if (comp->test == NULL) {
  1605. xsltTransformError(NULL, style, inst,
  1606. "xsl:when : test is not defined\n");
  1607. if (style != NULL) style->errors++;
  1608. return;
  1609. }
  1610. comp->comp = xsltXPathCompile(style, comp->test);
  1611. if (comp->comp == NULL) {
  1612. xsltTransformError(NULL, style, inst,
  1613. "xsl:when : could not compile test expression '%s'\n",
  1614. comp->test);
  1615. if (style != NULL) style->errors++;
  1616. }
  1617. }
  1618. /**
  1619. * xsltForEachComp:
  1620. * @style: an XSLT compiled stylesheet
  1621. * @inst: the xslt for-each node
  1622. *
  1623. * Process the xslt for-each node on the source node
  1624. */
  1625. static void
  1626. xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1627. #ifdef XSLT_REFACTORED
  1628. xsltStyleItemForEachPtr comp;
  1629. #else
  1630. xsltStylePreCompPtr comp;
  1631. #endif
  1632. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1633. return;
  1634. #ifdef XSLT_REFACTORED
  1635. comp = (xsltStyleItemForEachPtr)
  1636. xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
  1637. #else
  1638. comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
  1639. #endif
  1640. if (comp == NULL)
  1641. return;
  1642. inst->psvi = comp;
  1643. comp->inst = inst;
  1644. comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
  1645. XSLT_NAMESPACE);
  1646. if (comp->select == NULL) {
  1647. xsltTransformError(NULL, style, inst,
  1648. "xsl:for-each : select is missing\n");
  1649. if (style != NULL) style->errors++;
  1650. } else {
  1651. comp->comp = xsltXPathCompile(style, comp->select);
  1652. if (comp->comp == NULL) {
  1653. xsltTransformError(NULL, style, inst,
  1654. "xsl:for-each : could not compile select expression '%s'\n",
  1655. comp->select);
  1656. if (style != NULL) style->errors++;
  1657. }
  1658. }
  1659. /* TODO: handle and skip the xsl:sort */
  1660. }
  1661. /**
  1662. * xsltVariableComp:
  1663. * @style: an XSLT compiled stylesheet
  1664. * @inst: the xslt variable node
  1665. *
  1666. * Process the xslt variable node on the source node
  1667. */
  1668. static void
  1669. xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1670. #ifdef XSLT_REFACTORED
  1671. xsltStyleItemVariablePtr comp;
  1672. #else
  1673. xsltStylePreCompPtr comp;
  1674. #endif
  1675. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1676. return;
  1677. #ifdef XSLT_REFACTORED
  1678. comp = (xsltStyleItemVariablePtr)
  1679. xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
  1680. #else
  1681. comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
  1682. #endif
  1683. if (comp == NULL)
  1684. return;
  1685. inst->psvi = comp;
  1686. comp->inst = inst;
  1687. /*
  1688. * The full template resolution can be done statically
  1689. */
  1690. /*
  1691. * Attribute "name".
  1692. */
  1693. xsltGetQNameProperty(style, inst, BAD_CAST "name",
  1694. 1, &(comp->has_name), &(comp->ns), &(comp->name));
  1695. if (comp->ns)
  1696. comp->has_ns = 1;
  1697. /*
  1698. * Attribute "select".
  1699. */
  1700. comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
  1701. XSLT_NAMESPACE);
  1702. if (comp->select != NULL) {
  1703. #ifndef XSLT_REFACTORED
  1704. xmlNodePtr cur;
  1705. #endif
  1706. comp->comp = xsltXPathCompile(style, comp->select);
  1707. if (comp->comp == NULL) {
  1708. xsltTransformError(NULL, style, inst,
  1709. "XSLT-variable: Failed to compile the XPath expression '%s'.\n",
  1710. comp->select);
  1711. style->errors++;
  1712. }
  1713. #ifdef XSLT_REFACTORED
  1714. if (inst->children != NULL) {
  1715. xsltTransformError(NULL, style, inst,
  1716. "XSLT-variable: There must be no child nodes, since the "
  1717. "attribute 'select' was specified.\n");
  1718. style->errors++;
  1719. }
  1720. #else
  1721. for (cur = inst->children; cur != NULL; cur = cur->next) {
  1722. if (cur->type != XML_COMMENT_NODE &&
  1723. (cur->type != XML_TEXT_NODE || !xsltIsBlank(cur->content)))
  1724. {
  1725. xsltTransformError(NULL, style, inst,
  1726. "XSLT-variable: There must be no child nodes, since the "
  1727. "attribute 'select' was specified.\n");
  1728. style->errors++;
  1729. }
  1730. }
  1731. #endif
  1732. }
  1733. }
  1734. /**
  1735. * xsltParamComp:
  1736. * @style: an XSLT compiled stylesheet
  1737. * @inst: the xslt param node
  1738. *
  1739. * Process the xslt param node on the source node
  1740. */
  1741. static void
  1742. xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
  1743. #ifdef XSLT_REFACTORED
  1744. xsltStyleItemParamPtr comp;
  1745. #else
  1746. xsltStylePreCompPtr comp;
  1747. #endif
  1748. if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
  1749. return;
  1750. #ifdef XSLT_REFACTORED
  1751. comp = (xsltStyleItemParamPtr)
  1752. xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
  1753. #else
  1754. comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
  1755. #endif
  1756. if (comp == NULL)
  1757. return;
  1758. inst->psvi = comp;
  1759. comp->inst = inst;
  1760. /*
  1761. * Attribute "name".
  1762. */
  1763. xsltGetQNameProperty(style, inst, BAD_CAST "name",
  1764. 1, &(comp->has_name), &(comp->ns), &(comp->name));
  1765. if (comp->ns)
  1766. comp->has_ns = 1;
  1767. /*
  1768. * Attribute "select".
  1769. */
  1770. comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
  1771. XSLT_NAMESPACE);
  1772. if (comp->select != NULL) {
  1773. comp->comp = xsltXPathCompile(style, comp->select);
  1774. if (comp->comp == NULL) {
  1775. xsltTransformError(NULL, style, inst,
  1776. "XSLT-param: could not compile select expression '%s'.\n",
  1777. comp->select);
  1778. style->errors++;
  1779. }
  1780. if (inst->children != NULL) {
  1781. xsltTransformError(NULL, style, inst,
  1782. "XSLT-param: The content should be empty since the "
  1783. "attribute 'select' is present.\n");
  1784. style->warnings++;
  1785. }
  1786. }
  1787. }
  1788. /************************************************************************
  1789. * *
  1790. * Generic interface *
  1791. * *
  1792. ************************************************************************/
  1793. /**
  1794. * xsltFreeStylePreComps:
  1795. * @style: an XSLT transformation context
  1796. *
  1797. * Free up the memory allocated by all precomputed blocks
  1798. */
  1799. void
  1800. xsltFreeStylePreComps(xsltStylesheetPtr style) {
  1801. xsltElemPreCompPtr cur, next;
  1802. if (style == NULL)
  1803. return;
  1804. cur = style->preComps;
  1805. while (cur != NULL) {
  1806. next = cur->next;
  1807. if (cur->type == XSLT_FUNC_EXTENSION)
  1808. cur->free(cur);
  1809. else
  1810. xsltFreeStylePreComp((xsltStylePreCompPtr) cur);
  1811. cur = next;
  1812. }
  1813. }
  1814. #ifdef XSLT_REFACTORED
  1815. /**
  1816. * xsltStylePreCompute:
  1817. * @style: the XSLT stylesheet
  1818. * @node: the element in the XSLT namespace
  1819. *
  1820. * Precompute an XSLT element.
  1821. * This expects the type of the element to be already
  1822. * set in style->compCtxt->inode->type;
  1823. */
  1824. void
  1825. xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr node) {
  1826. /*
  1827. * The xsltXSLTElemMarker marker was set beforehand by
  1828. * the parsing mechanism for all elements in the XSLT namespace.
  1829. */
  1830. if (style == NULL) {
  1831. if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
  1832. node->psvi = NULL;
  1833. return;
  1834. }
  1835. if (node == NULL)
  1836. return;
  1837. if (! IS_XSLT_ELEM_FAST(node))
  1838. return;
  1839. node->psvi = NULL;
  1840. if (XSLT_CCTXT(style)->inode->type != 0) {
  1841. switch (XSLT_CCTXT(style)->inode->type) {
  1842. case XSLT_FUNC_APPLYTEMPLATES:
  1843. xsltApplyTemplatesComp(style, node);
  1844. break;
  1845. case XSLT_FUNC_WITHPARAM:
  1846. xsltWithParamComp(style, node);
  1847. break;
  1848. case XSLT_FUNC_VALUEOF:
  1849. xsltValueOfComp(style, node);
  1850. break;
  1851. case XSLT_FUNC_COPY:
  1852. xsltCopyComp(style, node);
  1853. break;
  1854. case XSLT_FUNC_COPYOF:
  1855. xsltCopyOfComp(style, node);
  1856. break;
  1857. case XSLT_FUNC_IF:
  1858. xsltIfComp(style, node);
  1859. break;
  1860. case XSLT_FUNC_CHOOSE:
  1861. xsltChooseComp(style, node);
  1862. break;
  1863. case XSLT_FUNC_WHEN:
  1864. xsltWhenComp(style, node);
  1865. break;
  1866. case XSLT_FUNC_OTHERWISE:
  1867. /* NOP yet */
  1868. return;
  1869. case XSLT_FUNC_FOREACH:
  1870. xsltForEachComp(style, node);
  1871. break;
  1872. case XSLT_FUNC_APPLYIMPORTS:
  1873. xsltApplyImportsComp(style, node);
  1874. break;
  1875. case XSLT_FUNC_ATTRIBUTE:
  1876. xsltAttributeComp(style, node);
  1877. break;
  1878. case XSLT_FUNC_ELEMENT:
  1879. xsltElementComp(style, node);
  1880. break;
  1881. case XSLT_FUNC_SORT:
  1882. xsltSortComp(style, node);
  1883. break;
  1884. case XSLT_FUNC_COMMENT:
  1885. xsltCommentComp(style, node);
  1886. break;
  1887. case XSLT_FUNC_NUMBER:
  1888. xsltNumberComp(style, node);
  1889. break;
  1890. case XSLT_FUNC_PI:
  1891. xsltProcessingInstructionComp(style, node);
  1892. break;
  1893. case XSLT_FUNC_CALLTEMPLATE:
  1894. xsltCallTemplateComp(style, node);
  1895. break;
  1896. case XSLT_FUNC_PARAM:
  1897. xsltParamComp(style, node);
  1898. break;
  1899. case XSLT_FUNC_VARIABLE:
  1900. xsltVariableComp(style, node);
  1901. break;
  1902. case XSLT_FUNC_FALLBACK:
  1903. /* NOP yet */
  1904. return;
  1905. case XSLT_FUNC_DOCUMENT:
  1906. /* The extra one */
  1907. node->psvi = (void *) xsltDocumentComp(style, node,
  1908. xsltDocumentElem);
  1909. break;
  1910. case XSLT_FUNC_MESSAGE:
  1911. /* NOP yet */
  1912. return;
  1913. default:
  1914. /*
  1915. * NOTE that xsl:text, xsl:template, xsl:stylesheet,
  1916. * xsl:transform, xsl:import, xsl:include are not expected
  1917. * to be handed over to this function.
  1918. */
  1919. xsltTransformError(NULL, style, node,
  1920. "Internal error: (xsltStylePreCompute) cannot handle "
  1921. "the XSLT element '%s'.\n", node->name);
  1922. style->errors++;
  1923. return;
  1924. }
  1925. } else {
  1926. /*
  1927. * Fallback to string comparison.
  1928. */
  1929. if (IS_XSLT_NAME(node, "apply-templates")) {
  1930. xsltApplyTemplatesComp(style, node);
  1931. } else if (IS_XSLT_NAME(node, "with-param")) {
  1932. xsltWithParamComp(style, node);
  1933. } else if (IS_XSLT_NAME(node, "value-of")) {
  1934. xsltValueOfComp(style, node);
  1935. } else if (IS_XSLT_NAME(node, "copy")) {
  1936. xsltCopyComp(style, node);
  1937. } else if (IS_XSLT_NAME(node, "copy-of")) {
  1938. xsltCopyOfComp(style, node);
  1939. } else if (IS_XSLT_NAME(node, "if")) {
  1940. xsltIfComp(style, node);
  1941. } else if (IS_XSLT_NAME(node, "choose")) {
  1942. xsltChooseComp(style, node);
  1943. } else if (IS_XSLT_NAME(node, "when")) {
  1944. xsltWhenComp(style, node);
  1945. } else if (IS_XSLT_NAME(node, "otherwise")) {
  1946. /* NOP yet */
  1947. return;
  1948. } else if (IS_XSLT_NAME(node, "for-each")) {
  1949. xsltForEachComp(style, node);
  1950. } else if (IS_XSLT_NAME(node, "apply-imports")) {
  1951. xsltApplyImportsComp(style, node);
  1952. } else if (IS_XSLT_NAME(node, "attribute")) {
  1953. xsltAttributeComp(style, node);
  1954. } else if (IS_XSLT_NAME(node, "element")) {
  1955. xsltElementComp(style, node);
  1956. } else if (IS_XSLT_NAME(node, "sort")) {
  1957. xsltSortComp(style, node);
  1958. } else if (IS_XSLT_NAME(node, "comment")) {
  1959. xsltCommentComp(style, node);
  1960. } else if (IS_XSLT_NAME(node, "number")) {
  1961. xsltNumberComp(style, node);
  1962. } else if (IS_XSLT_NAME(node, "processing-instruction")) {
  1963. xsltProcessingInstructionComp(style, node);
  1964. } else if (IS_XSLT_NAME(node, "call-template")) {
  1965. xsltCallTemplateComp(style, node);
  1966. } else if (IS_XSLT_NAME(node, "param")) {
  1967. xsltParamComp(style, node);
  1968. } else if (IS_XSLT_NAME(node, "variable")) {
  1969. xsltVariableComp(style, node);
  1970. } else if (IS_XSLT_NAME(node, "fallback")) {
  1971. /* NOP yet */
  1972. return;
  1973. } else if (IS_XSLT_NAME(node, "document")) {
  1974. /* The extra one */
  1975. node->psvi = (void *) xsltDocumentComp(style, node,
  1976. xsltDocumentElem);
  1977. } else if (IS_XSLT_NAME(node, "output")) {
  1978. /* Top-level */
  1979. return;
  1980. } else if (IS_XSLT_NAME(node, "preserve-space")) {
  1981. /* Top-level */
  1982. return;
  1983. } else if (IS_XSLT_NAME(node, "strip-space")) {
  1984. /* Top-level */
  1985. return;
  1986. } else if (IS_XSLT_NAME(node, "key")) {
  1987. /* Top-level */
  1988. return;
  1989. } else if (IS_XSLT_NAME(node, "message")) {
  1990. return;
  1991. } else if (IS_XSLT_NAME(node, "attribute-set")) {
  1992. /* Top-level */
  1993. return;
  1994. } else if (IS_XSLT_NAME(node, "namespace-alias")) {
  1995. /* Top-level */
  1996. return;
  1997. } else if (IS_XSLT_NAME(node, "decimal-format")) {
  1998. /* Top-level */
  1999. return;
  2000. } else if (IS_XSLT_NAME(node, "include")) {
  2001. /* Top-level */
  2002. } else {
  2003. /*
  2004. * NOTE that xsl:text, xsl:template, xsl:stylesheet,
  2005. * xsl:transform, xsl:import, xsl:include are not expected
  2006. * to be handed over to this function.
  2007. */
  2008. xsltTransformError(NULL, style, node,
  2009. "Internal error: (xsltStylePreCompute) cannot handle "
  2010. "the XSLT element '%s'.\n", node->name);
  2011. style->errors++;
  2012. return;
  2013. }
  2014. }
  2015. /*
  2016. * Assign the current list of in-scope namespaces to the
  2017. * item. This is needed for XPath expressions.
  2018. */
  2019. if (node->psvi != NULL) {
  2020. ((xsltStylePreCompPtr) node->psvi)->inScopeNs =
  2021. XSLT_CCTXT(style)->inode->inScopeNs;
  2022. }
  2023. }
  2024. #else
  2025. /**
  2026. * xsltStylePreCompute:
  2027. * @style: the XSLT stylesheet
  2028. * @inst: the instruction in the stylesheet
  2029. *
  2030. * Precompute an XSLT stylesheet element
  2031. */
  2032. void
  2033. xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
  2034. /*
  2035. * URGENT TODO: Normally inst->psvi Should never be reserved here,
  2036. * BUT: since if we include the same stylesheet from
  2037. * multiple imports, then the stylesheet will be parsed
  2038. * again. We simply must not try to compute the stylesheet again.
  2039. * TODO: Get to the point where we don't need to query the
  2040. * namespace- and local-name of the node, but can evaluate this
  2041. * using cctxt->style->inode->category;
  2042. */
  2043. if ((inst == NULL) || (inst->type != XML_ELEMENT_NODE) ||
  2044. (inst->psvi != NULL))
  2045. return;
  2046. if (IS_XSLT_ELEM(inst)) {
  2047. xsltStylePreCompPtr cur;
  2048. if (IS_XSLT_NAME(inst, "apply-templates")) {
  2049. xsltCheckInstructionElement(style, inst);
  2050. xsltApplyTemplatesComp(style, inst);
  2051. } else if (IS_XSLT_NAME(inst, "with-param")) {
  2052. xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
  2053. BAD_CAST "call-template");
  2054. xsltWithParamComp(style, inst);
  2055. } else if (IS_XSLT_NAME(inst, "value-of")) {
  2056. xsltCheckInstructionElement(style, inst);
  2057. xsltValueOfComp(style, inst);
  2058. } else if (IS_XSLT_NAME(inst, "copy")) {
  2059. xsltCheckInstructionElement(style, inst);
  2060. xsltCopyComp(style, inst);
  2061. } else if (IS_XSLT_NAME(inst, "copy-of")) {
  2062. xsltCheckInstructionElement(style, inst);
  2063. xsltCopyOfComp(style, inst);
  2064. } else if (IS_XSLT_NAME(inst, "if")) {
  2065. xsltCheckInstructionElement(style, inst);
  2066. xsltIfComp(style, inst);
  2067. } else if (IS_XSLT_NAME(inst, "when")) {
  2068. xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
  2069. xsltWhenComp(style, inst);
  2070. } else if (IS_XSLT_NAME(inst, "choose")) {
  2071. xsltCheckInstructionElement(style, inst);
  2072. xsltChooseComp(style, inst);
  2073. } else if (IS_XSLT_NAME(inst, "for-each")) {
  2074. xsltCheckInstructionElement(style, inst);
  2075. xsltForEachComp(style, inst);
  2076. } else if (IS_XSLT_NAME(inst, "apply-imports")) {
  2077. xsltCheckInstructionElement(style, inst);
  2078. xsltApplyImportsComp(style, inst);
  2079. } else if (IS_XSLT_NAME(inst, "attribute")) {
  2080. xmlNodePtr parent = inst->parent;
  2081. if ((parent == NULL) ||
  2082. (parent->type != XML_ELEMENT_NODE) || (parent->ns == NULL) ||
  2083. ((parent->ns != inst->ns) &&
  2084. (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
  2085. (!xmlStrEqual(parent->name, BAD_CAST "attribute-set"))) {
  2086. xsltCheckInstructionElement(style, inst);
  2087. }
  2088. xsltAttributeComp(style, inst);
  2089. } else if (IS_XSLT_NAME(inst, "element")) {
  2090. xsltCheckInstructionElement(style, inst);
  2091. xsltElementComp(style, inst);
  2092. } else if (IS_XSLT_NAME(inst, "text")) {
  2093. xsltCheckInstructionElement(style, inst);
  2094. xsltTextComp(style, inst);
  2095. } else if (IS_XSLT_NAME(inst, "sort")) {
  2096. xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
  2097. BAD_CAST "for-each");
  2098. xsltSortComp(style, inst);
  2099. } else if (IS_XSLT_NAME(inst, "comment")) {
  2100. xsltCheckInstructionElement(style, inst);
  2101. xsltCommentComp(style, inst);
  2102. } else if (IS_XSLT_NAME(inst, "number")) {
  2103. xsltCheckInstructionElement(style, inst);
  2104. xsltNumberComp(style, inst);
  2105. } else if (IS_XSLT_NAME(inst, "processing-instruction")) {
  2106. xsltCheckInstructionElement(style, inst);
  2107. xsltProcessingInstructionComp(style, inst);
  2108. } else if (IS_XSLT_NAME(inst, "call-template")) {
  2109. xsltCheckInstructionElement(style, inst);
  2110. xsltCallTemplateComp(style, inst);
  2111. } else if (IS_XSLT_NAME(inst, "param")) {
  2112. if (xsltCheckTopLevelElement(style, inst, 0) == 0)
  2113. xsltCheckInstructionElement(style, inst);
  2114. xsltParamComp(style, inst);
  2115. } else if (IS_XSLT_NAME(inst, "variable")) {
  2116. if (xsltCheckTopLevelElement(style, inst, 0) == 0)
  2117. xsltCheckInstructionElement(style, inst);
  2118. xsltVariableComp(style, inst);
  2119. } else if (IS_XSLT_NAME(inst, "otherwise")) {
  2120. xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
  2121. xsltCheckInstructionElement(style, inst);
  2122. return;
  2123. } else if (IS_XSLT_NAME(inst, "template")) {
  2124. xsltCheckTopLevelElement(style, inst, 1);
  2125. return;
  2126. } else if (IS_XSLT_NAME(inst, "output")) {
  2127. xsltCheckTopLevelElement(style, inst, 1);
  2128. return;
  2129. } else if (IS_XSLT_NAME(inst, "preserve-space")) {
  2130. xsltCheckTopLevelElement(style, inst, 1);
  2131. return;
  2132. } else if (IS_XSLT_NAME(inst, "strip-space")) {
  2133. xsltCheckTopLevelElement(style, inst, 1);
  2134. return;
  2135. } else if ((IS_XSLT_NAME(inst, "stylesheet")) ||
  2136. (IS_XSLT_NAME(inst, "transform"))) {
  2137. xmlNodePtr parent = inst->parent;
  2138. if ((parent == NULL) || (parent->type != XML_DOCUMENT_NODE)) {
  2139. xsltTransformError(NULL, style, inst,
  2140. "element %s only allowed only as root element\n",
  2141. inst->name);
  2142. style->errors++;
  2143. }
  2144. return;
  2145. } else if (IS_XSLT_NAME(inst, "key")) {
  2146. xsltCheckTopLevelElement(style, inst, 1);
  2147. return;
  2148. } else if (IS_XSLT_NAME(inst, "message")) {
  2149. xsltCheckInstructionElement(style, inst);
  2150. return;
  2151. } else if (IS_XSLT_NAME(inst, "attribute-set")) {
  2152. xsltCheckTopLevelElement(style, inst, 1);
  2153. return;
  2154. } else if (IS_XSLT_NAME(inst, "namespace-alias")) {
  2155. xsltCheckTopLevelElement(style, inst, 1);
  2156. return;
  2157. } else if (IS_XSLT_NAME(inst, "include")) {
  2158. xsltCheckTopLevelElement(style, inst, 1);
  2159. return;
  2160. } else if (IS_XSLT_NAME(inst, "import")) {
  2161. xsltCheckTopLevelElement(style, inst, 1);
  2162. return;
  2163. } else if (IS_XSLT_NAME(inst, "decimal-format")) {
  2164. xsltCheckTopLevelElement(style, inst, 1);
  2165. return;
  2166. } else if (IS_XSLT_NAME(inst, "fallback")) {
  2167. xsltCheckInstructionElement(style, inst);
  2168. return;
  2169. } else if (IS_XSLT_NAME(inst, "document")) {
  2170. xsltCheckInstructionElement(style, inst);
  2171. inst->psvi = (void *) xsltDocumentComp(style, inst,
  2172. xsltDocumentElem);
  2173. } else if ((style == NULL) || (style->forwards_compatible == 0)) {
  2174. xsltTransformError(NULL, style, inst,
  2175. "xsltStylePreCompute: unknown xsl:%s\n", inst->name);
  2176. if (style != NULL) style->warnings++;
  2177. }
  2178. cur = (xsltStylePreCompPtr) inst->psvi;
  2179. /*
  2180. * A ns-list is build for every XSLT item in the
  2181. * node-tree. This is needed for XPath expressions.
  2182. */
  2183. if (cur != NULL) {
  2184. int i = 0;
  2185. cur->nsList = xmlGetNsList(inst->doc, inst);
  2186. if (cur->nsList != NULL) {
  2187. while (cur->nsList[i] != NULL)
  2188. i++;
  2189. }
  2190. cur->nsNr = i;
  2191. }
  2192. } else {
  2193. inst->psvi =
  2194. (void *) xsltPreComputeExtModuleElement(style, inst);
  2195. /*
  2196. * Unknown element, maybe registered at the context
  2197. * level. Mark it for later recognition.
  2198. */
  2199. if (inst->psvi == NULL)
  2200. inst->psvi = (void *) xsltExtMarker;
  2201. }
  2202. }
  2203. #endif /* XSLT_REFACTORED */