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