xml_schema_mapper 0.0.1 → 0.0.5

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.
@@ -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