xml_schema_mapper 0.0.1 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
2
  <xs:schema xmlns:cm="http://example.com/common/" xmlns:xs="http://www.w3.org/2001/XMLSchema"
3
- targetNamespace="http://example.com/common/" version="1.0">
3
+ targetNamespace="http://example.com/common/" elementFormDefault="qualified" version="1.0">
4
4
 
5
5
  <xs:simpleType name="ZONE">
6
6
  <xs:restriction base="xs:string">
@@ -1,13 +1,13 @@
1
- <getFirstName xmlns:tns="http://example.com/UserService/type/" xmlns:cm="http://example.com/common/">
2
- <userIdentifier>001</userIdentifier>
1
+ <tns:getFirstName xmlns:tns="http://example.com/UserService/type/" xmlns:cm="http://example.com/common/">
2
+ <tns:userIdentifier>001</tns:userIdentifier>
3
3
  <tns:filter>
4
4
  <tns:age>50</tns:age>
5
5
  <tns:gender>male</tns:gender>
6
6
  </tns:filter>
7
- <isOut>a</isOut>
7
+ <tns:isOut>a</tns:isOut>
8
8
  <cm:zone>b</cm:zone>
9
- <options>
10
- <one>one</one>
11
- <two>two</two>
12
- </options>
13
- </getFirstName>
9
+ <tns:options>
10
+ <cm:one>one</cm:one>
11
+ <cm:two>two</cm:two>
12
+ </tns:options>
13
+ </tns:getFirstName>
@@ -1,14 +1,14 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <getFirstName xmlns:cm="http://example.com/common/" xmlns:tns="http://example.com/UserService/type/">
3
- <userIdentifier>xoMPRY</userIdentifier>
2
+ <tns:getFirstName xmlns:cm="http://example.com/common/" xmlns:tns="http://example.com/UserService/type/">
3
+ <tns:userIdentifier>xoMPRY</tns:userIdentifier>
4
4
  <tns:filter>
5
5
  <tns:age>94</tns:age>
6
6
  <tns:gender>male</tns:gender>
7
7
  </tns:filter>
8
- <isOut>a</isOut>
8
+ <tns:isOut>a</tns:isOut>
9
9
  <cm:zone>b</cm:zone>
10
- <options>
11
- <one>p6E58</one>
12
- <two>Vm1sk87pkU0pE4EKKSY</two>
13
- </options>
14
- </getFirstName>
10
+ <tns:options>
11
+ <cm:one>p6E58</cm:one>
12
+ <cm:two>Vm1sk87pkU0pE4EKKSY</cm:two>
13
+ </tns:options>
14
+ </tns:getFirstName>
@@ -0,0 +1,29 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <tns:getFirstNames xmlns:cm="http://example.com/common/" xmlns:tns="http://example.com/UserService/type/">
3
+ <tns:query>
4
+ <tns:userIdentifier>xoMPRY</tns:userIdentifier>
5
+ <tns:filter>
6
+ <tns:age>94</tns:age>
7
+ <tns:gender>male</tns:gender>
8
+ </tns:filter>
9
+ <tns:isOut>a</tns:isOut>
10
+ <cm:zone>b</cm:zone>
11
+ <tns:options>
12
+ <cm:one>p6E58</cm:one>
13
+ <cm:two>Vm1sk87pkU0pE4EKKSY</cm:two>
14
+ </tns:options>
15
+ </tns:query>
16
+ <tns:query>
17
+ <tns:userIdentifier>xoMPRY</tns:userIdentifier>
18
+ <tns:filter>
19
+ <tns:age>94</tns:age>
20
+ <tns:gender>male</tns:gender>
21
+ </tns:filter>
22
+ <tns:isOut>a</tns:isOut>
23
+ <cm:zone>b</cm:zone>
24
+ <tns:options>
25
+ <cm:one>p6E58</cm:one>
26
+ <cm:two>Vm1sk87pkU0pE4EKKSY</cm:two>
27
+ </tns:options>
28
+ </tns:query>
29
+ </tns:getFirstNames>
@@ -1,23 +1,132 @@
1
- class ZONE
1
+ class ZONEMapper
2
2
  include XmlSchemaMapper
3
3
  schema 'spec/fixtures/UserService.xsd'
4
4
  type 'ZONE'
5
+ elements.each do |e|
6
+ attr_accessor e.reader
7
+ end
5
8
  end
6
9
 
7
- class Filter
10
+ class FilterMapper
8
11
  include XmlSchemaMapper
9
12
  schema 'spec/fixtures/UserService.xsd'
10
13
  type 'Filter'
