Class: XMLROCS::XMLNode
- Inherits:
-
String
- Object
- String
- XMLROCS::XMLNode
- Includes:
- Comparable, Enumerable
- Defined in:
- lib/xmlrocs.rb
Overview
Represents an XML Element. You can access and modify it’s children and attributes.
Each XMLNode has exactly one parent (that happens to be nil if the node is the root of the tree) and a (possibly empty) list of children.
It also has a name (the name of the XML tag) that can be modified.
You can compare two XMLNodes or an XMLNode and a String. When you provide a String, only the text value of the XMLNode is compared.
You can enumerate the XMLNode Tree in the traversal-order defined in the @traversal accessor.
For more information have a look at the README or instance method documentation.
Instance Attribute Summary collapse
-
#attributes ⇒ Object
readonly
Hash containing the attributes of the current Node:.
-
#children ⇒ Object
readonly
Hash containing the children of the current Node.
-
#parent ⇒ Object
readonly
The parent of the current Node.
-
#traversal ⇒ Object
Defines the order in which the tree is traversed.
-
#xmlname ⇒ Object
readonly
The name of the current Node.
Instance Method Summary collapse
-
#<<(child) ⇒ Object
Append a child.
-
#==(other) ⇒ Object
Deep-compares to XMLNodes.
-
#>>(childname = nil) ⇒ Object
Remove a child from the current XMLNode.
-
#[](attribute) ⇒ Object
Access attributes by name.
-
#[]=(attribute, value) ⇒ Object
Modify attributes.
-
#all(name = nil) ⇒ Object
Returns an array of all XMLNodes in the order that is specified in the traversal accessor.
-
#delete_attribute!(attribute) ⇒ Object
Delete attributes.
-
#dup ⇒ Object
Deep-copies the Tree.
-
#each(&block) ⇒ Object
Iterates over the XMLNode-tree in the order that is specified in the traversal accessor.
- #initialize(options = {}) ⇒ XMLNode constructor
-
#leaf?(tag = nil) ⇒ Boolean
If a tag is provided it checks if the child with the given name is a leaf.
-
#leafs ⇒ Object
Generates an array of all leafs in the order specified in the traversal accessor.
-
#map(&block) ⇒ Object
Maps a function over the XMLNode-tree and returns a new XMLNode-tree with the mapped values.
-
#map!(&block) ⇒ Object
Maps a function over the current XMLNode-tree.
- #method_missing(method, *args) ⇒ Object
-
#set_text(text) ⇒ Object
Sets the text of the current node to text.
-
#single?(tag = nil) ⇒ Boolean
If a tag is provided it checks if the child with the given name has siblings.
-
#to_xml(flat = false) ⇒ Object
Deep-transforms the current node into plaintext XML.
Constructor Details
#initialize(options = {}) ⇒ XMLNode
Create a new XMLNode You have to either provide an REXML::Element as options or plaintext xml data as options. Otherwise an ArgumentError will be thrown.
Supported options:
:root # => REXML::Element that will be traversed.
:text # => XML plaintext that will be parsed by REXML and then
traversed.
:nil # => Will create a nil node. Useful if you need a global
parent.
:traversal # => The traversal order. See traversal.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/xmlrocs.rb', line 118 def initialize( = {}) xmlroot = if [:root] [:root] elsif [:text] REXML::Document.new([:text]).root elsif [:nil] nil end raise(ArgumentError, "Undefined") if !xmlroot and ![:nil] @children, @attributes = {}, {} @parent ,@traversal = [:parent], [:traversal] || :preorder @xmlname = xmlroot ? xmlroot.name.to_sym : :NIL set_text(xmlroot ? xmlroot.get_text.to_s : '') if xmlroot xmlroot.attributes.each { |k,v| self[k.to_sym] = v } # this recursions makes the whole library slow. basically we have # all information in xmlroot, so no recursive calls would be necessary xmlroot.select { |e| e.class == REXML::Element }.each do |e| self << XMLNode.new({ :root => e, :parent => self }) end end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args) ⇒ Object
294 295 296 297 298 299 300 |
# File 'lib/xmlrocs.rb', line 294 def method_missing(method, *args) if method.to_s[-1] == 33 and @children.has_key?(real_method = method.to_s.chomp("!").to_sym) return @children[real_method] end return @children[method].last if @children.has_key?(method) super(method, *args) end |
Instance Attribute Details
#attributes ⇒ Object (readonly)
Hash containing the attributes of the current Node:
{ :attribute_name => "Attribute" }
Attributes can also be modified using this accessor.
78 79 80 |
# File 'lib/xmlrocs.rb', line 78 def attributes @attributes end |
#children ⇒ Object (readonly)
Hash containing the children of the current Node. The Hash has the following structure:
{ :childname => [ XMLNode, ... ] }
You can either use the >> or << operators to modify children or use this accessor directly.
70 71 72 |
# File 'lib/xmlrocs.rb', line 70 def children @children end |
#parent ⇒ Object (readonly)
The parent of the current Node. The parent of the Root-Node is nil.
83 84 85 |
# File 'lib/xmlrocs.rb', line 83 def parent @parent end |
#traversal ⇒ Object
Defines the order in which the tree is traversed.
The following traversals are suppported:
:preorder
:postorder
:inorder
102 103 104 |
# File 'lib/xmlrocs.rb', line 102 def traversal @traversal end |
Instance Method Details
#<<(child) ⇒ Object
Append a child. child has to be an XMLNode or a String that contains the XML data in plaintext.
169 170 171 172 |
# File 'lib/xmlrocs.rb', line 169 def <<(child) return self << XMLROCS::XMLNode.new(:text => child) if is_real_string(child) (@children[child.xmlname] = (@children[child.xmlname] || []) << child).last end |
#==(other) ⇒ Object
Deep-compares to XMLNodes.
272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/xmlrocs.rb', line 272 def ==(other) # pure string comparison return super(other) if is_real_string(other) return false unless other == self.to_s [ [ self, other ], [ other, self ] ].each do |a,b| a.children.each do |k,v| return false if !b.children.has_key?(k) or v != b.children[k] end end true end |
#>>(childname = nil) ⇒ Object
Remove a child from the current XMLNode. Providing only a childname, it will delete all children with the given name. If you also provide a block, the block will be evaluated with each child as an argument and according to the return value of the call the child will be deleted or not (when the block returns true, the child will be deleted). If you provide a block you can optionally filter the children by providing a childname so only children with the given name will be evaluated.
186 187 188 189 190 191 192 193 194 |
# File 'lib/xmlrocs.rb', line 186 def >>(childname = nil) if block_given? @children.select { |k,v| childname ? k == childname : true }.each do |k,v| v.reject! { |child| yield(child) } end else @children.delete(childname) end end |
#[](attribute) ⇒ Object
Access attributes by name. Attributenames are stored as symbols.
145 146 147 |
# File 'lib/xmlrocs.rb', line 145 def [](attribute) @attributes[attribute] end |
#[]=(attribute, value) ⇒ Object
Modify attributes. Behaves like a Hash. Keys are symbols by convention, values are XMLNode-objects.
153 154 155 |
# File 'lib/xmlrocs.rb', line 153 def []=(attribute, value) @attributes[attribute] = value end |
#all(name = nil) ⇒ Object
Returns an array of all XMLNodes in the order that is specified in the traversal accessor.
200 201 202 |
# File 'lib/xmlrocs.rb', line 200 def all(name = nil) name ? select { |x| x.xmlname == name } : traverse end |
#delete_attribute!(attribute) ⇒ Object
Delete attributes. attribute has to be a symbol with the name of the attribute you want to delete.
161 162 163 |
# File 'lib/xmlrocs.rb', line 161 def delete_attribute!(attribute) @attributes.delete(attribute) end |
#dup ⇒ Object
Deep-copies the Tree.
231 232 233 |
# File 'lib/xmlrocs.rb', line 231 def dup XMLROCS::XMLNode.new(:text => to_xml) end |
#each(&block) ⇒ Object
Iterates over the XMLNode-tree in the order that is specified in the traversal accessor.
224 225 226 |
# File 'lib/xmlrocs.rb', line 224 def each(&block) traverse.each(&block) end |
#leaf?(tag = nil) ⇒ Boolean
If a tag is provided it checks if the child with the given name is a leaf. Otherwise it does the same for the current node.
248 249 250 |
# File 'lib/xmlrocs.rb', line 248 def leaf?(tag = nil) tag ? children[tag].all? { |x| x.leaf? } : children.empty? end |
#leafs ⇒ Object
Generates an array of all leafs in the order specified in the traversal accessor.
256 257 258 |
# File 'lib/xmlrocs.rb', line 256 def leafs traverse.select { |x| x.leaf? } end |
#map(&block) ⇒ Object
Maps a function over the XMLNode-tree and returns a new XMLNode-tree with the mapped values.
208 209 210 |
# File 'lib/xmlrocs.rb', line 208 def map(&block) dup.map!(&block) end |
#map!(&block) ⇒ Object
Maps a function over the current XMLNode-tree.
215 216 217 218 |
# File 'lib/xmlrocs.rb', line 215 def map!(&block) traverse.map!(&block) self end |
#set_text(text) ⇒ Object
Sets the text of the current node to text.
263 264 265 266 267 |
# File 'lib/xmlrocs.rb', line 263 def set_text(text) # special match for whitespace-only return gsub!(self.to_s, "") if text =~ /^\s+$/ gsub!(self.to_s, text) end |
#single?(tag = nil) ⇒ Boolean
If a tag is provided it checks if the child with the given name has siblings. Otherwise it does the same for the current node.
240 241 242 |
# File 'lib/xmlrocs.rb', line 240 def single?(tag = nil) tag ? @children[tag].length == 1 : @parent.children[@xmlname].length == 1 end |
#to_xml(flat = false) ⇒ Object
Deep-transforms the current node into plaintext XML. If flat is true, all children will be omitted.
288 289 290 291 292 |
# File 'lib/xmlrocs.rb', line 288 def to_xml(flat = false) "<#{@xmlname} " + @attributes.map { |k,v| "#{k}=\"#{v}\" "}.join(" ") + ">" + (flat ? "" : (leaf? ? self.to_s : @children.values.flatten.map { |e| e.to_xml }.join)) + "</#{@xmlname}>" end |