<commit_before>class Hash
  class << self
    # Converts valid XML into a Ruby Hash structure.
    # <tt>xml</tt>:: A string representation of valid XML
    # 
    # == Typecasting
    # Typecasting is performed on elements that have a "<tt>type</tt>" attribute of
    # <tt>integer</tt>:: 
    # <tt>boolean</tt>:: anything other than "true" evaluates to false
    # <tt>datetime</tt>:: Returns a Time object.  See +Time+ documentation for valid Time strings
    # <tt>date</tt>:: Returns a Date object.  See +Date+ documentation for valid Date strings 
    # 
    # Keys are automatically converted to +snake_case+
    #
    # == Caveats
    # * Mixed content tags are assumed to be text and any xml tags are kept as a String
    # * Any attributes other than type on a node containing a text node will be discarded
    #
    # == Examples
    #
    # === Standard 
    # <user gender='m'>
    #   <age type='integer'>35</age>
    #   <name><NAME></name>
    #   <dob type='date'>1988-01-01</dob>
    #   <joined-at type='datetime'>2000-04-28 23:01</joined-at>
    #   <is-cool type='boolean'>true</is-cool>
    # </user>
    #
    # evaluates to 
    # 
    # { "user" => 
    #         { "gender"    => "m",
    #           "age"       => 35,
    #           "name"      => "<NAME>",
    #           "dob"       => DateObject( 1998-01-01 ),
    #           "joined_at" => TimeObject( 2000-04-28 23:01),
    #           "is_cool"   => true 
    #         }
    #     }
    #
    # === Mixed Content
    # <story>
    #   A Quick <em>brown</em> Fox
    # </story>
    #
    # evaluates to
    # { "story" => "A Quick <em>brown</em> Fox" }
    # 
    # === Attributes other than type on a node containing text
    # <story is-good='fasle'>
    #   A Quick <em>brown</em> Fox
    # </story>
    #
    # evaluates to
    # { "story" => "A Quick <em>brown</em> Fox" }
    #
    # <bicep unit='inches' type='integer'>60</bicep>
    #
    # evaluates with a typecast to an integer.  But ignores the unit attribute
    # { "bicep" => 60 }
    def from_xml( xml )
      ToHashParser.from_xml(xml)
    end
  end
  
  # convert this hash into a Mash for string or symbol key access
  def to_mash
    hash = Mash.new(self)
    hash.default = default
    hash
  end
  
  # Convert this hash to a query string:
  #   
  #   { :name => "Bob",
  #     :address => {
  #       :street => '111 Ruby Ave.',
  #       :city => 'Ruby Central',
  #       :phones => ['111-111-1111', '222-222-2222']
  #     }
  #   }.to_params
  #   #=> "name=Bob&address[city]=Ruby Central&address[phones]=111-111-1111222-222-2222&address[street]=111 Ruby Ave."
  def to_params
    params = ''
    stack = []
    
    each do |k, v|
      if v.is_a?(Hash)
        stack << [k,v]
      else
        params << "#{k}=#{v}&"
      end
    end
    
    stack.each do |parent, hash|
      hash.each do |k, v|
        if v.is_a?(Hash)
          stack << ["#{parent}[#{k}]", v]
        else
          params << "#{parent}[#{k}]=#{v}&"
        end
      end
    end
    
    params.chop! # trailing &
    params
  end
  
  # Returns a new Hash with only the selected keys:
  #   
  #   { :one => 1, :two => 2, :three => 3 }.only(:one)
  #   #=> { :one => 1 }
  def only(*allowed) 
    reject { |k,v| !allowed.include?(k) }
  end
  
  # Returns a new hash without the selected keys:
  # 
  #   { :one => 1, :two => 2, :three => 3 }.except(:one)
  #   #=> { :two => 2, :three => 3 }
  # 
  def except(*rejected) 
    reject { |k,v| rejected.include?(k) }
  end
  
  # Converts the hash into xml attributes
  # 
  #   { :one => "ONE", "two"=>"TWO" }.to_xml_attributes
  #   #=> 'one="ONE" two="TWO"'
  # 
  def to_xml_attributes
    map do |k,v|
      %{#{k.to_s.camel_case.sub(/^(.{1,1})/) { |m| m.downcase }}="#{v}"} 
    end.join(' ')
  end
  
  alias_method :to_html_attributes, :to_xml_attributes
  
  # Adds the given class symbol or string to the hash in the
  # :class key.  This will add a html class if there are already any existing
  # or create the key and add this as the first class
  # 
  #   @hash[:class] #=> nil
  #   @hash.add_html_class!(:selected) #=> @hash[:class] == "selected"
  #   
  #   @hash.add_html_class!("class1 class2") #=> @hash[:class] == "selected class1 class2"
  # 
  def add_html_class!(html_class)
    if self[:class]
      self[:class] = "#{self[:class]} #{html_class}"
    else
      self[:class] = html_class.to_s
    end
  end
  
  # Destructively convert all keys which respond_to?(:to_sym) to symbols.
  # Works recursively if given nested hashes.
  # 
  #  { 'one' => 1, 'two' => 2 }.symbolize_keys!
  #  #=> { :one => 1, :two => 2 }
  # 
  def symbolize_keys!
    each do |k,v| 
      sym = k.respond_to?(:to_sym) ? k.to_sym : k 
      self[sym] = Hash === v ? v.symbolize_keys! : v 
      delete(k) unless k == sym
    end
    self
  end
  
  # Convert hashes with keys that are real references to classes into keys
  # that are strings. This is used during reloading to prevent the GC from
  # barfing when we remove classes that still
  def protect_keys!
    keys.each {|key| self[key.to_s] = delete(key) }
  end
  
  # Convert Hashes with String keys into Hashes with Class keys. We run this
  # after reloading to convert protected hashes back into usable hashes.
  def unprotect_keys!
    keys.each do |key| 
      (self[Object.full_const_get(key)] = delete(key)) rescue nil
    end
  end
  
  # Destructively and non-recursively convert each key to an uppercase string.
  # 
  #   { :name => "Bob", "age" => 12, "nick" => "Bobinator" }.environmentize_keys!
  #   #=> { "NAME" => "Bob", "NICK" => "Bobinator", "AGE" => 12 }
  # 
  def environmentize_keys!
    keys.each {|key| self[key.to_s.upcase] = delete(key) }
    self
  end
  
end

require 'rexml/parsers/streamparser'
require 'rexml/parsers/baseparser'
require 'rexml/light/node'

# This is a slighly modified version of the XMLUtilityNode from
# http://merb.devjavu.com/projects/merb/ticket/95 (<EMAIL>)
# It's mainly just adding vowels, as I ht cd wth n vwls :)
# This represents the hard part of the work, all I did was change the underlying
# parser
class REXMLUtilityNode # :nodoc:
  attr_accessor :name, :attributes, :children

  def initialize(name, attributes = {})
    @name       = name.tr("-", "_")
    @attributes = undasherize_keys(attributes)
    @children   = []
    @text       = false
  end<commit_msg>Hash#environmentize_keys! will ignore nil keys<commit_after>class Hash
  class << self
    # Converts valid XML into a Ruby Hash structure.
    # <tt>xml</tt>:: A string representation of valid XML
    # 
    # == Typecasting
    # Typecasting is performed on elements that have a "<tt>type</tt>" attribute of
    # <tt>integer</tt>:: 
    # <tt>boolean</tt>:: anything other than "true" evaluates to false
    # <tt>datetime</tt>:: Returns a Time object.  See +Time+ documentation for valid Time strings
    # <tt>date</tt>:: Returns a Date object.  See +Date+ documentation for valid Date strings 
    # 
    # Keys are automatically converted to +snake_case+
    #
    # == Caveats
    # * Mixed content tags are assumed to be text and any xml tags are kept as a String
    # * Any attributes other than type on a node containing a text node will be discarded
    #
    # == Examples
    #
    # === Standard 
    # <user gender='m'>
    #   <age type='integer'>35</age>
    #   <name><NAME></name>
    #   <dob type='date'>1988-01-01</dob>
    #   <joined-at type='datetime'>2000-04-28 23:01</joined-at>
    #   <is-cool type='boolean'>true</is-cool>
    # </user>
    #
    # evaluates to 
    # 
    # { "user" => 
    #         { "gender"    => "m",
    #           "age"       => 35,
    #           "name"      => "<NAME>",
    #           "dob"       => DateObject( 1998-01-01 ),
    #           "joined_at" => TimeObject( 2000-04-28 23:01),
    #           "is_cool"   => true 
    #         }
    #     }
    #
    # === Mixed Content
    # <story>
    #   A Quick <em>brown</em> Fox
    # </story>
    #
    # evaluates to
    # { "story" => "A Quick <em>brown</em> Fox" }
    # 
    # === Attributes other than type on a node containing text
    # <story is-good='fasle'>
    #   A Quick <em>brown</em> Fox
    # </story>
    #
    # evaluates to
    # { "story" => "A Quick <em>brown</em> Fox" }
    #
    # <bicep unit='inches' type='integer'>60</bicep>
    #
    # evaluates with a typecast to an integer.  But ignores the unit attribute
    # { "bicep" => 60 }
    def from_xml( xml )
      ToHashParser.from_xml(xml)
    end
  end
  
  # convert this hash into a Mash for string or symbol key access
  def to_mash
    hash = Mash.new(self)
    hash.default = default
    hash
  end
  
  # Convert this hash to a query string:
  #   
  #   { :name => "Bob",
  #     :address => {
  #       :street => '111 Ruby Ave.',
  #       :city => 'Ruby Central',
  #       :phones => ['111-111-1111', '222-222-2222']
  #     }
  #   }.to_params
  #   #=> "name=Bob&address[city]=Ruby Central&address[phones]=111-111-1111222-222-2222&address[street]=111 Ruby Ave."
  def to_params
    params = ''
    stack = []
    
    each do |k, v|
      if v.is_a?(Hash)
        stack << [k,v]
      else
        params << "#{k}=#{v}&"
      end
    end
    
    stack.each do |parent, hash|
      hash.each do |k, v|
        if v.is_a?(Hash)
          stack << ["#{parent}[#{k}]", v]
        else
          params << "#{parent}[#{k}]=#{v}&"
        end
      end
    end
    
    params.chop! # trailing &
    params
  end
  
  # Returns a new Hash with only the selected keys:
  #   
  #   { :one => 1, :two => 2, :three => 3 }.only(:one)
  #   #=> { :one => 1 }
  def only(*allowed) 
    reject { |k,v| !allowed.include?(k) }
  end
  
  # Returns a new hash without the selected keys:
  # 
  #   { :one => 1, :two => 2, :three => 3 }.except(:one)
  #   #=> { :two => 2, :three => 3 }
  # 
  def except(*rejected) 
    reject { |k,v| rejected.include?(k) }
  end
  
  # Converts the hash into xml attributes
  # 
  #   { :one => "ONE", "two"=>"TWO" }.to_xml_attributes
  #   #=> 'one="ONE" two="TWO"'
  # 
  def to_xml_attributes
    map do |k,v|
      %{#{k.to_s.camel_case.sub(/^(.{1,1})/) { |m| m.downcase }}="#{v}"} 
    end.join(' ')
  end
  
  alias_method :to_html_attributes, :to_xml_attributes
  
  # Adds the given class symbol or string to the hash in the
  # :class key.  This will add a html class if there are already any existing
  # or create the key and add this as the first class
  # 
  #   @hash[:class] #=> nil
  #   @hash.add_html_class!(:selected) #=> @hash[:class] == "selected"
  #   
  #   @hash.add_html_class!("class1 class2") #=> @hash[:class] == "selected class1 class2"
  # 
  def add_html_class!(html_class)
    if self[:class]
      self[:class] = "#{self[:class]} #{html_class}"
    else
      self[:class] = html_class.to_s
    end
  end
  
  # Destructively convert all keys which respond_to?(:to_sym) to symbols.
  # Works recursively if given nested hashes.
  # 
  #  { 'one' => 1, 'two' => 2 }.symbolize_keys!
  #  #=> { :one => 1, :two => 2 }
  # 
  def symbolize_keys!
    each do |k,v| 
      sym = k.respond_to?(:to_sym) ? k.to_sym : k 
      self[sym] = Hash === v ? v.symbolize_keys! : v 
      delete(k) unless k == sym
    end
    self
  end
  
  # Convert hashes with keys that are real references to classes into keys
  # that are strings. This is used during reloading to prevent the GC from
  # barfing when we remove classes that still
  def protect_keys!
    keys.each {|key| self[key.to_s] = delete(key) }
  end
  
  # Convert Hashes with String keys into Hashes with Class keys. We run this
  # after reloading to convert protected hashes back into usable hashes.
  def unprotect_keys!
    keys.each do |key| 
      (self[Object.full_const_get(key)] = delete(key)) rescue nil
    end
  end
  
  # Destructively and non-recursively convert each key to an uppercase string.
  # 
  #   { :name => "Bob", "age" => 12, "nick" => "Bobinator" }.environmentize_keys!
  #   #=> { "NAME" => "Bob", "NICK" => "Bobinator", "AGE" => 12 }
  # 
  def environmentize_keys!
    keys.each do |key|
      val = delete(key)
      next if val.nil?
      self[key.to_s.upcase] = val
    end
    self
  end  
end

require 'rexml/parsers/streamparser'
require 'rexml/parsers/baseparser'
require 'rexml/light/node'

# This is a slighly modified version of the XMLUtilityNode from
# http://merb.devjavu.com/projects/merb/ticket/95 (<EMAIL>)
# It's mainly just adding vowels, as I ht cd wth n vwls :)
# This represents the hard part of the work, all I did was change the underlying
# parser
class REXMLUtilityNode # :nodoc:
  attr_accessor :name, :attributes, :children

  def initialize(name, attributes = {})
    @name       = name.tr("-", "_")
    @attributes = undasherize_keys(attributes)
    @children   = []
    @text       = false
  end
{'fraction_non_alphanumeric': 0.14790321325760522, 'fraction_numerical': 0.018517077725044736, 'mean_word_length': 2.3526343244653103, 'pattern_counts': {'":': 0, '<': 105, '<?xml version=': 0, '>': 175, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 26}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1857207', 'n_tokens_mistral': 4747, 'n_tokens_neox': 4474, 'n_words': 1270}