simple-xml 1.0.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.
- 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
|