decontaminate 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +7 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +13 -0
- data/README.md +172 -0
- data/Rakefile +6 -0
- data/bin/pry +16 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/decontaminate.gemspec +32 -0
- data/lib/decontaminate/decoder/array.rb +19 -0
- data/lib/decontaminate/decoder/child_node_proxy.rb +17 -0
- data/lib/decontaminate/decoder/hash.rb +17 -0
- data/lib/decontaminate/decoder/scalar.rb +38 -0
- data/lib/decontaminate/decontaminator.rb +109 -0
- data/lib/decontaminate/version.rb +3 -0
- data/lib/decontaminate.rb +4 -0
- metadata +174 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 391a40ec6c400fea8dd7e0e0e236ccb54dd0d64c
|
4
|
+
data.tar.gz: ebc11740db0cd3ca3aa55dddcd6854a5b1b21d34
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5ce173bd8e3aa615abc225a2cd5dc921fbff1e7ed0509d7dd485c5670f8d398acfbdefadef498bb9a0a6ec1b1d1666f9a5557cf856d042f4f2d452bd104d981e
|
7
|
+
data.tar.gz: 151a004aafa09dfe7778e0d55ee5374a2d59ac6393f8ecba57e46ef27b573e64f38e780afb0afbb148f6599bd846f5954d3eee767ff234ac2b90741fef57a90b
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2015, Alexis King
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose
|
4
|
+
with or without fee is hereby granted, provided that the above copyright notice
|
5
|
+
and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
8
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
9
|
+
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
10
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
11
|
+
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
12
|
+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
13
|
+
THIS SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
# Decontaminate
|
2
|
+
|
3
|
+
Decontaminate is a tool for extracting information from large, potentially nested XML documents. It provides a simple Ruby DSL for selecting values from Nokogiri objects and storing the results in JSON-like Ruby hashes and arrays.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'decontaminate'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install decontaminate
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Decontaminate provides a DSL for creating *decontaminators*, which, when instantiated, accept XML nodes or documents and produce a hash as a result. To start, create a class that inherits from `Decontaminate::Decontaminator`:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
class MyDecontaminator < Decontaminate::Decontaminator
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
If parsing an entire document, you should specify the name of the root element:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
class MyDecontaminator < Decontaminate::Decontaminator
|
34
|
+
self.root = 'User'
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
### Scalar Values
|
39
|
+
|
40
|
+
To select values from the XML document, use the `scalar` class method:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
class MyDecontaminator < Decontaminate::Decontaminator
|
44
|
+
self.root = 'User'
|
45
|
+
|
46
|
+
scalar 'Name'
|
47
|
+
scalar 'Age', type: :integer
|
48
|
+
scalar 'DateRegistered', key: 'registered_at'
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
This might produce a result like the following:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
=> MyDecontaminator.new(xml_document).as_json
|
56
|
+
{
|
57
|
+
'name' => 'Jane Smith',
|
58
|
+
'age' => 28,
|
59
|
+
'registered_at' => '2013-08-16T20:51:34.236Z'
|
60
|
+
}
|
61
|
+
```
|
62
|
+
|
63
|
+
The first argument to `scalar` is the name of the node to extract data from. In fact, this can be any XPath string relative to the document root. By default, the resulting JSON key is inferred from the provided path, but it can also be overridden with the `key:` argument. Additionally, the type of the scalar can be specified with the `type:` argument, which defaults to `:string`.
|
64
|
+
|
65
|
+
Attributes can be specified with XPath syntax by prepending an `@` sign:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
scalar '@id', type: :integer
|
69
|
+
```
|
70
|
+
|
71
|
+
### Nested Values
|
72
|
+
|
73
|
+
It's also possible to specify nested or even deeply nested hashes with the `hash` class method:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
hash 'UserProfile', key: 'profile' do
|
77
|
+
scalar 'Description'
|
78
|
+
|
79
|
+
hash 'Specialization' do
|
80
|
+
scalar 'Area'
|
81
|
+
scalar 'Expertise', type: :float
|
82
|
+
end
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
The `hash` method accepts a block, which works just like the class body, but all paths are scoped to the path passed to `hash`. The `key` argument is optional, just like with `scalar`.
|
87
|
+
|
88
|
+
### Array Data
|
89
|
+
|
90
|
+
In addition to the `scalar` and `hash` methods, there are plural forms which allow parsing and extracting data that appears many times within a single document. These are named `scalars` and `hashes`, respectively. They work much like their singular counterparts, but the provided path should match multiple elements.
|
91
|
+
|
92
|
+
For example, given the following decontaminator:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
class ArticlesDecontaminator < Decontaminate::Decontaminator
|
96
|
+
hashes 'Articles' do
|
97
|
+
scalar 'Name'
|
98
|
+
scalars 'Tags'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
And given the following XML document:
|
104
|
+
|
105
|
+
```xml
|
106
|
+
<Articles>
|
107
|
+
<Article>
|
108
|
+
<Name>Article A</Name>
|
109
|
+
<Tags>
|
110
|
+
<Tag>News</Tag>
|
111
|
+
<Tag>Technology</Tag>
|
112
|
+
</Tags>
|
113
|
+
</Article>
|
114
|
+
<Article>
|
115
|
+
<Name>Article B</Name>
|
116
|
+
<Tags>
|
117
|
+
<Tag>Sports</Tag>
|
118
|
+
<Tag>Recreation</Tag>
|
119
|
+
</Tags>
|
120
|
+
</Article>
|
121
|
+
</Articles>
|
122
|
+
```
|
123
|
+
|
124
|
+
The resulting object will have the following structure:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
{
|
128
|
+
'articles' => [
|
129
|
+
{
|
130
|
+
'name' => 'Article A',
|
131
|
+
'tags' => ['News', 'Technology']
|
132
|
+
},
|
133
|
+
{
|
134
|
+
'name' => 'Article B',
|
135
|
+
'tags' => ['Sports', 'Recreation']
|
136
|
+
}
|
137
|
+
]
|
138
|
+
}
|
139
|
+
```
|
140
|
+
|
141
|
+
There are some special things to note in the above example:
|
142
|
+
|
143
|
+
- **The name of the individual elements is inferred from the parent key.**
|
144
|
+
|
145
|
+
In both cases, the parent element was the plural form of its children (`Articles`/`Article` and `Tags`/`Tag`). Since this is common, the plural forms automatically perform this name inference.
|
146
|
+
|
147
|
+
Since this behavior is sometimes unwanted, it can be disabled by passing the path as an explicit `path:` keyword argument.
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
scalars path: 'Tags/TagName', key: 'tags' # Performs no name inference
|
151
|
+
```
|
152
|
+
|
153
|
+
- **No `root` element was specified since the root element is a plural.**
|
154
|
+
|
155
|
+
When using name inference for a plural element at the root, specifying the root element is an error. By using the explicit `path:` form mentioned above, `root` could still be specified.
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
self.root = 'Articles'
|
159
|
+
hashes path: 'Article', key: 'articles' do; ...; end
|
160
|
+
```
|
161
|
+
|
162
|
+
### Flattening nested data
|
163
|
+
|
164
|
+
Since source data is sometimes more nested than is desired, the `with` method is a helper for scoping decontamination directives to a given XML element without increasing the nesting depth of the resulting object. Like `hash`, it accepts an XPath and a block, but the attributes created from within the block will not be wrapped in a hash.
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
with 'Some/Nested/Data' do
|
168
|
+
scalar 'Value'
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
172
|
+
There is no plural form for `with` since it would, by necessity, create duplicate keys.
|
data/Rakefile
ADDED
data/bin/pry
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'pry' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('pry', 'pry')
|
data/bin/rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rake' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rake', 'rake')
|
data/bin/rspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rspec' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rspec-core', 'rspec')
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'decontaminate/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'decontaminate'
|
8
|
+
spec.version = Decontaminate::VERSION
|
9
|
+
spec.authors = ['Alexis King']
|
10
|
+
spec.email = ['lexi.lambda@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'Convert XML to JSON with a DSL'
|
13
|
+
spec.homepage = 'https://github.com/lexi-lambda/decontaminate'
|
14
|
+
spec.licenses = ['ISC']
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>= 1.9'
|
22
|
+
|
23
|
+
spec.add_runtime_dependency 'activesupport', '~> 4.2'
|
24
|
+
spec.add_runtime_dependency 'nokogiri', '~> 1.6'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
27
|
+
spec.add_development_dependency 'pry', '~> 0.10.3'
|
28
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.2'
|
29
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
30
|
+
spec.add_development_dependency 'rspec', '~> 3.3'
|
31
|
+
spec.add_development_dependency 'yard', '~> 0.8.7'
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Decontaminate
|
2
|
+
module Decoder
|
3
|
+
class Array
|
4
|
+
attr_reader :xpath, :decoder
|
5
|
+
|
6
|
+
def initialize(xpath, decoder)
|
7
|
+
@xpath = xpath
|
8
|
+
@decoder = decoder
|
9
|
+
end
|
10
|
+
|
11
|
+
def decode(xml_node)
|
12
|
+
children = xml_node.xpath xpath
|
13
|
+
children.map do |child|
|
14
|
+
decoder.decode child
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Decontaminate
|
2
|
+
module Decoder
|
3
|
+
class ChildNodeProxy
|
4
|
+
attr_reader :xpath, :decoder
|
5
|
+
|
6
|
+
def initialize(xpath, decoder)
|
7
|
+
@xpath = xpath
|
8
|
+
@decoder = decoder
|
9
|
+
end
|
10
|
+
|
11
|
+
def decode(xml_node)
|
12
|
+
child = xml_node.at_xpath xpath
|
13
|
+
decoder.decode child
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Decontaminate
|
2
|
+
module Decoder
|
3
|
+
class Hash
|
4
|
+
attr_reader :xpath, :decontaminator
|
5
|
+
|
6
|
+
def initialize(xpath, decontaminator)
|
7
|
+
@xpath = xpath
|
8
|
+
@decontaminator = decontaminator
|
9
|
+
end
|
10
|
+
|
11
|
+
def decode(xml_node)
|
12
|
+
child = xml_node.at_xpath xpath
|
13
|
+
decontaminator.new(child).as_json
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Decontaminate
|
2
|
+
module Decoder
|
3
|
+
class Scalar
|
4
|
+
attr_reader :xpath, :type
|
5
|
+
|
6
|
+
def initialize(xpath, type)
|
7
|
+
@xpath = xpath
|
8
|
+
@type = type
|
9
|
+
end
|
10
|
+
|
11
|
+
def decode(xml_node)
|
12
|
+
child = xml_node.at_xpath xpath
|
13
|
+
text = coerce_node_to_text child
|
14
|
+
|
15
|
+
return unless text
|
16
|
+
|
17
|
+
case type
|
18
|
+
when :string
|
19
|
+
text
|
20
|
+
when :integer
|
21
|
+
text.to_i
|
22
|
+
when :float
|
23
|
+
text.to_f
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def coerce_node_to_text(node)
|
30
|
+
if node.is_a?(Nokogiri::XML::Text) || node.is_a?(Nokogiri::XML::Attr)
|
31
|
+
node.to_s
|
32
|
+
else
|
33
|
+
node.at_xpath('text()').to_s
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
require_relative 'decoder/array'
|
4
|
+
require_relative 'decoder/child_node_proxy'
|
5
|
+
require_relative 'decoder/hash'
|
6
|
+
require_relative 'decoder/scalar'
|
7
|
+
|
8
|
+
module Decontaminate
|
9
|
+
# Decontaminate::Decontaminator is the base class for creating XML extraction
|
10
|
+
# parsers. A DSL is exposed via class methods to allow specifying how the XML
|
11
|
+
# should be parsed.
|
12
|
+
class Decontaminator
|
13
|
+
class << self
|
14
|
+
attr_accessor :root
|
15
|
+
attr_reader :decoders
|
16
|
+
|
17
|
+
def inherited(subclass)
|
18
|
+
subclass.instance_eval do
|
19
|
+
@root = '.'
|
20
|
+
@decoders = {}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def scalar(xpath, type: :string, key: infer_key(xpath))
|
25
|
+
add_decoder key, Decontaminate::Decoder::Scalar.new(xpath, type)
|
26
|
+
end
|
27
|
+
|
28
|
+
def scalars(xpath = nil, path: nil, type: :string, key: nil)
|
29
|
+
resolved_path = path || infer_plural_path(xpath)
|
30
|
+
key ||= infer_key(path || xpath)
|
31
|
+
|
32
|
+
singular = Decontaminate::Decoder::Scalar.new('.', type)
|
33
|
+
decoder = Decontaminate::Decoder::Array.new(resolved_path, singular)
|
34
|
+
|
35
|
+
add_decoder key, decoder
|
36
|
+
end
|
37
|
+
|
38
|
+
def hash(xpath, key: infer_key(xpath), &body)
|
39
|
+
decontaminator = Class.new(Decontaminate::Decontaminator, &body)
|
40
|
+
add_decoder key, Decontaminate::Decoder::Hash.new(xpath, decontaminator)
|
41
|
+
end
|
42
|
+
|
43
|
+
def hashes(xpath = nil, path: nil, key: nil, &body)
|
44
|
+
resolved_path = path || infer_plural_path(xpath)
|
45
|
+
key ||= infer_key(path || xpath)
|
46
|
+
|
47
|
+
decontaminator = Class.new(Decontaminate::Decontaminator, &body)
|
48
|
+
singular = Decontaminate::Decoder::Hash.new('.', decontaminator)
|
49
|
+
decoder = Decontaminate::Decoder::Array.new(resolved_path, singular)
|
50
|
+
|
51
|
+
add_decoder key, decoder
|
52
|
+
end
|
53
|
+
|
54
|
+
def with(xpath, &body)
|
55
|
+
this = self
|
56
|
+
decontaminator = Class.new(Decontaminate::Decontaminator)
|
57
|
+
|
58
|
+
decontaminator.instance_eval do
|
59
|
+
define_singleton_method :add_decoder do |key, decoder|
|
60
|
+
proxy = Decontaminate::Decoder::ChildNodeProxy.new(xpath, decoder)
|
61
|
+
this.add_decoder key, proxy
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
decontaminator.class_eval(&body)
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_decoder(key, decoder)
|
69
|
+
fail "Decoder already registered for key #{key}" if decoders.key? key
|
70
|
+
decoders[key] = decoder
|
71
|
+
end
|
72
|
+
|
73
|
+
def infer_key(xpath)
|
74
|
+
xpath.delete('@').underscore
|
75
|
+
end
|
76
|
+
|
77
|
+
def infer_plural_path(xpath)
|
78
|
+
xpath + '/' + xpath.split('/').last.singularize
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
attr_reader :xml_node
|
83
|
+
|
84
|
+
def initialize(xml_node)
|
85
|
+
@xml_node = xml_node
|
86
|
+
end
|
87
|
+
|
88
|
+
def as_json
|
89
|
+
acc = {}
|
90
|
+
|
91
|
+
root_node = xml_node.at_xpath root
|
92
|
+
decoders.each do |key, decoder|
|
93
|
+
acc[key] = decoder.decode root_node
|
94
|
+
end
|
95
|
+
|
96
|
+
acc
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def decoders
|
102
|
+
self.class.decoders
|
103
|
+
end
|
104
|
+
|
105
|
+
def root
|
106
|
+
self.class.root
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: decontaminate
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexis King
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nokogiri
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.10.3
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.10.3
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.2'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.2'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.3'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.3'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.8.7
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.8.7
|
125
|
+
description:
|
126
|
+
email:
|
127
|
+
- lexi.lambda@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".travis.yml"
|
134
|
+
- Gemfile
|
135
|
+
- LICENSE.txt
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- bin/pry
|
139
|
+
- bin/rake
|
140
|
+
- bin/rspec
|
141
|
+
- decontaminate.gemspec
|
142
|
+
- lib/decontaminate.rb
|
143
|
+
- lib/decontaminate/decoder/array.rb
|
144
|
+
- lib/decontaminate/decoder/child_node_proxy.rb
|
145
|
+
- lib/decontaminate/decoder/hash.rb
|
146
|
+
- lib/decontaminate/decoder/scalar.rb
|
147
|
+
- lib/decontaminate/decontaminator.rb
|
148
|
+
- lib/decontaminate/version.rb
|
149
|
+
homepage: https://github.com/lexi-lambda/decontaminate
|
150
|
+
licenses:
|
151
|
+
- ISC
|
152
|
+
metadata: {}
|
153
|
+
post_install_message:
|
154
|
+
rdoc_options: []
|
155
|
+
require_paths:
|
156
|
+
- lib
|
157
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '1.9'
|
162
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
requirements: []
|
168
|
+
rubyforge_project:
|
169
|
+
rubygems_version: 2.4.5
|
170
|
+
signing_key:
|
171
|
+
specification_version: 4
|
172
|
+
summary: Convert XML to JSON with a DSL
|
173
|
+
test_files: []
|
174
|
+
has_rdoc:
|