Class | REXMLUtilityNode |
In: |
lib/extlib/hash.rb
|
Parent: | Object |
This is a slighly modified version of the XMLUtilityNode from merb.devjavu.com/projects/merb/ticket/95 (has.sox@gmail.com) 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.
attributes | [RW] | |
children | [RW] | |
name | [RW] | |
type | [RW] |
# File lib/extlib/hash.rb, line 279 279: def initialize(name, attributes = {}) 280: @name = name.tr("-", "_") 281: # leave the type alone if we don't know what it is 282: @type = self.class.available_typecasts.include?(attributes["type"]) ? attributes.delete("type") : attributes["type"] 283: 284: @nil_element = attributes.delete("nil") == "true" 285: @attributes = undasherize_keys(attributes) 286: @children = [] 287: @text = false 288: end
# File lib/extlib/hash.rb, line 290 290: def add_node(node) 291: @text = true if node.is_a? String 292: @children << node 293: end
Get the inner_html of the REXML node.
# File lib/extlib/hash.rb, line 396 396: def inner_html 397: @children.join 398: end
# File lib/extlib/hash.rb, line 295 295: def to_hash 296: if @type == "file" 297: f = StringIO.new((@children.first || '').unpack('m').first) 298: class << f 299: attr_accessor :original_filename, :content_type 300: end 301: f.original_filename = attributes['name'] || 'untitled' 302: f.content_type = attributes['content_type'] || 'application/octet-stream' 303: return {name => f} 304: end 305: 306: if @text 307: return { name => typecast_value( translate_xml_entities( inner_html ) ) } 308: else 309: #change repeating groups into an array 310: groups = @children.inject({}) { |s,e| (s[e.name] ||= []) << e; s } 311: 312: out = nil 313: if @type == "array" 314: out = [] 315: groups.each do |k, v| 316: if v.size == 1 317: out << v.first.to_hash.entries.first.last 318: else 319: out << v.map{|e| e.to_hash[k]} 320: end 321: end 322: out = out.flatten 323: 324: else # If Hash 325: out = {} 326: groups.each do |k,v| 327: if v.size == 1 328: out.merge!(v.first) 329: else 330: out.merge!( k => v.map{|e| e.to_hash[k]}) 331: end 332: end 333: out.merge! attributes unless attributes.empty? 334: out = out.empty? ? nil : out 335: end 336: 337: if @type && out.nil? 338: { name => typecast_value(out) } 339: else 340: { name => out } 341: end 342: end 343: end
Converts the node into a readable HTML node.
@return <String> The HTML node in text form.
# File lib/extlib/hash.rb, line 403 403: def to_html 404: attributes.merge!(:type => @type ) if @type 405: "<#{name}#{attributes.to_xml_attributes}>#{@nil_element ? '' : inner_html}</#{name}>" 406: end
Convert basic XML entities into their literal values.
@param value<gsub> An XML fragment.
@return <gsub> The XML fragment after converting entities.
# File lib/extlib/hash.rb, line 379 379: def translate_xml_entities(value) 380: value.gsub(/</, "<"). 381: gsub(/>/, ">"). 382: gsub(/"/, '"'). 383: gsub(/'/, "'"). 384: gsub(/&/, "&") 385: end
Typecasts a value based upon its type. For instance, if node has type == "integer", {{[node.typecast_value("12") #=> 12]}}
@param value<String> The value that is being typecast.
@details [:type options]
"integer":: converts +value+ to an integer with #to_i "boolean":: checks whether +value+, after removing spaces, is the literal "true" "datetime":: Parses +value+ using Time.parse, and returns a UTC Time "date":: Parses +value+ using Date.parse
@return <Integer, TrueClass, FalseClass, Time, Date, Object>
The result of typecasting +value+.
@note
If +self+ does not have a "type" key, or if it's not one of the options specified above, the raw +value+ will be returned.
# File lib/extlib/hash.rb, line 368 368: def typecast_value(value) 369: return value unless @type 370: proc = self.class.typecasts[@type] 371: proc.nil? ? value : proc.call(value) 372: end