xmlhasher 1.0.4 → 1.0.7
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 +4 -4
- data/.rubocop.yml +30 -0
- data/.travis.yml +4 -4
- data/CHANGELOG.md +82 -0
- data/Gemfile +7 -3
- data/README.md +6 -2
- data/Rakefile +5 -3
- data/benchmark/benchmark.rb +6 -5
- data/bin/rake +6 -6
- data/lib/xmlhasher/configurable.rb +6 -4
- data/lib/xmlhasher/handler.rb +16 -6
- data/lib/xmlhasher/node.rb +30 -12
- data/lib/xmlhasher/parser.rb +2 -1
- data/lib/xmlhasher/util.rb +2 -0
- data/lib/xmlhasher/version.rb +3 -1
- data/lib/xmlhasher.rb +6 -1
- data/scripts/ci +26 -0
- data/xmlhasher.gemspec +15 -13
- metadata +33 -35
- data/test/fixtures/institution.xml +0 -43
- data/test/fixtures/institutions.xml +0 -1
- data/test/test_helper.rb +0 -22
- data/test/xmlhasher/parser_test.rb +0 -250
- data/test/xmlhasher/xmlhasher_test.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dbccb044816ec6b39c01401f6e231c95e0c05dcc996b7c3d6983d50e2404ce7a
|
4
|
+
data.tar.gz: 2239c3929c3a49cef296a22cb7a1350cf685857ab646318ef58160fe757886bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 782e471f68ed17c0f676df8c7c83fb3ea2902e3767063db261e66d0782ab8536f36a596246a8170866e45545bdc587c590a1fd3a197d0c52de9512b973a8f88a
|
7
|
+
data.tar.gz: 65c6f0a2e9343c2e96f2c1905aa69b2efb494e1e1bba2b8318001dc92b6bd85ca849fff66a61669959757acb517ff7b4e45ce057b4209596f8164baaeebfac3b
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Style/Documentation:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
Metrics/LineLength:
|
5
|
+
Max: 200
|
6
|
+
|
7
|
+
Metrics/AbcSize:
|
8
|
+
Max: 42
|
9
|
+
|
10
|
+
Metrics/ClassLength:
|
11
|
+
Max: 300
|
12
|
+
|
13
|
+
Metrics/CyclomaticComplexity:
|
14
|
+
Max: 10
|
15
|
+
|
16
|
+
Metrics/MethodLength:
|
17
|
+
Max: 60
|
18
|
+
|
19
|
+
Metrics/PerceivedComplexity:
|
20
|
+
Max: 20
|
21
|
+
|
22
|
+
Style/MissingRespondToMissing:
|
23
|
+
Exclude:
|
24
|
+
- 'lib/xmlhasher.rb'
|
25
|
+
|
26
|
+
Naming/VariableNumber:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
Gemspec/RequiredRubyVersion:
|
30
|
+
Enabled: <%= ENV['CI'] != 'true' %>
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All changes to the XmlHasher gem are documented here. Releases follow semantic versioning.
|
4
|
+
|
5
|
+
## [1.0.7] - 2022-08-04
|
6
|
+
|
7
|
+
- Fix deprecation warning: "EscapeUtils.unescape_html is deprecated".
|
8
|
+
|
9
|
+
## [1.0.6] - 2021-03-10
|
10
|
+
|
11
|
+
- Resolve gem build warnings.
|
12
|
+
- Run tests on CI
|
13
|
+
- Little refactoring for Node hash builder.
|
14
|
+
- Use new ruby style guide and `rubocop` gem.
|
15
|
+
|
16
|
+
## [1.0.5] - 2019-06-16
|
17
|
+
|
18
|
+
- Updated ox version.
|
19
|
+
- Fixed warning for global variable `$INPUT_RECORD_SEPARATOR`.
|
20
|
+
- CHANGELOG.md added.
|
21
|
+
- Use new ruby style guide and `rubocop` gem.
|
22
|
+
- Added transform cache for keys.
|
23
|
+
|
24
|
+
## [1.0.4] - 2018-09-20
|
25
|
+
|
26
|
+
- Added `rake benchmark` command.
|
27
|
+
- Enabled CDATA parsing.
|
28
|
+
- Cleanup travis config.
|
29
|
+
- Updated ox version.
|
30
|
+
|
31
|
+
## [1.0.3] - 2018-09-20
|
32
|
+
|
33
|
+
- Updated ruby version requirement.
|
34
|
+
- Fix deprecation warning on SimpleCov::Formatter::MultiFormatter use.
|
35
|
+
- Update dependencies.
|
36
|
+
|
37
|
+
## [1.0.2] - 2016-02-20
|
38
|
+
|
39
|
+
- Cleaned up support environments.
|
40
|
+
- Updated ruby version requirement.
|
41
|
+
|
42
|
+
## [1.0.1] - 2016-02-20
|
43
|
+
|
44
|
+
- Bumped OX and escape_utils gem dependency versions.
|
45
|
+
|
46
|
+
|
47
|
+
## [1.0.0] - 2016-02-20
|
48
|
+
|
49
|
+
- Small changes in README.md.
|
50
|
+
- Removed roby-head from Travis - too unstable.
|
51
|
+
- Fixed ruby 2.2+ issue with single node parsing.
|
52
|
+
|
53
|
+
## [0.0.6] - 2013-09-09
|
54
|
+
|
55
|
+
- Added script for benchmarks.
|
56
|
+
- Added 'string_keys' option to keep keys at Strings vs Symbols.
|
57
|
+
|
58
|
+
## [0.0.5] - 2013-04-24
|
59
|
+
|
60
|
+
- Test release (CI).
|
61
|
+
|
62
|
+
## [0.0.4] - 2013-04-24
|
63
|
+
|
64
|
+
- Fixed mixed children array detection.
|
65
|
+
- Enable Coveralls.
|
66
|
+
- Add more examples and license into README.md
|
67
|
+
|
68
|
+
## [0.0.3] - 2013-04-24
|
69
|
+
|
70
|
+
- Added escape method for attributes and dependency from `escape_utils` gem.
|
71
|
+
- Some fixes for node children parsing.
|
72
|
+
- Added more tests.
|
73
|
+
|
74
|
+
## [0.0.2] - 2013-04-24
|
75
|
+
|
76
|
+
- Some fixes for node children parsing.
|
77
|
+
- Add more tests.
|
78
|
+
- Updated gem description.
|
79
|
+
|
80
|
+
## [0.0.1] - 2013-04-24
|
81
|
+
|
82
|
+
- The first implementation of the XML parser.
|
data/Gemfile
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
gemspec
|
4
6
|
|
7
|
+
gem 'rubocop', require: false if ENV['CI']
|
8
|
+
|
5
9
|
group :test do
|
10
|
+
gem 'coveralls', require: false
|
6
11
|
gem 'minitest'
|
12
|
+
gem 'simplecov', require: false
|
7
13
|
gem 'test-unit'
|
8
|
-
|
9
|
-
gem 'coveralls', :require => false
|
10
|
-
end
|
14
|
+
end
|
data/README.md
CHANGED
@@ -19,6 +19,10 @@ or add it to your Gemfile like this:
|
|
19
19
|
gem 'xmlhasher'
|
20
20
|
```
|
21
21
|
|
22
|
+
## Release Notes
|
23
|
+
|
24
|
+
See [CHANGELOG.md](CHANGELOG.md)
|
25
|
+
|
22
26
|
## Usage
|
23
27
|
|
24
28
|
```ruby
|
@@ -40,7 +44,7 @@ end
|
|
40
44
|
# alternatively, specify configuration options when instantiating a Parser
|
41
45
|
parser = XmlHasher::Parser.new(
|
42
46
|
:snakecase => true,
|
43
|
-
:ignore_namespaces => true
|
47
|
+
:ignore_namespaces => true,
|
44
48
|
:string_keys => false
|
45
49
|
)
|
46
50
|
|
@@ -82,7 +86,7 @@ Note: benchmarks were generated on a 2015 Macbook Pro using Ruby 2.5.1
|
|
82
86
|
|
83
87
|
## Requirements
|
84
88
|
|
85
|
-
* Ruby
|
89
|
+
* Ruby 2.0.0 or higher
|
86
90
|
|
87
91
|
## Copyright
|
88
92
|
Copyright (c) 2013 Gene Drabkin.
|
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bundler/gem_tasks'
|
2
4
|
require 'rake/testtask'
|
3
5
|
|
@@ -7,9 +9,9 @@ Rake::TestTask.new(:test) do |t|
|
|
7
9
|
t.verbose = true
|
8
10
|
end
|
9
11
|
|
10
|
-
desc
|
12
|
+
desc 'Run the benchmarks'
|
11
13
|
task :benchmark do
|
12
|
-
system(
|
14
|
+
system('ruby', File.join(File.dirname(__FILE__), 'benchmark', 'benchmark.rb'))
|
13
15
|
end
|
14
16
|
|
15
|
-
task :
|
17
|
+
task default: :test
|
data/benchmark/benchmark.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('../lib', __dir__)
|
2
4
|
|
3
5
|
require 'benchmark'
|
4
6
|
require 'xmlhasher'
|
@@ -28,7 +30,6 @@ rescue LoadError
|
|
28
30
|
puts "libxml gem in not installed, run 'gem install libxml-ruby'"
|
29
31
|
end
|
30
32
|
|
31
|
-
|
32
33
|
def benchmark(runs, xml)
|
33
34
|
label_width = 25 # needs to be >= any label's size
|
34
35
|
|
@@ -53,7 +54,7 @@ def benchmark(runs, xml)
|
|
53
54
|
end
|
54
55
|
|
55
56
|
x.report 'nori' do
|
56
|
-
runs.times { Nori.new(:
|
57
|
+
runs.times { Nori.new(advanced_typecasting: false).parse(xml) }
|
57
58
|
end
|
58
59
|
|
59
60
|
x.report 'xmlhasher' do
|
@@ -63,7 +64,7 @@ def benchmark(runs, xml)
|
|
63
64
|
end
|
64
65
|
|
65
66
|
puts 'Converting small xml from text to Hash:'
|
66
|
-
benchmark(100, File.read(File.expand_path('
|
67
|
+
benchmark(100, File.read(File.expand_path('../test/fixtures/institution.xml', __dir__)))
|
67
68
|
puts 'Converting large xml from file to Hash:'
|
68
|
-
benchmark(5, File.read(File.expand_path('
|
69
|
+
benchmark(5, File.read(File.expand_path('../test/fixtures/institutions.xml', __dir__)))
|
69
70
|
puts
|
data/bin/rake
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
#
|
4
5
|
# This file was generated by Bundler.
|
5
6
|
#
|
@@ -7,11 +8,10 @@
|
|
7
8
|
# this file is here to facilitate running it.
|
8
9
|
#
|
9
10
|
|
10
|
-
require
|
11
|
-
ENV[
|
12
|
-
Pathname.new(__FILE__).realpath)
|
11
|
+
require 'pathname'
|
12
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
|
13
13
|
|
14
|
-
require
|
15
|
-
require
|
14
|
+
require 'rubygems'
|
15
|
+
require 'bundler/setup'
|
16
16
|
|
17
|
-
load Gem.bin_path(
|
17
|
+
load Gem.bin_path('rake', 'rake')
|
@@ -1,9 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module XmlHasher
|
2
4
|
module Configurable
|
3
|
-
|
4
5
|
attr_writer :snakecase, :ignore_namespaces, :string_keys
|
5
6
|
|
6
|
-
KEYS = [
|
7
|
+
KEYS = %i[snakecase ignore_namespaces string_keys].freeze
|
7
8
|
|
8
9
|
def configure
|
9
10
|
yield self
|
@@ -13,8 +14,9 @@ module XmlHasher
|
|
13
14
|
private
|
14
15
|
|
15
16
|
def options
|
16
|
-
XmlHasher::Configurable::KEYS.
|
17
|
+
XmlHasher::Configurable::KEYS.each_with_object({}) do |key, hash|
|
18
|
+
hash[key] = instance_variable_get(:"@#{key}")
|
19
|
+
end
|
17
20
|
end
|
18
|
-
|
19
21
|
end
|
20
22
|
end
|
data/lib/xmlhasher/handler.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'ox'
|
2
4
|
require 'escape_utils'
|
3
5
|
|
@@ -6,6 +8,9 @@ module XmlHasher
|
|
6
8
|
def initialize(options = {})
|
7
9
|
@options = options
|
8
10
|
@stack = []
|
11
|
+
@transform_cache = {}
|
12
|
+
|
13
|
+
super()
|
9
14
|
end
|
10
15
|
|
11
16
|
def to_hash
|
@@ -17,9 +22,9 @@ module XmlHasher
|
|
17
22
|
end
|
18
23
|
|
19
24
|
def attr(name, value)
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
return if ignore_attribute?(name) || @stack.empty?
|
26
|
+
|
27
|
+
@stack.last.attributes[transform(name)] = escape(value)
|
23
28
|
end
|
24
29
|
|
25
30
|
def text(value)
|
@@ -30,7 +35,7 @@ module XmlHasher
|
|
30
35
|
@stack.last.text = escape(str)
|
31
36
|
end
|
32
37
|
|
33
|
-
def end_element(
|
38
|
+
def end_element(_name)
|
34
39
|
if @stack.size == 1
|
35
40
|
@hash = @stack.pop.to_hash
|
36
41
|
else
|
@@ -42,14 +47,19 @@ module XmlHasher
|
|
42
47
|
private
|
43
48
|
|
44
49
|
def transform(name)
|
50
|
+
return @transform_cache[name] if @transform_cache[name]
|
51
|
+
|
52
|
+
orig_name = name
|
53
|
+
|
45
54
|
name = name.to_s.split(':').last if @options[:ignore_namespaces]
|
46
55
|
name = Util.snakecase(name) if @options[:snakecase]
|
47
|
-
name =
|
56
|
+
name = @options[:string_keys] ? name.to_s : name.to_sym
|
57
|
+
@transform_cache[orig_name] = name
|
48
58
|
name
|
49
59
|
end
|
50
60
|
|
51
61
|
def escape(value)
|
52
|
-
|
62
|
+
CGI.unescapeHTML(value)
|
53
63
|
end
|
54
64
|
|
55
65
|
def ignore_attribute?(name)
|
data/lib/xmlhasher/node.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module XmlHasher
|
2
4
|
class Node
|
3
5
|
attr_accessor :name, :attributes, :children, :text
|
@@ -9,20 +11,36 @@ module XmlHasher
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def to_hash
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
node_content = content
|
15
|
+
{ name => node_content.empty? ? nil : node_content }
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def content
|
21
|
+
return text if text && !text.empty?
|
22
|
+
|
23
|
+
attributes_to_hash.merge(children_to_hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
def attributes_to_hash
|
27
|
+
attributes.each_with_object({}) do |(key, value), data|
|
28
|
+
next if value.nil? || value.to_s.empty?
|
29
|
+
|
30
|
+
data[key] = value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def children_to_hash
|
35
|
+
return children.first.to_hash if children.size == 1
|
36
|
+
|
37
|
+
children.group_by(&:name).each_with_object({}) do |(key, nodes), data|
|
38
|
+
next data.merge!(nodes.first.to_hash) if nodes.length == 1
|
39
|
+
|
40
|
+
data[key] = nodes.map do |node|
|
41
|
+
node.to_hash[node.name]
|
21
42
|
end
|
22
43
|
end
|
23
|
-
h[name] = nil if h[name].empty?
|
24
|
-
h
|
25
44
|
end
|
26
45
|
end
|
27
46
|
end
|
28
|
-
|
data/lib/xmlhasher/parser.rb
CHANGED
data/lib/xmlhasher/util.rb
CHANGED
data/lib/xmlhasher/version.rb
CHANGED
data/lib/xmlhasher.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'xmlhasher/configurable'
|
2
4
|
require 'xmlhasher/handler'
|
3
5
|
require 'xmlhasher/parser'
|
@@ -17,9 +19,12 @@ module XmlHasher
|
|
17
19
|
|
18
20
|
def method_missing(method_name, *args, &block)
|
19
21
|
return super unless parser.respond_to?(method_name)
|
22
|
+
|
20
23
|
parser.send(method_name, *args, &block)
|
21
24
|
end
|
22
25
|
|
26
|
+
def respond_to_missing?(method_name, include_private = false)
|
27
|
+
super
|
28
|
+
end
|
23
29
|
end
|
24
|
-
|
25
30
|
end
|
data/scripts/ci
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -euo pipefail
|
3
|
+
IFS=$'\n\t'
|
4
|
+
|
5
|
+
init_ruby_version() {
|
6
|
+
echo "Using $(ruby -v)"
|
7
|
+
echo "$(cut -d'@' -f1 <<<"$(rvm current)")" > .ruby-version
|
8
|
+
}
|
9
|
+
|
10
|
+
run_code_quality_checks() {
|
11
|
+
if [[ "$(rvm current)" != *"2.0.0"* ]]; then
|
12
|
+
bundle exec rubocop .
|
13
|
+
fi
|
14
|
+
}
|
15
|
+
|
16
|
+
run_tests() {
|
17
|
+
bundle exec rake test
|
18
|
+
}
|
19
|
+
|
20
|
+
main() {
|
21
|
+
init_ruby_version &&
|
22
|
+
run_code_quality_checks &&
|
23
|
+
run_tests
|
24
|
+
}
|
25
|
+
|
26
|
+
main
|
data/xmlhasher.gemspec
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'xmlhasher/version'
|
5
6
|
|
@@ -8,25 +9,26 @@ Gem::Specification.new do |spec|
|
|
8
9
|
spec.version = XmlHasher::VERSION
|
9
10
|
spec.authors = ['Gene Drabkin']
|
10
11
|
spec.email = ['gene.drabkin@gmail.com']
|
11
|
-
spec.description =
|
12
|
-
spec.summary =
|
12
|
+
spec.description = 'Fast XML to Ruby Hash converter'
|
13
|
+
spec.summary = 'XmlHasher converts XML to Ruby Hash'
|
13
14
|
spec.homepage = 'https://github.com/cloocher/xmlhasher'
|
14
15
|
spec.license = 'MIT'
|
15
16
|
|
16
|
-
spec.files
|
17
|
-
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
18
20
|
spec.require_paths = ['lib']
|
19
21
|
|
20
|
-
spec.required_ruby_version = '>= 1.9.3'
|
22
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 1.9.3')
|
21
23
|
spec.required_rubygems_version = '>= 1.3.6'
|
22
24
|
|
23
|
-
spec.add_dependency 'ox', '~> 2.10.0'
|
24
25
|
spec.add_dependency 'escape_utils', '~> 1.2'
|
26
|
+
spec.add_dependency 'ox', '~> 2.11'
|
25
27
|
|
26
|
-
spec.add_development_dependency '
|
27
|
-
spec.add_development_dependency 'bundler'
|
28
|
-
spec.add_development_dependency 'minitest', '~> 5.10'
|
29
|
-
spec.add_development_dependency 'test-unit', '~> 3.2'
|
30
|
-
spec.add_development_dependency 'simplecov', '~> 0.14.1'
|
28
|
+
spec.add_development_dependency 'bundler', '>= 1.6', '< 3'
|
31
29
|
spec.add_development_dependency 'coveralls', '~> 0.8.21'
|
30
|
+
spec.add_development_dependency 'minitest', '~> 5.10'
|
31
|
+
spec.add_development_dependency 'rake', '~> 12'
|
32
|
+
spec.add_development_dependency 'simplecov', '~> 0.14.1'
|
33
|
+
spec.add_development_dependency 'test-unit', '~> 3.2'
|
32
34
|
end
|