14
+ elements.each do |e|
15
+ attr_accessor e.reader
16
+ end
11
17
  end
12
18
 
13
- class Options
19
+ class OptionsMapper
14
20
  include XmlSchemaMapper
15
21
  schema 'spec/fixtures/UserService.xsd'
16
22
  type 'Options'
23
+ elements.each do |e|
24
+ attr_accessor e.reader
25
+ end
17
26
  end
18
27
 
19
- class GetFirstName
28
+ class GetFirstNameMapper
20
29
  include XmlSchemaMapper
21
30
  schema 'spec/fixtures/UserService.xsd'
22
31
  type 'GetFirstName'
32
+ elements.each do |e|
33
+ attr_accessor e.reader
34
+ end
23
35
  end
36
+
37
+
38
+ module AnotherNamespace
39
+ class ZONEMapper
40
+ include XmlSchemaMapper
41
+ schema 'spec/fixtures/UserService.xsd'
42
+ type 'ZONE'
43
+ elements.each do |e|
44
+ attr_accessor e.reader
45
+ end
46
+ end
47
+
48
+ class FilterMapper
49
+ include XmlSchemaMapper
50
+ schema 'spec/fixtures/UserService.xsd'
51
+ type 'Filter'
52
+ elements.each do |e|
53
+ attr_accessor e.reader
54
+ end
55
+ end
56
+
57
+ class OptionsMapper
58
+ include XmlSchemaMapper
59
+ schema 'spec/fixtures/UserService.xsd'
60
+ type 'Options'
61
+ elements.each do |e|
62
+ attr_accessor e.reader
63
+ end
64
+ end
65
+
66
+ class GetFirstNameMapper
67
+ include XmlSchemaMapper
68
+ schema 'spec/fixtures/UserService.xsd'
69
+ type 'GetFirstName'
70
+ elements.each do |e|
71
+ attr_accessor e.reader
72
+ end
73
+ end
74
+ end
75
+
76
+
77
+
78
+ module ArrayNamespace
79
+ class ZONEMapper
80
+ include XmlSchemaMapper
81
+ schema 'spec/fixtures/UserService.xsd'
82
+ type 'ZONE'
83
+ elements.each do |e|
84
+ attr_accessor e.reader
85
+ end
86
+ end
87
+
88
+ class FilterMapper
89
+ include XmlSchemaMapper
90
+ schema 'spec/fixtures/UserService.xsd'
91
+ type 'Filter'
92
+ elements.each do |e|
93
+ attr_accessor e.reader
94
+ end
95
+ end
96
+
97
+ class OptionsMapper
98
+ include XmlSchemaMapper
99
+ schema 'spec/fixtures/UserService.xsd'
100
+ type 'Options'
101
+ elements.each do |e|
102
+ attr_accessor e.reader
103
+ end
104
+ end
105
+
106
+ class GetFirstNameMapper
107
+ include XmlSchemaMapper
108
+ schema 'spec/fixtures/UserService.xsd'
109
+ type 'GetFirstName'
110
+ elements.each do |e|
111
+ attr_accessor e.reader
112
+ end
113
+ end
114
+
115
+ class ArrayOfGetFirstNameMapper
116
+ include XmlSchemaMapper
117
+ schema 'spec/fixtures/UserService.xsd'
118
+ type 'ArrayOfGetFirstName'
119
+ elements.each do |e|
120
+ attr_accessor e.reader
121
+ end
122
+ end
123
+
124
+ class ArrayOfStringsMapper
125
+ include XmlSchemaMapper
126
+ schema 'spec/fixtures/UserService.xsd'
127
+ type 'ArrayOfStrings'
128
+ elements.each do |e|
129
+ attr_accessor e.reader
130
+ end
131
+ end
132
+ end
@@ -2,35 +2,77 @@ require "spec_helper"
2
2
 
3
3
  describe "Parse XML" do
4
4
 
5
- context "by GetFirstName" do
5
+ context "by GetFirstNameMapper" do
6
6
  let(:xml) { File.read('spec/fixtures/instance1.xml') }
7
7
 
8
8
  it "should parse with XmlSchemaMapper::Parser" do
9
9
  XmlSchemaMapper::Parser.any_instance.should_receive(:parse).with(xml)
10
- GetFirstName.parse(xml)
10
+ GetFirstNameMapper.parse(xml)
11
11
  end
12
12
 
13
- it "should return instance of GetFirstName" do
14
- GetFirstName.parse(xml).should be_a GetFirstName
13
+ it "should return instance of GetFirstNameMapper" do
14
+ GetFirstNameMapper.parse(xml).should be_a GetFirstNameMapper
15
15
  end
