tilia-xml 1.2.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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rubocop.yml +32 -0
  4. data/.simplecov +4 -0
  5. data/.travis.yml +3 -0
  6. data/CHANGELOG.sabre.md +167 -0
  7. data/CONTRIBUTING.md +25 -0
  8. data/Gemfile +15 -0
  9. data/Gemfile.lock +56 -0
  10. data/LICENSE +27 -0
  11. data/LICENSE.sabre +27 -0
  12. data/README.md +30 -0
  13. data/Rakefile +17 -0
  14. data/lib/tilia/xml/context_stack_trait.rb +99 -0
  15. data/lib/tilia/xml/element/base.rb +73 -0
  16. data/lib/tilia/xml/element/cdata.rb +53 -0
  17. data/lib/tilia/xml/element/elements.rb +109 -0
  18. data/lib/tilia/xml/element/key_value.rb +110 -0
  19. data/lib/tilia/xml/element/uri.rb +98 -0
  20. data/lib/tilia/xml/element/xml_fragment.rb +128 -0
  21. data/lib/tilia/xml/element.rb +22 -0
  22. data/lib/tilia/xml/lib_xml_exception.rb +9 -0
  23. data/lib/tilia/xml/parse_exception.rb +7 -0
  24. data/lib/tilia/xml/reader.rb +240 -0
  25. data/lib/tilia/xml/service.rb +151 -0
  26. data/lib/tilia/xml/version.rb +9 -0
  27. data/lib/tilia/xml/writer.rb +261 -0
  28. data/lib/tilia/xml/xml_deserializable.rb +29 -0
  29. data/lib/tilia/xml/xml_serializable.rb +27 -0
  30. data/lib/tilia/xml.rb +23 -0
  31. data/test/test_helper.rb +4 -0
  32. data/test/xml/context_stack_test.rb +40 -0
  33. data/test/xml/element/cdata_test.rb +37 -0
  34. data/test/xml/element/eater.rb +60 -0
  35. data/test/xml/element/elements_test.rb +113 -0
  36. data/test/xml/element/key_value_test.rb +187 -0
  37. data/test/xml/element/mock.rb +52 -0
  38. data/test/xml/element/uri_test.rb +55 -0
  39. data/test/xml/element/xml_fragment_test.rb +121 -0
  40. data/test/xml/infite_loop_test.rb +47 -0
  41. data/test/xml/reader_test.rb +407 -0
  42. data/test/xml/service_test.rb +156 -0
  43. data/test/xml/writer_test.rb +260 -0
  44. data/tilia-xml.gemspec +15 -0
  45. metadata +132 -0
