1 package xml_test
2
3 import (
4 "bytes"
5 "log"
6 "sort"
7 "testing"
8
9 "github.com/aws/smithy-go/encoding/xml"
10 )
11
12 var root = xml.StartElement{Name: xml.Name{Local: "root"}}
13
14 func TestEncoder(t *testing.T) {
15 b := bytes.NewBuffer(nil)
16 encoder := xml.NewEncoder(b)
17
18 func() {
19 root := encoder.RootElement(root)
20 defer root.Close()
21
22 stringKey := xml.StartElement{Name: xml.Name{Local: "stringKey"}}
23 integerKey := xml.StartElement{Name: xml.Name{Local: "integerKey"}}
24 floatKey := xml.StartElement{Name: xml.Name{Local: "floatKey"}}
25 foo := xml.StartElement{Name: xml.Name{Local: "foo"}}
26 byteSlice := xml.StartElement{Name: xml.Name{Local: "byteSlice"}}
27
28 root.MemberElement(stringKey).String("stringValue")
29 root.MemberElement(integerKey).Integer(1024)
30 root.MemberElement(floatKey).Float(3.14)
31
32 ns := root.MemberElement(foo)
33 defer ns.Close()
34 ns.MemberElement(byteSlice).String("Zm9vIGJhcg==")
35 }()
36
37 e := []byte(`<root><stringKey>stringValue</stringKey><integerKey>1024</integerKey><floatKey>3.14</floatKey><foo><byteSlice>Zm9vIGJhcg==</byteSlice></foo></root>`)
38 verify(t, encoder, e)
39 }
40
41 func TestEncodeAttribute(t *testing.T) {
42 b := bytes.NewBuffer(nil)
43 encoder := xml.NewEncoder(b)
44
45 func() {
46 r := xml.StartElement{
47 Name: xml.Name{Local: "payload", Space: "baz"},
48 Attr: []xml.Attr{
49 xml.NewAttribute("attrkey", "value"),
50 },
51 }
52
53 obj := encoder.RootElement(r)
54 obj.String("")
55 }()
56
57 expect := `<baz:payload attrkey="value"></baz:payload>`
58
59 verify(t, encoder, []byte(expect))
60 }
61
62 func TestEncodeNamespace(t *testing.T) {
63 b := bytes.NewBuffer(nil)
64 encoder := xml.NewEncoder(b)
65
66 func() {
67 root := encoder.RootElement(root)
68 defer root.Close()
69
70 key := xml.StartElement{
71 Name: xml.Name{Local: "namespace"},
72 Attr: []xml.Attr{
73 xml.NewNamespaceAttribute("prefix", "https://example.com"),
74 },
75 }
76
77 n := root.MemberElement(key)
78 defer n.Close()
79
80 prefix := xml.StartElement{Name: xml.Name{Local: "user"}}
81 n.MemberElement(prefix).String("abc")
82 }()
83
84 e := []byte(`<root><namespace xmlns:prefix="https://example.com"><user>abc</user></namespace></root>`)
85 verify(t, encoder, e)
86 }
87
88 func TestEncodeEmptyNamespacePrefix(t *testing.T) {
89 b := bytes.NewBuffer(nil)
90 encoder := xml.NewEncoder(b)
91 func() {
92 root := encoder.RootElement(root)
93 defer root.Close()
94
95 key := xml.StartElement{
96 Name: xml.Name{Local: "namespace"},
97 Attr: []xml.Attr{
98 xml.NewNamespaceAttribute("", "https://example.com"),
99 },
100 }
101
102 n := root.MemberElement(key)
103 defer n.Close()
104
105 prefix := xml.StartElement{Name: xml.Name{Local: "user"}}
106 n.MemberElement(prefix).String("abc")
107 }()
108
109 e := []byte(`<root><namespace xmlns="https://example.com"><user>abc</user></namespace></root>`)
110 verify(t, encoder, e)
111 }
112
113 func verify(t *testing.T, encoder *xml.Encoder, e []byte) {
114 if a := encoder.Bytes(); bytes.Compare(e, a) != 0 {
115 t.Errorf("expected %+q, but got %+q", e, a)
116 }
117
118 if a := encoder.String(); string(encoder.Bytes()) != a {
119 t.Errorf("expected %s, but got %s", e, a)
120 }
121 }
122
123 func TestEncodeNestedShape(t *testing.T) {
124 b := bytes.NewBuffer(nil)
125 encoder := xml.NewEncoder(b)
126
127 func() {
128 r := encoder.RootElement(root)
129 defer r.Close()
130
131
132 nested := xml.StartElement{Name: xml.Name{Local: "nested"}}
133 n1 := r.MemberElement(nested)
134 defer n1.Close()
135
136
137 value := xml.StartElement{Name: xml.Name{Local: "value"}}
138 n1.MemberElement(value).String("expected value")
139 }()
140
141 e := []byte(`<root><nested><value>expected value</value></nested></root>`)
142 defer verify(t, encoder, e)
143 }
144
145 func TestEncodeMapString(t *testing.T) {
146 b := bytes.NewBuffer(nil)
147 encoder := xml.NewEncoder(b)
148 func() {
149 r := encoder.RootElement(root)
150 defer r.Close()
151
152
153 mapstr := xml.StartElement{Name: xml.Name{Local: "mapstr"}}
154 mapElement := r.MemberElement(mapstr)
155 defer mapElement.Close()
156
157 m := mapElement.Map()
158
159 key := xml.StartElement{Name: xml.Name{Local: "key"}}
160 value := xml.StartElement{Name: xml.Name{Local: "value"}}
161
162 e := m.Entry()
163 defer e.Close()
164 e.MemberElement(key).String("abc")
165 e.MemberElement(value).Integer(123)
166 }()
167
168 ex := []byte(`<root><mapstr><entry><key>abc</key><value>123</value></entry></mapstr></root>`)
169 verify(t, encoder, ex)
170 }
171
172 func TestEncodeMapFlatten(t *testing.T) {
173 b := bytes.NewBuffer(nil)
174 encoder := xml.NewEncoder(b)
175
176 func() {
177 r := encoder.RootElement(root)
178 defer r.Close()
179
180 mapstr := xml.StartElement{Name: xml.Name{Local: "mapstr"}}
181 flatElement := r.FlattenedElement(mapstr)
182
183 m := flatElement.Map()
184 e := m.Entry()
185 defer e.Close()
186
187 key := xml.StartElement{Name: xml.Name{Local: "key"}}
188 e.MemberElement(key).String("abc")
189
190 value := xml.StartElement{Name: xml.Name{Local: "value"}}
191 e.MemberElement(value).Integer(123)
192 }()
193
194 ex := []byte(`<root><mapstr><key>abc</key><value>123</value></mapstr></root>`)
195 verify(t, encoder, ex)
196 }
197
198 func TestEncodeMapNamed(t *testing.T) {
199 b := bytes.NewBuffer(nil)
200 encoder := xml.NewEncoder(b)
201
202 func() {
203 r := encoder.RootElement(root)
204 defer r.Close()
205
206 mapstr := xml.StartElement{Name: xml.Name{Local: "mapNamed"}}
207 mapElement := r.MemberElement(mapstr)
208 defer mapElement.Close()
209
210 m := mapElement.Map()
211 e := m.Entry()
212 defer e.Close()
213
214 key := xml.StartElement{Name: xml.Name{Local: "namedKey"}}
215 e.MemberElement(key).String("abc")
216
217 value := xml.StartElement{Name: xml.Name{Local: "namedValue"}}
218 e.MemberElement(value).Integer(123)
219 }()
220
221 ex := []byte(`<root><mapNamed><entry><namedKey>abc</namedKey><namedValue>123</namedValue></entry></mapNamed></root>`)
222 verify(t, encoder, ex)
223 }
224
225 func TestEncodeMapShape(t *testing.T) {
226 b := bytes.NewBuffer(nil)
227 encoder := xml.NewEncoder(b)
228
229 func() {
230 r := encoder.RootElement(root)
231 defer r.Close()
232
233
234 mapstr := xml.StartElement{Name: xml.Name{Local: "mapShape"}}
235 mapElement := r.MemberElement(mapstr)
236 defer mapElement.Close()
237
238 m := mapElement.Map()
239
240 e := m.Entry()
241 defer e.Close()
242
243 key := xml.StartElement{Name: xml.Name{Local: "key"}}
244 e.MemberElement(key).String("abc")
245
246 value := xml.StartElement{Name: xml.Name{Local: "value"}}
247 n1 := e.MemberElement(value)
248 defer n1.Close()
249
250 shapeVal := xml.StartElement{Name: xml.Name{Local: "shapeVal"}}
251 n1.MemberElement(shapeVal).Integer(1)
252 }()
253
254 ex := []byte(`<root><mapShape><entry><key>abc</key><value><shapeVal>1</shapeVal></value></entry></mapShape></root>`)
255 verify(t, encoder, ex)
256 }
257
258 func TestEncodeMapFlattenShape(t *testing.T) {
259 b := bytes.NewBuffer(nil)
260 encoder := xml.NewEncoder(b)
261
262 func() {
263 r := encoder.RootElement(root)
264 defer r.Close()
265
266 mapstr := xml.StartElement{Name: xml.Name{Local: "mapShape"}}
267 flatElement := r.FlattenedElement(mapstr)
268 m := flatElement.Map()
269
270 e := m.Entry()
271 defer e.Close()
272
273 key := xml.StartElement{Name: xml.Name{Local: "key"}}
274 e.MemberElement(key).String("abc")
275
276 value := xml.StartElement{Name: xml.Name{Local: "value"}}
277 n1 := e.MemberElement(value)
278 defer n1.Close()
279
280 shapeVal := xml.StartElement{Name: xml.Name{Local: "shapeVal"}}
281 n1.MemberElement(shapeVal).Integer(1)
282 }()
283 ex := []byte(`<root><mapShape><key>abc</key><value><shapeVal>1</shapeVal></value></mapShape></root>`)
284 verify(t, encoder, ex)
285 }
286
287 func TestEncodeMapNamedShape(t *testing.T) {
288 b := bytes.NewBuffer(nil)
289 encoder := xml.NewEncoder(b)
290
291 func() {
292 r := encoder.RootElement(root)
293 defer r.Close()
294
295
296 mapstr := xml.StartElement{Name: xml.Name{Local: "mapNamedShape"}}
297 mapElement := r.MemberElement(mapstr)
298 defer mapElement.Close()
299
300 m := mapElement.Map()
301 e := m.Entry()
302 defer e.Close()
303
304 key := xml.StartElement{Name: xml.Name{Local: "namedKey"}}
305 e.MemberElement(key).String("abc")
306
307 value := xml.StartElement{Name: xml.Name{Local: "namedValue"}}
308 n1 := e.MemberElement(value)
309 defer n1.Close()
310
311 shapeVal := xml.StartElement{Name: xml.Name{Local: "shapeVal"}}
312 n1.MemberElement(shapeVal).Integer(1)
313 }()
314
315 ex := []byte(`<root><mapNamedShape><entry><namedKey>abc</namedKey><namedValue><shapeVal>1</shapeVal></namedValue></entry></mapNamedShape></root>`)
316 verify(t, encoder, ex)
317 }
318
319 func TestEncodeListString(t *testing.T) {
320 b := bytes.NewBuffer(nil)
321 encoder := xml.NewEncoder(b)
322
323 func() {
324 r := encoder.RootElement(root)
325 defer r.Close()
326
327
328 liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
329 m := r.MemberElement(liststr)
330 defer m.Close()
331
332 a := m.Array()
333 a.Member().String("abc")
334 a.Member().Integer(123)
335 }()
336
337 ex := []byte(`<root><liststr><member>abc</member><member>123</member></liststr></root>`)
338 verify(t, encoder, ex)
339 }
340
341 func TestEncodeListFlatten(t *testing.T) {
342 b := bytes.NewBuffer(nil)
343 encoder := xml.NewEncoder(b)
344
345 func() {
346 r := encoder.RootElement(root)
347 defer r.Close()
348
349
350 liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
351 m := r.FlattenedElement(liststr)
352
353 a := m.Array()
354 a.Member().String("abc")
355 a.Member().Integer(123)
356 }()
357
358 ex := []byte(`<root><liststr>abc</liststr><liststr>123</liststr></root>`)
359 verify(t, encoder, ex)
360 }
361
362 func TestEncodeListNamed(t *testing.T) {
363 b := bytes.NewBuffer(nil)
364 encoder := xml.NewEncoder(b)
365
366 func() {
367 r := encoder.RootElement(root)
368 defer r.Close()
369
370
371 liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
372
373 namedMember := xml.StartElement{Name: xml.Name{Local: "namedMember"}}
374 m := r.MemberElement(liststr)
375 defer m.Close()
376
377 a := m.ArrayWithCustomName(namedMember)
378 a.Member().String("abc")
379 a.Member().Integer(123)
380 }()
381
382 ex := []byte(`<root><liststr><namedMember>abc</namedMember><namedMember>123</namedMember></liststr></root>`)
383 verify(t, encoder, ex)
384 }
385
386
387 func TestEncodeListShape(t *testing.T) {
388 b := bytes.NewBuffer(nil)
389 encoder := xml.NewEncoder(b)
390
391 func() {
392 r := encoder.RootElement(root)
393 defer r.Close()
394
395
396 liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
397
398 m := r.MemberElement(liststr)
399 defer m.Close()
400
401 a := m.Array()
402
403 value := xml.StartElement{Name: xml.Name{Local: "value"}}
404
405 m1 := a.Member()
406 m1.MemberElement(value).String("abc")
407 m1.Close()
408
409 m2 := a.Member()
410 m2.MemberElement(value).Integer(123)
411 m2.Close()
412 }()
413
414 ex := []byte(`<root><liststr><member><value>abc</value></member><member><value>123</value></member></liststr></root>`)
415 verify(t, encoder, ex)
416 }
417
418
419 func TestEncodeListFlattenShape(t *testing.T) {
420 b := bytes.NewBuffer(nil)
421 encoder := xml.NewEncoder(b)
422
423 func() {
424 r := encoder.RootElement(root)
425 defer r.Close()
426
427
428 liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
429
430 m := r.FlattenedElement(liststr)
431
432 a := m.Array()
433 value := xml.StartElement{Name: xml.Name{Local: "value"}}
434
435 m1 := a.Member()
436 m1.MemberElement(value).String("abc")
437 m1.Close()
438
439 m2 := a.Member()
440 m2.MemberElement(value).Integer(123)
441 m2.Close()
442 }()
443
444 ex := []byte(`<root><liststr><value>abc</value></liststr><liststr><value>123</value></liststr></root>`)
445 verify(t, encoder, ex)
446 }
447
448
449 func TestEncodeListNamedShape(t *testing.T) {
450 b := bytes.NewBuffer(nil)
451 encoder := xml.NewEncoder(b)
452
453 func() {
454 r := encoder.RootElement(root)
455 defer r.Close()
456
457
458 liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
459 namedMember := xml.StartElement{Name: xml.Name{Local: "namedMember"}}
460
461
462 m := r.MemberElement(liststr)
463 defer m.Close()
464
465
466 a := m.ArrayWithCustomName(namedMember)
467
468 value := xml.StartElement{Name: xml.Name{Local: "value"}}
469 m1 := a.Member()
470 m1.MemberElement(value).String("abc")
471 m1.Close()
472
473 m2 := a.Member()
474 m2.MemberElement(value).Integer(123)
475 m2.Close()
476 }()
477
478 ex := []byte(`<root><liststr><namedMember><value>abc</value></namedMember><namedMember><value>123</value></namedMember></liststr></root>`)
479 verify(t, encoder, ex)
480 }
481
482 func TestEncodeEscaping(t *testing.T) {
483 b := bytes.NewBuffer(nil)
484 encoder := xml.NewEncoder(b)
485
486 func() {
487 r := encoder.RootElement(root)
488 defer r.Close()
489
490 cases := map[string]rune{
491 "quote": '"',
492 "apos": '\'',
493 "amp": '&',
494 "lt": '<',
495 "gt": '>',
496 "tab": '\t',
497 "newLine": '\n',
498 "carriageReturn": '\r',
499 "nextLine": '\u0085',
500 "lineSeparator": '\u2028',
501 }
502
503 var sortedKeys []string
504 for name := range cases {
505 sortedKeys = append(sortedKeys, name)
506 }
507
508 sort.Strings(sortedKeys)
509
510 for _, name := range sortedKeys {
511 rr := cases[name]
512
513 st := xml.StartElement{Name: xml.Name{Local: name}}
514 st.Attr = append(st.Attr, xml.Attr{
515 Name: xml.Name{
516 Local: "key",
517 },
518 Value: name + string(rr) + name,
519 })
520 value := r.MemberElement(st)
521 value.String(name + string(rr) + name)
522 }
523 }()
524
525 ex := []byte(`<root><amp key="amp&amp">amp&amp</amp><apos key="apos'apos">apos'apos</apos><carriageReturn key="carriageReturn
carriageReturn">carriageReturn
carriageReturn</carriageReturn><gt key="gt>gt">gt>gt</gt><lineSeparator key="lineSeparator
lineSeparator">lineSeparator
lineSeparator</lineSeparator><lt key="lt<lt">lt<lt</lt><newLine key="newLine
newLine">newLine
newLine</newLine><nextLine key="nextLine…nextLine">nextLine…nextLine</nextLine><quote key="quote"quote">quote"quote</quote><tab key="tab	tab">tab	tab</tab></root>`)
526 verify(t, encoder, ex)
527 }
528
529
530 func ExampleEncoder() {
531 b := bytes.NewBuffer(nil)
532 encoder := xml.NewEncoder(b)
533
534
535
536 defer log.Printf("Encoded xml document: %v", encoder.String())
537
538 r := encoder.RootElement(root)
539 defer r.Close()
540
541
542 liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
543 namedMember := xml.StartElement{Name: xml.Name{Local: "namedMember"}}
544
545
546 m := r.MemberElement(liststr)
547 defer m.Close()
548
549
550 a := m.ArrayWithCustomName(namedMember)
551
552 value := xml.StartElement{Name: xml.Name{Local: "value"}}
553 m1 := a.Member()
554 m1.MemberElement(value).String("abc")
555 m1.Close()
556
557 m2 := a.Member()
558 m2.MemberElement(value).Integer(123)
559 m2.Close()
560 }
561
View as plain text