16
16
 
17
17
  it "should lookup all elements" do
18
- GetFirstName.elements.should_receive(:each)
19
- GetFirstName.parse(xml)
18
+ GetFirstNameMapper.elements.should_receive(:each)
19
+ GetFirstNameMapper.parse(xml)
20
20
  end
21
21
 
22
22
  context "its" do
23
- subject { GetFirstName.parse(xml) }
23
+ subject { GetFirstNameMapper.parse(xml) }
24
24
  its(:user_identifier) { should be_eql 'xoMPRY' }
25
- its(:filter) { should be_a Filter }
25
+ its(:filter) { should be_a FilterMapper }
26
26
  its(:'filter.age') { should eql '94' }
27
27
  its(:'filter.gender') { should eql 'male' }
28
28
  its(:is_out) { should eql 'a' }
29
29
  its(:zone) { should eql 'b' }
30
- its(:options) { should be_a Options }
30
+ its(:options) { should be_a OptionsMapper }
31
31
  its(:'options.one') { should eql 'p6E58' }
32
32
  its(:'options.two') { should eql 'Vm1sk87pkU0pE4EKKSY' }
33
33
  end
34
34
  end
35
35
 
36
+ context "by AnotherNamespace::GetFirstNameMapper" do
37
+ let(:xml) { File.read('spec/fixtures/instance1.xml') }
38
+
39
+ it "should parse with XmlSchemaMapper::Parser" do
40
+ XmlSchemaMapper::Parser.any_instance.should_receive(:parse).with(xml)
41
+ AnotherNamespace::GetFirstNameMapper.parse(xml)
42
+ end
43
+
44
+ it "should return instance of GetFirstNameMapper" do
45
+ AnotherNamespace::GetFirstNameMapper.parse(xml).should be_a AnotherNamespace::GetFirstNameMapper
46
+ end
47
+
48
+ it "should lookup all elements" do
49
+ AnotherNamespace::GetFirstNameMapper.elements.should_receive(:each)
50
+ AnotherNamespace::GetFirstNameMapper.parse(xml)
51
+ end
52
+
53
+ context "its" do
54
+ subject { AnotherNamespace::GetFirstNameMapper.parse(xml) }
55
+ its(:user_identifier) { should be_eql 'xoMPRY' }
56
+ its(:filter) { should be_a AnotherNamespace::FilterMapper }
57
+ its(:'filter.age') { should eql '94' }
58
+ its(:'filter.gender') { should eql 'male' }
59
+ its(:is_out) { should eql 'a' }
60
+ its(:zone) { should eql 'b' }
61
+ its(:options) { should be_a AnotherNamespace::OptionsMapper }
62
+ its(:'options.one') { should eql 'p6E58' }
63
+ its(:'options.two') { should eql 'Vm1sk87pkU0pE4EKKSY' }
64
+ end
65
+
66
+
67
+ context "parse arrays" do
68
+ let(:xml) { File.read('spec/fixtures/instance_with_arrays.xml') }
69
+ subject { ArrayNamespace::ArrayOfGetFirstNameMapper.parse(xml) }
70
+
71
+ it do
72
+ subject.query.should have(2).elements
73
+ ArrayNamespace::ArrayOfGetFirstNameMapper.parse(subject.to_xml).query.should have(2).elements
74
+ end
75
+ end
76
+ end
77
+
36
78
  end
