xmlhasher 0.0.5 → 0.0.6
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.
- data/README.md +38 -4
- data/benchmark/benchmark.rb +95 -0
- data/lib/xmlhasher/configurable.rb +2 -2
- data/lib/xmlhasher/handler.rb +1 -0
- data/lib/xmlhasher/util.rb +1 -1
- data/lib/xmlhasher/version.rb +1 -1
- data/test/test_helper.rb +0 -1
- data/test/xmlhasher/parser_test.rb +10 -0
- data/test/xmlhasher/xmlhasher_test.rb +4 -0
- metadata +3 -2
data/README.md
CHANGED
@@ -1,16 +1,13 @@
|
|
1
1
|
# XmlHasher
|
2
2
|
|
3
3
|
[](https://travis-ci.org/cloocher/xmlhasher)
|
4
|
-
[](https://coveralls.io/r/cloocher/xmlhasher)
|
5
4
|
[](http://badge.fury.io/rb/xmlhasher)
|
6
5
|
|
7
6
|
Fast XML to Ruby Hash converter
|
8
7
|
|
9
8
|
## Installation
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
Aggcat is available through [Rubygems](http://rubygems.org/gems/xmlhasher) and can be installed via:
|
10
|
+
XmlHasher is available through [Rubygems](http://rubygems.org/gems/xmlhasher) and can be installed via:
|
14
11
|
|
15
12
|
```
|
16
13
|
$ gem install xmlhasher
|
@@ -28,17 +25,27 @@ gem 'xmlhasher'
|
|
28
25
|
require 'xmlhasher'
|
29
26
|
|
30
27
|
# XmlHasher global configuration
|
28
|
+
#
|
29
|
+
# snakecase = true converts all keys to snake case notation
|
30
|
+
# ignore_namespaces = true will remove XML namespace attributes
|
31
|
+
# string_keys = true will convert all keys to Strings, otherwise they will be Symbols
|
32
|
+
#
|
33
|
+
# here is default configuration
|
31
34
|
XmlHasher.configure do |config|
|
32
35
|
config.snakecase = true
|
33
36
|
config.ignore_namespaces = true
|
37
|
+
config.string_keys = false
|
34
38
|
end
|
35
39
|
|
36
40
|
# alternatively, specify configuration options when instantiating a Parser
|
37
41
|
parser = XmlHasher::Parser.new(
|
38
42
|
:snakecase => true,
|
39
43
|
:ignore_namespaces => true
|
44
|
+
:string_keys => false
|
40
45
|
)
|
41
46
|
|
47
|
+
# by default, XmlHasher will convert all keys to symbols. If you want all keys to be Strings, set :string_keys option to 'true'
|
48
|
+
|
42
49
|
# parse XML file
|
43
50
|
XmlHasher.parse(File.new('/path/to/my/file.xml'))
|
44
51
|
|
@@ -47,6 +54,33 @@ XmlHasher.parse("<tag1><tag2>content</tag2></tag1>")
|
|
47
54
|
# => {:tag1=>{:tag2=>"content"}}
|
48
55
|
|
49
56
|
```
|
57
|
+
## Benchmarks
|
58
|
+
|
59
|
+
How fast is it? Try it for yourself - [benchmark.rb](https://github.com/cloocher/xmlhasher/blob/master/benchmark/benchmark.rb)
|
60
|
+
|
61
|
+
```
|
62
|
+
Converting small xml from text to Hash:
|
63
|
+
|
64
|
+
user system total real
|
65
|
+
activesupport(rexml) 0.380000 0.000000 0.380000 ( 0.385326)
|
66
|
+
activesupport(libxml) 0.060000 0.000000 0.060000 ( 0.062008)
|
67
|
+
activesupport(nokogiri) 0.090000 0.000000 0.090000 ( 0.089466)
|
68
|
+
xmlsimple 0.480000 0.010000 0.490000 ( 0.490938)
|
69
|
+
nori 0.120000 0.000000 0.120000 ( 0.123612)
|
70
|
+
xmlhasher 0.010000 0.000000 0.010000 ( 0.017366)
|
71
|
+
|
72
|
+
Converting large xml from file to Hash:
|
73
|
+
|
74
|
+
user system total real
|
75
|
+
activesupport(rexml) 57.230000 0.240000 57.470000 ( 57.460510)
|
76
|
+
activesupport(libxml) # Segmentation fault
|
77
|
+
activesupport(nokogiri) 12.650000 0.250000 12.900000 ( 12.908073)
|
78
|
+
xmlsimple 49.980000 0.160000 50.140000 ( 50.140775)
|
79
|
+
nori 15.590000 0.110000 15.700000 ( 15.697411)
|
80
|
+
xmlhasher 4.290000 0.030000 4.320000 ( 4.316379)
|
81
|
+
```
|
82
|
+
Note: benchmarks were generated on a Macbook Pro using Ruby 1.9.3p392
|
83
|
+
|
50
84
|
## Requirements
|
51
85
|
|
52
86
|
* Ruby 1.8.7 or higher
|
@@ -0,0 +1,95 @@
|
|
1
|
+
$:.push File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
require 'xmlhasher'
|
5
|
+
begin
|
6
|
+
require 'nori'
|
7
|
+
rescue
|
8
|
+
puts "nori gem in not installed, run 'gem install nori'"
|
9
|
+
end
|
10
|
+
begin
|
11
|
+
require 'active_support/core_ext/hash/conversions'
|
12
|
+
rescue
|
13
|
+
puts "active_support gem in not installed, run 'gem install activesupport'"
|
14
|
+
end
|
15
|
+
begin
|
16
|
+
require 'xmlsimple'
|
17
|
+
rescue
|
18
|
+
puts "xmlsimple gem in not installed, run 'gem install xml-simple'"
|
19
|
+
end
|
20
|
+
begin
|
21
|
+
require 'nokogiri'
|
22
|
+
rescue
|
23
|
+
puts "nokogiri gem in not installed, run 'gem install nokogiri'"
|
24
|
+
end
|
25
|
+
begin
|
26
|
+
require 'libxml'
|
27
|
+
rescue
|
28
|
+
puts "libxml gem in not installed, run 'gem install libxml-ruby'"
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
runs = 100
|
33
|
+
xml = File.read(File.expand_path('../../test/fixtures/institution.xml', __FILE__))
|
34
|
+
puts 'Converting small xml from text to Hash:'
|
35
|
+
Benchmark.bm 10 do |x|
|
36
|
+
ActiveSupport::XmlMini.backend = ActiveSupport::XmlMini_REXML
|
37
|
+
x.report 'activesupport(rexml) ' do
|
38
|
+
runs.times { Hash.from_xml(xml) }
|
39
|
+
end
|
40
|
+
|
41
|
+
ActiveSupport::XmlMini.backend = 'LibXML'
|
42
|
+
x.report 'activesupport(libxml) ' do
|
43
|
+
runs.times { Hash.from_xml(xml) }
|
44
|
+
end
|
45
|
+
|
46
|
+
ActiveSupport::XmlMini.backend = 'Nokogiri'
|
47
|
+
x.report 'activesupport(nokogiri)' do
|
48
|
+
runs.times { Hash.from_xml(xml) }
|
49
|
+
end
|
50
|
+
|
51
|
+
x.report 'xmlsimple ' do
|
52
|
+
runs.times { XmlSimple.xml_in(xml) }
|
53
|
+
end
|
54
|
+
|
55
|
+
x.report 'nori ' do
|
56
|
+
runs.times { Nori.new(:advanced_typecasting => false).parse(xml) }
|
57
|
+
end
|
58
|
+
|
59
|
+
x.report 'xmlhasher ' do
|
60
|
+
runs.times { XmlHasher.parse(xml) }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
puts
|
65
|
+
runs = 5
|
66
|
+
path = File.expand_path('../../test/fixtures/institutions.xml', __FILE__)
|
67
|
+
puts 'Converting large xml from file to Hash:'
|
68
|
+
Benchmark.bm 5 do |x|
|
69
|
+
ActiveSupport::XmlMini.backend = ActiveSupport::XmlMini_REXML
|
70
|
+
x.report 'activesupport(rexml) ' do
|
71
|
+
runs.times { Hash.from_xml(File.new(path)) }
|
72
|
+
end
|
73
|
+
|
74
|
+
ActiveSupport::XmlMini.backend = 'LibXML'
|
75
|
+
x.report 'activesupport(libxml) ' do
|
76
|
+
#runs.times { Hash.from_xml(File.new(path)) } # Segmentation fault
|
77
|
+
end
|
78
|
+
|
79
|
+
ActiveSupport::XmlMini.backend = 'Nokogiri'
|
80
|
+
x.report 'activesupport(nokogiri)' do
|
81
|
+
runs.times { Hash.from_xml(File.new(path)) }
|
82
|
+
end
|
83
|
+
|
84
|
+
x.report 'xmlsimple ' do
|
85
|
+
runs.times { XmlSimple.xml_in(path) }
|
86
|
+
end
|
87
|
+
|
88
|
+
x.report 'nori ' do
|
89
|
+
runs.times { Nori.new(:advanced_typecasting => false).parse(File.new(path).read) } # Nori doesn't support reading from a stream, load the file in memory
|
90
|
+
end
|
91
|
+
|
92
|
+
x.report 'xmlhasher ' do
|
93
|
+
runs.times { XmlHasher.parse(File.new(path)) }
|
94
|
+
end
|
95
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module XmlHasher
|
2
2
|
module Configurable
|
3
3
|
|
4
|
-
attr_writer :snakecase, :ignore_namespaces
|
4
|
+
attr_writer :snakecase, :ignore_namespaces, :string_keys
|
5
5
|
|
6
|
-
KEYS = [:snakecase, :ignore_namespaces]
|
6
|
+
KEYS = [:snakecase, :ignore_namespaces, :string_keys]
|
7
7
|
|
8
8
|
def configure
|
9
9
|
yield self
|
data/lib/xmlhasher/handler.rb
CHANGED
data/lib/xmlhasher/util.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module XmlHasher
|
2
2
|
module Util
|
3
3
|
def self.snakecase(str)
|
4
|
-
str.to_s.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z])([A-Z])/, '\1_\2').downcase.tr('-', '_')
|
4
|
+
str.to_s.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z])([A-Z])/, '\1_\2').downcase.tr('-', '_')
|
5
5
|
end
|
6
6
|
end
|
7
7
|
end
|
data/lib/xmlhasher/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -226,6 +226,16 @@ class XmlhasherTest < Test::Unit::TestCase
|
|
226
226
|
assert_equal expected, XmlHasher::Parser.new(options).parse(xml)
|
227
227
|
end
|
228
228
|
|
229
|
+
def test_snakecasing_string_elements
|
230
|
+
options = {
|
231
|
+
:snakecase => true,
|
232
|
+
:string_keys => true
|
233
|
+
}
|
234
|
+
xml = %[<my-tag><MyTag2>content</MyTag2></my-tag>]
|
235
|
+
expected = {'my_tag' => {'my_tag2' => 'content'}}
|
236
|
+
assert_equal expected, XmlHasher::Parser.new(options).parse(xml)
|
237
|
+
end
|
238
|
+
|
229
239
|
def test_empty_tag
|
230
240
|
xml = %[<tag></tag>]
|
231
241
|
expected = {:tag => nil}
|
@@ -6,18 +6,22 @@ class XmlhasherTest < Test::Unit::TestCase
|
|
6
6
|
configurable = XmlHasher.configure do |config|
|
7
7
|
config.snakecase = true
|
8
8
|
config.ignore_namespaces = true
|
9
|
+
config.string_keys = true
|
9
10
|
end
|
10
11
|
assert_equal true, configurable.instance_variable_get(:'@snakecase')
|
11
12
|
assert_equal true, configurable.instance_variable_get(:'@ignore_namespaces')
|
13
|
+
assert_equal true, configurable.instance_variable_get(:'@string_keys')
|
12
14
|
end
|
13
15
|
|
14
16
|
def test_configure_settings_all_off
|
15
17
|
configurable = XmlHasher.configure do |config|
|
16
18
|
config.snakecase = false
|
17
19
|
config.ignore_namespaces = false
|
20
|
+
config.string_keys = false
|
18
21
|
end
|
19
22
|
assert_equal false, configurable.instance_variable_get(:'@snakecase')
|
20
23
|
assert_equal false, configurable.instance_variable_get(:'@ignore_namespaces')
|
24
|
+
assert_equal false, configurable.instance_variable_get(:'@string_keys')
|
21
25
|
end
|
22
26
|
|
23
27
|
def test_parser
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xmlhasher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-09-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ox
|
@@ -88,6 +88,7 @@ files:
|
|
88
88
|
- LICENSE.txt
|
89
89
|
- README.md
|
90
90
|
- Rakefile
|
91
|
+
- benchmark/benchmark.rb
|
91
92
|
- lib/xmlhasher.rb
|
92
93
|
- lib/xmlhasher/configurable.rb
|
93
94
|
- lib/xmlhasher/handler.rb
|