PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/library/xslt/src/style/xm_xslt_stylesheet.e

http://github.com/gobo-eiffel/gobo
Specman e | 1426 lines | 1149 code | 151 blank | 126 comment | 88 complexity | c08d774d2e50762d87ca5b627126d0a3 MD5 | raw file
  1. note
  2. description:
  3. "xsl:transform or xsl:stylesheet element nodes"
  4. library: "Gobo Eiffel XSLT Library"
  5. copyright: "Copyright (c) 2004-2018, Colin Adams and others"
  6. license: "MIT License"
  7. date: "$Date$"
  8. revision: "$Revision$"
  9. class XM_XSLT_STYLESHEET
  10. inherit
  11. XM_XSLT_STYLE_ELEMENT
  12. redefine
  13. make_style_element, precedence, process_all_attributes, validate, is_global_variable_declared,
  14. any_compile_errors, stylesheet_compiler, system_id_from_module_number, is_stylesheet
  15. end
  16. XM_XSLT_PROCEDURE
  17. XM_XSLT_VALIDATION
  18. XM_XSLT_SHARED_FUNCTION_LIBRARY
  19. XM_XPATH_STANDARD_NAMESPACES
  20. KL_SHARED_PLATFORM
  21. export {NONE} all end
  22. create {XM_XSLT_NODE_FACTORY}
  23. make_style_element
  24. feature {NONE} -- Initialization
  25. make_style_element (an_error_listener: XM_XSLT_ERROR_LISTENER; a_document: XM_XPATH_TREE_DOCUMENT; a_parent: detachable XM_XPATH_TREE_COMPOSITE_NODE;
  26. an_attribute_collection: detachable XM_XPATH_ATTRIBUTE_COLLECTION; a_namespace_list: detachable DS_ARRAYED_LIST [INTEGER];
  27. a_name_code: INTEGER; a_sequence_number: INTEGER; a_configuration: like configuration)
  28. -- Establish invariant.
  29. local
  30. a_code_point_collator: ST_COLLATOR
  31. do
  32. create imports.make_default
  33. imports.set_equality_tester (string_equality_tester)
  34. create named_templates_index.make_map (5)
  35. create variables_index.make_map (5)
  36. create namespace_alias_list.make (5)
  37. create key_manager.make
  38. create decimal_format_manager.make
  39. create collation_map.make_with_equality_testers (1, Void, string_equality_tester)
  40. create a_code_point_collator
  41. create stylesheet_module_map.make_with_equality_testers (5, Void, string_equality_tester)
  42. create module_list.make_default
  43. module_list.set_equality_tester (string_equality_tester)
  44. default_validation := Validation_strip
  45. function_library := shared_function_library
  46. create rule_manager.make
  47. create slot_manager.make
  48. create executable.make (rule_manager, key_manager, decimal_format_manager,
  49. collation_map, shared_name_pool, module_list, function_library)
  50. Precursor (an_error_listener, a_document, a_parent, an_attribute_collection, a_namespace_list, a_name_code, a_sequence_number, a_configuration)
  51. declare_collation (a_code_point_collator, default_collation_name)
  52. end
  53. feature -- Access
  54. imports: DS_HASH_SET [STRING]
  55. -- Href attribute values of all included and imported stylesheet modules (if `Current' is the principal stylesheet module)
  56. collation_map: DS_HASH_TABLE [ST_COLLATOR, STRING]
  57. -- Map of collation names to collators
  58. importer: detachable like Current
  59. -- The stylesheet that imported or included `Current';
  60. -- `Void' for the prinicpal stylesheet.
  61. stylesheet_compiler: detachable XM_XSLT_STYLESHEET_COMPILER
  62. -- Stylesheet compiler object used to load `Current'
  63. top_level_elements: detachable DS_BILINKED_LIST [XM_XSLT_STYLE_ELEMENT]
  64. -- Top-level elements in this logical stylesheet (after include/import processing)
  65. import_precedence: INTEGER
  66. -- Import precedence for top-level elements
  67. minimum_import_precedence: INTEGER
  68. -- Lowest precedence of any stylesheet imported by `Current'
  69. rule_manager: XM_XSLT_RULE_MANAGER
  70. -- Manager of template-matching rules
  71. key_manager: XM_XSLT_KEY_MANAGER
  72. -- Manger of key definitions
  73. decimal_format_manager: XM_XSLT_DECIMAL_FORMAT_MANAGER
  74. -- Manager of decimal formats
  75. includes_processed: BOOLEAN
  76. -- Has import/include processing been performed?
  77. default_validation: INTEGER
  78. -- Default validation
  79. stripper_rules: detachable XM_XSLT_MODE
  80. -- Strip/preserve whitespace rules
  81. function_library: XM_XPATH_FUNCTION_LIBRARY_MANAGER
  82. -- Function libraries in use (only if this is the principal stylesheet module)
  83. precedence: INTEGER
  84. -- Import precedence of `Current'
  85. do
  86. if was_included then
  87. check attached importer as l_importer then
  88. Result := l_importer.precedence
  89. end
  90. else
  91. Result := import_precedence
  92. end
  93. end
  94. namespace_alias (a_uri_code: INTEGER): INTEGER
  95. -- Declared namespace alias for a given namespace URI code if there is one.
  96. -- If there is more than one, we get the last.
  97. require
  98. namespaces_aliases_present: has_namespace_aliases
  99. local
  100. l_index: INTEGER
  101. do
  102. check precondition_namespaces_aliases_present: attached namespace_alias_uri_codes as l_namespace_alias_uri_codes then
  103. Result := -1
  104. -- if there are several matches, the last in stylesheet takes priority;
  105. -- but the list is in reverse stylesheet order
  106. from
  107. l_index := 1
  108. until
  109. l_index > l_namespace_alias_uri_codes.count
  110. loop
  111. if a_uri_code = l_namespace_alias_uri_codes.item (l_index) then
  112. check attached namespace_alias_namespace_codes as l_namespace_alias_namespace_codes then
  113. Result := l_namespace_alias_namespace_codes.item (l_index)
  114. end
  115. l_index := l_namespace_alias_uri_codes.count + 1
  116. else
  117. l_index := l_index + 1
  118. end
  119. variant
  120. l_namespace_alias_uri_codes.count + 1 - l_index
  121. end
  122. end
  123. end
  124. find_collator (a_collator_uri: STRING): ST_COLLATOR
  125. -- Does `a_collator_uri' represent a defined collator? -- TODO rename to found_collator
  126. require
  127. collator_uri_not_void: a_collator_uri /= Void
  128. collator_is_defined: is_collator_defined (a_collator_uri)
  129. do
  130. Result := collation_map.item (a_collator_uri)
  131. ensure
  132. collator_not_void: Result /= Void
  133. end
  134. module_number (a_system_id: STRING): INTEGER
  135. -- Module number of `a_system_id'
  136. require
  137. system_id_not_void: a_system_id /= Void
  138. module_registered: is_module_registered (a_system_id)
  139. do
  140. Result := stylesheet_module_map.item (a_system_id)
  141. end
  142. gathered_output_properties (a_fingerprint: INTEGER): XM_XSLT_OUTPUT_PROPERTIES
  143. -- Accumulated output properties for format named by `a_fingerprint' (-1 = unnamed format)
  144. require
  145. nearly_positive_fingerprint: a_fingerprint > -2
  146. post_validated: post_validated
  147. output_properties_defined_somewhere: a_fingerprint > -1 implies is_named_output_property_defined (a_fingerprint)
  148. local
  149. l_found: BOOLEAN
  150. l_cursor: DS_BILINKED_LIST_CURSOR [XM_XSLT_STYLE_ELEMENT]
  151. l_message: STRING
  152. l_error: XM_XPATH_ERROR_VALUE
  153. do
  154. if a_fingerprint = -1 then
  155. l_found := True
  156. end
  157. create Result.make (Platform.Minimum_integer)
  158. -- Note that we process backwards, so as to find highest
  159. -- import precedence definitions first.
  160. -- This makes error reporting easier.
  161. from
  162. check attached top_level_elements as l_top_level_elements then
  163. l_cursor := l_top_level_elements.new_cursor
  164. end
  165. l_cursor.finish
  166. until
  167. Result.is_error or l_cursor.before
  168. loop
  169. if l_cursor.item.is_output and then l_cursor.item.as_output.output_fingerprint = a_fingerprint then
  170. l_found := True
  171. l_cursor.item.as_output.gather_output_properties (Result)
  172. end
  173. l_cursor.back
  174. variant
  175. l_cursor.index
  176. end
  177. if Result.is_error then
  178. if Result.is_duplication_error then
  179. check attached Result.duplicate_attribute_name as l_duplicate_attribute_name then
  180. l_message := STRING_.concat ("Two xsl:output statements specify conflicting values for attribute '", l_duplicate_attribute_name)
  181. end
  182. if a_fingerprint = -1 then
  183. l_message := STRING_.appended_string (l_message, "', in the unnamed output definition.")
  184. else
  185. l_message := STRING_.appended_string (l_message, "', in output definition named ")
  186. l_message := STRING_.appended_string (l_message, shared_name_pool.display_name_from_name_code (a_fingerprint))
  187. end
  188. create l_error.make_from_string (l_message, Xpath_errors_uri, "XTSE1560", Static_error)
  189. else
  190. check attached Result.error_message as l_error_message then
  191. create l_error.make_from_string (l_error_message, Gexslt_eiffel_type_uri, "OUTPUT+PROPERTY", Static_error)
  192. end
  193. end
  194. report_compile_error (l_error)
  195. elseif not l_found and then a_fingerprint > -1 then
  196. -- Result := Void -- triggers an exception
  197. check False then end
  198. end
  199. ensure
  200. output_properties_not_void: Result /= Void
  201. end
  202. character_map (a_fingerprint: INTEGER): detachable XM_XSLT_CHARACTER_MAP
  203. -- Character map named by `a_fingerprint'
  204. require
  205. positive_fingerprint: a_fingerprint >= 0
  206. local
  207. a_cursor: DS_BILINKED_LIST_CURSOR [XM_XSLT_STYLE_ELEMENT]
  208. do
  209. -- Note that we process backwards, so as to find highest
  210. -- import precedence definitions first.
  211. -- This makes error reporting easier.
  212. from
  213. check attached top_level_elements as l_top_level_elements then
  214. a_cursor := l_top_level_elements.new_cursor
  215. end
  216. a_cursor.finish
  217. until
  218. a_cursor.before
  219. loop
  220. if a_cursor.item.is_character_map and then a_cursor.item.as_character_map.character_map_fingerprint = a_fingerprint then
  221. Result := a_cursor.item.as_character_map
  222. a_cursor.go_before
  223. else
  224. a_cursor.back
  225. end
  226. variant
  227. a_cursor.index
  228. end
  229. end
  230. system_id_from_module_number (a_module_number: INTEGER): STRING
  231. -- System identifier
  232. do
  233. Result := module_list.item (a_module_number)
  234. end
  235. input_type_annotations: INTEGER
  236. -- Value of input-type-annotations attribute coded on `Current' and it's imports/inclusions
  237. Strip_annotations: INTEGER = 1
  238. Preserve_annotations: INTEGER = 2
  239. -- Bit-values for `input_type_annotations'
  240. feature -- Status report
  241. any_compile_errors: BOOLEAN
  242. -- Have any compile errors been reported?
  243. was_included: BOOLEAN
  244. -- Was `Current' pulled in by xsl:include?
  245. indices_built: BOOLEAN
  246. -- Have the indices been built?
  247. is_all_explaining: BOOLEAN
  248. -- Should compiled instructions explain themsleves?
  249. -- (Only significant for the principal stylesheet)
  250. needs_dynamic_output_properties: BOOLEAN
  251. -- Does `Current' require dynamic output formats?
  252. is_named_output_property_defined (a_fingerprint: INTEGER): BOOLEAN
  253. -- Is there an xsl:output statement for `a_fingerprint'?
  254. require
  255. nearly_positive_fingerprint: a_fingerprint > -2
  256. post_validated: post_validated
  257. local
  258. a_cursor: DS_BILINKED_LIST_CURSOR [XM_XSLT_STYLE_ELEMENT]
  259. do
  260. from
  261. check attached top_level_elements as l_top_level_elements then
  262. a_cursor := l_top_level_elements.new_cursor
  263. end
  264. a_cursor.finish
  265. until
  266. Result or else a_cursor.before
  267. loop
  268. if a_cursor.item.is_output and then a_cursor.item.as_output.output_fingerprint = a_fingerprint then
  269. Result := True
  270. end
  271. a_cursor.back
  272. variant
  273. a_cursor.index
  274. end
  275. end
  276. is_module_registered (a_system_id: STRING): BOOLEAN
  277. -- Is `a_system_id' registered as a module?
  278. require
  279. system_id_not_void: a_system_id /= Void
  280. do
  281. Result := stylesheet_module_map.has (a_system_id)
  282. end
  283. has_namespace_aliases: BOOLEAN
  284. -- Have any namespace aliases been declared?
  285. do
  286. Result := namespace_alias_uri_codes /= Void
  287. end
  288. is_alias_result_namespace (a_uri_code: INTEGER): BOOLEAN
  289. -- Is `a_uri_code' included in the result-prefix of a namespace-alias?
  290. local
  291. an_index: INTEGER
  292. do
  293. if attached namespace_alias_namespace_codes as l_namespace_alias_namespace_codes then
  294. from
  295. an_index := 1
  296. until
  297. an_index > l_namespace_alias_namespace_codes.count
  298. loop
  299. if a_uri_code = uri_code_from_namespace_code (l_namespace_alias_namespace_codes.item (an_index)) then
  300. Result := True
  301. an_index := l_namespace_alias_namespace_codes.count + 1
  302. else
  303. an_index := an_index + 1
  304. end
  305. variant
  306. l_namespace_alias_namespace_codes.count + 1 - an_index
  307. end
  308. end
  309. end
  310. is_collator_defined (a_collator_uri: STRING): BOOLEAN
  311. -- Does `a_collator_uri' represent a defined collator?
  312. require
  313. collator_uri_not_void: a_collator_uri /= Void
  314. do
  315. Result := collation_map.has (a_collator_uri)
  316. end
  317. strips_whitespace: BOOLEAN
  318. -- Does this stysheet do any whitespace stripping?
  319. local
  320. a_cursor: DS_BILINKED_LIST_CURSOR [XM_XSLT_STYLE_ELEMENT]
  321. do
  322. from
  323. check attached top_level_elements as l_top_level_elements then
  324. a_cursor := l_top_level_elements.new_cursor
  325. end
  326. a_cursor.start
  327. until
  328. a_cursor.after
  329. loop
  330. if a_cursor.item.fingerprint = Xslt_strip_space_type_code then
  331. Result := True
  332. a_cursor.go_after
  333. else
  334. a_cursor.forth
  335. end
  336. end
  337. end
  338. executable: XM_XSLT_EXECUTABLE
  339. -- Result of successful call to `compile_stylesheet'
  340. feature -- Status setting
  341. force_explaining
  342. -- Force gexslt:explain="all" on.
  343. do
  344. is_all_explaining := True
  345. ensure
  346. explaining_forced_on: is_all_explaining
  347. end
  348. set_compile_errors
  349. -- Mark this stylesheet as having compile errors
  350. do
  351. any_compile_errors := True
  352. ensure
  353. compile_errors_reported: any_compile_errors = True
  354. end
  355. set_needs_dynamic_output_properties
  356. -- Set dynamic output formats needed.
  357. do
  358. needs_dynamic_output_properties := True
  359. ensure
  360. dynamic_output_formats_needed: needs_dynamic_output_properties
  361. end
  362. feature -- Element change
  363. set_import_precedence (a_precedence: INTEGER)
  364. -- Set import precedence for top-level elements
  365. do
  366. import_precedence := a_precedence
  367. ensure
  368. import_precedence_set: import_precedence = a_precedence
  369. end
  370. set_minimum_import_precedence (a_precedence: INTEGER)
  371. -- Set minimum import precedence for top-level elements
  372. do
  373. minimum_import_precedence := a_precedence
  374. ensure
  375. minimum_import_precedence_set: minimum_import_precedence = a_precedence
  376. end
  377. set_importer (an_importer: like Current)
  378. -- Set stylesheet that imported or included `Current'
  379. require
  380. importer_not_void: an_importer /= Void
  381. do
  382. importer := an_importer
  383. ensure
  384. importer_set: importer = an_importer
  385. end
  386. set_was_included
  387. -- Mark `Current' as pulled in by xsl:include.
  388. do
  389. was_included := True
  390. ensure
  391. included: was_included = True
  392. end
  393. ensure_stripper_rules
  394. -- Ensure strip/preserve whitespace rules exist
  395. do
  396. if stripper_rules = Void then
  397. create stripper_rules.make_stripper
  398. end
  399. ensure
  400. stripper_rules_not_void: stripper_rules /= Void
  401. end
  402. register_module (a_system_id: STRING)
  403. -- Register `a_system_id' as a stylesheet module.
  404. require
  405. system_id_not_void: a_system_id /= Void
  406. module_not_registered: not is_module_registered (a_system_id)
  407. do
  408. if stylesheet_module_map.is_full then
  409. stylesheet_module_map.resize (2 * stylesheet_module_map.count)
  410. end
  411. stylesheet_module_map.put (stylesheet_module_map.count + 1, a_system_id)
  412. module_list.force_last (a_system_id)
  413. ensure
  414. module_registered: is_module_registered (a_system_id)
  415. end
  416. declare_collation (a_collator: ST_COLLATOR; a_name: STRING)
  417. -- Declare a collation.
  418. require
  419. collation_name_not_void: a_name /= Void -- TODO and then is a URI
  420. collator_not_void: a_collator /= Void
  421. do
  422. collation_map.search (a_name)
  423. if collation_map.found then
  424. collation_map.replace_found_item (a_collator)
  425. else
  426. collation_map.force_new (a_collator, a_name)
  427. end
  428. ensure
  429. collator_declared: is_collator_defined (a_name)
  430. end
  431. allocate_global_slot (a_variable_name: STRING)
  432. -- Allocate a slot for a global variable or parameter.
  433. require
  434. variable_name_not_empty: a_variable_name /= Void and then a_variable_name.count > 0
  435. do
  436. executable.global_slot_manager.allocate_slot_number (a_variable_name)
  437. ensure
  438. global_slot_allocated: executable.global_slot_manager.number_of_variables = old executable.global_slot_manager.number_of_variables + 1
  439. end
  440. allocate_pattern_slots (a_variable_count: INTEGER)
  441. -- Ensure there is enough space for local variables or parameters within match patterns in any template.
  442. require
  443. positive_variable_count: a_variable_count >= 0
  444. do
  445. if a_variable_count > largest_pattern_stack_frame then
  446. largest_pattern_stack_frame := a_variable_count
  447. end
  448. ensure
  449. no_smaller: largest_pattern_stack_frame >= old largest_pattern_stack_frame
  450. end
  451. merge_input_type_annotations (an_annotation_setting: INTEGER)
  452. -- Merge `input_type_annotations' with `an_annotation_setting'.
  453. require
  454. valid_annotation: an_annotation_setting <= Preserve_annotations and then an_annotation_setting >= 0
  455. local
  456. an_error: XM_XPATH_ERROR_VALUE
  457. do
  458. if an_annotation_setting /= 0 then
  459. if input_type_annotations = 0 then
  460. input_type_annotations := an_annotation_setting
  461. elseif input_type_annotations = an_annotation_setting then
  462. -- nothing to do
  463. else
  464. create an_error.make_from_string ("One stylesheet module specifies input-type-annotations='strip', another specifies input-type-annotations='preserve'",
  465. Xpath_errors_uri, "XTSE0265", Static_error)
  466. report_compile_error (an_error)
  467. end
  468. end
  469. end
  470. prepare_attributes
  471. -- Set the attribute list for the element.
  472. local
  473. l_cursor: DS_ARRAYED_LIST_CURSOR [INTEGER]
  474. l_name_code: INTEGER
  475. l_expanded_name: STRING
  476. l_input_type_annotations_attribute: detachable STRING
  477. l_error: XM_XPATH_ERROR_VALUE
  478. l_version_found: BOOLEAN
  479. do
  480. if attached attribute_collection as l_attribute_collection then
  481. from
  482. l_cursor := l_attribute_collection.name_code_cursor
  483. l_cursor.start
  484. until
  485. l_cursor.after or any_compile_errors
  486. loop
  487. l_name_code := l_cursor.item
  488. l_expanded_name := shared_name_pool.expanded_name_from_name_code (l_name_code)
  489. if STRING_.same_string (l_expanded_name, Version_attribute) then
  490. l_version_found := True
  491. elseif STRING_.same_string (l_expanded_name, Extension_element_prefixes_attribute) then
  492. -- do nothing
  493. elseif STRING_.same_string (l_expanded_name, Exclude_result_prefixes_attribute) then
  494. -- do nothing
  495. elseif STRING_.same_string (l_expanded_name, Id_attribute) then
  496. -- do nothing
  497. elseif STRING_.same_string (l_expanded_name, Default_validation_attribute) then
  498. default_validation := validation_code (attribute_value_by_index (l_cursor.index))
  499. if default_validation /= Validation_preserve and then default_validation /= Validation_strip then
  500. create l_error.make_from_string ("Invalid value for default-validation attribute. Permitted values are (preserve, strip)", Xpath_errors_uri, "XTSE0020", Static_error)
  501. report_compile_error (l_error)
  502. elseif conformance.basic_xslt_processor and then default_validation /= Validation_strip then
  503. create l_error.make_from_string ("Invalid value for default-validation attribute. Only 'strip' is permitted for a basic XSLT processor)", Xpath_errors_uri, "XTSE1660", Static_error)
  504. report_compile_error (l_error)
  505. end
  506. elseif STRING_.same_string (l_expanded_name, Input_type_annotations_attribute) then
  507. l_input_type_annotations_attribute := attribute_value_by_index (l_cursor.index)
  508. elseif STRING_.same_string (l_expanded_name, Gexslt_explain_attribute) then
  509. is_all_explaining := STRING_.same_string (attribute_value_by_index (l_cursor.index), "all")
  510. else
  511. check_unknown_attribute (l_name_code)
  512. end
  513. l_cursor.forth
  514. end
  515. end
  516. if version = Void or not l_version_found then
  517. report_absence ("version")
  518. end
  519. if l_input_type_annotations_attribute /= Void then
  520. if STRING_.same_string (l_input_type_annotations_attribute, "strip") then
  521. input_type_annotations := Strip_annotations
  522. elseif STRING_.same_string (l_input_type_annotations_attribute, "preserve") then
  523. input_type_annotations := Preserve_annotations
  524. elseif STRING_.same_string (l_input_type_annotations_attribute, "unspecified") then
  525. -- nothing to do
  526. else
  527. create l_error.make_from_string ("Invalid value for input-type-annotations attribute. Permitted values are (strip, preserve, unspecified)",
  528. Xpath_errors_uri, "XTSE0020", Static_error)
  529. report_compile_error (l_error)
  530. end
  531. end
  532. attributes_prepared := True
  533. end
  534. set_stylesheet_compiler (a_stylesheet_compiler: like stylesheet_compiler; a_configuration: XM_XSLT_CONFIGURATION)
  535. -- Set `stylesheet_compiler'.
  536. require
  537. stylesheet_compiler_not_void: a_stylesheet_compiler /= Void
  538. configuration_not_void: a_configuration /= Void
  539. local
  540. a_function_library: XM_XPATH_FUNCTION_LIBRARY
  541. a_cursor: DS_ARRAYED_LIST_CURSOR [XM_XPATH_FUNCTION_LIBRARY]
  542. do
  543. create function_library.make
  544. executable.set_function_library (function_library)
  545. stylesheet_compiler := a_stylesheet_compiler
  546. create {XM_XSLT_SYSTEM_FUNCTION_LIBRARY} a_function_library.make
  547. function_library.add_function_library (a_function_library)
  548. create {XM_XPATH_CONSTRUCTOR_FUNCTION_LIBRARY} a_function_library.make
  549. function_library.add_function_library (a_function_library)
  550. create {XM_XSLT_STYLESHEET_FUNCTION_LIBRARY} a_function_library.make (Current, True)
  551. function_library.add_function_library (a_function_library)
  552. from
  553. a_cursor := a_configuration.extension_functions.new_cursor; a_cursor.start
  554. until
  555. a_cursor.after
  556. loop
  557. function_library.add_function_library (a_cursor.item)
  558. a_cursor.forth
  559. variant
  560. a_configuration.extension_functions.count + 1 - a_cursor.index
  561. end
  562. create {XM_XSLT_STYLESHEET_FUNCTION_LIBRARY} a_function_library.make (Current, False)
  563. function_library.add_function_library (a_function_library)
  564. ensure
  565. stylesheet_compiler_set: stylesheet_compiler = a_stylesheet_compiler
  566. function_library_not_void: function_library /= Void
  567. end
  568. preprocess
  569. -- Perform all the processing possible before the source document is available.
  570. -- Done once per stylesheet, so the stylesheet can be reused for multiple source documents.
  571. require
  572. indices_not_built: not indices_built
  573. no_compile_errors_yet: not any_compile_errors
  574. local
  575. a_cursor: DS_BILINKED_LIST_CURSOR [XM_XSLT_STYLE_ELEMENT]
  576. a_style_element: XM_XSLT_STYLE_ELEMENT
  577. do
  578. -- Process any xsl:include and xsl:import elements.
  579. splice_includes
  580. -- Build indices for selected top-level elements.
  581. if not any_compile_errors then
  582. build_indices
  583. end
  584. -- Process the attributes of every node in the tree
  585. if not any_compile_errors then
  586. process_all_attributes
  587. end
  588. -- Collect any namespace aliases.
  589. if not any_compile_errors then
  590. collect_namespace_aliases
  591. end
  592. -- Fix up references from XPath expressions to variables and functions, for static typing
  593. if not any_compile_errors then
  594. check attached top_level_elements as l_top_level_elements then
  595. from
  596. a_cursor := l_top_level_elements.new_cursor
  597. a_cursor.start
  598. until
  599. a_cursor.after
  600. loop
  601. a_style_element := a_cursor.item
  602. a_style_element.fixup_references
  603. a_cursor.forth
  604. variant
  605. l_top_level_elements.count + 1 - a_cursor.index
  606. end
  607. end
  608. end
  609. -- Validate the whole logical style sheet (i.e. with included and imported sheets)
  610. if not any_compile_errors then
  611. validate
  612. check attached top_level_elements as l_top_level_elements then
  613. from
  614. a_cursor := l_top_level_elements.new_cursor
  615. a_cursor.start
  616. until
  617. any_compile_errors or else a_cursor.after
  618. loop
  619. a_style_element := a_cursor.item
  620. a_style_element.validate_subtree
  621. a_cursor.forth
  622. variant
  623. l_top_level_elements.count + 1 - a_cursor.index
  624. end
  625. end
  626. post_validated := True
  627. end
  628. ensure
  629. indices_built: not any_compile_errors implies indices_built
  630. end
  631. splice_includes
  632. -- Process xsl:include and xsl:import elements.
  633. require
  634. includes_not_processed: not includes_processed
  635. local
  636. l_previous_style_element: XM_XSLT_STYLE_ELEMENT
  637. l_child_iterator: XM_XPATH_SEQUENCE_ITERATOR [XM_XPATH_NODE]
  638. l_child: XM_XPATH_NODE
  639. l_module: XM_XSLT_MODULE
  640. l_found_non_import: BOOLEAN
  641. l_included_stylesheet: detachable XM_XSLT_STYLESHEET
  642. l_error: XM_XPATH_ERROR_VALUE
  643. l_top_level_elements: like top_level_elements
  644. do
  645. create l_top_level_elements.make
  646. top_level_elements := l_top_level_elements
  647. minimum_import_precedence := import_precedence
  648. l_previous_style_element := Current
  649. register_module (system_id)
  650. from
  651. l_child_iterator := new_axis_iterator (Child_axis)
  652. l_child_iterator.start
  653. until
  654. any_compile_errors or l_child_iterator.after
  655. loop
  656. l_child := l_child_iterator.item
  657. if l_child.node_type = Text_node then
  658. -- In an embedded stylesheet, white space nodes may still be there
  659. if not is_all_whitespace (l_child.string_value) then
  660. create l_error.make_from_string ("No character data is allowed between top-level elements", Xpath_errors_uri, "XTSE0120", Static_error)
  661. l_previous_style_element.report_compile_error (l_error)
  662. end
  663. else
  664. if attached {XM_XSLT_DATA_ELEMENT} l_child then
  665. l_found_non_import := True
  666. else
  667. check
  668. child_is_style_element: attached {XM_XSLT_STYLE_ELEMENT} l_child as l_previous_style_element_2
  669. -- Only data elements, style elements and white-space text nodes may be present
  670. then
  671. l_previous_style_element := l_previous_style_element_2
  672. if l_previous_style_element.is_module then
  673. l_module := l_previous_style_element.as_module
  674. l_module.create_static_context
  675. l_module.process_attributes
  676. if l_module.is_import then
  677. if l_found_non_import then
  678. create l_error.make_from_string ("xsl:import elements must come first", Xpath_errors_uri, "XTSE0200", Static_error)
  679. l_module.report_compile_error (l_error)
  680. end
  681. else
  682. l_found_non_import := True
  683. end
  684. if not any_compile_errors then
  685. l_included_stylesheet := l_module.included_stylesheet (Current, import_precedence)
  686. if l_included_stylesheet /= Void then
  687. if l_included_stylesheet.any_compile_errors then
  688. set_compile_errors
  689. else
  690. -- After processing the imported stylesheet and any others it brought in,
  691. -- adjust the import precedence of this stylesheet if necessary.
  692. if l_module.is_import then
  693. import_precedence := l_included_stylesheet.precedence + 1
  694. else
  695. import_precedence := l_included_stylesheet.precedence
  696. l_included_stylesheet.set_minimum_import_precedence (minimum_import_precedence)
  697. l_included_stylesheet.set_was_included
  698. end
  699. copy_top_level_elements (l_included_stylesheet)
  700. end
  701. end
  702. end
  703. else
  704. l_found_non_import := True
  705. l_top_level_elements.force_last (l_previous_style_element)
  706. end
  707. end
  708. end
  709. end
  710. l_child_iterator.forth
  711. end
  712. ensure
  713. top_level_elements_created: top_level_elements /= Void
  714. end
  715. process_all_attributes
  716. -- Process the attributes of every node in the stylesheet.
  717. local
  718. a_cursor: DS_BILINKED_LIST_CURSOR [XM_XSLT_STYLE_ELEMENT]
  719. a_style_element: XM_XSLT_STYLE_ELEMENT
  720. do
  721. create static_context.make (Current, configuration)
  722. process_attributes
  723. if attached top_level_elements as l_top_level_elements then
  724. from
  725. a_cursor := l_top_level_elements.new_cursor
  726. a_cursor.start
  727. until
  728. a_cursor.after
  729. loop
  730. a_style_element := a_cursor.item
  731. a_style_element.process_all_attributes
  732. a_cursor.forth
  733. variant
  734. l_top_level_elements.count + 1 - a_cursor.index
  735. end
  736. else
  737. -- then validation will fail later, and report the error
  738. end
  739. includes_processed := True
  740. ensure then
  741. includes_processed: includes_processed
  742. end
  743. validate
  744. -- Check that the stylesheet element is valid.
  745. -- This is called once for each element, after the entire tree has been built.
  746. -- As well as validation, it can perform first-time initialisation.
  747. local
  748. l_error: XM_XPATH_ERROR_VALUE
  749. do
  750. if attached validation_error as l_validation_error then
  751. report_compile_error (l_validation_error)
  752. elseif not attached parent as l_parent or else not l_parent.is_document then
  753. create l_error.make_from_string (STRING_.concat (node_name, " must be the outermost element"), Xpath_errors_uri, "XTSE0010", Static_error)
  754. report_compile_error (l_error)
  755. end
  756. validated := True
  757. end
  758. compile (an_executable: XM_XSLT_EXECUTABLE)
  759. -- Compile `Current' to an excutable instruction.
  760. do
  761. last_generated_expression := Void -- `compile_stylesheet' is used instead
  762. end
  763. compile_stylesheet (a_configuration: XM_XSLT_CONFIGURATION)
  764. -- Compile `Current' to an excutable instruction.
  765. require
  766. configuration_not_void: a_configuration /= Void
  767. no_compile_errors_so_far: not any_compile_errors
  768. post_validate: post_validated
  769. local
  770. a_cursor: DS_BILINKED_LIST_CURSOR [XM_XSLT_STYLE_ELEMENT]
  771. another_cursor: DS_HASH_TABLE_CURSOR [XM_XSLT_TEMPLATE, INTEGER]
  772. a_third_cursor: DS_ARRAYED_LIST_CURSOR [XM_XPATH_FUNCTION_LIBRARY]
  773. a_compiled_templates_index: DS_HASH_TABLE [XM_XSLT_COMPILED_TEMPLATE, INTEGER]
  774. a_property_set: XM_XSLT_OUTPUT_PROPERTIES
  775. a_message, a_system_id: STRING
  776. a_character_map_index: DS_HASH_TABLE [DS_HASH_TABLE [STRING, INTEGER], INTEGER]
  777. a_character_code_map: DS_HASH_TABLE [STRING, INTEGER]
  778. a_fingerprint, a_level: INTEGER
  779. a_function_library: XM_XPATH_FUNCTION_LIBRARY
  780. an_error: XM_XPATH_ERROR_VALUE
  781. explaining: BOOLEAN
  782. l_non_overriding_runtime_library: like non_overriding_runtime_library
  783. l_overriding_runtime_library: like overriding_runtime_library
  784. do
  785. -- Call compile method for each top-level object in the stylesheet
  786. explaining := is_all_explaining
  787. check attached top_level_elements as l_top_level_elements then
  788. from
  789. a_cursor := l_top_level_elements.new_cursor
  790. a_cursor.start
  791. until
  792. any_compile_errors or else a_cursor.after
  793. loop
  794. a_system_id := a_cursor.item.system_id
  795. if not is_module_registered (a_system_id) then register_module (a_system_id) end
  796. a_cursor.item.compile (executable)
  797. if attached a_cursor.item.last_generated_expression as l_last_generated_expression and then l_last_generated_expression.is_computed_expression then
  798. l_last_generated_expression.as_computed_expression.set_source_location (module_number (a_system_id), a_cursor.item.line_number)
  799. end
  800. if explaining and then attached a_cursor.item.last_generated_expression as l_last_generated_expression then
  801. if a_cursor.item.is_xslt_function then
  802. a_level := 2
  803. std.error.put_string ("xsl:function name=")
  804. check attached a_cursor.item.as_xslt_function.function_name as l_function_name then
  805. std.error.put_string (l_function_name)
  806. end
  807. if a_cursor.item.as_xslt_function.arity > 0 then
  808. std.error.put_string (" taking ")
  809. std.error.put_string (a_cursor.item.as_xslt_function.arity.out)
  810. std.error.put_string (" parameter")
  811. if a_cursor.item.as_xslt_function.arity > 1 then
  812. std.error.put_string ("s")
  813. end
  814. end
  815. std.error.put_string ("%N")
  816. else
  817. a_level := 1
  818. end
  819. l_last_generated_expression.display (a_level)
  820. end
  821. a_cursor.forth
  822. variant
  823. l_top_level_elements.count + 1 - a_cursor.index
  824. end
  825. end
  826. if not any_compile_errors then
  827. decimal_format_manager.fixup_default_default
  828. executable.set_pattern_slot_space (largest_pattern_stack_frame)
  829. a_property_set := gathered_output_properties (-1)
  830. if a_property_set.is_error then
  831. if a_property_set.is_duplication_error then
  832. check attached a_property_set.duplicate_attribute_name as l_duplicate_attribute_name then
  833. a_message := STRING_.concat ("Two xsl:output statements specify conflicting values for attribute '", l_duplicate_attribute_name)
  834. end
  835. a_message := STRING_.appended_string (a_message, "', in the unnamed output definition.")
  836. create an_error.make_from_string (a_message, Xpath_errors_uri, "XTSE1560", Static_error)
  837. else
  838. check is_error: attached a_property_set.error_message as l_error_message then
  839. create an_error.make_from_string (l_error_message, Gexslt_eiffel_type_uri, "OUTPUT+PROPERTY", Static_error)
  840. end
  841. end
  842. report_compile_error (an_error)
  843. else
  844. executable.set_default_output_properties (a_property_set)
  845. save_output_definitions
  846. create a_compiled_templates_index.make_map (named_templates_index.count)
  847. from
  848. another_cursor := named_templates_index.new_cursor; another_cursor.start
  849. until
  850. another_cursor.after
  851. loop
  852. check attached another_cursor.item.compiled_template as l_compiled_template then
  853. a_compiled_templates_index.put (l_compiled_template, another_cursor.key)
  854. end
  855. another_cursor.forth
  856. end
  857. executable.set_named_template_table (a_compiled_templates_index)
  858. end
  859. executable.set_strips_input_type_annotations (input_type_annotations = Strip_annotations)
  860. -- Build the index of named character maps.
  861. a_character_map_index := executable.character_map_index
  862. check attached top_level_elements as l_top_level_elements then
  863. from
  864. a_cursor := l_top_level_elements.new_cursor
  865. a_cursor.start
  866. until
  867. a_cursor.after
  868. loop
  869. if a_cursor.item.is_character_map and then not a_cursor.item.as_character_map.is_redundant then
  870. a_fingerprint := a_cursor.item.as_character_map.character_map_fingerprint
  871. create a_character_code_map.make_with_equality_testers (10, string_equality_tester, Void)
  872. a_cursor.item.as_character_map.assemble (a_character_code_map)
  873. a_character_map_index.force (a_character_code_map, a_fingerprint)
  874. end
  875. a_cursor.forth
  876. variant
  877. l_top_level_elements.count + 1 - a_cursor.index
  878. end
  879. end
  880. -- Build the run-time function library
  881. create function_library.make
  882. create {XM_XSLT_SYSTEM_FUNCTION_LIBRARY} a_function_library.make
  883. function_library.add_function_library (a_function_library)
  884. create {XM_XPATH_CONSTRUCTOR_FUNCTION_LIBRARY} a_function_library.make
  885. function_library.add_function_library (a_function_library)
  886. create l_overriding_runtime_library.make
  887. overriding_runtime_library := l_overriding_runtime_library
  888. function_library.add_function_library (l_overriding_runtime_library)
  889. from
  890. a_third_cursor := a_configuration.extension_functions.new_cursor; a_third_cursor.start
  891. until
  892. a_third_cursor.after
  893. loop
  894. function_library.add_function_library (a_third_cursor.item)
  895. a_third_cursor.forth
  896. variant
  897. a_configuration.extension_functions.count + 1 - a_third_cursor.index
  898. end
  899. create l_non_overriding_runtime_library.make
  900. non_overriding_runtime_library := l_non_overriding_runtime_library
  901. function_library.add_function_library (l_non_overriding_runtime_library)
  902. check attached top_level_elements as l_top_level_elements then
  903. from
  904. a_cursor := l_top_level_elements.new_cursor; a_cursor.start
  905. until
  906. a_cursor.after
  907. loop
  908. if a_cursor.item.is_xslt_function then
  909. if a_cursor.item.as_xslt_function.is_overriding then
  910. l_overriding_runtime_library.add_function (a_cursor.item.as_xslt_function)
  911. else
  912. l_non_overriding_runtime_library.add_function (a_cursor.item.as_xslt_function)
  913. end
  914. end
  915. a_cursor.forth
  916. variant
  917. l_top_level_elements.count + 1 - a_cursor.index
  918. end
  919. end
  920. executable.set_function_library (function_library)
  921. if attached stripper_rules as l_stripper_rules then
  922. executable.set_stripper_rules (l_stripper_rules)
  923. end
  924. end
  925. end
  926. feature {XM_XSLT_STYLE_ELEMENT} -- Local
  927. is_global_variable_declared (a_fingerprint: INTEGER): BOOLEAN
  928. -- Does `a_fingerprint' represent a global variable?
  929. do
  930. if principal_stylesheet = Current then
  931. Result := variables_index.has (a_fingerprint)
  932. else
  933. check
  934. is_global_variable_declared_called_for_non_principal_stylesheet: False
  935. end
  936. end
  937. end
  938. bind_global_variable (a_fingerprint: INTEGER; a_static_context: XM_XSLT_EXPRESSION_CONTEXT)
  939. -- Bind variable to it's declaration.
  940. require
  941. variable_declared: is_global_variable_declared (a_fingerprint)
  942. static_context_not_void: a_static_context /= Void
  943. do
  944. a_static_context.set_last_bound_variable (variables_index.item (a_fingerprint))
  945. ensure
  946. variable_bound: a_static_context.last_bound_variable /= Void
  947. end
  948. feature -- Conversion
  949. is_stylesheet: BOOLEAN
  950. -- Is `Current' an xsl:stylesheet or xsl:transform?
  951. do
  952. Result := True
  953. end
  954. feature {NONE} -- Implementation
  955. overriding_runtime_library: detachable XM_XSLT_RUNTIME_FUNCTION_LIBRARY
  956. -- Compiled xsl:functions with override="yes" (or omitted)
  957. non_overriding_runtime_library: detachable XM_XSLT_RUNTIME_FUNCTION_LIBRARY
  958. -- Compiled xsl:functions with override="no"
  959. named_templates_index: DS_HASH_TABLE [XM_XSLT_TEMPLATE, INTEGER]
  960. -- Index of named templates by `template_fingerprint'
  961. variables_index: DS_HASH_TABLE [XM_XSLT_VARIABLE_DECLARATION, INTEGER]
  962. -- Index of varaibles by `variable_fingerprint'
  963. -- These next three are only used at compile time
  964. namespace_alias_list: detachable DS_ARRAYED_LIST [XM_XSLT_NAMESPACE_ALIAS]
  965. -- List of namespace aliases
  966. namespace_alias_uri_codes: detachable ARRAY [INTEGER]
  967. -- URI codes for each namespace alias
  968. namespace_alias_namespace_codes: detachable ARRAY [INTEGER]
  969. -- Namespace codes for each namespace alias
  970. largest_pattern_stack_frame: INTEGER
  971. -- Maximum number of local variables within match attribute of any template
  972. stylesheet_module_map: DS_HASH_TABLE [INTEGER, STRING]
  973. -- Map of SYSTEM IDs to module numbers
  974. module_list: DS_ARRAYED_LIST [STRING]
  975. -- List of stylesheet modules indexed by module number
  976. build_indices
  977. -- Build indices from selected top-level declarations.
  978. require
  979. indices_not_built: not indices_built
  980. no_compile_errors_yet: not any_compile_errors
  981. local
  982. a_cursor: DS_BILINKED_LIST_CURSOR [XM_XSLT_STYLE_ELEMENT]
  983. do
  984. from
  985. check attached top_level_elements as l_top_level_elements then
  986. a_cursor := l_top_level_elements.new_cursor
  987. end
  988. a_cursor.finish
  989. until
  990. a_cursor.before
  991. loop
  992. if a_cursor.item.is_template then
  993. index_named_template (a_cursor.item.as_template)
  994. elseif a_cursor.item.is_xslt_variable_declaration then
  995. index_variable_declaration (a_cursor.item.as_xslt_variable_declaration)
  996. elseif a_cursor.item.is_namespace_alias then
  997. check attached namespace_alias_list as l_namespace_alias_list then
  998. if not l_namespace_alias_list.extendible (1) then
  999. l_namespace_alias_list.resize (2 * l_namespace_alias_list.count)
  1000. end
  1001. l_namespace_alias_list.put_last (a_cursor.item.as_namespace_alias)
  1002. end
  1003. elseif a_cursor.item.is_decimal_format then
  1004. a_cursor.item.as_decimal_format.register
  1005. end
  1006. a_cursor.back
  1007. end
  1008. indices_built := True
  1009. ensure
  1010. indices_built: indices_built
  1011. end
  1012. index_named_template (a_template: XM_XSLT_TEMPLATE)
  1013. -- Conditionally add an index entry for `a_template'.
  1014. require
  1015. indices_not_built: not indices_built
  1016. template_not_void: a_template /= Void
  1017. local
  1018. l_fingerprint: INTEGER
  1019. l_template: XM_XSLT_TEMPLATE
  1020. l_message: STRING
  1021. do
  1022. a_template.ensure_template_fingerprint
  1023. if not any_compile_errors then
  1024. l_fingerprint := a_template.template_fingerprint
  1025. if l_fingerprint /= -1 then
  1026. -- Named template
  1027. named_templates_index.search (l_fingerprint)
  1028. if named_templates_index.found then
  1029. -- Check the precedence.
  1030. l_template := named_templates_index.found_item
  1031. if a_template.precedence = l_template.precedence then
  1032. l_message := STRING_.concat ("Duplicate named template (see line ", l_template.line_number.out)
  1033. l_message := STRING_.appended_string (l_message, " of ")
  1034. l_message := STRING_.appended_string (l_message, l_template.system_id)
  1035. l_message := STRING_.appended_string (l_message, ")")
  1036. a_template.report_compile_error (create {XM_XPATH_ERROR_VALUE}.make_from_string (l_message, Xpath_errors_uri, "XTSE0660", Static_error))
  1037. elseif a_template.precedence < l_template.precedence then
  1038. a_template.set_redundant_named_template
  1039. else
  1040. -- This is not supposed to happen
  1041. l_template.set_redundant_named_template
  1042. named_templates_index.replace (a_template, l_fingerprint)
  1043. end
  1044. else
  1045. if named_templates_index.is_full then
  1046. named_templates_index.resize (2 * named_templates_index.count)
  1047. end
  1048. named_templates_index.put_new (a_template, l_fingerprint)
  1049. end
  1050. end
  1051. end
  1052. end
  1053. index_variable_declaration (a_variable_declaration: XM_XSLT_VARIABLE_DECLARATION)
  1054. -- Conditionally add an index entry for `a_variable_declaration'.
  1055. require
  1056. indices_not_built: not indices_built
  1057. variable_declaration_not_void: a_variable_declaration /= Void
  1058. local
  1059. a_fingerprint: INTEGER
  1060. another_variable: XM_XSLT_VARIABLE_DECLARATION
  1061. a_message: STRING
  1062. an_error: XM_XPATH_ERROR_VALUE
  1063. do
  1064. a_fingerprint := a_variable_declaration.variable_fingerprint
  1065. if a_fingerprint /= -1 then
  1066. -- See if there is already a global variable with this precedence
  1067. variables_index.search (a_fingerprint)
  1068. if variables_index.found then
  1069. -- Check the precedence
  1070. another_variable := variables_index.found_item
  1071. if another_variable.precedence = a_variable_declaration.precedence then
  1072. a_message := STRING_.appended_string ("Duplicate global variable declaration (see line ", another_variable.line_number.out)
  1073. a_message := STRING_.appended_string (a_message, " of ")
  1074. a_message := STRING_.appended_string (a_message, another_variable.system_id)
  1075. a_message := STRING_.appended_string (a_message, ")")
  1076. create an_error.make_from_string (a_message, Xpath_errors_uri, "XTSE0630", Static_error)
  1077. a_variable_declaration.report_compile_error (an_error)
  1078. elseif a_variable_declaration.precedence < another_variable.precedence then
  1079. a_variable_declaration.set_redundant_variable
  1080. else
  1081. -- This is not supposed to happen
  1082. check
  1083. redundant_variable_shouldnt_happen: False
  1084. end
  1085. another_variable.set_redundant_variable
  1086. variables_index.replace (a_variable_declaration, a_fingerprint)
  1087. end
  1088. else
  1089. if variables_index.is_full then
  1090. variables_index.resize (2 * variables_index.count)
  1091. end
  1092. variables_index.put_new (a_variable_declaration, a_fingerprint)
  1093. end
  1094. end
  1095. end
  1096. collect_namespace_aliases
  1097. -- Collect any namespace aliases.
  1098. require
  1099. indices_built: indices_built
  1100. namespaces_alias_list_not_void: namespace_alias_list /= Void
  1101. local
  1102. l_precedence_boundary, l_current_precedence, l_precedence, l_uri_code, l_namespace_code, l_index: INTEGER
  1103. l_alias: XM_XSLT_NAMESPACE_ALIAS
  1104. l_cursor: DS_ARRAYED_LIST_CURSOR [XM_XSLT_NAMESPACE_ALIAS]
  1105. l_error: XM_XPATH_ERROR_VALUE
  1106. i: INTEGER
  1107. l_namespace_alias_namespace_codes: like namespace_alias_namespace_codes
  1108. l_namespace_alias_uri_codes: like namespace_alias_uri_codes
  1109. do
  1110. check precondition_namespaces_alias_list_not_void: attached namespace_alias_list as l_namespace_alias_list then
  1111. if l_namespace_alias_list.count > 0 then
  1112. create l_namespace_alias_namespace_codes.make_filled (0, 1, l_namespace_alias_list.count)
  1113. namespace_alias_namespace_codes := l_namespace_alias_namespace_codes
  1114. create l_namespace_alias_uri_codes.make_filled (0, 1, l_namespace_alias_list.count)
  1115. namespace_alias_uri_codes := l_namespace_alias_uri_codes
  1116. from
  1117. i := 1
  1118. until
  1119. i > l_namespace_alias_list.count
  1120. loop
  1121. l_namespace_alias_namespace_codes.put (-1, i)
  1122. l_namespace_alias_uri_codes.put (-1, i)
  1123. i := i + 1
  1124. end
  1125. l_current_precedence := -1
  1126. -- Note that we are processing the list in reverse stylesheet order,
  1127. -- that is, highest precedence first (as `build_indices' proceeds in that order).
  1128. from
  1129. l_cursor := l_namespace_alias_list.new_cursor
  1130. l_cursor.start
  1131. until
  1132. l_cursor.after
  1133. loop
  1134. l_alias := l_cursor.item
  1135. l_uri_code := l_alias.stylesheet_uri_code
  1136. l_namespace_code := l_alias.result_namespace_code
  1137. l_precedence := l_alias.precedence
  1138. -- Check that there isn't a conflict with another xsl:namespace-alias
  1139. -- at the same precedence
  1140. if l_current_precedence /= l_precedence then
  1141. l_current_precedence := l_precedence
  1142. l_precedence_boundary := l_cursor.index
  1143. end
  1144. from
  1145. l_index := l_precedence_boundary
  1146. until
  1147. l_index > l_namespace_alias_list.count
  1148. loop
  1149. if l_uri_code = l_namespace_alias_uri_codes.item (l_index) then
  1150. if uri_code_from_namespace_code (l_namespace_code) /= uri_code_from_namespace_code (l_namespace_alias_namespace_codes.item (l_index)) then
  1151. create l_error.make_from_string ("Inconsistent namespace aliases", Xpath_errors_uri, "XTSE0810", Static_error)
  1152. l_alias.report_compile_error (l_error)
  1153. end
  1154. end
  1155. l_index := l_index + 1
  1156. variant
  1157. l_namespace_alias_list.count + 1 - l_index
  1158. end
  1159. l_namespace_alias_uri_codes.put (l_uri_code, l_cursor.index)
  1160. l_namespace_alias_namespace_codes.put (l_namespace_code, l_cursor.index)
  1161. l_cursor.forth
  1162. variant
  1163. l_namespace_alias_list.count + 1 - l_cursor.index
  1164. end
  1165. end
  1166. end
  1167. namespace_alias_list := Void -- Now it can be garbage-collected
  1168. ensure
  1169. namespaces_alias_list_void: namespace_alias_list = Void
  1170. end
  1171. copy_top_level_elements (an_included_stylesheet: XM_XSLT_STYLESHEET)
  1172. -- Copy the top-level elements of the included stylesheet into the top level of `Current'.
  1173. -- Normally we add these elements at the end, in order, but if the precedence
  1174. -- of an element is less than the precedence of the previous element, we promote it.
  1175. -- This implements the requirement in the spec that when xsl:include is used to
  1176. -- include a stylesheet, any xsl:import elements in the included document are moved
  1177. -- up in the including document to after any xsl:import elements in the including document.
  1178. require
  1179. included_stylesheet: an_included_stylesheet /= Void
  1180. local
  1181. a_top_level_list: DS_BILINKED_LIST [XM_XSLT_STYLE_ELEMENT]
  1182. a_cursor: DS_LINKED_LIST_CURSOR [XM_XSLT_STYLE_ELEMENT]
  1183. a_style_element: XM_XSLT_STYLE_ELEMENT
  1184. a_count: INTEGER
  1185. do
  1186. check
  1187. attached an_included_stylesheet.top_level_elements as l_included_stylesheet_top_level_elements
  1188. attached top_level_elements as l_top_level_elements
  1189. then
  1190. a_top_level_list := l_included_stylesheet_top_level_elements
  1191. from
  1192. a_cursor := a_top_level_list.new_cursor
  1193. a_cursor.start
  1194. until
  1195. a_cursor.after
  1196. loop
  1197. a_style_element := a_cursor.item
  1198. a_count := l_top_level_elements.count
  1199. if a_count = 0 or else a_style_element.precedence >= l_top_level_elements.item (a_count).precedence then
  1200. l_top_level_elements.force_last (a_style_element)
  1201. else
  1202. from
  1203. until
  1204. a_count = 0 or else a_style_element.precedence >= l_top_level_elements.item (a_count).precedence
  1205. loop
  1206. a_count := a_count - 1
  1207. variant
  1208. a_count
  1209. end
  1210. l_top_level_elements.force (a_style_element, a_count + 1)
  1211. end
  1212. a_cursor.forth
  1213. variant
  1214. a_top_level_list.count + 1 - a_cursor.index
  1215. end
  1216. end
  1217. end
  1218. save_output_definitions
  1219. -- Save output definitions in `executable.
  1220. require
  1221. executable_not_void: executable /= Void
  1222. local
  1223. a_set: DS_HASH_SET [INTEGER]
  1224. a_cursor: DS_BILINKED_LIST_CURSOR [XM_XSLT_STYLE_ELEMENT]
  1225. a_fingerprint: INTEGER
  1226. an_error: XM_XPATH_ERROR_VALUE
  1227. a_message: STRING
  1228. a_set_cursor: DS_HASH_SET_CURSOR [INTEGER]
  1229. a_property_set: XM_XSLT_OUTPUT_PROPERTIES
  1230. do
  1231. create a_set.make_default
  1232. from
  1233. check attached top_level_elements as l_top_level_elements then
  1234. a_cursor := l_top_level_elements.new_cursor
  1235. end
  1236. a_cursor.finish
  1237. until
  1238. any_compile_errors or else a_cursor.before
  1239. loop
  1240. if a_cursor.item.is_output then
  1241. a_fingerprint := a_cursor.item.as_output.output_fingerprint
  1242. if a_fingerprint /= -1 then a_set.force (a_fingerprint) end
  1243. end
  1244. a_cursor.back
  1245. variant
  1246. a_cursor.index
  1247. end
  1248. if a_set.is_empty then
  1249. if needs_dynamic_output_properties then
  1250. a_message := "The stylesheet contains xsl:result-document instructions that calculate the output " +
  1251. "format name at run-time, but there are no named xsl:output declarations"
  1252. create an_error.make_from_string (a_message, Xpath_errors_uri, "XTDE1460", Static_error)
  1253. report_compile_error (an_error)
  1254. end
  1255. else
  1256. from a_set_cursor := a_set.new_cursor; a_set_cursor.start until a_set_cursor.after loop
  1257. a_property_set := gathered_output_properties (a_set_cursor.item)
  1258. executable.set_output_properties (a_property_set, a_set_cursor.item)
  1259. a_set_cursor.forth
  1260. end
  1261. end
  1262. end
  1263. invariant
  1264. imports_not_void: imports /= Void
  1265. named_templates_index_not_void: named_templates_index /= Void
  1266. variables_index_not_void: variables_index /= Void
  1267. positive_largest_stack_frame: largest_pattern_stack_frame >= 0
  1268. key_manager_not_void: key_manager /= Void
  1269. decimal_format_manager_not_void: decimal_format_manager /= Void
  1270. stylesheet_module_map_not_void: stylesheet_module_map /= Void
  1271. module_list_not_void: module_list /= Void
  1272. function_library_not_void: function_library /= Void
  1273. executable_not_void: executable /= Void
  1274. valid_input_type_annotations: input_type_annotations <= Preserve_annotations and then input_type_annotations >= 0
  1275. end