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

build_xml(xml, root_element) click to toggle source

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
new(xml=nil) click to toggle source
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

[](key) click to toggle source

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_element(xpath, elems) click to toggle source

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
attr(key,name) click to toggle source

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_element(xpath) click to toggle source

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
each(xpath_str,&block) click to toggle source

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
each_xpath(xpath_str,&block) click to toggle source
# 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
element_xml(xpath) click to toggle source

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
has_elements?(xpath_str) click to toggle source

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_xml(xml, root_element) click to toggle source

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
name() click to toggle source
# File lib/opennebula/xml_element.rb, line 216
def name
    @xml.name
end
retrieve_elements(filter) click to toggle source

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
template_like_str(root_element, indent=true, xpath_exp=nil) click to toggle source

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
template_str(indent=true) click to toggle source

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
template_xml() click to toggle source

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
text() click to toggle source
# File lib/opennebula/xml_element.rb, line 220
def text
    if NOKOGIRI
        @xml.content
    else
        @xml.text
    end
end
to_hash() click to toggle source

@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
to_xml(pretty=false) click to toggle source
# 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

attr_to_str(attr) click to toggle source
# File lib/opennebula/xml_element.rb, line 394
def attr_to_str(attr)
    attr.gsub!('"',"\\\"")
    attr = "\"#{attr}\""

    return attr
end
build_hash(hash, element) click to toggle source
# 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