diff options
Diffstat (limited to 'lib/plist/parser.rb')
-rw-r--r-- | lib/plist/parser.rb | 186 |
1 files changed, 30 insertions, 156 deletions
diff --git a/lib/plist/parser.rb b/lib/plist/parser.rb index 64b404d..3d08a68 100644 --- a/lib/plist/parser.rb +++ b/lib/plist/parser.rb @@ -13,9 +13,7 @@ # This is the main point of the library: # # r = Plist::parse_xml( filename_or_xml ) -class Plist - VERSION = '0.0.1' - +module Plist TEMPLATE = <<-XML <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> @@ -27,15 +25,15 @@ XML TEMPLATE.sub( /%plist%/, xml ) end - # Note that I don't use these two elements much: - # - # + Date elements are returned as DateTime objects. - # + Data elements are implemented as Tempfiles - # - # Plist::parse_xml will blow up if it encounters a data element. - # If you encounter such an error, or if you have a Date element which - # can't be parsed into a Time object, please send your plist file to - # plist@hexane.org so that I can implement the proper support. +# Note that I don't use these two elements much: +# +# + Date elements are returned as DateTime objects. +# + Data elements are implemented as Tempfiles +# +# Plist::parse_xml will blow up if it encounters a data element. +# If you encounter such an error, or if you have a Date element which +# can't be parsed into a Time object, please send your plist file to +# plist@hexane.org so that I can implement the proper support. def Plist::parse_xml( filename_or_xml ) listener = Listener.new #parser = REXML::Parsers::StreamParser.new(File.new(filename), listener) @@ -46,7 +44,7 @@ XML class Listener #include REXML::StreamListener - + attr_accessor :result, :open def initialize @@ -54,11 +52,11 @@ XML @open = Array.new end - + def tag_start(name, attributes) @open.push PTag::mappings[name].new end - + def text( contents ) @open.last.text = contents if @open.last end @@ -78,23 +76,23 @@ XML @filename_or_xml = filename_or_xml @listener = listener end - + TEXT = /([^<]+)/ XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/um DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um - - - def parse - plist_tags = PTag::mappings.keys.join('|') - start_tag = /<(#{plist_tags})([^>]*)>/i - end_tag = /<\/(#{plist_tags})[^>]*>/i - - require 'strscan' - @scanner = StringScanner.new( if (File.exists? @filename_or_xml) - File.open(@filename_or_xml, "r") {|f| f.read} - else - @filename_or_xml - end ) + + + def parse + plist_tags = PTag::mappings.keys.join('|') + start_tag = /<(#{plist_tags})([^>]*)>/i + end_tag = /<\/(#{plist_tags})[^>]*>/i + + require 'strscan' + @scanner = StringScanner.new( if (File.exists? @filename_or_xml) + File.open(@filename_or_xml, "r") {|f| f.read} + else + @filename_or_xml + end ) until @scanner.eos? if @scanner.scan(XMLDECL_PATTERN) elsif @scanner.scan(DOCTYPE_PATTERN) @@ -148,7 +146,7 @@ XML def to_ruby dict = Hash.new key = nil - + children.each do |c| if key.nil? key = c.to_ruby @@ -161,13 +159,13 @@ XML dict end end - + class PKey < PTag def to_ruby text end end - + class PString < PTag def to_ruby text || '' @@ -225,128 +223,4 @@ XML tf end end - module Emit - def save_plist(filename) - File.open(filename, 'wb') do |f| - f.write(self.to_plist) - end - end - - # Only the expected classes can be emitted as a plist: - # String, Float, DateTime, Integer, TrueClass, FalseClass, Array, Hash - # - # Write me if you think another class can be coerced safely into one of the - # expected plist classes (plist@hexane.org) - def to_plist( header = true ) - if (header) - Plist::_xml(self.to_plist_fragment) - else - self.to_plist_fragment - end - end - end -end - -class String - include Plist::Emit - def to_plist_fragment - "<string>#{self}</string>" - end -end - -class Symbol - include Plist::Emit - def to_plist_fragment - "<string>#{self}</string>" - end -end - -class Float - include Plist::Emit - def to_plist_fragment - "<real>#{self}</real>" - end -end - -class Time - include Plist::Emit - def to_plist_fragment - "<date>#{self.utc.strftime('%Y-%m-%dT%H:%M:%SZ')}</date>" - end -end - -class Date - include Plist::Emit - def to_plist_fragment - "<date>#{self.strftime('%Y-%m-%dT%H:%M:%SZ')}</date>" - end -end - -class Integer - include Plist::Emit - def to_plist_fragment - "<integer>#{self}</integer>" - end -end - -class FalseClass - include Plist::Emit - def to_plist_fragment - "<false/>" - end -end - -class TrueClass - include Plist::Emit - def to_plist_fragment - "<true/>" - end -end - -class Array - include Plist::Emit - def to_plist_fragment - fragment = "<array>\n" - self.each do |e| - element_plist = e.to_plist_fragment - element_plist.each do |l| - fragment += "\t#{l.chomp}\n" - end - end - fragment += "</array>" - fragment - end end - -class Hash - include Plist::Emit - def to_plist_fragment - fragment = "<dict>\n" - self.keys.sort.each do |k| - fragment += "\t<key>#{k}</key>\n" - element_plist = self[k].to_plist_fragment - element_plist.each do |l| - fragment += "\t#{l.chomp}\n" - end - end - fragment += "</dict>" - fragment - end -end - -require 'stringio' -[ IO, StringIO ].each do |io_class| - io_class.module_eval do - include Plist::Emit - def to_plist_fragment - self.rewind - data = self.read - - output = "<data>\n" - Base64::encode64(data).gsub(/\s+/, '').scan(/.{1,68}/o) { output << $& << "\n" } - output << "</data>" - - output - end - end -end
\ No newline at end of file |