Class: Demolisher::Node
- Inherits:
-
Object
- Object
- Demolisher::Node
- Defined in:
- lib/demolisher.rb
Overview
Handles all the complexity of accessing the XML contents
Instance Method Summary collapse
-
#[](attr_name) ⇒ Object
Access an attribute of the current node.
- #_current_node ⇒ Object
-
#_element_from_symbol(el_or_ns, el_for_ns = nil) ⇒ Object
Transforms a symbol into a XML element path.
-
#_is_root_node? ⇒ Boolean
Indicates if the current node is the root of the XML document.
- #_xpath_for_element(el_or_ns, el_for_ns = nil) ⇒ Object
-
#initialize(xml, namespaces = nil, is_root = true) ⇒ Node
constructor
Creates a new Node object.
-
#inspect ⇒ Object
:nodoc:.
-
#method_missing(meth, *args, &block) ⇒ Object
The workhorse, finds the node matching meth.
-
#to_s ⇒ Object
Returns the current nodes contents.
Constructor Details
#initialize(xml, namespaces = nil, is_root = true) ⇒ Node
Creates a new Node object.
If the node is not the root node then the secondargument needs to be false.
35 36 37 38 39 40 |
# File 'lib/demolisher.rb', line 35 def initialize(xml, namespaces = nil, is_root = true) @nodes = [xml] @nodes.unshift(nil) unless is_root @namespaces = namespaces || {} @namespaces.merge!(xml.collect_namespaces) if xml.respond_to?(:collect_namespaces) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args, &block) ⇒ Object
The workhorse, finds the node matching meth.
Rough flow guide:
If a block is given then yield to it each for each instance
of the element found in the current node.
If no block given then get the first element found
If the node has only one text element check if the
method called has a ? suffix then return true if node content
looks like a boolean. Otherwise return text content
Otherwise return a new Node instance
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/demolisher.rb', line 72 def method_missing(meth, *args, &block) # :nodoc: xpath = _xpath_for_element(meth.to_s, args.shift) return nil if xpath.empty? if block_given? xpath.each_with_index do |node, idx| @nodes.push(node) case block.arity when 1 yield idx when 2 yield self.class.new(node, @namespaces, false), idx else yield end @nodes.pop end self else node = xpath.first if node.xpath('text()').length == 1 content = node.xpath('text()').first.content case meth.to_s when /\?$/ !! Regexp.new(/(t(rue)?|y(es)?|1)/i).match(content) else content end else self.class.new(node, @namespaces, false) end end end |
Instance Method Details
#[](attr_name) ⇒ Object
Access an attribute of the current node.
XML file:
<addressbook>
<person rel="friend">
<firstname>Steve</firstname>
</person>
</addressbook>
Example:
xml.addressbook do
xml.person do
puts "#{xml.firstname} is a #{xml['rel']}" #=> "Steve is a friend"
end
end
58 59 60 |
# File 'lib/demolisher.rb', line 58 def [](attr_name) _current_node.attributes[attr_name].to_s end |
#_current_node ⇒ Object
115 116 117 |
# File 'lib/demolisher.rb', line 115 def _current_node @nodes.last end |
#_element_from_symbol(el_or_ns, el_for_ns = nil) ⇒ Object
Transforms a symbol into a XML element path.
124 125 126 |
# File 'lib/demolisher.rb', line 124 def _element_from_symbol(el_or_ns,el_for_ns = nil) # :nodoc: "#{_is_root_node? ? '/' : nil}#{el_or_ns.gsub(/[^a-z0-9_-]/i, '')}#{el_for_ns && el_for_ns.inspect}" end |
#_is_root_node? ⇒ Boolean
Indicates if the current node is the root of the XML document.
129 130 131 |
# File 'lib/demolisher.rb', line 129 def _is_root_node? @nodes.size == 1 end |
#_xpath_for_element(el_or_ns, el_for_ns = nil) ⇒ Object
119 120 121 |
# File 'lib/demolisher.rb', line 119 def _xpath_for_element(el_or_ns, el_for_ns = nil) _current_node.xpath(_element_from_symbol(el_or_ns, el_for_ns), @namespaces) end |
#inspect ⇒ Object
:nodoc:
111 112 113 |
# File 'lib/demolisher.rb', line 111 def inspect # :nodoc: "#<#{self.class} node=#{_current_node.name}>" end |
#to_s ⇒ Object
Returns the current nodes contents.
108 109 110 |
# File 'lib/demolisher.rb', line 108 def to_s # :nodoc: _current_node.content.strip end |