| 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