multi_xml 0.5.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7bebe7a08139024835279d7ffc78a7d86d0cb9a5ff59787068e044f7c75dc6f9
4
+ data.tar.gz: a2f579d2e18a266fe9573174de87ac960fcf867081705a2a6feb458bfa573225
5
+ SHA512:
6
+ metadata.gz: be4ffea0dd836f1d1d1baf73ffded7de5a79fdc53a5b039b5e7fd0a615a786ca08dc0a7bbf5561266cdade44a9cb3c2382fe6e35a54599876f77ec74ec937d42
7
+ data.tar.gz: d579ab46f0122a1011704e397062b5d9e648eeaae85a8baa30ac8eda7f3d1cdaa9e57fe1922e6e3e7ac608ef9607033c1547773dbb2eb1fe6785176a3471764d
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/CONTRIBUTING.md CHANGED
@@ -16,8 +16,10 @@ Here are some ways *you* can contribute:
16
16
  * by refactoring code
17
17
  * by resolving [issues][]
18
18
  * by reviewing patches
19
+ * [financially][gittip]
19
20
 
20
21
  [issues]: https://github.com/sferik/multi_xml/issues
22
+ [gittip]: https://www.gittip.com/sferik/
21
23
 
22
24
  ## Submitting an Issue
23
25
  We use the [GitHub issue tracker][issues] to track bugs and features. Before
@@ -35,12 +37,12 @@ Ideally, a bug report should include a pull request with failing specs.
35
37
  3. Add specs for your unimplemented feature or bug fix.
36
38
  4. Run `bundle exec rake spec`. If your specs pass, return to step 3.
37
39
  5. Implement your feature or bug fix.
38
- 6. Run `bundle exec rake spec`. If your specs fail, return to step 5.
40
+ 6. Run `bundle exec rake`. If your specs fail, return to step 5.
39
41
  7. Run `open coverage/index.html`. If your changes are not completely covered
40
42
  by your tests, return to step 3.
41
43
  8. Add documentation for your feature or bug fix.
42
- 9. Run `bundle exec rake doc:yard`. If your changes are not 100% documented, go
43
- back to step 8.
44
+ 9. Run `bundle exec rake verify_measurements`. If your changes are not 100%
45
+ documented, go back to step 8.
44
46
  10. Add, commit, and push your changes.
45
47
  11. [Submit a pull request.][pr]
