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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0141c719c75bbae939e900964c22fc208f9dd1edcd5043d7dfa3ea1191a41d50
4
- data.tar.gz: 4c598efe5871498e9fea2a12d9ecd4acd2a930c7a783a13e5b5715f03e8dc881
3
+ metadata.gz: dbccb044816ec6b39c01401f6e231c95e0c05dcc996b7c3d6983d50e2404ce7a
4
+ data.tar.gz: 2239c3929c3a49cef296a22cb7a1350cf685857ab646318ef58160fe757886bf
5
5
  SHA512:
6
- metadata.gz: 81f2afb7c5cb3fa22b51f3567ef84e1c1538a92103f3b1d131ba1d1550f55e7b8e7c7fb18ad506d047cd847d5cff9b13a3bf73b60cbcaeb9d06b0a7eeb182388
7
- data.tar.gz: 51242da088ffc005df4db1769582fc1a1ac7adbb7756ff9ecefa0212d54eee3ea45b30804758b230a72f824a9334034adeaa397e7d05978a0a38ac320f56f150
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
@@ -1,10 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
- - 2.0.0
5
- - 2.2.3
6
- - 2.3.0
7
3
  - 2.5.1
4
+ - 2.6.3
5
+ env:
6
+ - CI=true
8
7
  script:
8
+ - ./scripts/ci
9
9
  - gem build xmlhasher.gemspec
10
10
  - gem install xmlhasher-*
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
- gem 'simplecov', :require => false
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 1.9.3 or higher
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 "Run the benchmarks"
12
+ desc 'Run the benchmarks'
11
13
  task :benchmark do
12
- system("ruby", File.join(File.dirname(__FILE__), "benchmark", "benchmark.rb"))
14
+ system('ruby', File.join(File.dirname(__FILE__), 'benchmark', 'benchmark.rb'))
13
15
  end
14
16
 
15
- task :default => :test
17
+ task default: :test
@@ -1,4 +1,6 @@
1
- $:.push File.expand_path('../../lib', __FILE__)
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(:advanced_typecasting => false).parse(xml) }
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('../../test/fixtures/institution.xml', __FILE__)))
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('../../test/fixtures/institutions.xml', __FILE__)))
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 "pathname"
11
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
- Pathname.new(__FILE__).realpath)
11
+ require 'pathname'
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
13
13
 
14
- require "rubygems"
15
- require "bundler/setup"
14
+ require 'rubygems'
15
+ require 'bundler/setup'
16
16
 
17
- load Gem.bin_path("rake", "rake")
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 = [:snakecase, :ignore_namespaces, :string_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.inject({}) { |hash, key| hash[key] = instance_variable_get(:"@#{key}"); hash }
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
@@ -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
- unless ignore_attribute?(name)
21
- @stack.last.attributes[transform(name)] = escape(value) unless @stack.empty?
22
- end
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(name)
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 = name.to_sym unless @options[:string_keys]
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
- EscapeUtils.unescape_html(value)
62
+ CGI.unescapeHTML(value)
53
63
  end
54
64
 
55
65
  def ignore_attribute?(name)
@@ -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
- h = {}
13
- if text && !text.empty?
14
- h[name] = text
15
- else
16
- h[name] = attributes.inject({}) { |r, (key, value)| r[key] = value if !value.nil? && !value.to_s.empty?; r }
17
- if children.size == 1
18
- h[name].merge!(children.first.to_hash)
19
- else
20
- h[name].merge!(children.group_by { |c| c.name }.inject({}) { |r, (k, v)| v.length == 1 ? r.merge!(v.first.to_hash) : r[k] = v.map { |c| c.to_hash[c.name] }; r })
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
-
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'stringio'
2
4
 
3
5
  module XmlHasher
4
6
  class Parser
5
-
6
7
  def initialize(options = {})
7
8
  @options = options
8
9
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module XmlHasher
2
4
  module Util
3
5
  def self.snakecase(str)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module XmlHasher
2
- VERSION = '1.0.4'
4
+ VERSION = '1.0.7'
3
5
  end
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
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
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 = %q{Fast XML to Ruby Hash converter}
12
- spec.summary = %q{XmlHasher converts XML to Ruby Hash}
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 = `git ls-files`.split($/)
17
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
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 'rake'
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