File: active_support/xml_mini/rexml.rb

Overview
Module Structure
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: ActiveSupport#2
  module: XmlMini_REXML#3
extends
  XmlMini_REXML ( ActiveSupport )
has properties
constant: CONTENT_KEY #6
method: parse / 1 #15
method: merge_element! / 2 #28
method: collapse / 1 #36
method: merge_texts! / 2 #54
method: merge! / 3 #74
method: get_attributes / 1 #94
method: empty_content? / 1 #104

Code

   1  # = XmlMini ReXML implementation
   2  module ActiveSupport
   3    module XmlMini_REXML #:nodoc:
   4      extend self
   5 
   6      CONTENT_KEY = '__content__'.freeze
   7 
   8      # Parse an XML Document string into a simple hash
   9      #
  10      # Same as XmlSimple::xml_in but doesn't shoot itself in the foot,
  11      # and uses the defaults from ActiveSupport
  12      #
  13      # string::
  14      #   XML Document string to parse
  15      def parse(string)
  16        require 'rexml/document' unless defined?(REXML::Document)
  17        doc = REXML::Document.new(string)
  18        merge_element!({}, doc.root)
  19      end
  20 
  21      private
  22        # Convert an XML element and merge into the hash
  23        #
  24        # hash::
  25        #   Hash to merge the converted element into.
  26        # element::
  27        #   XML element to merge into hash
  28        def merge_element!(hash, element)
  29          merge!(hash, element.name, collapse(element))
  30        end
  31 
  32        # Actually converts an XML document element into a data structure.
  33        #
  34        # element::
  35        #   The document element to be collapsed.
  36        def collapse(element)
  37          hash = get_attributes(element)
  38 
  39          if element.has_elements?
  40            element.each_element {|child| merge_element!(hash, child) }
  41            merge_texts!(hash, element) unless empty_content?(element)
  42            hash
  43          else
  44            merge_texts!(hash, element)
  45          end
  46        end
  47 
  48        # Merge all the texts of an element into the hash
  49        #
  50        # hash::
  51        #   Hash to add the converted emement to.
  52        # element::
  53        #   XML element whose texts are to me merged into the hash
  54        def merge_texts!(hash, element)
  55          unless element.has_text?
  56            hash
  57          else
  58            # must use value to prevent double-escaping
  59            merge!(hash, CONTENT_KEY, element.texts.sum(&:value))
  60          end
  61        end
  62 
  63        # Adds a new key/value pair to an existing Hash. If the key to be added
  64        # already exists and the existing value associated with key is not
  65        # an Array, it will be wrapped in an Array. Then the new value is
  66        # appended to that Array.
  67        #
  68        # hash::
  69        #   Hash to add key/value pair to.
  70        # key::
  71        #   Key to be added.
  72        # value::
  73        #   Value to be associated with key.
  74        def merge!(hash, key, value)
  75          if hash.has_key?(key)
  76            if hash[key].instance_of?(Array)
  77              hash[key] << value
  78            else
  79              hash[key] = [hash[key], value]
  80            end
  81          elsif value.instance_of?(Array)
  82            hash[key] = [value]
  83          else
  84            hash[key] = value
  85          end
  86          hash
  87        end
  88 
  89        # Converts the attributes array of an XML element into a hash.
  90        # Returns an empty Hash if node has no attributes.
  91        #
  92        # element::
  93        #   XML element to extract attributes from.
  94        def get_attributes(element)
  95          attributes = {}
  96          element.attributes.each { |n,v| attributes[n] = v }
  97          attributes
  98        end
  99 
 100        # Determines if a document element has text content
 101        #
 102        # element::
 103        #   XML element to be checked.
 104        def empty_content?(element)
 105          element.texts.join.blank?
 106        end
 107    end
 108  end