simple-xml 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ ```
@@ -0,0 +1,5 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ task :default => :spec
@@ -0,0 +1,7 @@
1
+ require "rexml/document"
2
+ require "rexml/xpath"
3
+ require File.join(File.dirname(__FILE__), "simple_xml", "simplifyer")
4
+
5
+ class REXML::Element
6
+ include SimpleXML::Simplifyer
7
+ end
@@ -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
@@ -0,0 +1,3 @@
1
+ module SimpleXML
2
+ VERSION = '1.0.0'
3
+ end
@@ -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
@@ -0,0 +1,2 @@
1
+ require "rspec"
2
+ require File.join(File.dirname(__FILE__), "..", "lib", "simple_xml")
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