simple-xml 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +22 -0
- data/Rakefile +5 -0
- data/lib/simple_xml.rb +7 -0
- data/lib/simple_xml/simplifyer.rb +90 -0
- data/lib/simple_xml/version.rb +3 -0
- data/simple-xml.gemspec +37 -0
- data/spec/simple_xml_spec.rb +91 -0
- data/spec/spec_helper.rb +2 -0
- metadata +72 -0
data/README.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# SimpleXML
|
2
|
+
|
3
|
+
A simple add on to rexml to parse xml data simply by converting them to a hash.
|
4
|
+
That hash can than easily be passed to model objects to validate etc.
|
5
|
+
|
6
|
+
Example usage:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
doc = REXML::Document.new(%Q{
|
10
|
+
<?xml version="1.0"?>
|
11
|
+
<address>
|
12
|
+
<country iso_code="de" nationality="deutsch">Deutschland</country>
|
13
|
+
<zip_code>76135</zip_code>
|
14
|
+
<city>Karlsruhe</city>
|
15
|
+
<street>
|
16
|
+
<name_and_number>Ernst-Frey-Str. 10</name_and_number>
|
17
|
+
</street>
|
18
|
+
</address>
|
19
|
+
}
|
20
|
+
doc.simplify("/address") #=> { :country => "Deutschland", :zip_code => "76135", :city => "Karlsruhe", :street => { :name_and_number => "Ernst-Frey-Str. 10" } }
|
21
|
+
doc.simplify_attributes("/address/country") #=> { :iso_code => "de", :nationality => "deutsch" }
|
22
|
+
```
|
data/Rakefile
ADDED
data/lib/simple_xml.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
module SimpleXML
|
2
|
+
# Extension to the element class of rexml to make working with simple xml
|
3
|
+
# documents more easy and intuitive. Therefor it uses the combination of hashes
|
4
|
+
# and the rexml XPath implementation.
|
5
|
+
# @example Usage with a simple document
|
6
|
+
# doc = REXML::Document.new(%Q{
|
7
|
+
# <?xml version="1.0"?>
|
8
|
+
# <address>
|
9
|
+
# <country iso_code="de" nationality="deutsch">Deutschland</country>
|
10
|
+
# <zip_code>76135</zip_code>
|
11
|
+
# <city>Karlsruhe</city>
|
12
|
+
# <street>
|
13
|
+
# <name_and_number>Ernst-Frey-Str. 10</name_and_number>
|
14
|
+
# </street>
|
15
|
+
# </address>
|
16
|
+
# }
|
17
|
+
# doc.simplify("/address") #=> { :country => "Deutschland", :zip_code => "76135", :city => "Karlsruhe", :street => { :name_and_number => "Ernst-Frey-Str. 10" } }
|
18
|
+
# doc.simplify_attributes("/address/country") #=> { :iso_code => "de", :nationality => "deutsch" }
|
19
|
+
#
|
20
|
+
module Simplifyer
|
21
|
+
# Simplifies the current element or an xpath to a subelement to a hash.
|
22
|
+
# @param [String] xpath an optional xpath for an element to convert
|
23
|
+
# @return [Hash, NilClass] nil if the xpath didn't match to a node or a hash otherwise.
|
24
|
+
# If elements have the same name they will be merged into an array.
|
25
|
+
def simplify(xpath = nil)
|
26
|
+
if xpath
|
27
|
+
if element = REXML::XPath.first(self, xpath)
|
28
|
+
element.simplify
|
29
|
+
else
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
else
|
33
|
+
# just convert the elements if there are some
|
34
|
+
if contains_no_text_elements?
|
35
|
+
tree = {} # the subtree
|
36
|
+
last_name = nil # helper for detecting duplicate element names
|
37
|
+
self.each do |element|
|
38
|
+
# we ignore all text elements that are in between the elements
|
39
|
+
if element.is_a? REXML::Element
|
40
|
+
name = element.name.to_sym
|
41
|
+
if last_name == name
|
42
|
+
# create an array if there is more than one element with
|
43
|
+
# the same name
|
44
|
+
tree[name] = [tree[name]] unless tree[name].is_a?(Array)
|
45
|
+
tree[name] += [element.simplify]
|
46
|
+
else
|
47
|
+
# create a simple element (key - value) in the hash
|
48
|
+
tree[name] = element.simplify
|
49
|
+
last_name = name
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
tree
|
54
|
+
else
|
55
|
+
# if there is just text left the text elements will be used
|
56
|
+
self.text
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Simplifies the current element attributes or an xpath to subelement
|
62
|
+
# attributes to a hash.
|
63
|
+
# @param [String] xpath an optional xpath for an element to convert
|
64
|
+
# @return [Hash, NilClass] nil if the xpath didn't match to a node or a hash otherwise.
|
65
|
+
def simplify_attributes(xpath = nil)
|
66
|
+
if xpath
|
67
|
+
if element = REXML::XPath.first(self, xpath)
|
68
|
+
element.simplify_attributes
|
69
|
+
else
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
else
|
73
|
+
hash = {}
|
74
|
+
attributes.each { |key, value| hash[key.to_sym] = value }
|
75
|
+
hash
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# Checks if the sub element has any other elements than text elements.
|
82
|
+
# @returns [Boolean] ture if there is at least one REXML::Element
|
83
|
+
def contains_no_text_elements?
|
84
|
+
children.each do |element|
|
85
|
+
return true if element.is_a? REXML::Element
|
86
|
+
end
|
87
|
+
false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/simple-xml.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push('lib')
|
3
|
+
require "simple_xml/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "simple-xml"
|
7
|
+
s.version = SimpleXML::VERSION.dup
|
8
|
+
s.date = "2011-11-21"
|
9
|
+
s.summary = "Some helpers for REXML::Element to create hashes from xml easily"
|
10
|
+
s.email = "vilandgr+simplexml@googlemail.com"
|
11
|
+
s.homepage = "https://github.com/threez/simple-xml"
|
12
|
+
s.authors = ['Vincent Landgraf']
|
13
|
+
|
14
|
+
s.description = "Some helpers for REXML::Element to create hashes from xml easily."
|
15
|
+
|
16
|
+
dependencies = [
|
17
|
+
[:development, "rspec", "~> 2.1"],
|
18
|
+
]
|
19
|
+
|
20
|
+
s.files = Dir['**/*']
|
21
|
+
s.test_files = Dir['test/**/*'] + Dir['spec/**/*']
|
22
|
+
s.executables = Dir['bin/*'].map { |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
|
25
|
+
## Make sure you can build the gem on older versions of RubyGems too:
|
26
|
+
s.rubygems_version = "1.8.10"
|
27
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
28
|
+
s.specification_version = 3 if s.respond_to? :specification_version
|
29
|
+
|
30
|
+
dependencies.each do |type, name, version|
|
31
|
+
if s.respond_to?("add_#{type}_dependency")
|
32
|
+
s.send("add_#{type}_dependency", name, version)
|
33
|
+
else
|
34
|
+
s.add_dependency(name, version)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe REXML::Element do
|
4
|
+
before(:each) do
|
5
|
+
@doc = REXML::Document.new(%Q{
|
6
|
+
<?xml version="1.0"?>
|
7
|
+
<user>
|
8
|
+
<address>
|
9
|
+
<country iso_code="de" nationality="deutsch">Deutschland</country>
|
10
|
+
<zip_code>76135</zip_code>
|
11
|
+
<city>Karlsruhe</city>
|
12
|
+
<street>
|
13
|
+
<name_and_number>Ernst-Frey-Str. 10</name_and_number>
|
14
|
+
</street>
|
15
|
+
</address>
|
16
|
+
<phones>
|
17
|
+
<phone type="MOBILE">
|
18
|
+
<country>+49</country>
|
19
|
+
<provider>171</provider>
|
20
|
+
<number>20333232</number>
|
21
|
+
</phone>
|
22
|
+
<phone type="HOME">+494534520085285</phone>
|
23
|
+
<phone type="WORK">+494534523453453</phone>
|
24
|
+
</phones>
|
25
|
+
</user>
|
26
|
+
})
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be possible not fail if the node doesn't exists" do
|
30
|
+
@doc.simplify("/user/no-element").should == nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should be possible to call on root element without a xpath" do
|
34
|
+
@doc.simplify.should == {
|
35
|
+
:user => {
|
36
|
+
:address => {
|
37
|
+
:country => "Deutschland",
|
38
|
+
:zip_code => "76135",
|
39
|
+
:city => "Karlsruhe",
|
40
|
+
:street => {
|
41
|
+
:name_and_number => "Ernst-Frey-Str. 10"
|
42
|
+
}
|
43
|
+
},
|
44
|
+
:phones => {
|
45
|
+
:phone => [
|
46
|
+
{ :number => "20333232", :provider => "171", :country => "+49" },
|
47
|
+
"+494534520085285",
|
48
|
+
"+494534523453453"
|
49
|
+
]
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should be possible to" do
|
56
|
+
@doc.simplify("/user").should == {
|
57
|
+
:address => {
|
58
|
+
:country => "Deutschland",
|
59
|
+
:zip_code => "76135",
|
60
|
+
:city => "Karlsruhe",
|
61
|
+
:street => {
|
62
|
+
:name_and_number => "Ernst-Frey-Str. 10"
|
63
|
+
}
|
64
|
+
},
|
65
|
+
:phones => {
|
66
|
+
:phone => [
|
67
|
+
{ :number => "20333232", :provider => "171", :country => "+49" },
|
68
|
+
"+494534520085285",
|
69
|
+
"+494534523453453"
|
70
|
+
]
|
71
|
+
}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should be possible to request for attributes of a not existing node" do
|
76
|
+
@doc.simplify_attributes("/test").should == nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should be possible to request for existing attributes" do
|
80
|
+
@doc.simplify_attributes("/user/phones/phone[1]").should == {
|
81
|
+
:type => "MOBILE"
|
82
|
+
}
|
83
|
+
@doc.simplify_attributes("/user/phones/phone[2]").should == {
|
84
|
+
:type => "HOME"
|
85
|
+
}
|
86
|
+
@doc.simplify_attributes("/user/address/country").should == {
|
87
|
+
:iso_code => "de",
|
88
|
+
:nationality => "deutsch"
|
89
|
+
}
|
90
|
+
end
|
91
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple-xml
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 1.0.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Vincent Landgraf
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-11-21 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "2.1"
|
24
|
+
type: :development
|
25
|
+
version_requirements: *id001
|
26
|
+
description: Some helpers for REXML::Element to create hashes from xml easily.
|
27
|
+
email: vilandgr+simplexml@googlemail.com
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files: []
|
33
|
+
|
34
|
+
files:
|
35
|
+
- Rakefile
|
36
|
+
- README.md
|
37
|
+
- simple-xml.gemspec
|
38
|
+
- lib/simple_xml.rb
|
39
|
+
- lib/simple_xml/simplifyer.rb
|
40
|
+
- lib/simple_xml/version.rb
|
41
|
+
- spec/simple_xml_spec.rb
|
42
|
+
- spec/spec_helper.rb
|
43
|
+
homepage: https://github.com/threez/simple-xml
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.8.9
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Some helpers for REXML::Element to create hashes from xml easily
|
70
|
+
test_files:
|
71
|
+
- spec/simple_xml_spec.rb
|
72
|
+
- spec/spec_helper.rb
|