xml-fu 0.1.1 → 0.1.2
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/CHANGELOG.md +20 -0
- data/lib/xml-fu/array.rb +9 -9
- data/lib/xml-fu/hash.rb +9 -30
- data/lib/xml-fu/node.rb +55 -25
- data/lib/xml-fu/version.rb +1 -1
- data/lib/xml-fu.rb +8 -3
- data/spec/lib/array_spec.rb +0 -1
- data/spec/lib/hash_spec.rb +4 -2
- data/spec/lib/node_spec.rb +55 -5
- data/spec/xmlfu_spec.rb +16 -2
- data/xml-fu.gemspec +0 -2
- metadata +4 -34
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
### 0.1.2
|
2
|
+
|
3
|
+
* Additional nesting support
|
4
|
+
* Further encapsulated functionality into Node
|
5
|
+
* xml.tag! is only used in Node
|
6
|
+
* Array collection vs content logic moved to Node
|
7
|
+
* Hash iteration logic reduced to a single Node call
|
8
|
+
* Node
|
9
|
+
* New attribute: "content_type"
|
10
|
+
* Special tag characters (\*, \/, !) can be mixed and matched
|
11
|
+
* "foo/\*" will return a collection of <foo/> siblings
|
12
|
+
* 12 new spec tests
|
13
|
+
* Removed development dependencies for:
|
14
|
+
* autotest
|
15
|
+
* mocha
|
16
|
+
|
17
|
+
### 0.1.1
|
18
|
+
|
19
|
+
* Rescue false positives when setting Node.value due to interaction with ActiveSupport
|
20
|
+
|
1
21
|
### 0.1.0
|
2
22
|
|
3
23
|
* Initial version. born as a replacement of
|
data/lib/xml-fu/array.rb
CHANGED
@@ -24,10 +24,6 @@ module XmlFu
|
|
24
24
|
raise(MissingKeyException, "Key name missing for collection") if key.empty?
|
25
25
|
|
26
26
|
case
|
27
|
-
when key[-1,1] == "/"
|
28
|
-
xml << Node.new(key, nil, attributes).to_xml
|
29
|
-
when ::Hash === item
|
30
|
-
xml.tag!(key, attributes) { xml << Hash.to_xml(item,options) }
|
31
27
|
when ::Array === item
|
32
28
|
xml << Array.to_xml(item.flatten,options)
|
33
29
|
else
|
@@ -42,9 +38,10 @@ module XmlFu
|
|
42
38
|
xml << Array.to_xml(item, options)
|
43
39
|
when XmlFu.infer_simple_value_nodes == true
|
44
40
|
xml << infer_node(item, attributes)
|
41
|
+
when item.respond_to?(:to_xml)
|
42
|
+
xml << item.to_xml
|
45
43
|
else
|
46
|
-
#
|
47
|
-
xml << item.to_xml if item.respond_to?(:to_xml)
|
44
|
+
# unknown xml tranfromation process
|
48
45
|
end
|
49
46
|
end
|
50
47
|
end
|
@@ -83,11 +80,14 @@ module XmlFu
|
|
83
80
|
|
84
81
|
if item.respond_to?(:keys)
|
85
82
|
filtered = Hash.filter(item)
|
86
|
-
attributes = filtered.last
|
87
|
-
item_content = filtered.first
|
83
|
+
item_content, attributes = filtered.first, filtered.last
|
88
84
|
end
|
89
85
|
|
90
|
-
|
86
|
+
item_name = ( Symbol === key ?
|
87
|
+
XmlFu::Node.symbol_conversion_algorithm.call(key) :
|
88
|
+
key.to_s )
|
89
|
+
|
90
|
+
yield xml, item_name, item_content, attributes
|
91
91
|
end
|
92
92
|
|
93
93
|
xml.target!
|
data/lib/xml-fu/hash.rb
CHANGED
@@ -11,33 +11,8 @@ module XmlFu
|
|
11
11
|
|
12
12
|
# Convert Hash to XML String
|
13
13
|
def self.to_xml(hash, options={})
|
14
|
-
each_with_xml hash do |xml,
|
15
|
-
|
16
|
-
tag_name = ( Symbol === key ?
|
17
|
-
XmlFu::Node.symbol_conversion_algorithm.call(key) :
|
18
|
-
key.to_s )
|
19
|
-
|
20
|
-
case
|
21
|
-
when tag_name[-1,1] == "/"
|
22
|
-
xml << Node.new(tag_name, nil, attributes).to_xml
|
23
|
-
when ::Array === value
|
24
|
-
if tag_name[-1,1] == '*'
|
25
|
-
options.merge!({
|
26
|
-
:content_type => "collection",
|
27
|
-
:key => tag_name.chop,
|
28
|
-
:attributes => attributes
|
29
|
-
})
|
30
|
-
# Collection is merely a set of sibling nodes
|
31
|
-
xml << Array.to_xml(value.flatten, options)
|
32
|
-
else
|
33
|
-
# Contents will contain a parent node
|
34
|
-
xml.tag!(tag_name, attributes) { xml << Array.to_xml(value, options) }
|
35
|
-
end
|
36
|
-
when ::Hash === value
|
37
|
-
xml.tag!(tag_name, attributes) { xml << Hash.to_xml(value, options) }
|
38
|
-
else
|
39
|
-
xml << Node.new(tag_name, value, attributes).to_xml
|
40
|
-
end
|
14
|
+
each_with_xml hash do |xml, name, value, attributes|
|
15
|
+
xml << Node.new(name, value, attributes).to_xml
|
41
16
|
end
|
42
17
|
end#self.to_xml
|
43
18
|
|
@@ -72,11 +47,15 @@ module XmlFu
|
|
72
47
|
# yank the attribute keys into their own hash
|
73
48
|
if value.respond_to?(:keys)
|
74
49
|
filtered = Hash.filter(value)
|
75
|
-
node_attrs = filtered.last
|
76
|
-
node_value = filtered.first
|
50
|
+
node_value, node_attrs = filtered.first, filtered.last
|
77
51
|
end
|
78
52
|
|
79
|
-
|
53
|
+
# Use symbol conversion algorithm to set tag name
|
54
|
+
node_name = ( Symbol === key ?
|
55
|
+
XmlFu::Node.symbol_conversion_algorithm.call(key) :
|
56
|
+
key.to_s )
|
57
|
+
|
58
|
+
yield xml, node_name, node_value, node_attrs
|
80
59
|
end
|
81
60
|
|
82
61
|
xml.target!
|
data/lib/xml-fu/node.rb
CHANGED
@@ -39,6 +39,7 @@ module XmlFu
|
|
39
39
|
|
40
40
|
attr_accessor :escape_xml
|
41
41
|
attr_accessor :self_closing
|
42
|
+
attr_accessor :content_type
|
42
43
|
|
43
44
|
# Create XmlFu::Node object
|
44
45
|
# @param [String, Symbol] name Name of node
|
@@ -47,6 +48,7 @@ module XmlFu
|
|
47
48
|
def initialize(name, value, attributes={})
|
48
49
|
@escape_xml = true
|
49
50
|
@self_closing = false
|
51
|
+
@content_type = "container"
|
50
52
|
self.attributes = attributes
|
51
53
|
self.value = value
|
52
54
|
self.name = name
|
@@ -85,21 +87,25 @@ module XmlFu
|
|
85
87
|
def name_parse_special_characters(val)
|
86
88
|
use_this = val.dup
|
87
89
|
|
88
|
-
# Will this be a self closing node?
|
89
|
-
if use_this.to_s[-1,1] == '/'
|
90
|
-
@self_closing = true
|
91
|
-
use_this.chop!
|
92
|
-
end
|
93
|
-
|
94
|
-
# Will this node contain escaped XML?
|
95
|
-
if use_this.to_s[-1,1] == '!'
|
96
|
-
@escape_xml = false
|
97
|
-
use_this.chop!
|
98
|
-
end
|
99
|
-
|
100
90
|
# Ensure that we don't have special characters at end of name
|
101
91
|
while ["!","/","*"].include?(use_this.to_s[-1,1]) do
|
102
|
-
|
92
|
+
# Will this node contain escaped XML?
|
93
|
+
if use_this.to_s[-1,1] == '!'
|
94
|
+
@escape_xml = false
|
95
|
+
use_this.chop!
|
96
|
+
end
|
97
|
+
|
98
|
+
# Will this be a self closing node?
|
99
|
+
if use_this.to_s[-1,1] == '/'
|
100
|
+
@self_closing = true
|
101
|
+
use_this.chop!
|
102
|
+
end
|
103
|
+
|
104
|
+
# Will this node contain a collection of sibling nodes?
|
105
|
+
if use_this.to_s[-1,1] == '*'
|
106
|
+
@content_type = "collection"
|
107
|
+
use_this.chop!
|
108
|
+
end
|
103
109
|
end
|
104
110
|
|
105
111
|
return use_this
|
@@ -107,16 +113,22 @@ module XmlFu
|
|
107
113
|
|
108
114
|
# Custom Setter for @value instance method
|
109
115
|
def value=(val)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
elsif val.nil?
|
117
|
-
@value = nil
|
116
|
+
case val
|
117
|
+
when ::Hash then @value = val
|
118
|
+
when ::Array then @value = val
|
119
|
+
when ::DateTime then @value = val.strftime XS_DATETIME_FORMAT
|
120
|
+
when ::Time then @value = val.strftime XS_DATETIME_FORMAT
|
121
|
+
when ::Date then @value = val.strftime XS_DATETIME_FORMAT
|
118
122
|
else
|
119
|
-
|
123
|
+
if val.respond_to?(:to_datetime)
|
124
|
+
@value = val.to_datetime
|
125
|
+
elsif val.respond_to?(:call)
|
126
|
+
@value = val.call
|
127
|
+
elsif val.nil?
|
128
|
+
@value = nil
|
129
|
+
else
|
130
|
+
@value = val.to_s
|
131
|
+
end
|
120
132
|
end
|
121
133
|
rescue => e
|
122
134
|
@value = val.to_s
|
@@ -133,9 +145,27 @@ module XmlFu
|
|
133
145
|
def to_xml
|
134
146
|
xml = Builder::XmlMarkup.new
|
135
147
|
case
|
136
|
-
when @self_closing
|
137
|
-
|
138
|
-
|
148
|
+
when @self_closing && @content_type == 'container'
|
149
|
+
xml.tag!(@name, @attributes)
|
150
|
+
when @value.nil?
|
151
|
+
xml.tag!(@name, @attributes.merge!("xsi:nil" => "true"))
|
152
|
+
when ::Hash === @value
|
153
|
+
xml.tag!(@name, @attributes) { xml << XmlFu::Hash.to_xml(@value) }
|
154
|
+
when ::Array === @value
|
155
|
+
case @content_type
|
156
|
+
when "collection"
|
157
|
+
xml << XmlFu::Array.to_xml(@value.flatten, {
|
158
|
+
:key => (@self_closing ? "#{@name}/" : @name),
|
159
|
+
:attributes => @attributes,
|
160
|
+
:content_type => "collection"
|
161
|
+
})
|
162
|
+
when "container"
|
163
|
+
xml.tag!(@name, @attributes) { xml << XmlFu::Array.to_xml(@value) }
|
164
|
+
else
|
165
|
+
# Shouldn't be anything else
|
166
|
+
end
|
167
|
+
else
|
168
|
+
xml.tag!(@name, @attributes) { xml << self.value }
|
139
169
|
end
|
140
170
|
xml.target!
|
141
171
|
end#to_xml
|
data/lib/xml-fu/version.rb
CHANGED
data/lib/xml-fu.rb
CHANGED
@@ -5,13 +5,12 @@ require "xml-fu/array"
|
|
5
5
|
module XmlFu
|
6
6
|
class << self
|
7
7
|
|
8
|
-
@@infer_simple_value_nodes = false
|
9
|
-
|
10
8
|
# Convert construct into XML
|
11
9
|
def xml(construct, options={})
|
12
10
|
case construct
|
13
11
|
when ::Hash then Hash.to_xml( construct.dup, options )
|
14
12
|
when ::Array then Array.to_xml( construct.dup, options )
|
13
|
+
else nil
|
15
14
|
end
|
16
15
|
end#convert
|
17
16
|
|
@@ -25,13 +24,19 @@ module XmlFu
|
|
25
24
|
# an array of one hash (the root node hash)
|
26
25
|
#
|
27
26
|
# <foo><bar/><baz/></foo> => [{"foo" => [{"bar/" => ""},{"baz/" => ""}] }]
|
28
|
-
def
|
27
|
+
def parse(xml, options)
|
29
28
|
end
|
30
29
|
|
31
30
|
def configure
|
32
31
|
yield self
|
33
32
|
end
|
34
33
|
|
34
|
+
################################################################################
|
35
|
+
## CONFIGURATIONS
|
36
|
+
################################################################################
|
37
|
+
|
38
|
+
@@infer_simple_value_nodes = false
|
39
|
+
|
35
40
|
# Set configuration option to be used with future releases
|
36
41
|
def infer_simple_value_nodes=(val)
|
37
42
|
@@infer_simple_value_nodes = val
|
data/spec/lib/array_spec.rb
CHANGED
data/spec/lib/hash_spec.rb
CHANGED
@@ -33,8 +33,10 @@ describe XmlFu::Hash do
|
|
33
33
|
|
34
34
|
describe "with a key that will contain multiple nodes" do
|
35
35
|
describe "when key explicitly denotes value is a collection" do
|
36
|
-
|
37
|
-
|
36
|
+
it "should return the correct collection" do
|
37
|
+
hash = { "foo*" => ["bar", "biz"] }
|
38
|
+
XmlFu::Hash.to_xml(hash).should == "<foo>bar</foo><foo>biz</foo>"
|
39
|
+
end
|
38
40
|
end
|
39
41
|
|
40
42
|
describe "when key denotes value contains children" do
|
data/spec/lib/node_spec.rb
CHANGED
@@ -1,6 +1,42 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe XmlFu::Node do
|
4
|
+
it "should remove special characters from name no matter how many times they appear at the end" do
|
5
|
+
node = XmlFu::Node.new("foo/*!", 'something')
|
6
|
+
node.name.should == 'foo'
|
7
|
+
|
8
|
+
node = XmlFu::Node.new("foo/*/**/!!!", 'something')
|
9
|
+
node.name.should == 'foo'
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "with hash as value" do
|
13
|
+
it "should store the value as a hash" do
|
14
|
+
node = XmlFu::Node.new("foo", {"bar" => "biz"})
|
15
|
+
node.value.class.should == Hash
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should create nested nodes with simple hash" do
|
19
|
+
node = XmlFu::Node.new("foo", {"bar" => "biz"})
|
20
|
+
node.to_xml.should == "<foo><bar>biz</bar></foo>"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "with array as value" do
|
25
|
+
it "should store the value as an array" do
|
26
|
+
node = XmlFu::Node.new("foo", ["bar", "biz"])
|
27
|
+
node.value.class.should == Array
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should create nodes with simple collection array" do
|
31
|
+
node = XmlFu::Node.new("foo*", ["bar", "biz"])
|
32
|
+
node.to_xml.should == "<foo>bar</foo><foo>biz</foo>"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should create nodes with simple contents array" do
|
36
|
+
node = XmlFu::Node.new("foo*", [{:bar => "biz"}])
|
37
|
+
node.to_xml.should == "<foo><bar>biz</bar></foo>"
|
38
|
+
end
|
39
|
+
end
|
4
40
|
|
5
41
|
describe "setting instance variables" do
|
6
42
|
it "should correctly remove special characters from a name" do
|
@@ -12,6 +48,9 @@ describe XmlFu::Node do
|
|
12
48
|
|
13
49
|
node = XmlFu::Node.new("foo!", "something")
|
14
50
|
node.name.should == "foo"
|
51
|
+
|
52
|
+
node = XmlFu::Node.new("foo:bar!", "something")
|
53
|
+
node.name.should == "foo:bar"
|
15
54
|
end
|
16
55
|
|
17
56
|
it "should set self-closing with special name character" do
|
@@ -24,6 +63,14 @@ describe XmlFu::Node do
|
|
24
63
|
node.escape_xml.should == false
|
25
64
|
end
|
26
65
|
|
66
|
+
it "should set content_type with special name character" do
|
67
|
+
node = XmlFu::Node.new("foo", "something")
|
68
|
+
node.content_type.should == "container"
|
69
|
+
|
70
|
+
node = XmlFu::Node.new("foo*", "something")
|
71
|
+
node.content_type.should == "collection"
|
72
|
+
end
|
73
|
+
|
27
74
|
it "should set attributes with a hash" do
|
28
75
|
node = XmlFu::Node.new("foo", "bar", {:this => "that"})
|
29
76
|
node.attributes.should == {:this => "that"}
|
@@ -54,13 +101,14 @@ describe XmlFu::Node do
|
|
54
101
|
it "should properly preserve namespaceds names" do
|
55
102
|
node = XmlFu::Node.new("foo:bar", "biz")
|
56
103
|
node.name.should == "foo:bar"
|
104
|
+
|
105
|
+
node = XmlFu::Node.new("foo:bar!", "biz")
|
106
|
+
node.name.should == "foo:bar"
|
57
107
|
end
|
58
108
|
end
|
59
109
|
|
60
110
|
describe "to_xml" do
|
61
|
-
|
62
111
|
describe "should return self-closing nil XML node for nil value" do
|
63
|
-
|
64
112
|
it "provided ANY non-blank name" do
|
65
113
|
nil_foo = "<foo xsi:nil=\"true\"/>"
|
66
114
|
node = XmlFu::Node.new("foo", nil)
|
@@ -75,9 +123,12 @@ describe XmlFu::Node do
|
|
75
123
|
|
76
124
|
it "with additional attributes provided" do
|
77
125
|
node = XmlFu::Node.new("foo", nil, {:this => "that"})
|
78
|
-
|
126
|
+
# Depending on the version of ruby, one of
|
127
|
+
# these two acceptible values would be returned
|
128
|
+
[ "<foo this=\"that\" xsi:nil=\"true\"/>",
|
129
|
+
"<foo xsi:nil=\"true\" this=\"that\"/>"
|
130
|
+
].should include(node.to_xml)
|
79
131
|
end
|
80
|
-
|
81
132
|
end
|
82
133
|
|
83
134
|
it "should escape values by default" do
|
@@ -108,5 +159,4 @@ describe XmlFu::Node do
|
|
108
159
|
end
|
109
160
|
end
|
110
161
|
end
|
111
|
-
|
112
162
|
end
|
data/spec/xmlfu_spec.rb
CHANGED
@@ -2,6 +2,12 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe XmlFu do
|
4
4
|
describe ".xml" do
|
5
|
+
it "should return nil for value that isn't a Hash or Array" do
|
6
|
+
XmlFu.xml(1).should == nil
|
7
|
+
XmlFu.xml(nil).should == nil
|
8
|
+
XmlFu.xml(Object.new).should == nil
|
9
|
+
end
|
10
|
+
|
5
11
|
it "translates a given Hash to XML" do
|
6
12
|
XmlFu.xml( :id => 1 ).should == "<id>1</id>"
|
7
13
|
end
|
@@ -41,6 +47,16 @@ describe XmlFu do
|
|
41
47
|
XmlFu.xml(hash).should == "<foo bar=\"biz\"></foo><foo biz=\"bang\"></foo>"
|
42
48
|
end
|
43
49
|
|
50
|
+
it "should return list of self-closing nodes" do
|
51
|
+
hash = {
|
52
|
+
"foo/*" => [
|
53
|
+
{"@bar" => "biz"},
|
54
|
+
{"@biz" => "bang"}
|
55
|
+
]
|
56
|
+
}
|
57
|
+
XmlFu.xml(hash).should == "<foo bar=\"biz\"/><foo biz=\"bang\"/>"
|
58
|
+
end
|
59
|
+
|
44
60
|
it "should ignore nested values for content array" do
|
45
61
|
output = XmlFu.xml("foo/" => [{:bar => "biz"}, {:bar => "biz"}])
|
46
62
|
output.should == "<foo/>"
|
@@ -53,7 +69,6 @@ describe XmlFu do
|
|
53
69
|
output = XmlFu.xml("foo/" => {"@id" => "0"})
|
54
70
|
output.should == "<foo id=\"0\"/>"
|
55
71
|
end
|
56
|
-
|
57
72
|
end
|
58
73
|
|
59
74
|
describe "configure" do
|
@@ -71,5 +86,4 @@ describe XmlFu do
|
|
71
86
|
XmlFu.infer_simple_value_nodes = false
|
72
87
|
XmlFu.infer_simple_value_nodes.should == false
|
73
88
|
end
|
74
|
-
|
75
89
|
end
|
data/xml-fu.gemspec
CHANGED
@@ -19,8 +19,6 @@ Gem::Specification.new do |gem|
|
|
19
19
|
gem.add_dependency "builder", ">= 2.1.2"
|
20
20
|
|
21
21
|
gem.add_development_dependency "rspec", ">= 2.4.0"
|
22
|
-
gem.add_development_dependency "autotest"
|
23
|
-
gem.add_development_dependency "mocha", "~> 0.9.9"
|
24
22
|
|
25
23
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
24
|
gem.files = `git ls-files`.split("\n")
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xml-fu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ryan Johnson
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-03-
|
18
|
+
date: 2012-03-16 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: builder
|
@@ -49,36 +49,6 @@ dependencies:
|
|
49
49
|
version: 2.4.0
|
50
50
|
type: :development
|
51
51
|
version_requirements: *id002
|
52
|
-
- !ruby/object:Gem::Dependency
|
53
|
-
name: autotest
|
54
|
-
prerelease: false
|
55
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
-
none: false
|
57
|
-
requirements:
|
58
|
-
- - ">="
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
hash: 3
|
61
|
-
segments:
|
62
|
-
- 0
|
63
|
-
version: "0"
|
64
|
-
type: :development
|
65
|
-
version_requirements: *id003
|
66
|
-
- !ruby/object:Gem::Dependency
|
67
|
-
name: mocha
|
68
|
-
prerelease: false
|
69
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
70
|
-
none: false
|
71
|
-
requirements:
|
72
|
-
- - ~>
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
hash: 41
|
75
|
-
segments:
|
76
|
-
- 0
|
77
|
-
- 9
|
78
|
-
- 9
|
79
|
-
version: 0.9.9
|
80
|
-
type: :development
|
81
|
-
version_requirements: *id004
|
82
52
|
description: "\n Inspired by the Gyoku gem for hash to xml conversion, \n XmlFu is designed to require no meta tagging for \n node attributes and content. (i.e. no :attributes! and no :order!)\n "
|
83
53
|
email:
|
84
54
|
- rhino.citguy@gmail.com
|