@@ -0,0 +1,156 @@
1
+ require 'test_helper'
2
+ require 'stringio'
3
+
4
+ module Tilia
5
+ module Xml
6
+ class ServiceTest < Minitest::Test
7
+ def setup
8
+ @util = Service.new
9
+ end
10
+
11
+ def test_get_reader
12
+ elems = { '{http://sabre.io/ns}test' => 'Test!' }
13
+
14
+ @util.element_map = elems
15
+
16
+ reader = @util.reader
17
+ assert_instance_of(Reader, reader)
18
+ assert_equal(elems, reader.element_map)
19
+ end
20
+
21
+ def test_get_writer
22
+ ns = { 'http://sabre.io/ns' => 's' }
23
+
24
+ @util.namespace_map = ns
25
+ writer = @util.writer
26
+
27
+ assert_instance_of(Writer, writer)
28
+ assert_equal(ns, writer.namespace_map)
29
+ end
30
+
31
+ def test_parse
32
+ xml = <<XML
33
+ <root xmlns="http://sabre.io/ns">
34
+ <child>value</child>
35
+ </root>
36
+ XML
37
+ root_element = ''
38
+ result = @util.parse(xml, nil, root_element)
39
+ assert_equal('{http://sabre.io/ns}root', root_element)
40
+
41
+ expected = [
42
+ {
43
+ 'name' => '{http://sabre.io/ns}child',
44
+ 'value' => 'value',
45
+ 'attributes' => {}
46
+ }
47
+ ]
48
+
49
+ assert_equal(expected, result)
50
+ end
51
+
52
+ def test_parse_stream
53
+ xml = <<XML
54
+ <root xmlns="http://sabre.io/ns">
55
+ <child>value</child>
56
+ </root>
57
+ XML
58
+ stream = StringIO.new
59
+ stream.write xml
60
+ stream.rewind
61
+
62
+ root_element = ''
63
+ result = @util.parse(stream, nil, root_element)
64
+ assert_equal('{http://sabre.io/ns}root', root_element)
65
+
66
+ expected = [
67
+ {
68
+ 'name' => '{http://sabre.io/ns}child',
69
+ 'value' => 'value',
70
+ 'attributes' => {}
71
+ }
72
+ ]
73
+
74
+ assert_equal(expected, result)
75
+ end
76
+
77
+ def test_expect
78
+ xml = <<XML
79
+ <root xmlns="http://sabre.io/ns">
80
+ <child>value</child>
81
+ </root>
82
+ XML
83
+ result = @util.expect('{http://sabre.io/ns}root', xml)
84
+
85
+ expected = [
86
+ {
87
+ 'name' => '{http://sabre.io/ns}child',
88
+ 'value' => 'value',
89
+ 'attributes' => {}
90
+ }
91
+ ]
92
+
93
+ assert_equal(expected, result)
94
+ end
95
+
96
+ def test_expect_stream
97
+ xml = <<XML
98
+ <root xmlns="http://sabre.io/ns">
99
+ <child>value</child>
100
+ </root>
101
+ XML
102
+
103
+ stream = StringIO.new
104
+ stream.write xml
105
+ stream.rewind
106
+
107
+ result = @util.expect('{http://sabre.io/ns}root', xml)
108
+
109
+ expected = [
110
+ {
111
+ 'name' => '{http://sabre.io/ns}child',
112
+ 'value' => 'value',
113
+ 'attributes' => {}
114
+ }
115
+ ]
116
+
117
+ assert_equal(expected, result)
118
+ end
119
+
120
+ def test_expect_wrong
121
+ xml = <<XML
122
+ <root xmlns="http://sabre.io/ns">
123
+ <child>value</child>
124
+ </root>
125
+ XML
126
+ assert_raises(ParseException) { @util.expect('{http://sabre.io/ns}error', xml) }
127
+ end
128
+
129
+ def test_write
130
+ @util.namespace_map = { 'http://sabre.io/ns' => 's' }
131
+ result = @util.write(
132
+ '{http://sabre.io/ns}root',
133
+ '{http://sabre.io/ns}child' => 'value'
134
+ )
135
+
136
+ expected = <<XML
137
+ <?xml version="1.0"?>
138
+ <s:root xmlns:s="http://sabre.io/ns">
139
+ <s:child>value</s:child>
140
+ </s:root>
141
+ XML
142
+ assert_equal(expected, result)
143
+ end
144
+
145
+ def test_parse_clark_notation
146
+ expected = ['http://sabredav.org/ns', 'elem']
147
+ result = Service.parse_clark_notation('{http://sabredav.org/ns}elem')
148
+ assert_equal(expected, result)
149
+ end
150
+
151
+ def test_parse_clark_notation_fail
152
+ assert_raises(ArgumentError) { Service.parse_clark_notation('http://sabredav.org/ns}elem') }
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,260 @@
1
+ require 'test_helper'
2
+ require 'stringio'
3
+
4
+ module Tilia
5
+ module Xml
6
+ class WriterTest < Minitest::Test
7
+ def setup
8
+ @writer = Tilia::Xml::Writer.new
9
+ @writer.namespace_map = { 'http://sabredav.org/ns' => 's' }
10
+ @writer.open_memory
11
+ @writer.set_indent(true)
12
+ @writer.start_document
13
+ end
14
+
15
+ def compare(input, output)
16
+ @writer.write(input)
17
+ assert_equal(output, @writer.output_memory)
18
+ end
19
+
20
+ # rubocop:disable Style/ClosingParenthesisIndentation
21
+ # Rubocop has a problem with the closing parenthesis of the long compare()
22
+ # statements, but IMO that's the best way.
23
+ def test_simple
24
+ compare(
25
+ { '{http://sabredav.org/ns}root' => 'text' },
26
+ <<HI
27
+ <?xml version="1.0"?>
28
+ <s:root xmlns:s="http://sabredav.org/ns">text</s:root>
29
+ HI
30
+ )
31
+ end
32
+
33
+ def test_simple_quotes
34
+ compare({ '{http://sabredav.org/ns}root' => '"text"' }, <<HI
35
+ <?xml version="1.0"?>
36
+ <s:root xmlns:s="http://sabredav.org/ns">&quot;text&quot;</s:root>
37
+ HI
38
+ )
39
+ end
40
+
41
+ def test_simple_attributes
42
+ compare(
43
+ {
44
+ '{http://sabredav.org/ns}root' => {
45
+ 'value' => 'text',
46
+ 'attributes' => {
47
+ 'attr1' => 'attribute value'
48
+ }
49
+ }
50
+ }, <<HI
51
+ <?xml version="1.0"?>
52
+ <s:root xmlns:s="http://sabredav.org/ns" attr1="attribute value">text</s:root>
53
+ HI
54
+ )
55
+ end
56
+
57
+ def test_mixed_syntax
58
+ compare(
59
+ {
60
+ '{http://sabredav.org/ns}root' => {
61
+ 'single' => 'value',
62
+ 'multiple' => [
63
+ {
64
+ 'name' => 'foo',
65
+ 'value' => 'bar'
66
+ },
67
+ {
68
+ 'name' => 'foo',
69
+ 'value' => 'foobar'
70
+ }
71
+ ],
72
+ 'attributes' => {
73
+ 'value' => nil,
74
+ 'attributes' => {
75
+ 'foo' => 'bar'
76
+ }
77
+ },
78
+ 'verbose' => { # RUBY
79
+ # 'name' => 'verbose', # RUBY
80
+ 'value' => 'syntax',
81
+ 'attributes' => {
82
+ 'foo' => 'bar'
83
+ }
84
+ }
85
+ }
86
+ }, <<HI
87
+ <?xml version="1.0"?>
88
+ <s:root xmlns:s="http://sabredav.org/ns">
89
+ <single>value</single>
90
+ <multiple>
91
+ <foo>bar</foo>
92
+ <foo>foobar</foo>
93
+ </multiple>
94
+ <attributes foo="bar"/>
95
+ <verbose foo="bar">syntax</verbose>
96
+ </s:root>
97
+ HI
98
+ )
99
+ end
100
+
101
+ def test_null
102
+ compare({ '{http://sabredav.org/ns}root' => nil }, <<HI
103
+ <?xml version="1.0"?>
104
+ <s:root xmlns:s="http://sabredav.org/ns"/>
105
+ HI
106
+ )
107
+ end
108
+
109
+ def test_array_format2
110
+ compare(
111
+ {
112
+ '{http://sabredav.org/ns}root' => [
113
+ {
114
+ 'name' => '{http://sabredav.org/ns}elem1',
115
+ 'value' => 'text',
116
+ 'attributes' => {
117
+ 'attr1' => 'attribute value'
118
+ }
119
+ }
120
+ ]
121
+ }, <<HI
122
+ <?xml version="1.0"?>
123
+ <s:root xmlns:s="http://sabredav.org/ns">
124
+ <s:elem1 attr1="attribute value">text</s:elem1>
125
+ </s:root>
126
+ HI
127
+ )
128
+ end
129
+
130
+ def test_custom_namespace
131
+ compare(
132
+ {
133
+ '{http://sabredav.org/ns}root' => {
134
+ '{urn:foo}elem1' => 'bar'
135
+ }
136
+ }, <<HI
137
+ <?xml version="1.0"?>
138
+ <s:root xmlns:s="http://sabredav.org/ns">
139
+ <x1:elem1 xmlns:x1="urn:foo">bar</x1:elem1>
140
+ </s:root>
141
+ HI
142
+ )
143
+ end
144
+
145
+ def test_empty_namespace
146
+ # Empty namespaces are allowed, so we should support this.
147
+ compare({ '{http://sabredav.org/ns}root' => { '{}elem1' => 'bar' } }, <<HI
148
+ <?xml version="1.0"?>
149
+ <s:root xmlns:s="http://sabredav.org/ns">
150
+ <elem1 xmlns="">bar</elem1>
151
+ </s:root>
152
+ HI
153
+ )
154
+ end
155
+
156
+ def test_attributes
157
+ compare(
158
+ {
159
+ '{http://sabredav.org/ns}root' => [
160
+ {
161
+ 'name' => '{http://sabredav.org/ns}elem1',
162
+ 'value' => 'text',
163
+ 'attributes' => {
164
+ 'attr1' => 'val1',
165
+ '{http://sabredav.org/ns}attr2' => 'val2',
166
+ '{urn:foo}attr3' => 'val3'
167
+ }
168
+ }
169
+ ]
170
+ }, <<HI
171
+ <?xml version="1.0"?>
172
+ <s:root xmlns:s="http://sabredav.org/ns">
173
+ <s:elem1 attr1="val1" s:attr2="val2" x1:attr3="val3" xmlns:x1="urn:foo">text</s:elem1>
174
+ </s:root>
175
+ HI
176
+ )
177
+ end
178
+
179
+ def test_invalid_format
180
+ assert_raises(ArgumentError) do
181
+ compare(
182
+ {
183
+ '{http://sabredav.org/ns}root' => [
184
+ { 'incorrect' => '0', 'keynames' => 1 }
185
+ ]
186
+ },
187
+ ''
188
+ )
189
+ end
190
+ end
191
+
192
+ def test_base_element
193
+ compare({ '{http://sabredav.org/ns}root' => Tilia::Xml::Element::Base.new('hello') }, <<HI
194
+ <?xml version="1.0"?>
195
+ <s:root xmlns:s="http://sabredav.org/ns">hello</s:root>
196
+ HI
197
+ )
198
+ end
199
+
200
+ def test_element_obj
201
+ compare({ '{http://sabredav.org/ns}root' => Tilia::Xml::Element::Mock.new }, <<HI
202
+ <?xml version="1.0"?>
203
+ <s:root xmlns:s="http://sabredav.org/ns">
204
+ <s:elem1>hiiii!</s:elem1>
205
+ </s:root>
206
+ HI
207
+ )
208
+ end
209
+
210
+ def test_empty_namespace_prefix
211
+ @writer.namespace_map['http://sabredav.org/ns'] = nil
212
+ compare({ '{http://sabredav.org/ns}root' => Tilia::Xml::Element::Mock.new }, <<HI
213
+ <?xml version="1.0"?>
214
+ <root xmlns="http://sabredav.org/ns">
215
+ <elem1>hiiii!</elem1>
216
+ </root>
217
+ HI
218
+ )
219
+ end
220
+
221
+ def test_write_element
222
+ @writer.write_element('{http://sabredav.org/ns}foo', 'content')
223
+
224
+ output = <<HI
225
+ <?xml version="1.0"?>
226
+ <s:foo xmlns:s="http://sabredav.org/ns">content</s:foo>
227
+ HI
228
+ assert_equal(output, @writer.output_memory)
229
+ end
230
+
231
+ def test_write_element_complex
232
+ @writer.write_element('{http://sabredav.org/ns}foo', Tilia::Xml::Element::KeyValue.new('{http://sabredav.org/ns}bar' => 'test'))
233
+
234
+ output = <<HI
235
+ <?xml version="1.0"?>
236
+ <s:foo xmlns:s="http://sabredav.org/ns">
237
+ <s:bar>test</s:bar>
238
+ </s:foo>
239
+ HI
240
+ assert_equal(output, @writer.output_memory)
241
+ end
242
+
243
+ def test_write_bad_object
244
+ assert_raises(ArgumentError) { @writer.write(Class.new) }
245
+ end
246
+
247
+ def test_start_element_simple
248
+ @writer.start_element('foo')
249
+ @writer.end_element
250
+
251
+ output = <<HI
252
+ <?xml version="1.0"?>
253
+ <foo xmlns:s="http://sabredav.org/ns"/>
254
+ HI
255
+ assert_equal(output, @writer.output_memory)
256
+ end
257
+ # rubocop:enable Style/ClosingParenthesisIndentation
258
+ end
259
+ end
260
+ end
data/tilia-xml.gemspec ADDED
@@ -0,0 +1,15 @@
1
+ require File.join(File.dirname(__FILE__), 'lib', 'tilia', 'xml', 'version')
2
+ Gem::Specification.new do |s|
3
+ s.name = 'tilia-xml'
4
+ s.version = Tilia::Xml::Version::VERSION
5
+ s.licenses = ['BSD-3-Clause']
6
+ s.summary = 'Port of the sabre-xml library to ruby.'
7
+ s.description = "Port of the sabre-xml library to ruby.\n\nThe Tilia XML parser is the only XML library that you may not hate."
8
+ s.author = 'Jakob Sack'
9
+ s.email = 'tilia@jakobsack.de'
10
+ s.files = `git ls-files`.split("\n")
11
+ s.homepage = 'https://github.com/tilia/tilia-xml'
12
+ s.add_runtime_dependency 'activesupport', '~> 4.2'
13
+ s.add_runtime_dependency 'libxml-ruby', '~> 2.8'
14
+ s.add_runtime_dependency 'tilia-uri', '~> 1.0'
15
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tilia-xml
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Jakob Sack
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: libxml-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.8'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tilia-uri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ description: |-
56
+ Port of the sabre-xml library to ruby.
57
+
58
+ The Tilia XML parser is the only XML library that you may not hate.
59
+ email: tilia@jakobsack.de
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - ".rubocop.yml"
66
+ - ".simplecov"
67
+ - ".travis.yml"
68
+ - CHANGELOG.sabre.md
69
+ - CONTRIBUTING.md
70
+ - Gemfile
71
+ - Gemfile.lock
72
+ - LICENSE
73
+ - LICENSE.sabre
74
+ - README.md
75
+ - Rakefile
76
+ - lib/tilia/xml.rb
77
+ - lib/tilia/xml/context_stack_trait.rb
78
+ - lib/tilia/xml/element.rb
79
+ - lib/tilia/xml/element/base.rb
80
+ - lib/tilia/xml/element/cdata.rb
81
+ - lib/tilia/xml/element/elements.rb
82
+ - lib/tilia/xml/element/key_value.rb
83
+ - lib/tilia/xml/element/uri.rb
84
+ - lib/tilia/xml/element/xml_fragment.rb
85
+ - lib/tilia/xml/lib_xml_exception.rb
86
+ - lib/tilia/xml/parse_exception.rb
87
+ - lib/tilia/xml/reader.rb
88
+ - lib/tilia/xml/service.rb
89
+ - lib/tilia/xml/version.rb
90
+ - lib/tilia/xml/writer.rb
91
+ - lib/tilia/xml/xml_deserializable.rb
92
+ - lib/tilia/xml/xml_serializable.rb
93
+ - test/test_helper.rb
94
+ - test/xml/context_stack_test.rb
95
+ - test/xml/element/cdata_test.rb
96
+ - test/xml/element/eater.rb
97
+ - test/xml/element/elements_test.rb
98
+ - test/xml/element/key_value_test.rb
99
+ - test/xml/element/mock.rb
100
+ - test/xml/element/uri_test.rb
101
+ - test/xml/element/xml_fragment_test.rb
102
+ - test/xml/infite_loop_test.rb
103
+ - test/xml/reader_test.rb
104
+ - test/xml/service_test.rb
105
+ - test/xml/writer_test.rb
106
+ - tilia-xml.gemspec
107
+ homepage: https://github.com/tilia/tilia-xml
108
+ licenses:
109
+ - BSD-3-Clause
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 2.2.5
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Port of the sabre-xml library to ruby.
131
+ test_files: []
132
+ has_rdoc: