multi_xml 0.5.5 → 0.6.0
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 +7 -0
- data/CONTRIBUTING.md +5 -3
- data/README.md +15 -17
- data/lib/multi_xml.rb +80 -71
- data/lib/multi_xml/parsers/libxml.rb +5 -2
- data/lib/multi_xml/parsers/libxml2_parser.rb +18 -20
- data/lib/multi_xml/parsers/nokogiri.rb +6 -3
- data/lib/multi_xml/parsers/oga.rb +73 -0
- data/lib/multi_xml/parsers/ox.rb +8 -14
- data/lib/multi_xml/parsers/rexml.rb +13 -13
- data/lib/multi_xml/version.rb +43 -1
- data/multi_xml.gemspec +5 -10
- metadata +15 -55
- data.tar.gz.sig +0 -0
- data/Rakefile +0 -21
- data/spec/helper.rb +0 -17
- data/spec/multi_xml_spec.rb +0 -43
- data/spec/parser_shared_example.rb +0 -694
- data/spec/speed.rb +0 -63
- metadata.gz.sig +0 -0
@@ -5,17 +5,20 @@ module MultiXml
|
|
5
5
|
module Parsers
|
6
6
|
module Nokogiri #:nodoc:
|
7
7
|
include Libxml2Parser
|
8
|
-
|
9
8
|
extend self
|
10
9
|
|
11
|
-
def parse_error
|
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
|
16
|
+
raise(doc.errors.first) unless doc.errors.empty?
|
16
17
|
node_to_hash(doc.root)
|
17
18
|
end
|
18
19
|
|
20
|
+
private
|
21
|
+
|
19
22
|
def each_child(node, &block)
|
20
23
|
node.children.each(&block)
|
21
24
|
end
|
@@ -0,0 +1,73 @@
|
|
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 AbcSize, CyclomaticComplexity, MethodLength, PerceivedComplexity
|
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
|
+
if node_hash[MultiXml::CONTENT_ROOT].strip.empty?
|
45
|
+
node_hash.delete(MultiXml::CONTENT_ROOT)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Handle attributes
|
49
|
+
each_attr(node) do |a|
|
50
|
+
key = node_name(a)
|
51
|
+
v = node_hash[key]
|
52
|
+
node_hash[key] = (v ? [a.value, v] : a.value)
|
53
|
+
end
|
54
|
+
|
55
|
+
hash
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def each_child(node, &block)
|
61
|
+
node.children.each(&block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def each_attr(node, &block)
|
65
|
+
node.attributes.each(&block)
|
66
|
+
end
|
67
|
+
|
68
|
+
def node_name(node)
|
69
|
+
node.name
|
70
|
+
end
|
71
|
+
end # Oga
|
72
|
+
end # Parsers
|
73
|
+
end # MultiXml
|
data/lib/multi_xml/parsers/ox.rb
CHANGED
@@ -21,7 +21,6 @@ require 'ox' unless defined?(Ox)
|
|
21
21
|
module MultiXml
|
22
22
|
module Parsers
|
23
23
|
module Ox #:nodoc:
|
24
|
-
|
25
24
|
extend self
|
26
25
|
|
27
26
|
def parse_error
|
@@ -37,7 +36,7 @@ module MultiXml
|
|
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
|
-
|
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(
|
72
|
-
@stack.pop
|
66
|
+
def end_element(_)
|
67
|
+
@stack.pop
|
73
68
|
end
|
74
69
|
|
75
70
|
def error(message, line, column)
|
76
|
-
raise
|
71
|
+
raise(Exception.new("#{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.
|
77
|
+
if h.key?(key)
|
83
78
|
v = h[key]
|
84
79
|
if v.is_a?(Array)
|
85
80
|
v << value
|
@@ -90,7 +85,6 @@ module MultiXml
|
|
90
85
|
h[key] = value
|
91
86
|
end
|
92
87
|
end
|
93
|
-
|
94
88
|
end # Handler
|
95
89
|
end # Ox
|
96
90
|
end # Parsers
|
@@ -4,7 +4,10 @@ module MultiXml
|
|
4
4
|
module Parsers
|
5
5
|
module Rexml #:nodoc:
|
6
6
|
extend self
|
7
|
-
|
7
|
+
|
8
|
+
def parse_error
|
9
|
+
::REXML::ParseException
|
10
|
+
end
|
8
11
|
|
9
12
|
# Parse an XML Document IO into a simple hash using REXML
|
10
13
|
#
|
@@ -12,14 +15,11 @@ module MultiXml
|
|
12
15
|
# XML Document IO to parse
|
13
16
|
def parse(xml)
|
14
17
|
doc = REXML::Document.new(xml)
|
15
|
-
|
16
|
-
|
17
|
-
else
|
18
|
-
raise REXML::ParseException, "The document #{doc.to_s.inspect} does not have a valid root"
|
19
|
-
end
|
18
|
+
raise(REXML::ParseException.new("The document #{doc.to_s.inspect} does not have a valid root")) unless doc.root
|
19
|
+
merge_element!({}, doc.root)
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
private
|
23
23
|
|
24
24
|
# Convert an XML element and merge into the hash
|
25
25
|
#
|
@@ -39,7 +39,7 @@ module MultiXml
|
|
39
39
|
hash = get_attributes(element)
|
40
40
|
|
41
41
|
if element.has_elements?
|
42
|
-
element.each_element {|child| merge_element!(hash, child) }
|
42
|
+
element.each_element { |child| merge_element!(hash, child) }
|
43
43
|
merge_texts!(hash, element) unless empty_content?(element)
|
44
44
|
hash
|
45
45
|
else
|
@@ -54,13 +54,13 @@ module MultiXml
|
|
54
54
|
# element::
|
55
55
|
# XML element whose texts are to me merged into the hash
|
56
56
|
def merge_texts!(hash, element)
|
57
|
-
|
58
|
-
hash
|
59
|
-
else
|
57
|
+
if element.has_text?
|
60
58
|
# must use value to prevent double-escaping
|
61
59
|
texts = ''
|
62
60
|
element.texts.each { |t| texts << t.value }
|
63
61
|
merge!(hash, MultiXml::CONTENT_ROOT, texts)
|
62
|
+
else
|
63
|
+
hash
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -76,7 +76,7 @@ module MultiXml
|
|
76
76
|
# value::
|
77
77
|
# Value to be associated with key.
|
78
78
|
def merge!(hash, key, value)
|
79
|
-
if hash.
|
79
|
+
if hash.key?(key)
|
80
80
|
if hash[key].instance_of?(Array)
|
81
81
|
hash[key] << value
|
82
82
|
else
|
@@ -97,7 +97,7 @@ module MultiXml
|
|
97
97
|
# XML element to extract attributes from.
|
98
98
|
def get_attributes(element)
|
99
99
|
attributes = {}
|
100
|
-
element.attributes.each { |n,v| attributes[n] = v }
|
100
|
+
element.attributes.each { |n, v| attributes[n] = v }
|
101
101
|
attributes
|
102
102
|
end
|
103
103
|
|
data/lib/multi_xml/version.rb
CHANGED
@@ -1,3 +1,45 @@
|
|
1
1
|
module MultiXml
|
2
|
-
|
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
|
3
45
|
end
|
data/multi_xml.gemspec
CHANGED
@@ -5,20 +5,15 @@ require 'multi_xml/version'
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.add_development_dependency 'bundler', '~> 1.0'
|
8
|
-
spec.author =
|
9
|
-
spec.
|
10
|
-
spec.description = %q{Provides swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML.}
|
8
|
+
spec.author = 'Erik Michaels-Ober'
|
9
|
+
spec.description = 'Provides swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML.'
|
11
10
|
spec.email = 'sferik@gmail.com'
|
12
|
-
spec.files = %w(.yardopts CHANGELOG.md CONTRIBUTING.md LICENSE.md README.md
|
13
|
-
spec.files += Dir.glob("lib/**/*.rb")
|
14
|
-
spec.files += Dir.glob("spec/**/*")
|
11
|
+
spec.files = %w(.yardopts CHANGELOG.md CONTRIBUTING.md LICENSE.md README.md multi_xml.gemspec) + Dir['lib/**/*.rb']
|
15
12
|
spec.homepage = 'https://github.com/sferik/multi_xml'
|
16
13
|
spec.licenses = ['MIT']
|
17
14
|
spec.name = 'multi_xml'
|
18
15
|
spec.require_paths = ['lib']
|
19
16
|
spec.required_rubygems_version = '>= 1.3.5'
|
20
|
-
spec.
|
21
|
-
spec.
|
22
|
-
spec.test_files = Dir.glob("spec/**/*")
|
23
|
-
spec.version = MultiXml::VERSION
|
17
|
+
spec.summary = 'A generic swappable back-end for XML parsing'
|
18
|
+
spec.version = MultiXml::Version
|
24
19
|
end
|
metadata
CHANGED
@@ -1,57 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: multi_xml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.6.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Erik Michaels-Ober
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
|
-
cert_chain:
|
12
|
-
-
|
13
|
-
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURMakNDQWhhZ0F3SUJB
|
14
|
-
Z0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREE5TVE4d0RRWURWUVFEREFaelpt
|
15
|
-
VnkKYVdzeEZUQVRCZ29Ka2lhSmsvSXNaQUVaRmdWbmJXRnBiREVUTUJFR0Nn
|
16
|
-
bVNKb21UOGl4a0FSa1dBMk52YlRBZQpGdzB4TXpBeU1ETXhNREF5TWpkYUZ3
|
17
|
-
MHhOREF5TURNeE1EQXlNamRhTUQweER6QU5CZ05WQkFNTUJuTm1aWEpwCmF6
|
18
|
-
RVZNQk1HQ2dtU0pvbVQ4aXhrQVJrV0JXZHRZV2xzTVJNd0VRWUtDWkltaVpQ
|
19
|
-
eUxHUUJHUllEWTI5dE1JSUIKSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4
|
20
|
-
QU1JSUJDZ0tDQVFFQWwweDVkeDh1S3hpN1Rrckl1eUJVVEpWQgp2MW85M25V
|
21
|
-
QjlqL3k0TTk2Z1Yycll3QWNpMUpQQnNlTmQ2RnliempvM1lHdUhsN0VRSHVT
|
22
|
-
SE5hZjFwMmx4ZXcvCnk2MEpYSUpCQmdQY0RLL0tDUDROVUhvZm0wamZvWUQr
|
23
|
-
SDV1TkpmSENOcTcvWnNUeE90RTNSYTkyczBCQ01UcG0Kd0JNTWxXUjVNdGRF
|
24
|
-
aElZdUJPNFhobmVqWWdIMEwvN0JMMmx5bW50Vm5zci9hZ2RRb29qUUNOMUlR
|
25
|
-
bXNSSnZyUgpkdVpSTzN0WnZvSW8xcEJjNEpFZWhEdXFDZXlCZ1BMT3FNb0t0
|
26
|
-
UWxvbGQxVFFzMWtXVUJLN0tXTUZFaEtDL0tnCnp5ektSSFFvOXlEWXdPdllu
|
27
|
-
Z29CTFkrVC9sd0NUNGR5c3NkaHpSYmZueEFoYUt1NFNBc3NJd2FDMDF5Vm93
|
28
|
-
SUQKQVFBQm96a3dOekFKQmdOVkhSTUVBakFBTUIwR0ExVWREZ1FXQkJTMHJ1
|
29
|
-
RGZSYWs1Y2kxT3BETlgvWmRERWtJcwppVEFMQmdOVkhROEVCQU1DQkxBd0RR
|
30
|
-
WUpLb1pJaHZjTkFRRUZCUUFEZ2dFQkFISFNNcy9NUDBzT2FMa0V2NEpvCnp2
|
31
|
-
a20zcW41QTZ0MHZhSHg3NzRjbWVqeU1VKzV3eVN4UmV6c3BMN1VMaDlOZXVL
|
32
|
-
Mk9oVStPZTNUcHFyQWc1VEsKUjhHUUlMblZ1MkZlbUdBNnNBa1BEbGNQdGdB
|
33
|
-
NmllSTE5UFpPRjZIVkxtYy9JRC9kUC9OZ1pXV3pFZXFRS21jSwoyK0hNK1NF
|
34
|
-
RURoWmtTY1lla3c0Wk9lMTY0WnRaRzgxNm9BdjV4MHBHaXRTSWt1bVVwN1Y4
|
35
|
-
aUVaLzZlaHI3WTllClhPZzRlZXVuNUwvSmptakFSb1cya05kdmtSRDNjMkVl
|
36
|
-
U0xxV3ZRUnNCbHlwSGZoczZKSnVMbHlaUEdoVTNSL3YKU2YzbFZLcEJDV2dS
|
37
|
-
cEdUdnk0NVhWcEIrNTl5MzNQSm1FdVExUFRFT1l2UXlhbzlVS01BQWFBTi83
|
38
|
-
cVdRdGpsMApobHc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
|
39
|
-
date: 2013-08-06 00:00:00.000000000 Z
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-06 00:00:00.000000000 Z
|
40
12
|
dependencies:
|
41
13
|
- !ruby/object:Gem::Dependency
|
42
14
|
name: bundler
|
43
15
|
requirement: !ruby/object:Gem::Requirement
|
44
|
-
none: false
|
45
16
|
requirements:
|
46
|
-
- - ~>
|
17
|
+
- - "~>"
|
47
18
|
- !ruby/object:Gem::Version
|
48
19
|
version: '1.0'
|
49
20
|
type: :development
|
50
21
|
prerelease: false
|
51
22
|
version_requirements: !ruby/object:Gem::Requirement
|
52
|
-
none: false
|
53
23
|
requirements:
|
54
|
-
- - ~>
|
24
|
+
- - "~>"
|
55
25
|
- !ruby/object:Gem::Version
|
56
26
|
version: '1.0'
|
57
27
|
description: Provides swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML.
|
@@ -60,52 +30,42 @@ executables: []
|
|
60
30
|
extensions: []
|
61
31
|
extra_rdoc_files: []
|
62
32
|
files:
|
63
|
-
- .yardopts
|
33
|
+
- ".yardopts"
|
64
34
|
- CHANGELOG.md
|
65
35
|
- CONTRIBUTING.md
|
66
36
|
- LICENSE.md
|
67
37
|
- README.md
|
68
|
-
-
|
69
|
-
- multi_xml.gemspec
|
38
|
+
- lib/multi_xml.rb
|
70
39
|
- lib/multi_xml/parsers/libxml.rb
|
71
40
|
- lib/multi_xml/parsers/libxml2_parser.rb
|
72
41
|
- lib/multi_xml/parsers/nokogiri.rb
|
42
|
+
- lib/multi_xml/parsers/oga.rb
|
73
43
|
- lib/multi_xml/parsers/ox.rb
|
74
44
|
- lib/multi_xml/parsers/rexml.rb
|
75
45
|
- lib/multi_xml/version.rb
|
76
|
-
-
|
77
|
-
- spec/helper.rb
|
78
|
-
- spec/multi_xml_spec.rb
|
79
|
-
- spec/parser_shared_example.rb
|
80
|
-
- spec/speed.rb
|
46
|
+
- multi_xml.gemspec
|
81
47
|
homepage: https://github.com/sferik/multi_xml
|
82
48
|
licenses:
|
83
49
|
- MIT
|
50
|
+
metadata: {}
|
84
51
|
post_install_message:
|
85
52
|
rdoc_options: []
|
86
53
|
require_paths:
|
87
54
|
- lib
|
88
55
|
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
56
|
requirements:
|
91
|
-
- -
|
57
|
+
- - ">="
|
92
58
|
- !ruby/object:Gem::Version
|
93
59
|
version: '0'
|
94
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
-
none: false
|
96
61
|
requirements:
|
97
|
-
- -
|
62
|
+
- - ">="
|
98
63
|
- !ruby/object:Gem::Version
|
99
64
|
version: 1.3.5
|
100
65
|
requirements: []
|
101
66
|
rubyforge_project:
|
102
|
-
rubygems_version:
|
67
|
+
rubygems_version: 2.5.2
|
103
68
|
signing_key:
|
104
|
-
specification_version:
|
69
|
+
specification_version: 4
|
105
70
|
summary: A generic swappable back-end for XML parsing
|
106
|
-
test_files:
|
107
|
-
- spec/helper.rb
|
108
|
-
- spec/multi_xml_spec.rb
|
109
|
-
- spec/parser_shared_example.rb
|
110
|
-
- spec/speed.rb
|
111
|
-
has_rdoc:
|
71
|
+
test_files: []
|
data.tar.gz.sig
DELETED
Binary file
|
data/Rakefile
DELETED
@@ -1,21 +0,0 @@
|
|
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
|
-
task :default => :spec
|
9
|
-
|
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
|
21
|
-
end
|