class OpenNebula::XMLElement
The XMLElement class provides an abstraction of the underlying XML parser engine. It provides XML-related methods for the Pool and PoolElement classes
Public Class Methods
Builds a XML document
- xml
-
String the XML document of the object
- root_element
-
String Base xml element
- return
-
XML object for the underlying XML engine
# File lib/opennebula/xml_element.rb, line 54 def self.build_xml(xml, root_element) begin if NOKOGIRI doc = Nokogiri::XML(xml).xpath("/#{root_element}") else doc = REXML::Document.new(xml).root end rescue Exception => e return OpenNebula::Error.new(e.message) end return doc end
- xml
-
_opaque xml object_ an xml object as returned by ::build_xml
# File lib/opennebula/xml_element.rb, line 25 def initialize(xml=nil) @xml = xml end
Public Instance Methods
Extract a text element from the XML description of the PoolElement.
@param [String] key Xpath expression
@return [String, nil] If a text element is found, the element's
text value. Otherwise, an empty string or nil, depending on the backend
@example
vm['VID'] # gets VM id vm['HISTORY/HOSTNAME'] # get the hostname from the history
# File lib/opennebula/xml_element.rb, line 79 def [](key) if NOKOGIRI element=@xml.xpath(key.to_s) return nil if element.size == 0 else element=@xml.elements[key.to_s] return "" if element && !element.has_text? end element.text if element end
Add a new element to the xml xpath::String xpath xpression where the elemente will be added elems::Hash Hash containing the pairs key-value to be included Examples:
add_element('VM', 'NEW_ITEM' => 'NEW_VALUE') <VM><NEW_ITEM>NEW_VALUE</NEW_ITEM>...</VM> add_element('VM/TEMPLATE', 'V1' => {'X1' => 'A1', 'Y2' => 'A2'}) <VM><TEMPLATE><V1><X1>A1</X1><Y2>A2</Y2>...</TEMPLATE></VM>
# File lib/opennebula/xml_element.rb, line 112 def add_element(xpath, elems) elems.each { |key, value| if value.instance_of?(Hash) if NOKOGIRI elem = Nokogiri::XML::Node.new key, @xml.document value.each { |k2, v2| child = Nokogiri::XML::Node.new k2, elem child.content = v2 elem.add_child(child) } @xml.xpath(xpath.to_s).first.add_child(elem) else elem = REXML::Element.new(key) value.each { |k2, v2| elem.add_element(k2).text = v2 } @xml.elements[xpath].add_element(elem) end else if NOKOGIRI elem = Nokogiri::XML::Node.new key, @xml.document elem.content = value @xml.xpath(xpath.to_s).first.add_child(elem) else @xml.elements[xpath].add_element(key).text = value end end } end
Gets an attribute from an elemenT
- key
-
String xpath for the element
- name
-
String name of the attribute
# File lib/opennebula/xml_element.rb, line 168 def attr(key,name) value = nil if NOKOGIRI element=@xml.xpath(key.to_s.upcase) if element.size == 0 return nil end attribute = element.attr(name) value = attribute.text if attribute != nil else element=@xml.elements[key.to_s.upcase] value = element.attributes[name] if element != nil end return value end
Delete an element from the xml xpath::String xpath expression that selects the elemnts to be deleted
# File lib/opennebula/xml_element.rb, line 95 def delete_element(xpath) if NOKOGIRI @xml.xpath(xpath.to_s).remove else @xml.delete_element(xpath.to_s) end end
Iterates over every Element in the XPath and calls the block with a a XMLElement
- block
-
Block
# File lib/opennebula/xml_element.rb, line 192 def each(xpath_str,&block) if NOKOGIRI @xml.xpath(xpath_str).each { |pelem| block.call XMLElement.new(pelem) } else @xml.elements.each(xpath_str) { |pelem| block.call XMLElement.new(pelem) } end end
# File lib/opennebula/xml_element.rb, line 204 def each_xpath(xpath_str,&block) if NOKOGIRI @xml.xpath(xpath_str).each { |pelem| block.call pelem.text } else @xml.elements.each(xpath_str) { |pelem| block.call pelem.text } end end
Returns the xml of an element
# File lib/opennebula/xml_element.rb, line 256 def element_xml(xpath) if NOKOGIRI @xml.xpath(xpath).to_s else @xml.elements[xpath].to_s end end
Returns wheter there are elements for a given XPath
- xpath_str
-
String XPath expression to locate the element
# File lib/opennebula/xml_element.rb, line 230 def has_elements?(xpath_str) if NOKOGIRI element = @xml.xpath(xpath_str.to_s.upcase) return element != nil && element.children.size > 0 else element = @xml.elements[xpath_str.to_s] return element != nil && element.has_elements? end end
Initialize a XML document for the element
- xml
-
String the XML document of the object
- root_element
-
String Base xml element
# File lib/opennebula/xml_element.rb, line 32 def initialize_xml(xml, root_element) @xml = XMLElement.build_xml(xml, root_element) if OpenNebula.is_error?(@xml) @xml = nil else if NOKOGIRI if @xml.size == 0 @xml = nil end else if @xml.name != root_element @xml = nil end end end end
# File lib/opennebula/xml_element.rb, line 216 def name @xml.name end
Gets an array of text from elemenets extracted using the XPATH expression passed as filter
# File lib/opennebula/xml_element.rb, line 144 def retrieve_elements(filter) elements_array = Array.new if NOKOGIRI @xml.xpath(filter.to_s).each { |pelem| elements_array << pelem.text if pelem.text } else @xml.elements.each(filter.to_s) { |pelem| elements_array << pelem.text if pelem.text } end if elements_array.size == 0 return nil else return elements_array end end
Returns elements in text form
- root_element
-
String base element
- indent
-
Boolean indents the resulting string, default true
- xpath_exp
-
String filter elements with a XPath
# File lib/opennebula/xml_element.rb, line 268 def template_like_str(root_element, indent=true, xpath_exp=nil) if NOKOGIRI xml_template = @xml.xpath(root_element).to_s rexml = REXML::Document.new(xml_template).root else rexml = @xml.elements[root_element] end if indent ind_enter = "\n" ind_tab = ' ' else ind_enter = '' ind_tab = ' ' end str = rexml.elements.collect(xpath_exp) {|n| next if n.class != REXML::Element str_line = "" if n.has_elements? str_line << "#{n.name}=[#{ind_enter}" << n.collect { |n2| next if n2.class != REXML::Element or !n2.has_text? str = "#{ind_tab}#{n2.name}=#{attr_to_str(n2.text)}" }.compact.join(",#{ind_enter}") << " ]" else next if !n.has_text? str_line << "#{n.name}=#{attr_to_str(n.text)}" end str_line }.compact.join("\n") return str end
Returns the <TEMPLATE> element in text form
- indent
-
Boolean indents the resulting string, default true
# File lib/opennebula/xml_element.rb, line 242 def template_str(indent=true) template_like_str('TEMPLATE', indent) end
Returns the <TEMPLATE> element in XML form
# File lib/opennebula/xml_element.rb, line 247 def template_xml if NOKOGIRI @xml.xpath('TEMPLATE').to_s else @xml.elements['TEMPLATE'].to_s end end
# File lib/opennebula/xml_element.rb, line 220 def text if NOKOGIRI @xml.content else @xml.text end end
@return [Hash] a hash representing the resource
# File lib/opennebula/xml_element.rb, line 330 def to_hash hash = {} if NOKOGIRI if @xml.instance_of?(Nokogiri::XML::NodeSet) @xml.each { |c| if c.element? build_hash(hash, c) end } else build_hash(hash, @xml) end else build_hash(hash, @xml) end hash end
# File lib/opennebula/xml_element.rb, line 312 def to_xml(pretty=false) if NOKOGIRI && pretty str = @xml.to_xml elsif REXML_FORMATTERS && pretty str = String.new formatter = REXML::Formatters::Pretty.new formatter.compact = true formatter.write(@xml,str) else str = @xml.to_s end return str end
Private Instance Methods
# File lib/opennebula/xml_element.rb, line 394 def attr_to_str(attr) attr.gsub!('"',"\\\"") attr = "\"#{attr}\"" return attr end
# File lib/opennebula/xml_element.rb, line 355 def build_hash(hash, element) if NOKOGIRI array = element.children if array.length==1 and (array.first.text? or array.first.cdata?) r = array.first.text else r = {} array.each { |c| if c.element? build_hash(r, c) end } end else r = {} if element.has_elements? element.each_element { |c| build_hash(r, c) } elsif element.has_text? r = element.text end end key = element.name if hash.has_key?(key) if hash[key].instance_of?(Array) hash[key] << r else hash[key] = [hash[key], r] end else hash[key] = r end hash end