nokogiri-plist 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 Casey Howard
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,80 @@
1
+ = Nokogiri-PList
2
+
3
+ == DESCRIPTION:
4
+
5
+ Nokogiri-plist provides the functionality for dealing with XML in Apple's property list format.
6
+
7
+ There is already a plist gem (http://github.com/bleything/plist) that has similar functionality. I didn't realize it until I had written most of this gem. However this gem uses Nokogiri, so the implementation is simpler. The plist gem does it's own XML parsing. I figured since I was already using Nokogiri in my project, it's better to build on top of that. I did get ideas from the original gem. I have benchmarked my gem against that gem and it performs similarly. Once I come up with a little more scientific benchmarks, I'll show them.'
8
+
9
+
10
+ == FEATURES:
11
+
12
+ * Parsers plist files into simple basic Ruby objects
13
+ * Generates plist XML from Ruby objects
14
+ * Uses the awesome Nokogiri gem
15
+
16
+
17
+ == USAGE:
18
+
19
+ Sample plist (test.plist)
20
+
21
+ <plist>
22
+ <dict>
23
+ <key>Beers</key>
24
+ <array>
25
+ <string>Black Butte</string>
26
+ <string>Steel Reserve</string>
27
+ <string>Bass Pale Ale</string>
28
+ </array>
29
+ <key>Beer Drinker</key><string>Casey</key>
30
+ <key>Beers Drank</key><integer>4123</integer>
31
+ </dict>
32
+ </plist>
33
+
34
+
35
+ > require 'nokogiri-plist'
36
+
37
+ > plist = Nokogiri::PList(open('test.plist'))
38
+ => { "Beers" => ["Black Butte", "Steel Reserve", "Bass Pale Ale"], "Beers Drank" => 4123, "Beer Drinker" => "Casey"}
39
+
40
+ > plist["Beers"]
41
+ => ["Black Butte", "Steel Reserve", "Bass Pale Ale"]
42
+
43
+ > plist["Beer Drinker"]
44
+ => "Casey"
45
+
46
+ > puts plist.to_plist_xml
47
+ <dict>
48
+ <key>Beers</key>
49
+ <array>
50
+ <string>Black Butte</string>
51
+ <string>Steel Reserve</string>
52
+ <string>Bass Pale Ale</string>
53
+ </array>
54
+ <key>Beers Drank</key><integer>4123</integer>
55
+ <key>Beer Drinker</key><string>Casey</string>
56
+ </dict>
57
+
58
+ > "beer".to_plist_xml
59
+ => "<string>beer</string>"
60
+
61
+ > puts (1..3).to_a.to_plist_xml
62
+ <array>
63
+ <integer>1</integer>
64
+ <integer>2</integer>
65
+ <integer>3</integer>
66
+ </array>
67
+
68
+ == REQUIREMENTS:
69
+
70
+ * ruby 1.9 (I'll eventually make sure it works in 1.8, but I'm using 1.9 at the moment)
71
+ * nokogiri
72
+ * shoulda and mocha (only if you want to run the tests)
73
+
74
+
75
+ == INSTALL:
76
+
77
+ I haven't published this gem yet, but once I write tests and more documentation the following will work:
78
+
79
+ * gem install nokogiri-plist
80
+
@@ -0,0 +1,82 @@
1
+ module Nokogiri
2
+
3
+ module PList
4
+
5
+ class Generator
6
+
7
+ def self.indent_size
8
+ 2
9
+ end
10
+
11
+ def self.to_s(value, current_indent = 0)
12
+ case value
13
+ when Array
14
+ tag("array", nil, current_indent) do
15
+ value.inject("") do |result, item|
16
+ result + item.to_plist_xml_unchomped(current_indent + 1)
17
+ end
18
+ end
19
+ when Hash
20
+ tag("dict", nil, current_indent) do
21
+ value.inject("") do |result, (dict_key, dict_value)|
22
+ result + tag("key", dict_key, current_indent + 1).chomp +
23
+ dict_value.to_plist_xml_unchomped
24
+ end
25
+ end
26
+ when TrueClass
27
+ tag("true", nil, current_indent)
28
+ when FalseClass
29
+ tag("false", nil, current_indent)
30
+ when Time
31
+ tag("date", value.utc.strftime('%Y-%m-%dT%H:%M:%SZ'), current_indent)
32
+ when Date # also catches DateTime
33
+ tag("date", value.strftime('%Y-%m-%dT%H:%M:%SZ'), current_indent)
34
+ when String, Symbol
35
+ tag("string", value, current_indent)
36
+ when Fixnum, Bignum, Integer
37
+ tag("integer", value, current_indent)
38
+ when Float
39
+ tag("real", value, current_indent)
40
+ end
41
+ end
42
+
43
+ def self.indent(number)
44
+ " " * (number * indent_size)
45
+ end
46
+
47
+ def self.array_or_hash?(item)
48
+ item.is_a?(Hash) or item.is_a?(Array)
49
+ end
50
+
51
+ def self.tag(name, content=nil, current_indent=0, &block)
52
+ if content or block_given?
53
+ new_line = (["array", "dict"].include? name) ? "\n" : ""
54
+ closing_tag_indent = (new_line != "\n") ? 0 : current_indent
55
+ indent(current_indent) + "<#{name}>" + new_line +
56
+ (block_given? ? yield : content).to_s +
57
+ indent(closing_tag_indent) + "</#{name}>\n"
58
+ else
59
+ indent(current_indent) + "<#{name}/>\n"
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ [String, Symbol, Integer, Float, Date, Time, Hash, Array, TrueClass, FalseClass].each do |klass|
69
+
70
+ klass.class_eval do
71
+
72
+ def to_plist_xml(current_indent = 0)
73
+ self.to_plist_xml_unchomped(current_indent).chomp
74
+ end
75
+
76
+ def to_plist_xml_unchomped(current_indent = 0)
77
+ Nokogiri::PList::Generator.to_s(self, current_indent)
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -0,0 +1,60 @@
1
+ module Nokogiri
2
+
3
+ module PList
4
+
5
+ class Parser
6
+
7
+ def parse(xml)
8
+ @converters = {
9
+ 'integer' => Proc.new { |node| node.content.to_i },
10
+ 'real' => Proc.new { |node| node.content.to_f },
11
+ 'string' => Proc.new { |node| node.content.to_s },
12
+ 'date' => Proc.new { |node| DateTime.parse(node.content) },
13
+ 'true' => Proc.new { |node| true },
14
+ 'false' => Proc.new { |node| false },
15
+ 'dict' => Proc.new { |node| parse_dict node },
16
+ 'array' => Proc.new { |node| parse_array node },
17
+ 'data' => Proc.new { |node| node.content }
18
+ }
19
+ plist = xml.xpath('/plist').first
20
+ parse_value_node next_valid_sibling(plist.children.first)
21
+ end
22
+
23
+ def parse_value_node(value_node)
24
+ @converters[value_node.name].call(value_node)
25
+ end
26
+
27
+ def valid_type?(type)
28
+ not @converters[type].nil?
29
+ end
30
+
31
+ def valid_node?(node)
32
+ valid_type?(node.name) or node.name == "key"
33
+ end
34
+
35
+ def parse_dict(node)
36
+ node.xpath('./key').inject({}) do |return_value, key_node|
37
+ return_value[key_node.content] = parse_value_node(next_valid_sibling key_node)
38
+ return_value
39
+ end
40
+ end
41
+
42
+ def parse_array(node)
43
+ node.children.inject([]) do |return_value, node|
44
+ return_value << parse_value_node(node) if valid_node? node
45
+ return_value
46
+ end
47
+ end
48
+
49
+ def next_valid_sibling(node)
50
+ until node.nil? or valid_type? node.name
51
+ node = node.next_sibling
52
+ end
53
+ node
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,11 @@
1
+ module Nokogiri
2
+
3
+ class << self
4
+
5
+ def PList(xml)
6
+ Nokogiri::PList::Parser.new.parse(Nokogiri::XML(xml))
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,15 @@
1
+ module Nokogiri
2
+
3
+ module XML
4
+
5
+ class Node
6
+
7
+ def to_plist
8
+ Nokogiri::PList::Parser.new.parse(self)
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,10 @@
1
+
2
+ require 'nokogiri'
3
+ require 'date'
4
+
5
+ # TODO: Do this a not so stupid way
6
+ require File.join(File.dirname(__FILE__), 'string')
7
+ require File.join(File.dirname(__FILE__), 'nokogiri', 'plist', 'generator')
8
+ require File.join(File.dirname(__FILE__), 'nokogiri', 'plist', 'parser')
9
+ require File.join(File.dirname(__FILE__), 'nokogiri', 'plist')
10
+ require File.join(File.dirname(__FILE__), 'nokogiri', 'xml', 'node')
data/lib/string.rb ADDED
@@ -0,0 +1,7 @@
1
+ String.class_eval do
2
+
3
+ define_method :to_plist do
4
+ Nokogiri::PList(self)
5
+ end
6
+
7
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nokogiri-plist
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
+ platform: ruby
12
+ authors:
13
+ - Casey Howard
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-27 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ description: Allows Nokogiri objects to be converted to PLists
36
+ email:
37
+ - caseyhoward@caseyhoward.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - lib/nokogiri-plist.rb
46
+ - lib/string.rb
47
+ - lib/nokogiri/plist/parser.rb
48
+ - lib/nokogiri/plist/generator.rb
49
+ - lib/nokogiri/xml/node.rb
50
+ - lib/nokogiri/plist.rb
51
+ - LICENSE
52
+ - README.rdoc
53
+ has_rdoc: true
54
+ homepage: http://github.com/caseyhoward/nokogiri-plist
55
+ licenses: []
56
+
57
+ post_install_message:
58
+ rdoc_options: []
59
+
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ hash: 3
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 23
77
+ segments:
78
+ - 1
79
+ - 3
80
+ - 6
81
+ version: 1.3.6
82
+ requirements: []
83
+
84
+ rubyforge_project: nokogiri-plist
85
+ rubygems_version: 1.3.7
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: PList parsing capabilities built using Nokogiri
89
+ test_files: []
90
+