46
48
 
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,42 +1,16 @@
1
1
  # MultiXML
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/multi_xml.png)][gem]
4
- [![Build Status](https://secure.travis-ci.org/sferik/multi_xml.png?branch=master)][travis]
5
- [![Dependency Status](https://gemnasium.com/sferik/multi_xml.png?travis)][gemnasium]
6
- [![Code Climate](https://codeclimate.com/github/sferik/multi_xml.png)][codeclimate]
7
- [![Coverage Status](https://coveralls.io/repos/sferik/multi_xml/badge.png?branch=master)][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
18
6
  gem install multi_xml
19
7
 
20
- To ensure the code you're installing hasn't been tampered with, it's
21
- recommended that you verify the signature. To do this, you need to add my
22
- public key as a trusted certificate (you only need to do this once):
23
-
24
- gem cert --add <(curl -Ls https://raw.github.com/sferik/multi_xml/master/certs/sferik.pem)
25
-
26
- Then, install the gem with the high security trust policy:
27
-
28
- gem install multi_xml -P HighSecurity
29
-
30
8
  ## Documentation
31
9
  [http://rdoc.info/gems/multi_xml][documentation]
32
10
 
33
11
  [documentation]: http://rdoc.info/gems/multi_xml
34
12
 
35
13
  ## Usage Examples
36
- Lots of Ruby libraries utilize XML parsing in some form, and everyone has their
37
- favorite XML library. In order to best support multiple XML parsers and
38
- libraries, `multi_xml` is a general-purpose swappable XML backend library. You
39
- use it like so:
40
14
  ```ruby
41
15
  require 'multi_xml'
42
16
 
@@ -55,25 +29,28 @@ MultiXml.parse('<tag>This is the contents</tag>') # Parsed using Nokogiri
55
29
  MultiXml.parser = :rexml
56
30
  MultiXml.parser = MultiXml::Parsers::Rexml # Same as above
57
31
  MultiXml.parse('<tag>This is the contents</tag>') # Parsed using REXML
32
+
33
+ MultiXml.parser = :oga
34
+ MultiXml.parser = MultiXml::Parsers::Oga # Same as above
35
+ MultiXml.parse('<tag>This is the contents</tag>') # Parsed using Oga
58
36
  ```
59
37
  The `parser` setter takes either a symbol or a class (to allow for custom XML
60
38
  parsers) that responds to `.parse` at the class level.
61
39
 
62
40
  MultiXML tries to have intelligent defaulting. That is, if you have any of the
63
- supported parsers already loaded, it will utilize them before attempting to
64
- 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,
65
43
  then Nokogiri, and finally REXML.
66
44
 
67
45
  ## Supported Ruby Versions
68
- 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
69
47
  implementations:
70
48
 
71
- * Ruby 1.8.7
72
- * Ruby 1.9.2
73
- * Ruby 1.9.3
74
- * Ruby 2.0.0
49
+ * 3.1
50
+ * 3.2
51
+ * 3.3
75
52
 
76
- 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.
77
54
 
78
55
  This library may inadvertently work (or seem to work) on other Ruby
79
56
  implementations, however support will only be provided for the versions listed
@@ -92,6 +69,6 @@ MultiXML was inspired by [MultiJSON][].
92
69
  [multijson]: https://github.com/intridea/multi_json/
93
70
 
94
71
  ## Copyright
95
- Copyright (c) 2010-2013 Erik Michaels-Ober. See [LICENSE][] for details.
72
+ Copyright (c) 2010-2024 Erik Berlin. See [LICENSE][] for details.
96
73
 
97
74
  [license]: LICENSE.md
data/Rakefile CHANGED
@@ -1,21 +1,33 @@
1
- require 'bundler'
1
+ require "bundler"
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
- require 'rspec/core/rake_task'
4
+ require "rspec/core/rake_task"
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
 
7
- task :test => :spec
8
- task :default => :spec
7
+ task test: :spec
9
8
 
10
- namespace :doc do
11
- require 'yard'
12
- YARD::Rake::YardocTask.new do |task|
13
- task.files = ['lib/**/*.rb', '-', 'LICENSE.md']
14
- task.options = [
15
- '--no-private',
16
- '--protected',
17
- '--output-dir', 'doc/yard',
18
- '--markup', 'markdown',
19
- ]
20
- end
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"
21
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,25 +1,28 @@
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
-
9
8
  extend self
10
9
 
11
- def parse_error() ::LibXML::XML::Error end
10
+ def parse_error
11
+ ::LibXML::XML::Error
12
+ end
12
13
 
13
14
  def parse(xml)
14
15
  node_to_hash(LibXML::XML::Parser.io(xml).parse.root)
15
16
  end
16
17
 
17
- def each_child(node, &block)
18
- node.each_child(&block)
18
+ private
19
+
20
+ def each_child(node, &)
21
+ node.each_child(&)
19
22
  end
20
23
 
21
- def each_attr(node, &block)
22
- node.each_attr(&block)
24
+ def each_attr(node, &)
25
+ node.each_attr(&)
23
26
  end
24
27
 
25
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,16 +8,19 @@ module MultiXml
8
8
  #
9
9
  # hash::
10
10
  # Hash to merge the converted element into.
11
- def node_to_hash(node, hash={})
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
 
16
16
  # Insert node hash into parent hash correctly.
17
17
  case hash[name]
18
- when Array then hash[name] << node_hash
19
- when Hash then hash[name] = [hash[name], node_hash]
20
- when nil then hash[name] = node_hash
18
+ when Array
19
+ hash[name] << node_hash
20
+ when Hash
21
+ hash[name] = [hash[name], node_hash]
22
+ when NilClass
23
+ hash[name] = node_hash
21
24
  end
22
25
 
23
26
  # Handle child elements
@@ -25,24 +28,18 @@ module MultiXml
25
28
  if c.element?
26
29
  node_to_hash(c, node_hash)
27
30
  elsif c.text? || c.cdata?
28
- node_hash[MultiXml::CONTENT_ROOT] << c.content
31
+ node_hash[MultiXml::CONTENT_ROOT] += c.content
29
32
  end
30
33
  end
31
34
 
32
35
  # Remove content node if it is empty
33
- if node_hash[MultiXml::CONTENT_ROOT].strip.empty?
34
- node_hash.delete(MultiXml::CONTENT_ROOT)
35
- end
36
+ node_hash.delete(MultiXml::CONTENT_ROOT) if node_hash[MultiXml::CONTENT_ROOT].strip.empty?
36
37
 
37
38
  # Handle attributes
38
39
  each_attr(node) do |a|
39
40
  key = node_name(a)
40
-
41
- node_hash[key] = if v = node_hash[key]
42
- [a.value, v]
43
- else
44
- a.value
45
- end
41
+ v = node_hash[key]
42
+ node_hash[key] = ((v) ? [a.value, v] : a.value)
46
43
  end
47
44
 
48
45
  hash
@@ -51,23 +48,22 @@ module MultiXml
51
48
  # Parse an XML Document IO into a simple hash.
52
49
  # xml::
53
50
  # XML Document IO to parse
54
- def parse(xml)
55
- raise NotImplementedError, "inheritor should define #{__method__}"
51
+ def parse(_)
52
+ raise(NotImplementedError, "inheritor should define #{__method__}")
56
53
  end
57
54
 
58
- # :stopdoc:
59
55
  private
60
56
 
61
- def each_child(*args)
62
- raise NotImplementedError, "inheritor should define #{__method__}"
57
+ def each_child(*)
58
+ raise(NotImplementedError, "inheritor should define #{__method__}")
63
59
  end
64
60
 
65
- def each_attr(*args)
66
- raise NotImplementedError, "inheritor should define #{__method__}"
61
+ def each_attr(*)
62
+ raise(NotImplementedError, "inheritor should define #{__method__}")
67
63
  end
68
64
 
69
- def node_name(*args)
70
- raise NotImplementedError, "inheritor should define #{__method__}"
65
+ def node_name(*)
66
+ raise(NotImplementedError, "inheritor should define #{__method__}")
71
67
  end
72
68
  end
73
69
  end
@@ -1,27 +1,31 @@
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
-
9
8
  extend self
10
9
 
11
- def parse_error() ::Nokogiri::XML::SyntaxError end
10
+ def parse_error
11
+ ::Nokogiri::XML::SyntaxError
12
+ end
12
13
 
13
14
  def parse(xml)
14
15
  doc = ::Nokogiri::XML(xml)
15
- raise doc.errors.first if doc.errors.length > 0
16
+ raise(doc.errors.first) unless doc.errors.empty?
17
+
16
18
  node_to_hash(doc.root)
17
19
  end
18
20
 
19
- def each_child(node, &block)
20
- node.children.each(&block)
21
+ private
22
+
23
+ def each_child(node, &)
24
+ node.children.each(&)
21
25
  end
22
26
 
23
- def each_attr(node, &block)
24
- node.attribute_nodes.each(&block)
27
+ def each_attr(node, &)
28
+ node.attribute_nodes.each(&)
25
29
  end
26
30
 
27
31
  def node_name(node)
@@ -0,0 +1,71 @@
1
+ require "oga" unless defined?(Oga)
2
+ require "multi_xml/parsers/libxml2_parser"
3
+
4
+ module MultiXml
5
+ module Parsers
6
+ module Oga # :nodoc:
7
+ include Libxml2Parser
8
+ extend self
9
+
10
+ def parse_error
11
+ LL::ParserError
12
+ end
13
+
14
+ def parse(io)
15
+ document = ::Oga.parse_xml(io)
16
+ node_to_hash(document.children[0])
17
+ end
18
+
19
+ def node_to_hash(node, hash = {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
20
+ node_hash = {MultiXml::CONTENT_ROOT => ""}
21
+
22
+ name = node_name(node)
23
+
24
+ # Insert node hash into parent hash correctly.
25
+ case hash[name]
26
+ when Array
27
+ hash[name] << node_hash
28
+ when Hash
29
+ hash[name] = [hash[name], node_hash]
30
+ when NilClass
31
+ hash[name] = node_hash
32
+ end
33
+
34
+ # Handle child elements
35
+ each_child(node) do |c|
36
+ if c.is_a?(::Oga::XML::Element)
37
+ node_to_hash(c, node_hash)
38
+ elsif c.is_a?(::Oga::XML::Text) || c.is_a?(::Oga::XML::Cdata)
39
+ node_hash[MultiXml::CONTENT_ROOT] += c.text
40
+ end
41
+ end
42
+
43
+ # Remove content node if it is empty
44
+ node_hash.delete(MultiXml::CONTENT_ROOT) if node_hash[MultiXml::CONTENT_ROOT].strip.empty?
45
+
46
+ # Handle attributes
47
+ each_attr(node) do |a|
48
+ key = node_name(a)
49
+ v = node_hash[key]
50
+ node_hash[key] = ((v) ? [a.value, v] : a.value)
51
+ end
52
+
53
+ hash
54
+ end
55
+
56
+ private
57
+
58
+ def each_child(node, &)
59
+ node.children.each(&)
60
+ end
61
+
62
+ def each_attr(node, &)
63
+ node.attributes.each(&)
64
+ end
65
+
66
+ def node_name(node)
67
+ node.name
68
+ end
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,9 +20,8 @@ require 'ox' unless defined?(Ox)
20
20
 
21
21
  module MultiXml
22
22
  module Parsers
23
- module Ox #:nodoc:
24
-
25
- extend self
23
+ module Ox # :nodoc:
24
+ module_function
26
25
 
27
26
  def parse_error
28
27
  Exception
@@ -30,14 +29,14 @@ module MultiXml
30
29
 
31
30
  def parse(io)
32
31
  handler = Handler.new
33
- ::Ox.sax_parse(handler, io, :convert_special => true)
32
+ ::Ox.sax_parse(handler, io, convert_special: true, skip: :skip_return)
34
33
  handler.doc
35
34
  end
36
35
 
37
36
  class Handler
38
37
  attr_accessor :stack
39
38
 
40
- def initialize()
39
+ def initialize
41
40
  @stack = []
42
41
  end
43
42
 
@@ -46,9 +45,7 @@ module MultiXml
46
45
  end
47
46
 
48
47
  def attr(name, value)
49
- unless @stack.empty?
50
- append(name, value)
51
- end
48
+ append(name, value) unless @stack.empty?
52
49
  end
53
50
 
54
51
  def text(value)
@@ -60,26 +57,24 @@ module MultiXml
60
57
  end
61
58
 
62
59
  def start_element(name)
63
- if @stack.empty?
64
- @stack.push(Hash.new)
65
- end
66
- h = Hash.new
60
+ @stack.push({}) if @stack.empty?
61
+ h = {}
67
62
  append(name, h)
68
63
  @stack.push(h)
69
64
  end
70
65
 
71
- def end_element(name)
72
- @stack.pop()
66
+ def end_element(_)
67
+ @stack.pop
73
68
  end
74
69
 
75
70
  def error(message, line, column)
76
- raise Exception.new("#{message} at #{line}:#{column}")
71
+ raise(StandardError, "#{message} at #{line}:#{column}")
77
72
  end
78
73
 
79
74
  def append(key, value)
80
75
  key = key.to_s
81
76
  h = @stack.last
82
- if h.has_key?(key)
77
+ if h.key?(key)
83
78
  v = h[key]
84
79
  if v.is_a?(Array)
85
80
  v << value
@@ -90,8 +85,7 @@ module MultiXml
90
85
  h[key] = value
91
86
  end
92
87
  end
93
-
94
- end # Handler
95
- end # Ox
96
- end # Parsers
97
- end # MultiXml
88
+ end
89
+ end
90
+ end
91
+ end