xmlhasher 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.travis.yml +15 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +23 -0
- data/Rakefile +10 -0
- data/lib/xmlhasher/configurable.rb +20 -0
- data/lib/xmlhasher/handler.rb +49 -0
- data/lib/xmlhasher/node.rb +34 -0
- data/lib/xmlhasher/parser.rb +22 -0
- data/lib/xmlhasher/util.rb +7 -0
- data/lib/xmlhasher/version.rb +3 -0
- data/lib/xmlhasher.rb +25 -0
- data/test/fixures/institution.xml +343 -0
- data/test/fixures/institutions.xml +1 -0
- data/test/test_helper.rb +22 -0
- data/test/xmlhasher/xmlhasher_test.rb +13 -0
- data/xmlhasher.gemspec +28 -0
- metadata +116 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Gene Drabkin
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# XmlHasher
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/cloocher/xmlhasher.png)](https://travis-ci.org/cloocher/xmlhasher)
|
4
|
+
|
5
|
+
Xml to Ruby Hash converter
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'xmlhasher'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install xmlhasher
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
TODO: Write usage instructions here
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module XmlHasher
|
2
|
+
module Configurable
|
3
|
+
|
4
|
+
attr_writer :snakecase, :ignore_namespaces
|
5
|
+
|
6
|
+
KEYS = [:snakecase, :ignore_namespaces]
|
7
|
+
|
8
|
+
def configure
|
9
|
+
yield self
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def options
|
16
|
+
XmlHasher::Configurable::KEYS.inject({}) { |hash, key| hash[key] = instance_variable_get(:"@#{key}"); hash }
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'ox'
|
2
|
+
|
3
|
+
module XmlHasher
|
4
|
+
class Handler < ::Ox::Sax
|
5
|
+
def initialize(options = {})
|
6
|
+
@options = options
|
7
|
+
@stack = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_hash
|
11
|
+
@hash || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def start_element(name)
|
15
|
+
@stack.push(Node.new(transform(name)))
|
16
|
+
end
|
17
|
+
|
18
|
+
def attr(name, value)
|
19
|
+
unless ignore_attribute?(name)
|
20
|
+
@stack.last.attributes[transform(name)] = value unless @stack.empty?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def text(value)
|
25
|
+
@stack.last.text = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def end_element(name)
|
29
|
+
if @stack.size == 1
|
30
|
+
@hash = @stack.pop.to_hash
|
31
|
+
else
|
32
|
+
node = @stack.pop
|
33
|
+
@stack.last.children << node
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def transform(name)
|
40
|
+
name = name.to_s.split(':').last if @options[:ignore_namespaces]
|
41
|
+
name = Util.snakecase(name) if @options[:snakecase]
|
42
|
+
name
|
43
|
+
end
|
44
|
+
|
45
|
+
def ignore_attribute?(name)
|
46
|
+
@options[:ignore_namespaces] ? !name.to_s[/^(xmlns|xsi)/].nil? : false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module XmlHasher
|
2
|
+
class Node
|
3
|
+
attr_accessor :name, :attributes, :children, :text
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
@name = name
|
7
|
+
@attributes = {}
|
8
|
+
@children = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_hash
|
12
|
+
h = {}
|
13
|
+
if text
|
14
|
+
h[name] = text
|
15
|
+
else
|
16
|
+
if children.size == 1
|
17
|
+
child = children.first
|
18
|
+
h[name] = child.to_hash
|
19
|
+
else
|
20
|
+
if children.map(&:name).uniq.size == 1
|
21
|
+
h[name] = children.map { |child| child.to_hash }
|
22
|
+
else
|
23
|
+
h[name] = children.inject({}) { |r, child| r.merge!(child.to_hash); r }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
attributes.each do |key, value|
|
28
|
+
h[key] = value if value
|
29
|
+
end
|
30
|
+
h
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module XmlHasher
|
4
|
+
class Parser
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse(xml)
|
11
|
+
handler = Handler.new(@options)
|
12
|
+
Ox.sax_parse(handler, convert(xml))
|
13
|
+
handler.to_hash
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def convert(xml)
|
19
|
+
xml.respond_to?(:read) || xml.respond_to?(:readpartial) ? xml : StringIO.new(xml)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/xmlhasher.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'xmlhasher/configurable'
|
2
|
+
require 'xmlhasher/handler'
|
3
|
+
require 'xmlhasher/parser'
|
4
|
+
require 'xmlhasher/node'
|
5
|
+
require 'xmlhasher/util'
|
6
|
+
require 'xmlhasher/version'
|
7
|
+
|
8
|
+
module XmlHasher
|
9
|
+
class << self
|
10
|
+
include XmlHasher::Configurable
|
11
|
+
|
12
|
+
def parser
|
13
|
+
@parser ||= XmlHasher::Parser.new(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def method_missing(method_name, *args, &block)
|
19
|
+
return super unless parser.respond_to?(method_name)
|
20
|
+
parser.send(method_name, *args, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|