| 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