xmlparsable 1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # XmlParsable
2
+
3
+ XmlParsable is a simple means to declare how an XML grammar maps to Ruby objects. It does not
4
+ perform validation of the input, and it is only able to describe fairly simple structures. It
5
+ relies on LibXML::XML::SaxParser.
6
+
7
+ 1. Declare XML grammar
8
+
9
+ require "xmlparsable"
10
+
11
+ # Needed only for using the "collection" declaration or
12
+ # implement your own String#pluralize, String#singularize
13
+ require "active_support/core_ext"
14
+
15
+ class AddressBook
16
+ include XmlParsable
17
+
18
+ class Contact
19
+ include XmlParsable
20
+ element :givenname
21
+ element :familyname
22
+ element :phone
23
+ element :email
24
+ element :spouse, Contact
25
+ collection :children, Contact
26
+ element :birthdate, DateElement
27
+ element :updated, TimeElement
28
+ end
29
+
30
+ collection :contact, Contact
31
+ end
32
+
33
+ 2. Parse input XML from string, IO, or File
34
+
35
+ book = AddressBook.parse(<<-XML)
36
+ <contacts>
37
+ <contact>
38
+ <familyname>Kim</familyname>
39
+ <givenname>Jong-il</givenname>
40
+ <birthdate>1942-02-16</birthdate>
41
+ <updated>2010-01-01T12:45:30</updated>
42
+ <children>
43
+ <child><givenname>Sul-song</givenname></child>
44
+ <child><givenname>Jong-chul</givenname></child>
45
+ <child><givenname>Jong-un</givenname></child>
46
+ <child>
47
+ <givenname>Jong-nam</givenname>
48
+ <spouse>
49
+ <givenname>Jong-hui</givenname>
50
+ <familyname>Shin</familyname>
51
+ </spouse>
52
+ </child>
53
+ </children>
54
+ </contact>
55
+
56
+ <contact>
57
+ <givenname>Vladimir</givenname>
58
+ <familyname>Putin</familyname>
59
+ <email>vlad@gmail.com</email>
60
+ <spouse>
61
+ <givenname>Lyudmila</givenname>
62
+ <familyname>Putina</familyname>
63
+ </spouse>
64
+ </contact>
65
+ </contacts>
66
+ XML
67
+
68
+ 3. Iterate parsed data
69
+
70
+ kim, vlad = book.contacts
71
+ kim.givenname #=> "Kim"
72
+ kim.birthdate #=> #<Date: 4860813/2,0,2299161>
73
+ kim.updated #=> Fri Jan 01 12:45:30 2010
74
+
75
+ sulsong, jongchul, jongun, jongnam = kim.children
76
+ jongnam.spouse.givenname #=> "Jong-hui"
77
+ jongnam.spouse.familyname #=> "Shin"
78
+
79
+ vlad.email #=> "vlad@gmail.com"
80
+ vlad.spouse #=> #<AddressBook::Contact @givenname="Lyudmila" @familyname="Putina">
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ begin
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new do |t|
5
+ t.verbose = false
6
+ t.pattern = "spec/examples/**/*.example"
7
+ t.rspec_opts = ["--color", "--format=p"]
8
+ end
9
+ rescue LoadError
10
+ require "spec/rake/spectask"
11
+
12
+ Spec::Rake::SpecTask.new do |t|
13
+ t.pattern = "spec/examples/**/*.example"
14
+ t.spec_opts << "--color"
15
+ t.spec_opts << "--format=p"
16
+ end
17
+ end
18
+
19
+ task :default => :spec
@@ -0,0 +1,21 @@
1
+ module XmlParsable
2
+ module Elements
3
+ class AbstractElement
4
+ def self.parsable
5
+ self
6
+ end
7
+
8
+ def open(name, attributes)
9
+ end
10
+
11
+ def read(text)
12
+ end
13
+
14
+ def comment(text)
15
+ end
16
+
17
+ def finalize
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ require "date"
2
+
3
+ module XmlParsable
4
+ module Elements
5
+ #
6
+ # Parses content into a ruby Date value
7
+ #
8
+ class DateElement < AbstractElement
9
+ attr_reader :name
10
+
11
+ def initialize(name, attributes, parent, *arguments)
12
+ @name, @parent, @string = name, parent, ""
13
+ end
14
+
15
+ def read(text)
16
+ @string << text
17
+ end
18
+
19
+ def finalize
20
+ stripped = @string.strip
21
+ @parent.closed(self, Date.parse(stripped)) if stripped != ""
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ module XmlParsable
2
+ module Elements
3
+
4
+ class ListElement < AbstractElement
5
+ attr_reader :name
6
+
7
+ def initialize(name, attributes, parent, *arguments)
8
+ @name, @parent, @elements = name, parent, []
9
+
10
+ @cname = arguments.shift.to_s
11
+ @cparser = arguments.shift
12
+ @cargs = arguments
13
+ end
14
+
15
+ def open(name, attributes)
16
+ if name == @cname
17
+ @cparser.parsable.new(name, attributes, self, *@cargs)
18
+ end
19
+ end
20
+
21
+ def closed(element, value)
22
+ @elements << value
23
+ end
24
+
25
+ def finalize
26
+ @parent.closed(self, @elements)
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,48 @@
1
+ module XmlParsable
2
+ module Elements
3
+ class RecordElement < AbstractElement
4
+ attr_reader :name, :attributes, :parent, :target
5
+
6
+ def initialize(name, attributes, parent, target, parsers, *arguments)
7
+ @name = name
8
+ @attributes = attributes
9
+ @parent = parent
10
+ @target = target
11
+ @parsers = parsers
12
+ @elements = Hash.new
13
+ end
14
+
15
+ def open(name, attributes)
16
+ parser, *arguments = @parsers[name]
17
+ if parser
18
+ parser.new(name, attributes, self, *arguments)
19
+ end
20
+ end
21
+
22
+ def closed(element, value)
23
+ parser, *arguments = @parsers[element.name]
24
+ if arguments.include?(:repeated)
25
+ (@elements[element.name] ||= []) << value
26
+ else
27
+ @elements[element.name] = value
28
+ end
29
+ end
30
+
31
+ def finalize
32
+ @elements.each{|name, value| @target.instance_variable_set("@#{name}", value) }
33
+ @parent.closed(self, @target) if @parent
34
+ end
35
+
36
+ class Proxy
37
+ def initialize(base, parsers)
38
+ @base, @parsers = base, parsers
39
+ end
40
+
41
+ def new(name, attributes, parent, *arguments)
42
+ RecordElement.new(name, attributes, parent, @base.new, @parsers)
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ module XmlParsable
2
+ module Elements
3
+ #
4
+ # Parses content into a ruby String value. This discards comments and children
5
+ # elements so "abc <!-- foo --> def <b>whatever</b>" is read as "abc def"
6
+ #
7
+ class StringElement < AbstractElement
8
+ attr_reader :name
9
+
10
+ def initialize(name, attributes, parent, *arguments)
11
+ @name, @parent, @string = name, parent, ""
12
+ end
13
+
14
+ def read(text)
15
+ @string << text
16
+ end
17
+
18
+ def finalize
19
+ @parent.closed(self, @string)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ module XmlParsable
2
+ module Elements
3
+ #
4
+ # Parses content into a ruby String value. Discards comments and flattens children
5
+ # elements so "abc def <b>what<!-- foo -->ever</b>" is read as "abc def whatever"
6
+ #
7
+ class TextElement < XmlElement::Node
8
+ attr_reader :name, :attributes, :parent
9
+
10
+ def initialize(name, attributes, parent, *arguments)
11
+ @name, @attributes, @parent, @text = name, attributes, parent, ""
12
+ end
13
+
14
+ def open(name, attributes)
15
+ TextElement.new(name, attributes, self)
16
+ end
17
+
18
+ def read(text)
19
+ @text << text
20
+ end
21
+
22
+ def comment(text)
23
+ end
24
+
25
+ def closed(element, value)
26
+ @text << value
27
+ end
28
+
29
+ def finalize
30
+ @parent.closed(self, @text)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,25 @@
1
+ require "time"
2
+
3
+ module XmlParsable
4
+ module Elements
5
+ #
6
+ # Parses content into a ruby Time value
7
+ #
8
+ class TimeElement < AbstractElement
9
+ attr_reader :name
10
+
11
+ def initialize(name, attributes, parent, *arguments)
12
+ @name, @parent, @string = name, parent, ""
13
+ end
14
+
15
+ def read(text)
16
+ @string << text
17
+ end
18
+
19
+ def finalize
20
+ stripped = @string.strip
21
+ @parent.closed(self, Time.parse(stripped)) if stripped != ""
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,79 @@
1
+ module XmlParsable
2
+ module Elements
3
+ #
4
+ # Parses content into a generic tree structure, consisting of three
5
+ # classes -- Node, Text, and Comment.
6
+ #
7
+ class XmlElement
8
+
9
+ def self.parsable
10
+ Node
11
+ end
12
+
13
+ class Node < AbstractElement
14
+ attr_reader :name, :attributes, :parent, :children
15
+
16
+ def initialize(name, attributes, parent, *arguments)
17
+ @parent, @name, @attributes, @children = parent, name, attributes, Array.new
18
+ end
19
+
20
+ def open(name, attributes)
21
+ Node.new(name, attributes, self)
22
+ end
23
+
24
+ def read(text)
25
+ @children << Text.new(text, self)
26
+ end
27
+
28
+ def comment(text)
29
+ @children << Comment.new(text, self)
30
+ end
31
+
32
+ def closed(element, value)
33
+ @children << value
34
+ end
35
+
36
+ def finalize
37
+ @parent.closed(self, self)
38
+ end
39
+
40
+ def to_s(buffer = "")
41
+ buffer << "<#{@name}"
42
+ @attributes.each{|name, value| buffer << %[ #{name}='#{value}'] }
43
+
44
+ if @children.empty?
45
+ buffer << "/>"
46
+ else
47
+ buffer << ">"
48
+ @children.each{|child| child.to_s(buffer) }
49
+ buffer << "</#{@name}>"
50
+ end
51
+ end
52
+ end
53
+
54
+ class Text
55
+ attr_reader :text, :parent
56
+
57
+ def initialize(text, parent)
58
+ @text, @parent = text, parent
59
+ end
60
+
61
+ def to_s(buffer = "")
62
+ buffer << @text
63
+ end
64
+ end
65
+
66
+ class Comment
67
+ attr_reader :text, :parent
68
+
69
+ def initialize(text, parent)
70
+ @text, @parent = text, parent
71
+ end
72
+
73
+ def to_s(buffer = "")
74
+ buffer << "<!--" << @text << "-->"
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,12 @@
1
+ module XmlParsable
2
+ module Elements
3
+ autoload :AbstractElement, "xmlparsable/elements/abstract"
4
+ autoload :DateElement, "xmlparsable/elements/date"
5
+ autoload :ListElement, "xmlparsable/elements/list"
6
+ autoload :RecordElement, "xmlparsable/elements/record"
7
+ autoload :StringElement, "xmlparsable/elements/string"
8
+ autoload :TextElement, "xmlparsable/elements/text"
9
+ autoload :TimeElement, "xmlparsable/elements/time"
10
+ autoload :XmlElement, "xmlparsable/elements/xml"
11
+ end
12
+ end
@@ -0,0 +1,42 @@
1
+ module XmlParsable
2
+ class Parser
3
+ attr_reader :documents
4
+
5
+ def initialize(constructed = nil, &constructor)
6
+ @documents = Array.new
7
+ @constructor = constructor || lambda { constructed }
8
+ end
9
+
10
+ def on_start_document
11
+ @stack = [@constructor.call]
12
+ end
13
+
14
+ def on_end_document
15
+ @documents << @stack.shift.finalize
16
+ end
17
+
18
+ def on_characters(text)
19
+ @stack.first.read(text)
20
+ end
21
+
22
+ def on_comment(comment)
23
+ @stack.first.comment(comment)
24
+ end
25
+
26
+ def on_start_element_ns(name, attributes, prefix, uri, namespaces)
27
+ @stack.unshift(@stack.first.open(name, attributes) || StubElement)
28
+ end
29
+
30
+ def on_end_element_ns(name, prefix, uri)
31
+ @stack.shift.finalize
32
+ end
33
+
34
+ module StubElement
35
+ def self.open(name, attributes) self end
36
+ def self.close(element, value) end
37
+ def self.comment(text) end
38
+ def self.read(text) end
39
+ def self.finalize; end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,74 @@
1
+ require "libxml"
2
+
3
+ module XmlParsable
4
+
5
+ autoload :Parser, "xmlparsable/parser"
6
+ autoload :Elements, "xmlparsable/elements"
7
+
8
+ def self.parser(input)
9
+ case input
10
+ when String then LibXML::XML::SaxParser.string(input)
11
+ when File then LibXML::XML::SaxParser.file(input)
12
+ when IO then LibXML::XML::SaxParser.io(input)
13
+ else raise ArgumentError, "argument must be a String, File, or IO"
14
+ end
15
+ end
16
+
17
+ def self.included(base)
18
+ base.extend(ClassMethods)
19
+ base.__send__(:include, Elements)
20
+ end
21
+
22
+ module ClassMethods
23
+ def element(name, *arguments)
24
+ element ||= arguments.pop.delete(:class) if arguments.last.is_a?(Hash)
25
+ element ||= arguments.shift if arguments.first.is_a?(Class)
26
+ element ||= Elements::StringElement
27
+
28
+ (@parsers ||= {})[name.to_s] = [element.parsable, *arguments]
29
+
30
+ define_method(name) { instance_variable_get("@#{name}") }
31
+ end
32
+
33
+ def repeated(name, *arguments)
34
+ element ||= arguments.pop.delete(:class) if arguments.last.is_a?(Hash)
35
+ element ||= arguments.shift if arguments.first.is_a?(Class)
36
+ element ||= Elements::StringElement
37
+
38
+ (@parsers ||= {})[name.to_s.singularize] = [element.parsable, *arguments.push(:repeated)]
39
+
40
+ define_method(name) { instance_variable_get("@#{name.to_s.singularize}") }
41
+ end
42
+
43
+ def collection(name, *arguments)
44
+ item ||= arguments.pop.delete(:class) if arguments.last.is_a?(Hash)
45
+ item ||= arguments.shift if arguments.first.is_a?(Class)
46
+ item ||= Elements::StringElement
47
+
48
+ if arguments.empty?
49
+ single = name.to_s.singularize
50
+ plural = name.to_s.pluralize
51
+ else
52
+ plural = name
53
+ single = arguments.shift
54
+ end
55
+
56
+ element(plural, Elements::ListElement, single, item)
57
+ end
58
+
59
+ def parse(input)
60
+ root = XmlParsable::Elements::RecordElement.new(nil, nil, nil, new, @parsers)
61
+ stack = XmlParsable::Parser.new(root)
62
+ parser = XmlParsable.parser(input)
63
+
64
+ parser.callbacks = stack
65
+ parser.parse
66
+ root.target
67
+ end
68
+
69
+ def parsable
70
+ Elements::RecordElement::Proxy.new(self, @parsers)
71
+ end
72
+ end
73
+
74
+ end
@@ -0,0 +1,229 @@
1
+ require "spec_helper"
2
+
3
+ describe XmlParsable::Elements::RecordElement do
4
+
5
+ class Record
6
+ include XmlParsable
7
+
8
+ element :date, DateElement
9
+ element :record, self
10
+ element :string, StringElement
11
+ element :text, TextElement
12
+ element :time, TimeElement
13
+ element :xml, XmlElement
14
+
15
+ collection :kids, self
16
+ collection :list, :item
17
+ end
18
+
19
+ describe "date" do
20
+ it "parses date into a ruby Date" do
21
+ Record.parse("<date>#{Date.today}</date>").date.should == Date.today
22
+ end
23
+
24
+ it "parses missing date as nil" do
25
+ Record.parse("<date><!-- nope --></date>").date.should == nil
26
+ end
27
+
28
+ it "ignores children" do
29
+ Record.parse("<date><x>2010-01-01</x></date>").date.should == nil
30
+ end
31
+
32
+ it "ignores comments" do
33
+ Record.parse("<date>#{Date.today} <!-- that's today --></date>").date.should == Date.today
34
+ end
35
+
36
+ it "ignores whitespace" do
37
+ Record.parse("<date>\n #{Date.today}\n </date>").date.should == Date.today
38
+ end
39
+ end
40
+
41
+ describe "list of strings" do
42
+ it "parses empty list into an empty Array" do
43
+ Record.parse("<list/>").list.should == []
44
+ end
45
+
46
+ it "parses non-empty list into an Array" do
47
+ Record.parse("<list><item>a</item><item>b</item></list>").list.should == ["a", "b"]
48
+ end
49
+
50
+ it "ignores non-matching children" do
51
+ Record.parse("<list><fail/><item/><boat/><item/><item/></list>").list.should == ["", "", ""]
52
+ end
53
+
54
+ it "ignores comments" do
55
+ Record.parse("<list><!-- <item>x</item> --><item><!-- y --></item></list>").list.should == [""]
56
+ end
57
+
58
+ it "ignores whitespace between children" do
59
+ Record.parse(<<-XML).list.should == ["a", "b", "c"]
60
+ <list>
61
+ <item>a</item>
62
+ <item>b</item>
63
+ <item>c</item>
64
+ </list>
65
+ XML
66
+ end
67
+ end
68
+
69
+ describe "list of records" do
70
+ it "parses empty list into an empty Array" do
71
+ Record.parse("<kids/>").kids.should == []
72
+ end
73
+
74
+ it "parses non-empty list into an array" do
75
+ x = Record.parse(<<-XML)
76
+ <kids>
77
+ <kid><text>first</text></kid>
78
+ <kid><text>second</text></kid>
79
+ <kid><text>third</text></kid>
80
+ </kids>
81
+ XML
82
+
83
+ x.kids.should have(3).items
84
+ x.kids[0].text.should == "first"
85
+ x.kids[1].text.should == "second"
86
+ x.kids[2].text.should == "third"
87
+ end
88
+ end
89
+
90
+ describe "string" do
91
+ it "parses empty string" do
92
+ Record.parse("<string></string>").string.should == ""
93
+ end
94
+
95
+ it "parses non-empty string" do
96
+ Record.parse("<string>lo and behold</string>").string.should == "lo and behold"
97
+ end
98
+
99
+ it "ignores comments" do
100
+ Record.parse("<string>hi<!-- secret message --></string>").string.should == "hi"
101
+ end
102
+
103
+ it "ignores children" do
104
+ Record.parse("<string><b>bold</b>, <i>italic</i>, plain</string>").string.should == ", , plain"
105
+ end
106
+
107
+ it "does not ignore whitespace" do
108
+ Record.parse("<string> foob ar</string>").string.should == " foob ar"
109
+ end
110
+ end
111
+
112
+ describe "text" do
113
+ it "parses text" do
114
+ Record.parse("<text>lo and behold</text>").text.should == "lo and behold"
115
+ end
116
+
117
+ it "ignores comments" do
118
+ Record.parse("<text>lo <!--and--> behold</text>").text.should == "lo behold"
119
+ end
120
+
121
+ it "strips away markup" do
122
+ Record.parse("<text>lo <span class='x'><i>and</i> behold</span></text>").text.should == "lo and behold"
123
+ end
124
+
125
+ it "does not ignore whitespace" do
126
+ Record.parse("<text> foob ar</text>").text.should == " foob ar"
127
+ end
128
+ end
129
+
130
+ describe "time" do
131
+ it "parses time" do
132
+ time = Time.now
133
+ Record.parse("<time>#{time}</time>").time.to_i.should == time.to_i
134
+ end
135
+
136
+ it "ignores comments" do
137
+ Record.parse("<time><!-- #{Time.now} --></time>").time.should be_nil
138
+ end
139
+
140
+ it "ignores children" do
141
+ Record.parse("<time><b>#{Time.now}</b></time>").time.should be_nil
142
+ end
143
+
144
+ it "ignores whitespace" do
145
+ time = Time.now
146
+ Record.parse("<time> #{time} </time>").time.to_i.should == time.to_i
147
+ end
148
+ end
149
+
150
+ describe "record" do
151
+ it "parses date" do
152
+ x = Record.parse("<record><date>#{Date.today}</date></record>")
153
+ x.date.should be_nil
154
+ x.record.date.should == Date.today
155
+ end
156
+
157
+ it "parses list" do
158
+ x = Record.parse("<record><list/></record>")
159
+ x.list.should be_nil
160
+ x.record.list.should == []
161
+ end
162
+
163
+ it "parses string" do
164
+ x = Record.parse("<record><string>abc</string></record>")
165
+ x.string.should be_nil
166
+ x.record.string.should == "abc"
167
+ end
168
+
169
+ it "parses text" do
170
+ x = Record.parse("<record><text><b>big</b><i>little</i></text></record>")
171
+ x.text.should be_nil
172
+ x.record.text.should == "biglittle"
173
+ end
174
+
175
+ it "parses time" do
176
+ time = Time.now
177
+ Record.parse("<record><time>#{time}</time></record>").record.time.to_i.should == time.to_i
178
+ end
179
+
180
+ it "parses multiple elements" do
181
+ time = Time.now
182
+ x = Record.parse <<-XML
183
+ <record>
184
+ <date>#{Date.today}</date>
185
+ <list>
186
+ <item>a</item>
187
+ <item>b</item>
188
+ <item>c</item>
189
+ </list>
190
+ <string>xyz</string>
191
+ <text>
192
+ <ul>
193
+ <li>vim</li>
194
+ <li>emacs</li>
195
+ <li>ctags</li>
196
+ <li>lint</li>
197
+ <li>gdb</li>
198
+ </ul>
199
+ </text>
200
+ <time>#{time}</time>
201
+ </record>
202
+ XML
203
+
204
+ x.record.date.should == Date.today
205
+ x.record.list.should == ["a","b","c"]
206
+ x.record.string.should == "xyz"
207
+ x.record.text.strip.should == <<-DOC.strip
208
+ vim
209
+ emacs
210
+ ctags
211
+ lint
212
+ gdb
213
+ DOC
214
+
215
+ x.record.time.to_i.should == time.to_i
216
+ end
217
+
218
+ it "parses recursive records" do
219
+ x = Record.parse("<record><record><record><record></record></record></record></record>")
220
+ x.should be_a(Record)
221
+ x.record.should be_a(Record)
222
+ x.record.record.should be_a(Record)
223
+ x.record.record.record.should be_a(Record)
224
+ x.record.record.record.record.should be_a(Record)
225
+ x.record.record.record.record.record.should be_nil
226
+ end
227
+ end
228
+
229
+ end
@@ -0,0 +1,13 @@
1
+ begin
2
+ require "rspec"
3
+ rescue LoadError
4
+ require "spec"
5
+ end
6
+
7
+ spec = File.dirname(__FILE__)
8
+
9
+ $:.unshift(spec)
10
+ $:.unshift(File.dirname(spec) + "/lib")
11
+
12
+ require "xmlparsable"
13
+ require "active_support/core_ext"
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xmlparsable
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kyle Putnam
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-14 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Simple declarative XML parsing
15
+ email: putnam.kyle@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - README.md
21
+ - Rakefile
22
+ - lib/xmlparsable/elements/abstract.rb
23
+ - lib/xmlparsable/elements/date.rb
24
+ - lib/xmlparsable/elements/list.rb
25
+ - lib/xmlparsable/elements/record.rb
26
+ - lib/xmlparsable/elements/string.rb
27
+ - lib/xmlparsable/elements/text.rb
28
+ - lib/xmlparsable/elements/time.rb
29
+ - lib/xmlparsable/elements/xml.rb
30
+ - lib/xmlparsable/elements.rb
31
+ - lib/xmlparsable/parser.rb
32
+ - lib/xmlparsable.rb
33
+ - spec/examples/record.example
34
+ - spec/spec_helper.rb
35
+ homepage: https://github.com/kputnam/xmlparsable
36
+ licenses: []
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 1.8.24
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: Simple declarative XML parsing
59
+ test_files:
60
+ - spec/examples/record.example