xmlhasher 1.0.4 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
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