You can dump an object to a plist in one of two ways:
Plist::Emit.dump(obj)
obj.to_plist
This requires that you mixin the Plist::Emit module, which is already done for Array and Hash.
The following Ruby classes are converted into native plist types:
Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time, true, false
Array and Hash are both recursive; their elements will be
converted into plist nodes inside the
IO (and its descendants) and StringIO objects are read from and their contents placed in a element.
User classes may implement to_plist_node to dictate how they should be serialized; otherwise the object will be passed to Marshal.dump and the result placed in a element.
For detailed usage instructions, refer to USAGE and the methods documented below.
The following Ruby classes are converted into native plist types:
Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time
Write us (via RubyForge) if you think another class can be coerced safely into one of the expected plist classes.
IO and StringIO objects are encoded and placed in elements; other objects are Marshal.dump‘ed unless they implement to_plist_node.
The envelope parameters dictates whether or not the resultant plist fragment is wrapped in the normal XML/plist header and footer. Set it to false if you only want the fragment.
# File lib/facter/util/plist/generator.rb, line 43 43: def self.dump(obj, envelope = true) 44: output = plist_node(obj) 45: 46: output = wrap(output) if envelope 47: 48: return output 49: end
# File lib/facter/util/plist/generator.rb, line 156 156: def self.element_type(item) 157: return case item 158: when String, Symbol; 'string' 159: when Fixnum, Bignum, Integer; 'integer' 160: when Float; 'real' 161: else 162: raise "Don't know about this data type... something must be wrong!" 163: end 164: end
# File lib/facter/util/plist/generator.rb, line 59 59: def self.plist_node(element) 60: output = '' 61: 62: if element.respond_to? :to_plist_node 63: output << element.to_plist_node 64: else 65: case element 66: when Array 67: if element.empty? 68: output << "<array/>\n" 69: else 70: output << tag('array') { 71: element.collect {|e| plist_node(e)} 72: } 73: end 74: when Hash 75: if element.empty? 76: output << "<dict/>\n" 77: else 78: inner_tags = [] 79: 80: element.keys.sort.each do |k| 81: v = element[k] 82: inner_tags << tag('key', CGI::escapeHTML(k.to_s)) 83: inner_tags << plist_node(v) 84: end 85: 86: output << tag('dict') { 87: inner_tags 88: } 89: end 90: when true, false 91: output << "<#{element}/>\n" 92: when Time 93: output << tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ')) 94: when Date # also catches DateTime 95: output << tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ')) 96: when String, Symbol, Fixnum, Bignum, Integer, Float 97: output << tag(element_type(element), CGI::escapeHTML(element.to_s)) 98: when IO, StringIO 99: element.rewind 100: contents = element.read 101: # note that apple plists are wrapped at a different length then 102: # what ruby's base64 wraps by default. 103: # I used #encode64 instead of #b64encode (which allows a length arg) 104: # because b64encode is b0rked and ignores the length arg. 105: data = "\n" 106: Base64::encode64(contents).gsub(/\s+/, '').scan(/.{1,68}/) { data << $& << "\n" } 107: output << tag('data', data) 108: else 109: output << comment( 'The <data> element below contains a Ruby object which has been serialized with Marshal.dump.' ) 110: data = "\n" 111: Base64::encode64(Marshal.dump(element)).gsub(/\s+/, '').scan(/.{1,68}/) { data << $& << "\n" } 112: output << tag('data', data ) 113: end 114: end 115: 116: return output 117: end
# File lib/facter/util/plist/generator.rb, line 123 123: def self.tag(type, contents = '', &block) 124: out = nil 125: 126: if block_given? 127: out = IndentedString.new 128: out << "<#{type}>" 129: out.raise_indent 130: 131: out << block.call 132: 133: out.lower_indent 134: out << "</#{type}>" 135: else 136: out = "<#{type}>#{contents.to_s}</#{type}>\n" 137: end 138: 139: return out.to_s 140: end
# File lib/facter/util/plist/generator.rb, line 142 142: def self.wrap(contents) 143: output = '' 144: 145: output << '<?xml version="1.0" encoding="UTF-8"?>' + "\n" 146: output << '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' + "\n" 147: output << '<plist version="1.0">' + "\n" 148: 149: output << contents 150: 151: output << '</plist>' + "\n" 152: 153: return output 154: end
Helper method for injecting into classes. Calls Plist::Emit.save_plist with self.
# File lib/facter/util/plist/generator.rb, line 31 31: def save_plist(filename) 32: Plist::Emit.save_plist(self, filename) 33: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.