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 281 281: def initialize(name, attributes = {}) 282: @name = name.tr("-", "_") 283: # leave the type alone if we don't know what it is 284: @type = self.class.available_typecasts.include?(attributes["type"]) ? attributes.delete("type") : attributes["type"] 285: 286: @nil_element = attributes.delete("nil") == "true" 287: @attributes = undasherize_keys(attributes) 288: @children = [] 289: @text = false 290: end
# File lib/extlib/hash.rb, line 292 292: def add_node(node) 293: @text = true if node.is_a? String 294: @children << node 295: end
Get the inner_html of the REXML node.
# File lib/extlib/hash.rb, line 398 398: def inner_html 399: @children.join 400: end
# File lib/extlib/hash.rb, line 297 297: def to_hash 298: if @type == "file" 299: f = StringIO.new((@children.first || '').unpack('m').first) 300: class << f 301: attr_accessor :original_filename, :content_type 302: end 303: f.original_filename = attributes['name'] || 'untitled' 304: f.content_type = attributes['content_type'] || 'application/octet-stream' 305: return {name => f} 306: end 307: 308: if @text 309: return { name => typecast_value( translate_xml_entities( inner_html ) ) } 310: else 311: #change repeating groups into an array 312: groups = @children.inject({}) { |s,e| (s[e.name] ||= []) << e; s } 313: 314: out = nil 315: if @type == "array" 316: out = [] 317: groups.each do |k, v| 318: if v.size == 1 319: out << v.first.to_hash.entries.first.last 320: else 321: out << v.map{|e| e.to_hash[k]} 322: end 323: end 324: out = out.flatten 325: 326: else # If Hash 327: out = {} 328: groups.each do |k,v| 329: if v.size == 1 330: out.merge!(v.first) 331: else 332: out.merge!( k => v.map{|e| e.to_hash[k]}) 333: end 334: end 335: out.merge! attributes unless attributes.empty? 336: out = out.empty? ? nil : out 337: end 338: 339: if @type && out.nil? 340: { name => typecast_value(out) } 341: else 342: { name => out } 343: end 344: end 345: end
Converts the node into a readable HTML node.
@return <String> The HTML node in text form.
# File lib/extlib/hash.rb, line 405 405: def to_html 406: attributes.merge!(:type => @type ) if @type 407: "<#{name}#{attributes.to_xml_attributes}>#{@nil_element ? '' : inner_html}</#{name}>" 408: 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 381 381: def translate_xml_entities(value) 382: value.gsub(/</, "<"). 383: gsub(/>/, ">"). 384: gsub(/"/, '"'). 385: gsub(/'/, "'"). 386: gsub(/&/, "&") 387: 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 370 370: def typecast_value(value) 371: return value unless @type 372: proc = self.class.typecasts[@type] 373: proc.nil? ? value : proc.call(value) 374: end