multi_xml 0.6.0 → 0.7.1

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
- SHA1:
3
- metadata.gz: add5ff8df4d736d143b1d83c38c5f1b8b35d21cd
4
- data.tar.gz: ec8e8a3657ff340a9a4abefa2561e44dfee8371d
2
+ SHA256:
3
+ metadata.gz: aba2c87b84168b0804c96f8591fd112f81da3f42e7f57b5fc432e47d18953868
4
+ data.tar.gz: 1c5b5f1afcac257dfd674e3dc1c1aeee4ef663c25b605bbdf271ef83fe2c4578
5
5
  SHA512:
6
- metadata.gz: 1cb437e88276aa09e33c5b10a1e32bbf181ecae9543976ab13acc4ca458b00b1315a59f1e3e1cd95fd24e47559a85058585578ba16441ac83c98ffa81c5ee902
7
- data.tar.gz: 1931768faabe059174c01e24d12f9b1c8bcc0c9717891ec9ba9098f55c98535ad2a0efab7dcc4bfd756a569f137bf86e4b45b652a182652e6a468393103de9f5
6
+ metadata.gz: a20fa4f096960b393d375ab9310f30f8851c621e4e2b15ea26bd38c9d8fb582f8941262ce8c9f920c7c2b25378c77598d6449422d4f018aa78e5767975625fd5
7
+ data.tar.gz: 4143efbbef77c5398f9f54396ff431cf184521b2dabe03466e32c6d0a946edf272e6fedf19a0bafa9a3de5f8af7e9b0bead864a803067808b6c1ff7b94c2bff9
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --order random
data/.rubocop.yml ADDED
@@ -0,0 +1,54 @@
1
+ require:
2
+ - rubocop-performance
3
+ - rubocop-rake
4
+ - rubocop-rspec
5
+ - standard
6
+ - standard-performance
7
+
8
+ AllCops:
9
+ NewCops: enable
10
+ TargetRubyVersion: 3.1
11
+
12
+ Layout/ArgumentAlignment:
13
+ EnforcedStyle: with_fixed_indentation
14
+ IndentationWidth: 2
15
+
16
+ Layout/CaseIndentation:
17
+ EnforcedStyle: end
18
+
19
+ Layout/EndAlignment:
20
+ EnforcedStyleAlignWith: start_of_line
21
+
22
+ Layout/LineLength:
23
+ Max: 140
24
+
25
+ Layout/ParameterAlignment:
26
+ EnforcedStyle: with_fixed_indentation
27
+ IndentationWidth: 2
28
+
29
+ Layout/SpaceInsideHashLiteralBraces:
30
+ EnforcedStyle: no_space
31
+
32
+ Metrics/ParameterLists:
33
+ CountKeywordArgs: false
34
+
35
+ Style/Alias:
36
+ EnforcedStyle: prefer_alias_method
37
+
38
+ Style/Documentation:
39
+ Enabled: false
40
+
41
+ Style/FrozenStringLiteralComment:
42
+ EnforcedStyle: never
43
+
44
+ Style/OpenStructUse:
45
+ Enabled: false
46
+
47
+ Style/StringLiterals:
48
+ EnforcedStyle: double_quotes
49
+
50
+ Style/StringLiteralsInInterpolation:
51
+ EnforcedStyle: double_quotes
52
+
53
+ Style/TernaryParentheses:
54
+ EnforcedStyle: require_parentheses
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ 0.7.0
2
+ -----
3
+ * [Add support for Ruby 3.3](https://github.com/sferik/multi_xml/pull/67)
4
+ * [Drop support for Ruby 3.0](https://github.com/sferik/multi_xml/commit/eec72c56307fede3a93f1a61553587cb278b0c8a) [and](https://github.com/sferik/multi_xml/commit/6a6dec80a36c30774a5525b45f71d346fb561e69) [earlier](https://github.com/sferik/multi_xml/commit/e7dad37a0a0be8383a26ffe515c575b5b4d04588)
5
+ * [Don't mutate strings](https://github.com/sferik/multi_xml/commit/71be3fff4afb0277a7e1c47c5f1f4b6106a8eb45)
6
+
7
+ 0.6.0
8
+ -----
9
+ * [Duplexed Streams](https://github.com/sferik/multi_xml/pull/45)
10
+ * [Support for Oga](https://github.com/sferik/multi_xml/pull/47)
11
+ * [Integer unification for Ruby 2.4](https://github.com/sferik/multi_xml/pull/54)
12
+
1
13
  0.5.5
2
14
  -----
3
15
  * [Fix symbolize_keys function](https://github.com/sferik/multi_xml/commit/a4cae3aeb690999287cd30206399abaa5ce1ae81)
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "libxml-ruby", require: nil, platforms: :ruby
4
+ gem "nokogiri", require: nil
5
+ gem "oga", ">= 2.3", require: nil
6
+ gem "ox", require: nil, platforms: :ruby
7
+ gem "rexml", require: nil
8
+
9
+ gem "rake", ">= 13.2.1"
10
+ gem "rspec", ">= 3.12"
11
+ gem "rubocop", ">= 1.62.1"
12
+ gem "rubocop-performance", ">= 1.20.2"
13
+ gem "rubocop-rake", ">= 0.6"
14
+ gem "rubocop-rspec", ">= 2.24"
15
+ gem "simplecov", ">= 0.22"
16
+ gem "standard", ">= 1.35.1"
17
+ gem "standard-performance", ">= 1.3.1"
18
+ gem "yard", ">= 0.9.36"
19
+ gem "yardstick", ">= 0.9.9"
20
+
21
+ gemspec
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2013 Erik Michaels-Ober
1
+ Copyright (c) 2010-2024 Erik Berlin
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,17 +1,5 @@
1
1
  # MultiXML
2
2
 
3
- [![Gem Version](http://img.shields.io/gem/v/multi_xml.svg)][gem]
4
- [![Build Status](http://img.shields.io/travis/sferik/multi_xml.svg)][travis]
5
- [![Dependency Status](http://img.shields.io/gemnasium/sferik/multi_xml.svg)][gemnasium]
6
- [![Code Climate](http://img.shields.io/codeclimate/github/sferik/multi_xml.svg)][codeclimate]
7
- [![Coverage Status](http://img.shields.io/coveralls/sferik/multi_xml.svg)][coveralls]
8
-
9
- [gem]: https://rubygems.org/gems/multi_xml
10
- [travis]: http://travis-ci.org/sferik/multi_xml
11
- [gemnasium]: https://gemnasium.com/sferik/multi_xml
12
- [codeclimate]: https://codeclimate.com/github/sferik/multi_xml
13
- [coveralls]: https://coveralls.io/r/sferik/multi_xml
14
-
15
3
  A generic swappable back-end for XML parsing
16
4
 
17
5
  ## Installation
@@ -23,10 +11,6 @@ A generic swappable back-end for XML parsing
23
11
  [documentation]: http://rdoc.info/gems/multi_xml
24
12
 
25
13
  ## Usage Examples
26
- Lots of Ruby libraries utilize XML parsing in some form, and everyone has their
27
- favorite XML library. In order to best support multiple XML parsers and
28
- libraries, `multi_xml` is a general-purpose swappable XML backend library. You
29
- use it like so:
30
14
  ```ruby
31
15
  require 'multi_xml'
32
16
 
@@ -54,24 +38,19 @@ The `parser` setter takes either a symbol or a class (to allow for custom XML
54
38
  parsers) that responds to `.parse` at the class level.
55
39
 
56
40
  MultiXML tries to have intelligent defaulting. That is, if you have any of the
57
- supported parsers already loaded, it will utilize them before attempting to
58
- load any. When loading, libraries are ordered by speed: first Ox, then LibXML,
41
+ supported parsers already loaded, it will use them before attempting to load
42
+ a new one. When loading, libraries are ordered by speed: first Ox, then LibXML,
59
43
  then Nokogiri, and finally REXML.
60
44
 
61
45
  ## Supported Ruby Versions
62
- This library aims to support and is [tested against][travis] the following Ruby
46
+ This library aims to support and is tested against the following Ruby
63
47
  implementations:
64
48
 
65
- * Ruby 1.9.3
66
- * Ruby 2.0.0
67
- * Ruby 2.1
68
- * Ruby 2.2
69
- * Ruby 2.3
70
- * [JRuby 9000][jruby]
71
-
72
- [jruby]: http://jruby.org/
49
+ * 3.1
50
+ * 3.2
51
+ * 3.3
73
52
 
74
- If something doesn't work on one of these interpreters, it's a bug.
53
+ If something doesn't work on one of these versions, it's a bug.
75
54
 
76
55
  This library may inadvertently work (or seem to work) on other Ruby
77
56
  implementations, however support will only be provided for the versions listed
@@ -90,6 +69,6 @@ MultiXML was inspired by [MultiJSON][].
90
69
  [multijson]: https://github.com/intridea/multi_json/
91
70
 
92
71
  ## Copyright
93
- Copyright (c) 2010-2013 Erik Michaels-Ober. See [LICENSE][] for details.
72
+ Copyright (c) 2010-2024 Erik Berlin. See [LICENSE][] for details.
94
73
 
95
74
  [license]: LICENSE.md
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "rspec/core/rake_task"
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task test: :spec
8
+
9
+ require "rubocop/rake_task"
10
+ RuboCop::RakeTask.new
11
+
12
+ require "yard"
13
+ YARD::Rake::YardocTask.new do |task|
14
+ task.files = ["lib/**/*.rb", "-", "LICENSE.md"]
15
+ task.options = [
16
+ "--no-private",
17
+ "--protected",
18
+ "--output-dir", "doc/yard",
19
+ "--markup", "markdown"
20
+ ]
21
+ end
22
+
23
+ require "yardstick/rake/measurement"
24
+ Yardstick::Rake::Measurement.new do |measurement|
25
+ measurement.output = "measurement/report.txt"
26
+ end
27
+
28
+ require "yardstick/rake/verify"
29
+ Yardstick::Rake::Verify.new do |verify|
30
+ verify.threshold = 48.8
31
+ end
32
+
33
+ task default: %i[spec rubocop verify_measurements]
@@ -1,9 +1,9 @@
1
- require 'libxml' unless defined?(LibXML)
2
- require 'multi_xml/parsers/libxml2_parser'
1
+ require "libxml" unless defined?(LibXML)
2
+ require "multi_xml/parsers/libxml2_parser"
3
3
 
4
4
  module MultiXml
5
5
  module Parsers
6
- module Libxml #:nodoc:
6
+ module Libxml # :nodoc:
7
7
  include Libxml2Parser
8
8
  extend self
9
9
 
@@ -15,14 +15,14 @@ module MultiXml
15
15
  node_to_hash(LibXML::XML::Parser.io(xml).parse.root)
16
16
  end
17
17
 
18
- private
18
+ private
19
19
 
20
- def each_child(node, &block)
21
- node.each_child(&block)
20
+ def each_child(node, &)
21
+ node.each_child(&)
22
22
  end
23
23
 
24
- def each_attr(node, &block)
25
- node.each_attr(&block)
24
+ def each_attr(node, &)
25
+ node.each_attr(&)
26
26
  end
27
27
 
28
28
  def node_name(node)
@@ -1,6 +1,6 @@
1
1
  module MultiXml
2
2
  module Parsers
3
- module Libxml2Parser #:nodoc:
3
+ module Libxml2Parser # :nodoc:
4
4
  # Convert XML document to hash
5
5
  #
6
6
  # node::
@@ -8,8 +8,8 @@ module MultiXml
8
8
  #
9
9
  # hash::
10
10
  # Hash to merge the converted element into.
11
- def node_to_hash(node, hash = {}) # rubocop:disable AbcSize, CyclomaticComplexity, MethodLength, PerceivedComplexity
12
- node_hash = {MultiXml::CONTENT_ROOT => ''}
11
+ def node_to_hash(node, hash = {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
12
+ node_hash = {MultiXml::CONTENT_ROOT => ""}
13
13
 
14
14
  name = node_name(node)
15
15
 
@@ -28,20 +28,18 @@ module MultiXml
28
28
  if c.element?
29
29
  node_to_hash(c, node_hash)
30
30
  elsif c.text? || c.cdata?
31
- node_hash[MultiXml::CONTENT_ROOT] << c.content
31
+ node_hash[MultiXml::CONTENT_ROOT] += c.content
32
32
  end
33
33
  end
34
34
 
35
35
  # Remove content node if it is empty
36
- if node_hash[MultiXml::CONTENT_ROOT].strip.empty?
37
- node_hash.delete(MultiXml::CONTENT_ROOT)
38
- end
36
+ node_hash.delete(MultiXml::CONTENT_ROOT) if node_hash[MultiXml::CONTENT_ROOT].strip.empty?
39
37
 
40
38
  # Handle attributes
41
39
  each_attr(node) do |a|
42
40
  key = node_name(a)
43
41
  v = node_hash[key]
44
- node_hash[key] = (v ? [a.value, v] : a.value)
42
+ node_hash[key] = ((v) ? [a.value, v] : a.value)
45
43
  end
46
44
 
47
45
  hash
@@ -51,21 +49,21 @@ module MultiXml
51
49
  # xml::
52
50
  # XML Document IO to parse
53
51
  def parse(_)
54
- raise(NotImplementedError.new("inheritor should define #{__method__}"))
52
+ raise(NotImplementedError, "inheritor should define #{__method__}")
55
53
  end
56
54
 
57
- private
55
+ private
58
56
 
59
57
  def each_child(*)
60
- raise(NotImplementedError.new("inheritor should define #{__method__}"))
58
+ raise(NotImplementedError, "inheritor should define #{__method__}")
61
59
  end
62
60
 
63
61
  def each_attr(*)
64
- raise(NotImplementedError.new("inheritor should define #{__method__}"))
62
+ raise(NotImplementedError, "inheritor should define #{__method__}")
65
63
  end
66
64
 
67
65
  def node_name(*)
68
- raise(NotImplementedError.new("inheritor should define #{__method__}"))
66
+ raise(NotImplementedError, "inheritor should define #{__method__}")
69
67
  end
70
68
  end
71
69
  end
@@ -1,9 +1,9 @@
1
- require 'nokogiri' unless defined?(Nokogiri)
2
- require 'multi_xml/parsers/libxml2_parser'
1
+ require "nokogiri" unless defined?(Nokogiri)
2
+ require "multi_xml/parsers/libxml2_parser"
3
3
 
4
4
  module MultiXml
5
5
  module Parsers
6
- module Nokogiri #:nodoc:
6
+ module Nokogiri # :nodoc:
7
7
  include Libxml2Parser
8
8
  extend self
9
9
 
@@ -14,17 +14,18 @@ module MultiXml
14
14
  def parse(xml)
15
15
  doc = ::Nokogiri::XML(xml)
16
16
  raise(doc.errors.first) unless doc.errors.empty?
17
+
17
18
  node_to_hash(doc.root)
18
19
  end
19
20
 
20
- private
21
+ private
21
22
 
22
- def each_child(node, &block)
23
- node.children.each(&block)
23
+ def each_child(node, &)
24
+ node.children.each(&)
24
25
  end
25
26
 
26
- def each_attr(node, &block)
27
- node.attribute_nodes.each(&block)
27
+ def each_attr(node, &)
28
+ node.attribute_nodes.each(&)
28
29
  end
29
30
 
30
31
  def node_name(node)
@@ -1,9 +1,9 @@
1
- require 'oga' unless defined?(Oga)
2
- require 'multi_xml/parsers/libxml2_parser'
1
+ require "oga" unless defined?(Oga)
2
+ require "multi_xml/parsers/libxml2_parser"
3
3
 
4
4
  module MultiXml
5
5
  module Parsers
6
- module Oga #:nodoc:
6
+ module Oga # :nodoc:
7
7
  include Libxml2Parser
8
8
  extend self
9
9
 
@@ -16,8 +16,8 @@ module MultiXml
16
16
  node_to_hash(document.children[0])
17
17
  end
18
18
 
19
- def node_to_hash(node, hash = {}) # rubocop:disable AbcSize, CyclomaticComplexity, MethodLength, PerceivedComplexity
20
- node_hash = {MultiXml::CONTENT_ROOT => ''}
19
+ def node_to_hash(node, hash = {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
20
+ node_hash = {MultiXml::CONTENT_ROOT => ""}
21
21
 
22
22
  name = node_name(node)
23
23
 
@@ -36,38 +36,36 @@ module MultiXml
36
36
  if c.is_a?(::Oga::XML::Element)
37
37
  node_to_hash(c, node_hash)
38
38
  elsif c.is_a?(::Oga::XML::Text) || c.is_a?(::Oga::XML::Cdata)
39
- node_hash[MultiXml::CONTENT_ROOT] << c.text
39
+ node_hash[MultiXml::CONTENT_ROOT] += c.text
40
40
  end
41
41
  end
42
42
 
43
43
  # Remove content node if it is empty
44
- if node_hash[MultiXml::CONTENT_ROOT].strip.empty?
45
- node_hash.delete(MultiXml::CONTENT_ROOT)
46
- end
44
+ node_hash.delete(MultiXml::CONTENT_ROOT) if node_hash[MultiXml::CONTENT_ROOT].strip.empty?
47
45
 
48
46
  # Handle attributes
49
47
  each_attr(node) do |a|
50
48
  key = node_name(a)
51
49
  v = node_hash[key]
52
- node_hash[key] = (v ? [a.value, v] : a.value)
50
+ node_hash[key] = ((v) ? [a.value, v] : a.value)
53
51
  end
54
52
 
55
53
  hash
56
54
  end
57
55
 
58
- private
56
+ private
59
57
 
60
- def each_child(node, &block)
61
- node.children.each(&block)
58
+ def each_child(node, &)
59
+ node.children.each(&)
62
60
  end
63
61
 
64
- def each_attr(node, &block)
65
- node.attributes.each(&block)
62
+ def each_attr(node, &)
63
+ node.attributes.each(&)
66
64
  end
67
65
 
68
66
  def node_name(node)
69
67
  node.name
70
68
  end
71
- end # Oga
72
- end # Parsers
73
- end # MultiXml
69
+ end
70
+ end
71
+ end
@@ -1,4 +1,4 @@
1
- require 'ox' unless defined?(Ox)
1
+ require "ox" unless defined?(Ox)
2
2
 
3
3
  # Each MultiXml parser is expected to parse an XML document into a Hash. The
4
4
  # conversion rules are:
@@ -20,8 +20,8 @@ require 'ox' unless defined?(Ox)
20
20
 
21
21
  module MultiXml
22
22
  module Parsers
23
- module Ox #:nodoc:
24
- extend self
23
+ module Ox # :nodoc:
24
+ module_function
25
25
 
26
26
  def parse_error
27
27
  Exception
@@ -29,7 +29,7 @@ module MultiXml
29
29
 
30
30
  def parse(io)
31
31
  handler = Handler.new
32
- ::Ox.sax_parse(handler, io, :convert_special => true)
32
+ ::Ox.sax_parse(handler, io, convert_special: true, skip: :skip_return)
33
33
  handler.doc
34
34
  end
35
35
 
@@ -68,7 +68,7 @@ module MultiXml
68
68
  end
69
69
 
70
70
  def error(message, line, column)
71
- raise(Exception.new("#{message} at #{line}:#{column}"))
71
+ raise(StandardError, "#{message} at #{line}:#{column}")
72
72
  end
73
73
 
74
74
  def append(key, value)
@@ -85,7 +85,7 @@ module MultiXml
85
85
  h[key] = value
86
86
  end
87
87
  end
88
- end # Handler
89
- end # Ox
90
- end # Parsers
91
- end # MultiXml
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,8 +1,8 @@
1
- require 'rexml/document' unless defined?(REXML::Document)
1
+ require "rexml/document" unless defined?(REXML::Document)
2
2
 
3
3
  module MultiXml
4
4
  module Parsers
5
- module Rexml #:nodoc:
5
+ module Rexml # :nodoc:
6
6
  extend self
7
7
 
8
8
  def parse_error
@@ -15,11 +15,12 @@ module MultiXml
15
15
  # XML Document IO to parse
16
16
  def parse(xml)
17
17
  doc = REXML::Document.new(xml)
18
- raise(REXML::ParseException.new("The document #{doc.to_s.inspect} does not have a valid root")) unless doc.root
18
+ raise(REXML::ParseException, "The document #{doc.to_s.inspect} does not have a valid root") unless doc.root
19
+
19
20
  merge_element!({}, doc.root)
20
21
  end
21
22
 
22
- private
23
+ private
23
24
 
24
25
  # Convert an XML element and merge into the hash
25
26
  #
@@ -56,8 +57,7 @@ module MultiXml
56
57
  def merge_texts!(hash, element)
57
58
  if element.has_text?
58
59
  # must use value to prevent double-escaping
59
- texts = ''
60
- element.texts.each { |t| texts << t.value }
60
+ texts = element.texts.map(&:value).join
61
61
  merge!(hash, MultiXml::CONTENT_ROOT, texts)
62
62
  else
63
63
  hash
@@ -1,45 +1,3 @@
1
1
  module MultiXml
2
- module Version
3
- module_function
4
-
5
- # @return [Integer]
6
- def major
7
- 0
8
- end
9
-
10
- # @return [Integer]
11
- def minor
12
- 6
13
- end
14
-
15
- # @return [Integer]
16
- def patch
17
- 0
18
- end
19
-
20
- # @return [Integer, NilClass]
21
- def pre
22
- nil
23
- end
24
-
25
- # @return [Hash]
26
- def to_h
27
- {
28
- :major => major,
29
- :minor => minor,
30
- :patch => patch,
31
- :pre => pre,
32
- }
33
- end
34
-
35
- # @return [Array]
36
- def to_a
37
- [major, minor, patch, pre].compact
38
- end
39
-
40
- # @return [String]
41
- def to_s
42
- to_a.join('.')
43
- end
44
- end
2
+ VERSION = Gem::Version.create("0.7.1")
45
3
  end
data/lib/multi_xml.rb CHANGED
@@ -1,81 +1,83 @@
1
- require 'base64'
2
- require 'bigdecimal'
3
- require 'date'
4
- require 'stringio'
5
- require 'time'
6
- require 'yaml'
7
-
8
- module MultiXml # rubocop:disable ModuleLength
1
+ require "bigdecimal"
2
+ require "date"
3
+ require "stringio"
4
+ require "time"
5
+ require "yaml"
6
+
7
+ module MultiXml # rubocop:disable Metrics/ModuleLength
9
8
  class ParseError < StandardError; end
9
+
10
10
  class NoParserError < StandardError; end
11
+
11
12
  class DisallowedTypeError < StandardError
12
13
  def initialize(type)
13
- super "Disallowed type attribute: #{type.inspect}"
14
+ super("Disallowed type attribute: #{type.inspect}")
14
15
  end
15
16
  end
16
17
 
17
18
  unless defined?(REQUIREMENT_MAP)
18
19
  REQUIREMENT_MAP = [
19
- ['ox', :ox],
20
- ['libxml', :libxml],
21
- ['nokogiri', :nokogiri],
22
- ['rexml/document', :rexml],
23
- ['oga', :oga],
20
+ ["ox", :ox],
21
+ ["libxml", :libxml],
22
+ ["nokogiri", :nokogiri],
23
+ ["rexml/document", :rexml],
24
+ ["oga", :oga]
24
25
  ].freeze
25
26
  end
26
27
 
27
- CONTENT_ROOT = '__content__'.freeze unless defined?(CONTENT_ROOT)
28
+ CONTENT_ROOT = "__content__".freeze unless defined?(CONTENT_ROOT)
28
29
 
29
30
  unless defined?(PARSING)
30
31
  float_proc = proc { |float| float.to_f }
31
- datetime_proc = proc { |time| Time.parse(time).utc rescue DateTime.parse(time).utc } # rubocop:disable RescueModifier
32
+ datetime_proc = proc { |time| Time.parse(time).utc rescue DateTime.parse(time).utc } # rubocop:disable Style/RescueModifier
32
33
 
33
34
  PARSING = {
34
- 'symbol' => proc { |symbol| symbol.to_sym },
35
- 'date' => proc { |date| Date.parse(date) },
36
- 'datetime' => datetime_proc,
37
- 'dateTime' => datetime_proc,
38
- 'integer' => proc { |integer| integer.to_i },
39
- 'float' => float_proc,
40
- 'double' => float_proc,
41
- 'decimal' => proc { |number| BigDecimal(number) },
42
- 'boolean' => proc { |boolean| !%w(0 false).include?(boolean.strip) },
43
- 'string' => proc { |string| string.to_s },
44
- 'yaml' => proc { |yaml| YAML.load(yaml) rescue yaml }, # rubocop:disable RescueModifier
45
- 'base64Binary' => proc { |binary| ::Base64.decode64(binary) },
46
- 'binary' => proc { |binary, entity| parse_binary(binary, entity) },
47
- 'file' => proc { |file, entity| parse_file(file, entity) },
35
+ "symbol" => proc { |symbol| symbol.to_sym },
36
+ "date" => proc { |date| Date.parse(date) },
37
+ "datetime" => datetime_proc,
38
+ "dateTime" => datetime_proc,
39
+ "integer" => proc { |integer| integer.to_i },
40
+ "float" => float_proc,
41
+ "double" => float_proc,
42
+ "decimal" => proc { |number| BigDecimal(number) },
43
+ "boolean" => proc { |boolean| !%w[0 false].include?(boolean.strip) },
44
+ "string" => proc { |string| string.to_s },
45
+ "yaml" => proc { |yaml| YAML.load(yaml) rescue yaml }, # rubocop:disable Style/RescueModifier
46
+ "base64Binary" => proc { |binary| base64_decode(binary) },
47
+ "binary" => proc { |binary, entity| parse_binary(binary, entity) },
48
+ "file" => proc { |file, entity| parse_file(file, entity) }
48
49
  }.freeze
49
50
  end
50
51
 
51
52
  unless defined?(TYPE_NAMES)
52
53
  TYPE_NAMES = {
53
- 'Symbol' => 'symbol',
54
- 'Integer' => 'integer',
55
- 'BigDecimal' => 'decimal',
56
- 'Float' => 'float',
57
- 'TrueClass' => 'boolean',
58
- 'FalseClass' => 'boolean',
59
- 'Date' => 'date',
60
- 'DateTime' => 'datetime',
61
- 'Time' => 'datetime',
62
- 'Array' => 'array',
63
- 'Hash' => 'hash',
54
+ "Symbol" => "symbol",
55
+ "Integer" => "integer",
56
+ "BigDecimal" => "decimal",
57
+ "Float" => "float",
58
+ "TrueClass" => "boolean",
59
+ "FalseClass" => "boolean",
60
+ "Date" => "date",
61
+ "DateTime" => "datetime",
62
+ "Time" => "datetime",
63
+ "Array" => "array",
64
+ "Hash" => "hash"
64
65
  }.freeze
65
66
  end
66
67
 
67
- DISALLOWED_XML_TYPES = %w(symbol yaml).freeze
68
+ DISALLOWED_XML_TYPES = %w[symbol yaml].freeze
68
69
 
69
70
  DEFAULT_OPTIONS = {
70
- :typecast_xml_value => true,
71
- :disallowed_types => DISALLOWED_XML_TYPES,
72
- :symbolize_keys => false,
71
+ typecast_xml_value: true,
72
+ disallowed_types: DISALLOWED_XML_TYPES,
73
+ symbolize_keys: false
73
74
  }.freeze
74
75
 
75
76
  class << self
76
77
  # Get the current parser class.
77
78
  def parser
78
79
  return @parser if defined?(@parser)
80
+
79
81
  self.parser = default_parser
80
82
  @parser
81
83
  end
@@ -91,14 +93,13 @@ module MultiXml # rubocop:disable ModuleLength
91
93
  return :oga if defined?(::Oga)
92
94
 
93
95
  REQUIREMENT_MAP.each do |library, parser|
94
- begin
95
- require library
96
- return parser
97
- rescue LoadError
98
- next
99
- end
96
+ require library
97
+ return parser
98
+ rescue LoadError
99
+ next
100
100
  end
101
- raise(NoParserError.new("No XML parser detected. If you're using Rubinius and Bundler, try adding an XML parser to your Gemfile (e.g. libxml-ruby, nokogiri, or rubysl-rexml). For more information, see https://github.com/sferik/multi_xml/issues/42."))
101
+ raise(NoParserError,
102
+ "No XML parser detected. If you're using Rubinius and Bundler, try adding an XML parser to your Gemfile (e.g. libxml-ruby, nokogiri, or rubysl-rexml). For more information, see https://github.com/sferik/multi_xml/issues/42.")
102
103
  end
103
104
 
104
105
  # Set the XML parser utilizing a symbol, string, or class.
@@ -113,11 +114,11 @@ module MultiXml # rubocop:disable ModuleLength
113
114
  case new_parser
114
115
  when String, Symbol
115
116
  require "multi_xml/parsers/#{new_parser.to_s.downcase}"
116
- @parser = MultiXml::Parsers.const_get(new_parser.to_s.split('_').collect(&:capitalize).join('').to_s)
117
+ @parser = MultiXml::Parsers.const_get(new_parser.to_s.split("_").collect(&:capitalize).join.to_s)
117
118
  when Class, Module
118
119
  @parser = new_parser
119
120
  else
120
- raise('Did not recognize your parser specification. Please specify either a symbol or a class.')
121
+ raise("Did not recognize your parser specification. Please specify either a symbol or a class.")
121
122
  end
122
123
  end
123
124
 
@@ -130,8 +131,8 @@ module MultiXml # rubocop:disable ModuleLength
130
131
  # <tt>:disallowed_types</tt> :: Types to disallow from being typecasted. Defaults to `['yaml', 'symbol']`. Use `[]` to allow all types.
131
132
  #
132
133
  # <tt>:typecast_xml_value</tt> :: If true, won't typecast values for parsed document
133
- def parse(xml, options = {}) # rubocop:disable AbcSize, CyclomaticComplexity, MethodLength, PerceivedComplexity
134
- xml ||= ''
134
+ def parse(xml, options = {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
135
+ xml ||= ""
135
136
 
136
137
  options = DEFAULT_OPTIONS.merge(options)
137
138
 
@@ -141,14 +142,15 @@ module MultiXml # rubocop:disable ModuleLength
141
142
 
142
143
  char = xml.getc
143
144
  return {} if char.nil?
145
+
144
146
  xml.ungetc(char)
145
147
 
146
148
  hash = undasherize_keys(parser.parse(xml) || {})
147
- hash = options[:typecast_xml_value] ? typecast_xml_value(hash, options[:disallowed_types]) : hash
149
+ hash = typecast_xml_value(hash, options[:disallowed_types]) if options[:typecast_xml_value]
148
150
  rescue DisallowedTypeError
149
151
  raise
150
- rescue parser.parse_error => error
151
- raise(ParseError, error.message, error.backtrace) # rubocop:disable RaiseArgs
152
+ rescue parser.parse_error => e
153
+ raise(ParseError, e.message, e.backtrace)
152
154
  end
153
155
  hash = symbolize_keys(hash) if options[:symbolize_keys]
154
156
  hash
@@ -156,38 +158,42 @@ module MultiXml # rubocop:disable ModuleLength
156
158
 
157
159
  # This module decorates files with the <tt>original_filename</tt>
158
160
  # and <tt>content_type</tt> methods.
159
- module FileLike #:nodoc:
161
+ module FileLike # :nodoc:
160
162
  attr_writer :original_filename, :content_type
161
163
 
162
164
  def original_filename
163
- @original_filename || 'untitled'
165
+ @original_filename || "untitled"
164
166
  end
165
167
 
166
168
  def content_type
167
- @content_type || 'application/octet-stream'
169
+ @content_type || "application/octet-stream"
168
170
  end
169
171
  end
170
172
 
171
- private
173
+ private
172
174
 
173
175
  # TODO: Add support for other encodings
174
- def parse_binary(binary, entity) #:nodoc:
175
- case entity['encoding']
176
- when 'base64'
177
- Base64.decode64(binary)
176
+ def parse_binary(binary, entity) # :nodoc:
177
+ case entity["encoding"]
178
+ when "base64"
179
+ base64_decode(binary)
178
180
  else
179
181
  binary
180
182
  end
181
183
  end
182
184
 
183
185
  def parse_file(file, entity)
184
- f = StringIO.new(Base64.decode64(file))
186
+ f = StringIO.new(base64_decode(file))
185
187
  f.extend(FileLike)
186
- f.original_filename = entity['name']
187
- f.content_type = entity['content_type']
188
+ f.original_filename = entity["name"]
189
+ f.content_type = entity["content_type"]
188
190
  f
189
191
  end
190
192
 
193
+ def base64_decode(input)
194
+ input.unpack1("m")
195
+ end
196
+
191
197
  def symbolize_keys(params)
192
198
  case params
193
199
  when Hash
@@ -204,8 +210,8 @@ module MultiXml # rubocop:disable ModuleLength
204
210
  def undasherize_keys(params)
205
211
  case params
206
212
  when Hash
207
- params.inject({}) do |hash, (key, value)|
208
- hash[key.to_s.tr('-'.freeze, '_'.freeze)] = undasherize_keys(value)
213
+ params.each_with_object({}) do |(key, value), hash|
214
+ hash[key.to_s.tr("-", "_")] = undasherize_keys(value)
209
215
  hash
210
216
  end
211
217
  when Array
@@ -215,16 +221,16 @@ module MultiXml # rubocop:disable ModuleLength
215
221
  end
216
222
  end
217
223
 
218
- def typecast_xml_value(value, disallowed_types = nil) # rubocop:disable AbcSize, CyclomaticComplexity, MethodLength, PerceivedComplexity
224
+ def typecast_xml_value(value, disallowed_types = nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
219
225
  disallowed_types ||= DISALLOWED_XML_TYPES
220
226
 
221
227
  case value
222
228
  when Hash
223
- if value.include?('type') && !value['type'].is_a?(Hash) && disallowed_types.include?(value['type'])
224
- raise(DisallowedTypeError.new(value['type']))
229
+ if value.include?("type") && !value["type"].is_a?(Hash) && disallowed_types.include?(value["type"])
230
+ raise(DisallowedTypeError, value["type"])
225
231
  end
226
232
 
227
- if value['type'] == 'array'
233
+ if value["type"] == "array"
228
234
 
229
235
  # this commented-out suggestion helps to avoid the multiple attribute
230
236
  # problem, but it breaks when there is only one item in the array.
@@ -239,7 +245,7 @@ module MultiXml # rubocop:disable ModuleLength
239
245
 
240
246
  # This approach ignores attribute entries that are not convertable
241
247
  # to an Array which allows attributes to be ignored.
242
- _, entries = value.detect { |k, v| k != 'type' && (v.is_a?(Array) || v.is_a?(Hash)) }
248
+ _, entries = value.detect { |k, v| k != "type" && (v.is_a?(Array) || v.is_a?(Hash)) }
243
249
 
244
250
  case entries
245
251
  when NilClass
@@ -256,10 +262,10 @@ module MultiXml # rubocop:disable ModuleLength
256
262
 
257
263
  elsif value.key?(CONTENT_ROOT)
258
264
  content = value[CONTENT_ROOT]
259
- block = PARSING[value['type']]
265
+ block = PARSING[value["type"]]
260
266
  if block
261
267
  if block.arity == 1
262
- value.delete('type') if PARSING[value['type']]
268
+ value.delete("type") if PARSING[value["type"]]
263
269
  if value.keys.size > 1
264
270
  value[CONTENT_ROOT] = block.call(content)
265
271
  value
@@ -270,31 +276,31 @@ module MultiXml # rubocop:disable ModuleLength
270
276
  block.call(content, value)
271
277
  end
272
278
  else
273
- value.keys.size > 1 ? value : content
279
+ (value.keys.size > 1) ? value : content
274
280
  end
275
- elsif value['type'] == 'string' && value['nil'] != 'true'
276
- ''
281
+ elsif value["type"] == "string" && value["nil"] != "true"
282
+ ""
277
283
  # blank or nil parsed values are represented by nil
278
- elsif value.empty? || value['nil'] == 'true'
284
+ elsif value.empty? || value["nil"] == "true"
279
285
  nil
280
286
  # If the type is the only element which makes it then
281
287
  # this still makes the value nil, except if type is
282
288
  # a XML node(where type['value'] is a Hash)
283
- elsif value['type'] && value.size == 1 && !value['type'].is_a?(Hash)
289
+ elsif value["type"] && value.size == 1 && !value["type"].is_a?(Hash)
284
290
  nil
285
291
  else
286
- xml_value = value.inject({}) do |hash, (k, v)|
292
+ xml_value = value.each_with_object({}) do |(k, v), hash|
287
293
  hash[k] = typecast_xml_value(v, disallowed_types)
288
294
  hash
289
295
  end
290
296
 
291
297
  # Turn {:files => {:file => #<StringIO>} into {:files => #<StringIO>} so it is compatible with
292
298
  # how multipart uploaded files from HTML appear
293
- xml_value['file'].is_a?(StringIO) ? xml_value['file'] : xml_value
299
+ (xml_value["file"].is_a?(StringIO)) ? xml_value["file"] : xml_value
294
300
  end
295
301
  when Array
296
302
  value.map! { |i| typecast_xml_value(i, disallowed_types) }
297
- value.length > 1 ? value : value.first
303
+ (value.length > 1) ? value : value.first
298
304
  when String
299
305
  value
300
306
  else
metadata CHANGED
@@ -1,40 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multi_xml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
- - Erik Michaels-Ober
8
- autorequire:
9
- bindir: bin
7
+ - Erik Berlin
8
+ autorequire:
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-06 00:00:00.000000000 Z
11
+ date: 2024-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: bigdecimal
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
20
- type: :development
19
+ version: '3.1'
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
27
- description: Provides swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML.
28
- email: sferik@gmail.com
26
+ version: '3.1'
27
+ description:
28
+ email:
29
+ - sferik@gmail.com
29
30
  executables: []
30
31
  extensions: []
31
32
  extra_rdoc_files: []
32
33
  files:
34
+ - ".rspec"
35
+ - ".rubocop.yml"
33
36
  - ".yardopts"
34
37
  - CHANGELOG.md
35
38
  - CONTRIBUTING.md
39
+ - Gemfile
36
40
  - LICENSE.md
37
41
  - README.md
42
+ - Rakefile
38
43
  - lib/multi_xml.rb
39
44
  - lib/multi_xml/parsers/libxml.rb
40
45
  - lib/multi_xml/parsers/libxml2_parser.rb
@@ -43,12 +48,16 @@ files:
43
48
  - lib/multi_xml/parsers/ox.rb
44
49
  - lib/multi_xml/parsers/rexml.rb
45
50
  - lib/multi_xml/version.rb
46
- - multi_xml.gemspec
47
51
  homepage: https://github.com/sferik/multi_xml
48
52
  licenses:
49
53
  - MIT
50
- metadata: {}
51
- post_install_message:
54
+ metadata:
55
+ allowed_push_host: https://rubygems.org
56
+ homepage_uri: https://github.com/sferik/multi_xml
57
+ source_code_uri: https://github.com/sferik/multi_xml
58
+ changelog_uri: https://github.com/sferik/multi_xml/blob/master/CHANGELOG.md
59
+ rubygems_mfa_required: 'true'
60
+ post_install_message:
52
61
  rdoc_options: []
53
62
  require_paths:
54
63
  - lib
@@ -56,16 +65,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
56
65
  requirements:
57
66
  - - ">="
58
67
  - !ruby/object:Gem::Version
59
- version: '0'
68
+ version: 3.1.2
60
69
  required_rubygems_version: !ruby/object:Gem::Requirement
61
70
  requirements:
62
71
  - - ">="
63
72
  - !ruby/object:Gem::Version
64
- version: 1.3.5
73
+ version: '0'
65
74
  requirements: []
66
- rubyforge_project:
67
- rubygems_version: 2.5.2
68
- signing_key:
75
+ rubygems_version: 3.3.7
76
+ signing_key:
69
77
  specification_version: 4
70
- summary: A generic swappable back-end for XML parsing
78
+ summary: Provides swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML.
71
79
  test_files: []
data/multi_xml.gemspec DELETED
@@ -1,19 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'multi_xml/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.add_development_dependency 'bundler', '~> 1.0'
8
- spec.author = 'Erik Michaels-Ober'
9
- spec.description = 'Provides swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML.'
10
- spec.email = 'sferik@gmail.com'
11
- spec.files = %w(.yardopts CHANGELOG.md CONTRIBUTING.md LICENSE.md README.md multi_xml.gemspec) + Dir['lib/**/*.rb']
12
- spec.homepage = 'https://github.com/sferik/multi_xml'
13
- spec.licenses = ['MIT']
14
- spec.name = 'multi_xml'
15
- spec.require_paths = ['lib']
16
- spec.required_rubygems_version = '>= 1.3.5'
17
- spec.summary = 'A generic swappable back-end for XML parsing'
18
- spec.version = MultiXml::Version
19
- end