PageRenderTime 94ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/library/xslt/src/style/xm_xslt_result_document.e

http://github.com/gobo-eiffel/gobo
Specman e | 393 lines | 338 code | 37 blank | 18 comment | 26 complexity | 55c7f54fa591dd38f73a4f6c62719611 MD5 | raw file
  1. note
  2. description:
  3. "xsl:result-document 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_RESULT_DOCUMENT
  10. inherit
  11. XM_XSLT_STYLE_ELEMENT
  12. redefine
  13. validate, make_style_element, may_contain_sequence_constructor
  14. end
  15. XM_XSLT_OUTPUT_ROUTINES
  16. export {NONE} all end
  17. KL_SHARED_PLATFORM
  18. export {NONE} all end
  19. create {XM_XSLT_NODE_FACTORY}
  20. make_style_element
  21. feature {NONE} -- Initialization
  22. make_style_element (an_error_listener: XM_XSLT_ERROR_LISTENER; a_document: XM_XPATH_TREE_DOCUMENT; a_parent: detachable XM_XPATH_TREE_COMPOSITE_NODE;
  23. an_attribute_collection: detachable XM_XPATH_ATTRIBUTE_COLLECTION; a_namespace_list: detachable DS_ARRAYED_LIST [INTEGER];
  24. a_name_code: INTEGER; a_sequence_number: INTEGER; a_configuration: like configuration)
  25. -- Establish invariant.
  26. do
  27. is_instruction := True
  28. validation_action := Validation_strip
  29. create formatting_attributes.make_with_equality_testers (Formatting_attributes_count, expression_tester, Void)
  30. Precursor (an_error_listener, a_document, a_parent, an_attribute_collection, a_namespace_list, a_name_code, a_sequence_number, a_configuration)
  31. end
  32. feature -- Access
  33. may_contain_sequence_constructor: BOOLEAN
  34. -- Is `Current' allowed to contain a sequence constructor?
  35. do
  36. Result := True
  37. end
  38. http_method: detachable STRING
  39. -- Value of gexslt:method extension attribute;
  40. -- Intended principally for http protocol, but value is unchecked here.
  41. feature -- Element change
  42. prepare_attributes
  43. -- Set the attribute list for the element.
  44. local
  45. a_cursor: DS_ARRAYED_LIST_CURSOR [INTEGER]
  46. a_name_code: INTEGER
  47. an_expanded_name, a_format_attribute, an_href_attribute: detachable STRING
  48. a_validation_attribute, a_type_attribute, a_value, a_message: detachable STRING
  49. an_expression: XM_XPATH_EXPRESSION
  50. an_error: XM_XPATH_ERROR_VALUE
  51. l_use_character_maps: like use_character_maps
  52. l_http_method: like http_method
  53. do
  54. if attached attribute_collection as l_attribute_collection then
  55. from
  56. a_cursor := l_attribute_collection.name_code_cursor
  57. a_cursor.start
  58. until
  59. a_cursor.after or any_compile_errors
  60. loop
  61. a_name_code := a_cursor.item
  62. an_expanded_name := shared_name_pool.expanded_name_from_name_code (a_name_code)
  63. if STRING_.same_string (an_expanded_name, Format_attribute) then
  64. a_format_attribute := attribute_value_by_index (a_cursor.index); STRING_.left_adjust (a_format_attribute); STRING_.right_adjust (a_format_attribute)
  65. elseif STRING_.same_string (an_expanded_name, Href_attribute) then
  66. an_href_attribute := attribute_value_by_index (a_cursor.index); STRING_.left_adjust (an_href_attribute); STRING_.right_adjust (an_href_attribute)
  67. elseif STRING_.same_string (an_expanded_name, Use_character_maps_attribute) then
  68. l_use_character_maps := attribute_value_by_index (a_cursor.index)
  69. STRING_.left_adjust (l_use_character_maps)
  70. STRING_.right_adjust (l_use_character_maps)
  71. use_character_maps := l_use_character_maps
  72. elseif STRING_.same_string (an_expanded_name, Validation_attribute) then
  73. a_validation_attribute := attribute_value_by_index (a_cursor.index)
  74. elseif STRING_.same_string (an_expanded_name, Type_attribute) then
  75. a_type_attribute := attribute_value_by_index (a_cursor.index)
  76. elseif STRING_.same_string (an_expanded_name, Gexslt_method_attribute) then
  77. l_http_method := attribute_value_by_index (a_cursor.index)
  78. STRING_.left_adjust (l_http_method)
  79. STRING_.right_adjust (l_http_method)
  80. http_method := l_http_method
  81. elseif formatting_attribute_names.has (an_expanded_name) or else
  82. (an_expanded_name.substring_index ("#", 1) /= 0
  83. and then an_expanded_name.substring_index (Gexslt_eiffel_type_uri, 1) /= 1
  84. and then an_expanded_name.substring_index (Xslt_uri, 1) /= 1 ) then
  85. -- it's a (plausible) serialization parameter
  86. a_value := attribute_value_by_index (a_cursor.index)
  87. STRING_.left_adjust (a_value); STRING_.right_adjust (a_value)
  88. check attached static_context as l_static_context then
  89. generate_attribute_value_template (a_value, l_static_context)
  90. end
  91. check postcondition_of_generate_attribute_value_template: attached last_generated_expression as l_last_generated_expression then
  92. an_expression := l_last_generated_expression
  93. end
  94. formatting_attributes.force (an_expression, fingerprint_from_name_code (a_name_code))
  95. else
  96. check_unknown_attribute (a_name_code)
  97. end
  98. a_cursor.forth
  99. variant
  100. l_attribute_collection.number_of_attributes + 1 - a_cursor.index
  101. end
  102. end
  103. if an_href_attribute /= Void then
  104. check attached static_context as l_static_context then
  105. generate_attribute_value_template (an_href_attribute, l_static_context)
  106. end
  107. href := last_generated_expression
  108. end
  109. if a_format_attribute /= Void then
  110. check attached static_context as l_static_context then
  111. generate_attribute_value_template (a_format_attribute, l_static_context)
  112. end
  113. check postcondition_of_generate_attribute_value_template: attached last_generated_expression as l_last_generated_expression then
  114. if l_last_generated_expression.is_string_value then
  115. if is_qname (a_format_attribute) then
  116. generate_name_code (a_format_attribute)
  117. output_fingerprint := fingerprint_from_name_code (last_generated_name_code)
  118. else
  119. output_fingerprint := -1
  120. end
  121. if output_fingerprint = -1 then
  122. a_message := STRING_.concat ("XTDE1460: xsl:result-document format='", a_format_attribute)
  123. a_message := STRING_.appended_string (a_message, "' does not specify a valid QName")
  124. create an_error.make_from_string (a_message, Xpath_errors_uri, "XTDE1460", Static_error)
  125. report_compile_error (an_error)
  126. end
  127. else
  128. format_expression := last_generated_expression
  129. end
  130. end
  131. else
  132. output_fingerprint := -1
  133. end
  134. if a_validation_attribute /= Void then
  135. validation_action := validation_code (a_validation_attribute)
  136. if validation_action /= Validation_strip then
  137. create an_error.make_from_string ("To perform validation, a schema-aware XSLT processor is needed", Xpath_errors_uri, "XTSE1660", Static_error)
  138. report_compile_error (an_error)
  139. elseif validation_action = Validation_invalid then
  140. create an_error.make_from_string ("Invalid value of validation attribute", Xpath_errors_uri, "XTSE0020", Static_error)
  141. report_compile_error (an_error)
  142. end
  143. end
  144. if a_type_attribute /= Void then
  145. create an_error.make_from_string ("The type attribute is available only with a schema-aware XSLT processor", Xpath_errors_uri, "XTSE1660", Static_error)
  146. report_compile_error (an_error)
  147. end
  148. if a_type_attribute /= Void and then a_validation_attribute /= Void then
  149. create an_error.make_from_string ("The validation and type attributes are mutually exclusive", Xpath_errors_uri, "XTSE1505", Static_error)
  150. report_compile_error (an_error)
  151. end
  152. attributes_prepared := True
  153. end
  154. validate
  155. -- Check that the stylesheet element is valid.
  156. local
  157. l_cursor: DS_HASH_TABLE_CURSOR [XM_XPATH_EXPRESSION, INTEGER]
  158. l_fingerprint: INTEGER
  159. l_attribute_name: STRING
  160. l_expression: XM_XPATH_EXPRESSION
  161. l_replacement: DS_CELL [detachable XM_XPATH_EXPRESSION]
  162. do
  163. check_within_template
  164. create l_replacement.make (Void)
  165. if attached href as l_href then
  166. type_check_expression (l_replacement, "href", l_href)
  167. href := l_replacement.item
  168. end
  169. if attached format_expression as l_format_expression then
  170. l_replacement.put (Void)
  171. type_check_expression (l_replacement, "format", l_format_expression)
  172. format_expression := l_replacement.item
  173. end
  174. from
  175. l_cursor := formatting_attributes.new_cursor
  176. l_cursor.start
  177. until
  178. l_cursor.after
  179. loop
  180. l_fingerprint := l_cursor.key
  181. l_attribute_name := shared_name_pool.display_name_from_name_code (l_fingerprint)
  182. l_expression := l_cursor.item
  183. l_replacement.put (Void)
  184. type_check_expression (l_replacement, l_attribute_name, l_expression)
  185. check attached l_replacement.item as l_replacement_item then
  186. if l_expression /= l_replacement_item then
  187. l_cursor.replace (l_replacement_item)
  188. end
  189. end
  190. l_cursor.forth
  191. end
  192. validated := True
  193. end
  194. compile (an_executable: XM_XSLT_EXECUTABLE)
  195. -- Compile `Current' to an excutable instruction.
  196. local
  197. l_global_property_set: detachable XM_XSLT_OUTPUT_PROPERTIES
  198. l_local_property_set: XM_XSLT_OUTPUT_PROPERTIES
  199. l_stylesheet: XM_XSLT_STYLESHEET
  200. l_message: STRING
  201. l_error: XM_XPATH_ERROR_VALUE
  202. l_namespace_resolver: XM_XPATH_NAMESPACE_RESOLVER
  203. l_content: detachable XM_XPATH_EXPRESSION
  204. l_result: XM_XSLT_COMPILED_RESULT_DOCUMENT
  205. do
  206. last_generated_expression := Void
  207. check attached principal_stylesheet as l_principal_stylesheet then
  208. l_stylesheet := l_principal_stylesheet
  209. end
  210. if format_expression /= Void then
  211. create l_global_property_set.make (Platform.Minimum_integer)
  212. l_stylesheet.set_needs_dynamic_output_properties
  213. elseif output_fingerprint = -1 or l_stylesheet.is_named_output_property_defined (output_fingerprint) then
  214. l_global_property_set := l_stylesheet.gathered_output_properties (output_fingerprint)
  215. if l_global_property_set.is_error then
  216. check attached l_global_property_set.duplicate_attribute_name as l_duplicate_attribute_name then
  217. l_message := STRING_.concat ("Two xsl:output statements specify conflicting values for attribute '", l_duplicate_attribute_name)
  218. end
  219. l_message := STRING_.appended_string (l_message, "', in the output definition named '")
  220. l_message := STRING_.appended_string (l_message, shared_name_pool.display_name_from_name_code (output_fingerprint))
  221. l_message := STRING_.appended_string (l_message, "'.")
  222. create l_error.make_from_string (l_message, Xpath_errors_uri, "XTSE1560", Static_error)
  223. report_compile_error (l_error)
  224. end
  225. else
  226. l_message := STRING_.concat ("Output definition named '", shared_name_pool.display_name_from_name_code (output_fingerprint))
  227. l_message := STRING_.appended_string (l_message, "' by the format attribute of xsl:result-document has not been defined.")
  228. create l_error.make_from_string (l_message, Xpath_errors_uri, "XTDE1460", Static_error)
  229. report_compile_error (l_error)
  230. end
  231. if not any_compile_errors then
  232. -- TODO: we can optimize by determining method now, in some cases
  233. create l_local_property_set.make (Platform.Minimum_integer)
  234. build_local_properties (l_local_property_set)
  235. if not any_compile_errors then
  236. check attached static_context as l_static_context then
  237. l_namespace_resolver := l_static_context.namespace_resolver
  238. end
  239. compile_sequence_constructor (an_executable, new_axis_iterator (Child_axis), True)
  240. l_content := last_generated_expression
  241. if l_content = Void then
  242. create {XM_XPATH_EMPTY_SEQUENCE} l_content.make
  243. end
  244. check
  245. l_global_property_set /= Void
  246. attached base_uri as l_base_uri
  247. then
  248. create l_result.make (an_executable, l_global_property_set, l_local_property_set, href,
  249. format_expression, l_base_uri, validation_action,
  250. Void, formatting_attributes, l_namespace_resolver, l_content)
  251. end
  252. if http_method /= Void then
  253. l_result.set_http_method (http_method)
  254. end
  255. last_generated_expression := l_result
  256. end
  257. end
  258. end
  259. build_local_properties (a_local_property_set: XM_XSLT_OUTPUT_PROPERTIES)
  260. -- Add properties defined on `Current'.
  261. require
  262. local_properties_not_void: a_local_property_set /= Void
  263. local
  264. a_fingerprint_list: DS_ARRAYED_LIST [INTEGER]
  265. l_cursor: DS_HASH_TABLE_CURSOR [XM_XPATH_EXPRESSION, INTEGER]
  266. another_cursor: DS_ARRAYED_LIST_CURSOR [INTEGER]
  267. a_fingerprint: INTEGER
  268. an_expression: XM_XPATH_EXPRESSION
  269. a_namespace_resolver: XM_XPATH_NAMESPACE_RESOLVER
  270. a_local_name: STRING
  271. an_error: XM_XPATH_ERROR_VALUE
  272. do
  273. create a_fingerprint_list.make (formatting_attributes.count)
  274. check attached static_context as l_static_context then
  275. a_namespace_resolver := l_static_context.namespace_resolver
  276. end
  277. from
  278. l_cursor := formatting_attributes.new_cursor; l_cursor.start
  279. until
  280. l_cursor.after
  281. loop
  282. a_fingerprint := l_cursor.key
  283. an_expression := l_cursor.item
  284. if an_expression.is_string_value then
  285. a_local_property_set.set_property (a_fingerprint, an_expression.as_string_value.string_value, a_namespace_resolver)
  286. if attached a_local_property_set.error_message as l_error_message then
  287. check is_error: a_local_property_set.is_error end
  288. l_cursor.go_after
  289. create an_error.make_from_string (l_error_message, Xpath_errors_uri, "XTSE0020", Static_error)
  290. report_compile_error (an_error)
  291. else
  292. a_fingerprint_list.put_last (a_fingerprint)
  293. end
  294. else
  295. a_local_name := shared_name_pool.local_name_from_name_code (a_fingerprint)
  296. if STRING_.same_string (a_local_name, Method_attribute) or else
  297. STRING_.same_string (a_local_name, Cdata_section_elements_attribute) then
  298. end
  299. end
  300. if not l_cursor.after then l_cursor.forth end
  301. end
  302. from
  303. another_cursor := a_fingerprint_list.new_cursor; another_cursor.start
  304. until
  305. another_cursor.after
  306. loop
  307. a_fingerprint := another_cursor.item
  308. formatting_attributes.remove (a_fingerprint)
  309. another_cursor.forth
  310. variant
  311. a_fingerprint_list.count + 1 - another_cursor.index
  312. end
  313. if use_character_maps /= Void and then not a_local_property_set.is_error then
  314. gather_used_character_maps_property (a_local_property_set, precedence)
  315. end
  316. end
  317. feature {NONE} -- Implementation
  318. Formatting_attributes_count: INTEGER = 17
  319. -- Number of formatting attributes
  320. output_fingerprint: INTEGER
  321. -- Fingerprint of name of output definition
  322. href: detachable XM_XPATH_EXPRESSION
  323. -- URI of output destination
  324. format_expression: detachable XM_XPATH_EXPRESSION
  325. -- Format attribute, when supplied as an AVT
  326. validation_action: INTEGER
  327. -- Validation action
  328. formatting_attributes: DS_HASH_TABLE [XM_XPATH_EXPRESSION, INTEGER]
  329. -- Overrides of xsl:output attributes
  330. formatting_attribute_names: DS_HASH_SET [STRING]
  331. -- Names of formatting attributes permitted as AVTs;
  332. -- `Use_character_maps_attribute' is also permitted, but not as an AVT.
  333. once
  334. create Result.make (Formatting_attributes_count)
  335. Result.set_equality_tester (string_equality_tester)
  336. Result.put (Method_attribute)
  337. Result.put (Output_version_attribute)
  338. Result.put (Indent_attribute)
  339. Result.put (Encoding_attribute)
  340. Result.put (Media_type_attribute)
  341. Result.put (Doctype_system_attribute)
  342. Result.put (Doctype_public_attribute)
  343. Result.put (Normalization_form_attribute)
  344. Result.put (Omit_xml_declaration_attribute)
  345. Result.put (Standalone_attribute)
  346. Result.put (Escape_uri_attributes_attribute)
  347. Result.put (Include_content_type_attribute)
  348. Result.put (Undeclare_prefixes_attribute)
  349. Result.put (Byte_order_mark_attribute)
  350. Result.put (Cdata_section_elements_attribute)
  351. Result.put (Gexslt_character_representation_attribute)
  352. Result.put (Gexslt_indent_spaces_attribute)
  353. end
  354. invariant
  355. formatting_attributes_not_void: formatting_attributes /= Void
  356. end