@@ -0,0 +1,167 @@
1
+ require "spec_helper"
2
+ require "stringio"
3
+
4
+ describe "Generate XML by Visitor Pattern" do
5
+
6
+ class MarshalVisitor
7
+
8
+ attr_reader :namespace_mapper
9
+
10
+ def initialize(data, namespace_mapper)
11
+ @data = data
12
+ @namespace_mapper = namespace_mapper
13
+ @tab = 0
14
+ @buf = ""
15
+ @io = StringIO.new @buf
16
+ end
17
+
18
+ def visit_array(element, data, *args)
19
+ data.each { |d| element.accept(self, d) }
20
+ end
21
+
22
+ def visit(element, data, *args)
23
+ @io.print tag_open(element, data)
24
+
25
+ with_padding(element) do
26
+ element.elements.each do |e|
27
+ e.accept(self, data.elements[e.reader])
28
+ end
29
+ end
30
+
31
+ @io.print tag_close(element)
32
+ end
33
+
34
+ def to_xml
35
+ @data.class.elements.each do |e|
36
+ e.accept(self, @data.elements[e.reader])
37
+ end
38
+ @buf
39
+ end
40
+
41
+ private
42
+
43
+ def tag_name(element)
44
+ prefix = namespace_mapper.prefix(element.namespace)
45
+ if prefix.present?
46
+ "#{prefix}:#{element.name}"
47
+ else
48
+ element.name
49
+ end
50
+ end
51
+
52
+ def tag_open(element, data)
53
+ if element.type.attributes.empty?
54
+ attrs = ""
55
+ else
56
+ attrs = " " << data.attrs.map { |name, val| %Q{#{name}="#{val}"} }.join(' ')
57
+ end
58
+
59
+ if element.simple?
60
+ padding << "<#{tag_name(element)}#{attrs}>" << "#{data}"
61
+ else
62
+ padding << "<#{tag_name(element)}#{attrs}>\n"
63
+ end
64
+ end
65
+
66
+ def tag_close(element)
67
+ if element.simple?
68
+ "</#{tag_name(element)}>\n"
69
+ else
70
+ padding << "</#{tag_name(element)}>\n"
71
+ end
72
+ end
73
+
74
+ def padding
75
+ (" " * @tab)
76
+ end
77
+
78
+ def with_padding(element)
79
+ inc_tab! if element.elements.present?
80
+ yield
81
+ dec_tab! if element.elements.present?
82
+ end
83
+
84
+ def inc_tab!
85
+ @tab = @tab + 1
86
+ end
87
+
88
+ def dec_tab!
89
+ @tab = @tab - 1
90
+ end
91
+ end
92
+
93
+ class NamespacePrefixMapper
94
+ class_attribute :map
95
+ self.map = { }
96
+
97
+ map["ds"] = "http://www.w3.org/2000/09/xmldsig#"
98
+ map["xsi"] = "http://www.w3.org/2001/XMLSchema-instance"
99
+ map["xml"] = "http://www.w3.org/XML/1998/namespace"
100
+ map["xs"] = "http://www.w3.org/2001/XMLSchema"
101
+ map["xop"] = "http://www.w3.org/2004/08/xop/include"
102
+ map["xmime"] = "http://www.w3.org/2005/05/xmlmime"
103
+
104
+ def self.add(hash = { })
105
+ map.merge! hash.stringify_keys
106
+ end
107
+
108
+ def self.prefix(uri)
109
+ map.invert[uri] or ''
110
+ end
111
+
112
+ def self.uri(prefix)
113
+ map[prefix]
114
+ end
115
+ end
116
+
117
+ let(:options) { o = OptionsMapper.new; o.one = 'one'; o.two = 'two'; o }
118
+ let(:object) do
119
+ f = FilterMapper.new; f.age = 50; f.gender = 'male'
120
+ g = GetFirstNameMapper.new; g.user_identifier = '001'; g.is_out = 'a'; g.zone = 'b'; g.filter = f; g.options = options
121
+ g.attrs = { 'id' => '1000', 'default' => '1' }
122
+ g
123
+ end
124
+
125
+ it "" do
126
+ mapper = ArrayNamespace::ArrayOfGetFirstNameMapper.new
127
+ mapper.query = [object, object.dup]
128
+
129
+ class UserNamespaceMapper < NamespacePrefixMapper
130
+
131
+ end
132
+
133
+ UserNamespaceMapper.add type: "http://example.com/UserService/type/",
134
+ com: "http://example.com/common/"
135
+
136
+ visitor = MarshalVisitor.new(mapper, UserNamespaceMapper)
137
+ visitor.to_xml.should eql <<-X
138
+ <type:query id="1000" default="1">
139
+ <type:userIdentifier>001</type:userIdentifier>
140
+ <type:filter>
141
+ <type:age>50</type:age>
142
+ <type:gender>male</type:gender>
143
+ </type:filter>
144
+ <type:isOut>a</type:isOut>
145
+ <com:zone>b</com:zone>
146
+ <type:options>
147
+ <com:one>one</com:one>
148
+ <com:two>two</com:two>
149
+ </type:options>
150
+ </type:query>
151
+ <type:query id="1000" default="1">
152
+ <type:userIdentifier>001</type:userIdentifier>
153
+ <type:filter>
154
+ <type:age>50</type:age>
155
+ <type:gender>male</type:gender>
156
+ </type:filter>
157
+ <type:isOut>a</type:isOut>
158
+ <com:zone>b</com:zone>
159
+ <type:options>
160
+ <com:one>one</com:one>
161
+ <com:two>two</com:two>
162
+ </type:options>
163
+ </type:query>
164
+ X
165
+ end
166
+
167
+ end