Class: Persia::Element
- Inherits:
-
Object
- Object
- Persia::Element
- Defined in:
- lib/xml.rb
Constant Summary collapse
- SLOW_RENDER =
false
Instance Attribute Summary collapse
-
#children ⇒ Object
readonly
Returns the value of attribute children.
-
#inner ⇒ Object
readonly
Returns the value of attribute inner.
-
#name ⇒ Object
Returns the value of attribute name.
-
#outer ⇒ Object
readonly
Returns the value of attribute outer.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
-
#persia_class ⇒ Object
readonly
Returns the value of attribute persia_class.
-
#persia_id ⇒ Object
readonly
Returns the value of attribute persia_id.
-
#source ⇒ Object
Returns the value of attribute source.
Instance Method Summary collapse
-
#assert_attr_eql?(attrib) ⇒ Boolean
raise Exception unless attributes of element are equal to attrib param.
-
#assert_equal(obj) ⇒ Object
raise Exception unless current element is equal to obj.
- #attempt_concat(first) ⇒ Object
-
#attributes ⇒ Object
returns attribute hash.
- #cache ⇒ Object
- #change_attributes {|@attributes| ... } ⇒ Object
- #change_type(newtype) ⇒ Object
- #clear_inner ⇒ Object
- #clear_outer ⇒ Object
-
#clone(parent = nil) ⇒ Object
clones current element, giving it parent as parent.
-
#copy_children(parent) ⇒ Object
return copy of children.
- #delete_all_children ⇒ Object
- #delete_child(index) ⇒ Object
- #delete_self ⇒ Object
-
#detect(&cmd) ⇒ Object
returns first element for which block returns true, going depth first.
- #dump(array) ⇒ Object
-
#each_descendant_element(&cmd) ⇒ Object
calls each descendant element (no textnodes) including current one.
- #el_close ⇒ Object
- #el_open ⇒ Object
-
#elements ⇒ Object
returns all children that are elements.
- #freeze ⇒ Object
-
#has_class?(name) ⇒ Boolean
has this element a persia class of name?.
-
#has_id?(name) ⇒ Boolean
has this element a persia id of name?.
- #index(node) ⇒ Object
- #index_self ⇒ Object
-
#initialize(r = nil, id_hash = nil) ⇒ Element
constructor
create new element, creating from rexml document if document, or with name if string.
-
#insert_after_self(node) ⇒ Object
insert node after self (as sibling).
-
#insert_before_self(node) ⇒ Object
insert node before self (as sibling).
- #insert_child(index, node) ⇒ Object
- #insert_child_after_node(node, newnode) ⇒ Object
- #insert_child_before_node(node, newnode) ⇒ Object
-
#insert_child_first(node) ⇒ Object
insert node as first child.
-
#insert_child_last(node) ⇒ Object
insert node as last child.
- #populate_document(r, id_hash) ⇒ Object
-
#populate_from_element(el, parent) ⇒ Object
populate from native element with given parent.
-
#populate_from_rexml(e, parent = nil, id_hash = nil) ⇒ Object
populate from rexml element with given parent.
-
#render(array) ⇒ Object
end modify.
- #render_children(array) ⇒ Object
- #render_tags(array) ⇒ Object
-
#root ⇒ Object
returns root element.
- #root? ⇒ Boolean
- #to_s ⇒ Object
- #touch(first, size) ⇒ Object
Constructor Details
#initialize(r = nil, id_hash = nil) ⇒ Element
create new element, creating from rexml document if document, or with name if string.
11 12 13 14 15 16 17 18 |
# File 'lib/xml.rb', line 11 def initialize(r = nil, id_hash = nil) @children = [] if r and r.kind_of?(String) @name = r.to_s elsif r and r.kind_of?(REXML::Document) populate_document(r, id_hash) end end |
Instance Attribute Details
#children ⇒ Object (readonly)
Returns the value of attribute children.
7 8 9 |
# File 'lib/xml.rb', line 7 def children @children end |
#inner ⇒ Object (readonly)
Returns the value of attribute inner.
7 8 9 |
# File 'lib/xml.rb', line 7 def inner @inner end |
#name ⇒ Object
Returns the value of attribute name.
6 7 8 |
# File 'lib/xml.rb', line 6 def name @name end |
#outer ⇒ Object (readonly)
Returns the value of attribute outer.
7 8 9 |
# File 'lib/xml.rb', line 7 def outer @outer end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
7 8 9 |
# File 'lib/xml.rb', line 7 def parent @parent end |
#persia_class ⇒ Object (readonly)
Returns the value of attribute persia_class.
7 8 9 |
# File 'lib/xml.rb', line 7 def persia_class @persia_class end |
#persia_id ⇒ Object (readonly)
Returns the value of attribute persia_id.
7 8 9 |
# File 'lib/xml.rb', line 7 def persia_id @persia_id end |
#source ⇒ Object
Returns the value of attribute source.
6 7 8 |
# File 'lib/xml.rb', line 6 def source @source end |
Instance Method Details
#assert_attr_eql?(attrib) ⇒ Boolean
raise Exception unless attributes of element are equal to attrib param
141 142 143 144 145 |
# File 'lib/xml.rb', line 141 def assert_attr_eql?(attrib) unless @attributes == attrib raise "Attributes #{attrib.inspect} and #{@attributes.inspect} not equal\nself:#{self.to_s}" end end |
#assert_equal(obj) ⇒ Object
raise Exception unless current element is equal to obj
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/xml.rb', line 122 def assert_equal(obj) unless obj.kind_of? Element raise "element (#{name}) != #{obj.to_s}[#{obj.class}]" end obj.assert_attr_eql? @attributes unless name == obj.name raise "element (#{name}) != element(#{obj.name})" end @children.each_with_index do |e,i| e2 = obj.children[i] if e.kind_of?(Element) e.assert_equal e2 elsif e != e2 raise "'#{e}'[#{e.class}] and '#{e2}'[#{e2.class}] not equal" end end end |
#attempt_concat(first) ⇒ Object
198 199 200 201 202 203 204 205 206 |
# File 'lib/xml.rb', line 198 def attempt_concat(first) second = first + 1 return if second == 0 return unless second < @children.size if String === @children[first] and String === @children[second] @children[first] << @children[second] @children.delete_at second end end |
#attributes ⇒ Object
returns attribute hash
102 103 104 |
# File 'lib/xml.rb', line 102 def attributes @attributes || {} end |
#cache ⇒ Object
273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/xml.rb', line 273 def cache array = [] dump array cursor = 0 array.each do |fr| if fr.kind_of? Array fr[1].touch(cursor, fr[0].size) cursor += fr[0].size else cursor += fr.size end end root.source = array.map {|x,*y| x }.join end |
#change_attributes {|@attributes| ... } ⇒ Object
208 209 210 211 212 213 |
# File 'lib/xml.rb', line 208 def change_attributes raise TypeError, "Element is frozen" if frozen? @attributes ||= {} yield @attributes clear_outer end |
#change_type(newtype) ⇒ Object
215 216 217 218 219 |
# File 'lib/xml.rb', line 215 def change_type(newtype) raise TypeError, "Element is frozen" if frozen? @name = newtype clear_outer end |
#clear_inner ⇒ Object
259 260 261 262 |
# File 'lib/xml.rb', line 259 def clear_inner @inner = nil @parent.clear_inner if @parent end |
#clear_outer ⇒ Object
264 265 266 267 |
# File 'lib/xml.rb', line 264 def clear_outer @outer = nil @parent.clear_inner if @parent end |
#clone(parent = nil) ⇒ Object
clones current element, giving it parent as parent
112 113 114 |
# File 'lib/xml.rb', line 112 def clone(parent = nil) Element.populate_from_element self, parent end |
#copy_children(parent) ⇒ Object
return copy of children
66 67 68 69 70 |
# File 'lib/xml.rb', line 66 def copy_children(parent) @children.map do |c| c.kind_of?(String) ? c.dup : Element.new.populate_from_element(c, parent) end if @children end |
#delete_all_children ⇒ Object
227 228 229 |
# File 'lib/xml.rb', line 227 def delete_all_children @children = [] end |
#delete_child(index) ⇒ Object
190 191 192 193 194 195 196 |
# File 'lib/xml.rb', line 190 def delete_child(index) raise TypeError, "Element is frozen" if frozen? clear_inner index = index(index) unless Numeric === index @children.delete_at index attempt_concat(index - 1) end |
#delete_self ⇒ Object
185 186 187 188 |
# File 'lib/xml.rb', line 185 def delete_self raise TypeError, "Element is frozen" if frozen? @parent.delete_child(self) if @parent end |
#detect(&cmd) ⇒ Object
returns first element for which block returns true, going depth first
73 74 75 76 77 78 79 |
# File 'lib/xml.rb', line 73 def detect(&cmd) if cmd.call self return self end elements.each {|x| r = x.detect(&cmd) and return r } nil end |
#dump(array) ⇒ Object
292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/xml.rb', line 292 def dump(array) array << [el_open, self] @children.each do |c| if c.kind_of? String array << c else c.dump array end end array << [el_close, self] end |
#each_descendant_element(&cmd) ⇒ Object
calls each descendant element (no textnodes) including current one
82 83 84 85 86 87 88 89 |
# File 'lib/xml.rb', line 82 def each_descendant_element(&cmd) cmd.call self @children.each do |c| if c.kind_of? Element c.each_descendant_element &cmd end end end |
#el_close ⇒ Object
318 319 320 |
# File 'lib/xml.rb', line 318 def el_close "</#{@name}>" end |
#el_open ⇒ Object
314 315 316 |
# File 'lib/xml.rb', line 314 def el_open "<#{@name}#{attributes.map{|k,v|%Q! #{k}="#{v}"!}.join}>" end |
#elements ⇒ Object
returns all children that are elements
117 118 119 |
# File 'lib/xml.rb', line 117 def elements @children.select {|c| c.kind_of?(Element) } end |
#freeze ⇒ Object
30 31 32 33 |
# File 'lib/xml.rb', line 30 def freeze @attributes.freeze super end |
#has_class?(name) ⇒ Boolean
has this element a persia class of name?
97 98 99 |
# File 'lib/xml.rb', line 97 def has_class?(name) name.to_sym == @persia_class end |
#has_id?(name) ⇒ Boolean
has this element a persia id of name?
92 93 94 |
# File 'lib/xml.rb', line 92 def has_id?(name) name.to_sym == @persia_id end |
#index(node) ⇒ Object
221 222 223 224 225 |
# File 'lib/xml.rb', line 221 def index(node) index = -1 @children.detect {|c| index += 1; node.equal? c } index end |
#index_self ⇒ Object
231 232 233 |
# File 'lib/xml.rb', line 231 def index_self @parent.index self if @parent end |
#insert_after_self(node) ⇒ Object
insert node after self (as sibling)
155 156 157 |
# File 'lib/xml.rb', line 155 def insert_after_self(node) parent.insert_child index_self + 1, node end |
#insert_before_self(node) ⇒ Object
insert node before self (as sibling)
150 151 152 |
# File 'lib/xml.rb', line 150 def insert_before_self(node) parent.insert_child index_self, node end |
#insert_child(index, node) ⇒ Object
177 178 179 180 181 182 183 |
# File 'lib/xml.rb', line 177 def insert_child(index, node) raise TypeError, "Element is frozen" if frozen? clear_inner (@children ||= []).insert index, node attempt_concat(index - 1) attempt_concat(index) end |
#insert_child_after_node(node, newnode) ⇒ Object
173 174 175 |
# File 'lib/xml.rb', line 173 def insert_child_after_node(node, newnode) insert_child 1 + index(node), newnode end |
#insert_child_before_node(node, newnode) ⇒ Object
169 170 171 |
# File 'lib/xml.rb', line 169 def insert_child_before_node(node, newnode) insert_child index(node), newnode end |
#insert_child_first(node) ⇒ Object
insert node as first child
160 161 162 |
# File 'lib/xml.rb', line 160 def insert_child_first(node) insert_child 0, node end |
#insert_child_last(node) ⇒ Object
insert node as last child
165 166 167 |
# File 'lib/xml.rb', line 165 def insert_child_last(node) insert_child -1, node end |
#populate_document(r, id_hash) ⇒ Object
20 21 22 23 24 25 26 27 28 |
# File 'lib/xml.rb', line 20 def populate_document(r, id_hash) populate_from_rexml(r.root, nil, id_hash) # cache roots if id_hash id_hash.values.select(&:root?).each(&:cache) id_hash.freeze end each_descendant_element(&:freeze) end |
#populate_from_element(el, parent) ⇒ Object
populate from native element with given parent
54 55 56 57 58 59 60 61 62 63 |
# File 'lib/xml.rb', line 54 def populate_from_element(el, parent) raise TypeError, "Element is frozen" if frozen? @name = el.name @parent = parent @persia_id = el.persia_id @persia_class = el.persia_class load_attr(el.attributes) @children = el.copy_children(self) self end |
#populate_from_rexml(e, parent = nil, id_hash = nil) ⇒ Object
populate from rexml element with given parent
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/xml.rb', line 36 def populate_from_rexml(e, parent = nil, id_hash = nil) @name = e.name @parent = parent # skip children if element contains skip attribute if load_attr(e.attributes, id_hash) e.children.each do |c| @children << Element.new.populate_from_rexml(c, self, id_hash) if c.kind_of? REXML::Element if c.kind_of?(REXML::Text) && (s = c.to_s) s.strip! @children << s unless s.empty? end end end self end |
#render(array) ⇒ Object
end modify
237 238 239 240 241 242 243 244 245 |
# File 'lib/xml.rb', line 237 def render(array) if SLOW_RENDER or not @inner (array) { render_children(array) } elsif @outer array << root.source[@outer] if @outer else (array) { array << root.source[@inner] } end end |
#render_children(array) ⇒ Object
253 254 255 256 257 |
# File 'lib/xml.rb', line 253 def render_children(array) @children.each do |c| c.kind_of?(String) ? array << c : c.render(array) end end |
#render_tags(array) ⇒ Object
247 248 249 250 251 |
# File 'lib/xml.rb', line 247 def (array) array << el_open yield array << el_close end |
#root ⇒ Object
returns root element
107 108 109 |
# File 'lib/xml.rb', line 107 def root @parent ? @parent.root : self end |
#root? ⇒ Boolean
269 270 271 |
# File 'lib/xml.rb', line 269 def root? !@parent end |
#to_s ⇒ Object
288 289 290 |
# File 'lib/xml.rb', line 288 def to_s render([]).join "\n" end |
#touch(first, size) ⇒ Object
304 305 306 307 308 309 310 311 312 |
# File 'lib/xml.rb', line 304 def touch(first, size) if @first @outer = @first ... first + size @inner = @last ... first @first,@last = nil, nil else @first,@last = first, first + size end end |