nokogiri-plist 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README.rdoc +80 -0
- data/lib/nokogiri/plist/generator.rb +82 -0
- data/lib/nokogiri/plist/parser.rb +60 -0
- data/lib/nokogiri/plist.rb +11 -0
- data/lib/nokogiri/xml/node.rb +15 -0
- data/lib/nokogiri-plist.rb +10 -0
- data/lib/string.rb +7 -0
- metadata +90 -0
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,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
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
|
+
|