/src/lib/xml/namespaces/xmlns_tree.e

http://github.com/tybor/Liberty · Specman e · 326 lines · 263 code · 32 blank · 31 comment · 14 complexity · 3bc79f0012e444306cfa6e415a8185f1 MD5 · raw file

  1. -- See the Copyright notice at the end of this file.
  2. --
  3. class XMLNS_TREE
  4. --
  5. -- DOM-like namespace-aware representation of an XML document
  6. --
  7. -- See also XMLNS_PARSER, XML_TREE
  8. --
  9. inherit
  10. XMLNS_CALLBACKS
  11. create {ANY}
  12. make, with_error_handler
  13. feature {ANY}
  14. root: XMLNS_COMPOSITE_NODE
  15. -- The root of the tree
  16. attribute_at (a_attribute_name: UNICODE_STRING): UNICODE_STRING
  17. -- Usually to recover the "version" or "encoding" attributes
  18. do
  19. Result := tree_attributes.reference_at(a_attribute_name)
  20. end
  21. set_processing_instruction (target: UNICODE_STRING; processor: PROCEDURE[TUPLE[UNICODE_STRING]])
  22. require
  23. target /= Void
  24. processor /= Void
  25. local
  26. processors: FAST_ARRAY[PROCEDURE[TUPLE[UNICODE_STRING]]]
  27. do
  28. processors := processing_instructions.reference_at(target)
  29. if processors = Void then
  30. create processors.make(0)
  31. processing_instructions.add(processors, target.twin)
  32. end
  33. processors.add_last(processor)
  34. end
  35. feature {}
  36. attributes: HASHED_DICTIONARY[HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING], UNICODE_STRING]
  37. no_namespace_attributes: HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]
  38. tree_attributes: HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]
  39. open_nodes: STACK[XMLNS_COMPOSITE_NODE]
  40. processing_instructions: HASHED_DICTIONARY[FAST_ARRAY[PROCEDURE[TUPLE[UNICODE_STRING]]], UNICODE_STRING]
  41. once
  42. create Result.make
  43. end
  44. feature {XMLNS_PARSER}
  45. with_attribute (attribute_namespace, attribute_name: UNICODE_STRING; attribute_value: UNICODE_STRING; line, column: INTEGER)
  46. do
  47. attributes_for(attribute_namespace).put(attribute_value.twin, attribute_name.twin)
  48. end
  49. open_node (node_namespace, node_name: UNICODE_STRING; line, column: INTEGER)
  50. local
  51. node: XMLNS_COMPOSITE_NODE; i, j: INTEGER; att: HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]; ns: UNICODE_STRING
  52. do
  53. if node_namespace = Void then
  54. node := new_node(Void, node_name.twin, line, column)
  55. else
  56. node := new_node(node_namespace.twin, node_name.twin, line, column)
  57. end
  58. from
  59. i := attributes.lower
  60. until
  61. i > attributes.upper
  62. loop
  63. ns := attributes.key(i)
  64. att := attributes.item(i)
  65. from
  66. j := att.lower
  67. until
  68. j > att.upper
  69. loop
  70. node.set_attribute(ns, att.key(j), att.item(j))
  71. j := j + 1
  72. end
  73. i := i + 1
  74. end
  75. from
  76. j := no_namespace_attributes.lower
  77. until
  78. j > no_namespace_attributes.upper
  79. loop
  80. node.set_attribute(Void, no_namespace_attributes.key(j), no_namespace_attributes.item(j))
  81. j := j + 1
  82. end
  83. clear_attributes
  84. open_nodes.push(node)
  85. end
  86. close_node (node_namespace, node_name: UNICODE_STRING; line, column: INTEGER)
  87. local
  88. node: XMLNS_COMPOSITE_NODE
  89. do
  90. node := open_nodes.top
  91. open_nodes.pop
  92. if open_nodes.is_empty then
  93. root := node
  94. else
  95. open_nodes.top.add_child(node)
  96. end
  97. end
  98. open_close_node (node_namespace, node_name: UNICODE_STRING; line, column: INTEGER)
  99. do
  100. open_node(node_namespace, node_name, line, column)
  101. close_node(node_namespace, node_name, line, column)
  102. end
  103. xml_header (line, column: INTEGER)
  104. do
  105. check
  106. tree_attributes.is_empty
  107. end
  108. tree_attributes.copy(attributes_for(once U""))
  109. clear_attributes
  110. end
  111. processing_instruction (a_target, a_data: UNICODE_STRING)
  112. local
  113. processors: FAST_ARRAY[PROCEDURE[TUPLE[UNICODE_STRING]]]; i: INTEGER
  114. do
  115. processors := processing_instructions.reference_at(a_target)
  116. if processors /= Void then
  117. from
  118. i := processors.lower
  119. until
  120. i > processors.upper
  121. loop
  122. processors.item(i).call([a_data])
  123. i := i + 1
  124. end
  125. end
  126. end
  127. current_node: UNICODE_STRING
  128. do
  129. if not open_nodes.is_empty then
  130. Result := open_nodes.top.name
  131. end
  132. end
  133. current_namespace: UNICODE_STRING
  134. do
  135. if not open_nodes.is_empty then
  136. Result := open_nodes.top.namespace
  137. end
  138. end
  139. entity (a_entity: UNICODE_STRING; line, column: INTEGER): UNICODE_STRING
  140. do
  141. -- The default tree does not recognize any other entity than XML defaults.
  142. end
  143. data (a_data: UNICODE_STRING; line, column: INTEGER)
  144. local
  145. d: XMLNS_DATA_NODE
  146. do
  147. create d.make(a_data.twin, line, column)
  148. open_nodes.top.add_child(d)
  149. end
  150. parse_error (line, column: INTEGER; message: STRING)
  151. do
  152. at_error := True
  153. if error_handler /= Void then
  154. error_handler.call([line, column, message])
  155. else
  156. std_error.put_string(message)
  157. std_error.put_string(" at line ")
  158. std_error.put_integer(line)
  159. std_error.put_string(", column ")
  160. std_error.put_integer(column)
  161. std_error.put_new_line
  162. die_with_code(1)
  163. end
  164. end
  165. at_error: BOOLEAN
  166. feature {}
  167. error_handler: PROCEDURE[TUPLE[INTEGER, INTEGER, STRING]]
  168. make (url: URL)
  169. -- read the xml tree at the given `url'
  170. require
  171. url.is_connected implies url.read
  172. do
  173. create attributes.make
  174. create no_namespace_attributes.make
  175. create tree_attributes.make
  176. create open_nodes.make
  177. parser.connect_to(url)
  178. parser.parse(Current)
  179. parser.disconnect
  180. end
  181. with_error_handler (url: URL; a_error_handler: like error_handler)
  182. do
  183. error_handler := a_error_handler
  184. make(url)
  185. end
  186. new_node (node_namespace, node_name: UNICODE_STRING; line, column: INTEGER): XMLNS_COMPOSITE_NODE
  187. do
  188. create Result.make(node_namespace, node_name, line, column)
  189. end
  190. parser: XMLNS_PARSER
  191. once
  192. create Result.make
  193. end
  194. feature {} -- Memory management
  195. unused_attributes: FAST_ARRAY[WEAK_REFERENCE[HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]]]
  196. once
  197. create Result.make(0)
  198. end
  199. new_attributes: HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]
  200. local
  201. i: INTEGER
  202. do
  203. from
  204. i := unused_attributes.upper
  205. until
  206. Result /= Void or else i < unused_attributes.lower
  207. loop
  208. Result := unused_attributes.item(i).item
  209. i := i - 1
  210. end
  211. if Result = Void then
  212. create Result.make
  213. else
  214. Result.clear_count
  215. end
  216. ensure
  217. Result.is_empty
  218. end
  219. old_attributes (a_attributes: HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING])
  220. local
  221. i: INTEGER; done: BOOLEAN; wr: WEAK_REFERENCE[HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]]
  222. do
  223. from
  224. i := unused_attributes.lower
  225. until
  226. done or else i > unused_attributes.upper
  227. loop
  228. wr := unused_attributes.item(i)
  229. if wr.item = Void then
  230. wr.set_item(a_attributes)
  231. done := True
  232. end
  233. i := i + 1
  234. end
  235. if not done then
  236. create wr.set_item(a_attributes)
  237. unused_attributes.add_last(wr)
  238. end
  239. end
  240. attributes_for (namespace: UNICODE_STRING): HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]
  241. do
  242. if namespace = Void then
  243. Result := no_namespace_attributes
  244. else
  245. Result := attributes.reference_at(namespace)
  246. if Result = Void then
  247. Result := new_attributes
  248. attributes.add(Result, namespace.twin)
  249. end
  250. end
  251. ensure
  252. Result /= Void
  253. namespace /= Void implies attributes.fast_occurrences(Result) = 1
  254. namespace = Void implies Result = no_namespace_attributes
  255. end
  256. clear_attributes
  257. local
  258. i: INTEGER
  259. do
  260. from
  261. i := attributes.lower
  262. until
  263. i > attributes.upper
  264. loop
  265. old_attributes(attributes.item(i))
  266. i := i + 1
  267. end
  268. attributes.clear_count
  269. no_namespace_attributes.clear_count
  270. ensure
  271. attributes.is_empty
  272. no_namespace_attributes.is_empty
  273. end
  274. end -- class XMLNS_TREE
  275. --
  276. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  277. --
  278. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  279. -- of this software and associated documentation files (the "Software"), to deal
  280. -- in the Software without restriction, including without limitation the rights
  281. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  282. -- copies of the Software, and to permit persons to whom the Software is
  283. -- furnished to do so, subject to the following conditions:
  284. --
  285. -- The above copyright notice and this permission notice shall be included in
  286. -- all copies or substantial portions of the Software.
  287. --
  288. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  289. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  290. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  291. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  292. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  293. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  294. -- THE SOFTWARE.