1
2
3
4
5 package xml
6
7 import (
8 "bytes"
9 "encoding"
10 "errors"
11 "fmt"
12 "reflect"
13 "strconv"
14 "strings"
15 )
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 func Unmarshal(data []byte, v any) error {
133 return NewDecoder(bytes.NewReader(data)).Decode(v)
134 }
135
136
137
138 func (d *Decoder) Decode(v any) error {
139 return d.DecodeElement(v, nil)
140 }
141
142
143
144
145
146 func (d *Decoder) DecodeElement(v any, start *StartElement) error {
147 val := reflect.ValueOf(v)
148 if val.Kind() != reflect.Pointer {
149 return errors.New("non-pointer passed to Unmarshal")
150 }
151 return d.unmarshal(val.Elem(), start)
152 }
153
154
155 type UnmarshalError string
156
157 func (e UnmarshalError) Error() string { return string(e) }
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 type Unmarshaler interface {
175 UnmarshalXML(d *Decoder, start StartElement) error
176 }
177
178
179
180
181
182
183
184
185
186 type UnmarshalerAttr interface {
187 UnmarshalXMLAttr(attr Attr) error
188 }
189
190
191 func receiverType(val any) string {
192 t := reflect.TypeOf(val)
193 if t.Name() != "" {
194 return t.String()
195 }
196 return "(" + t.String() + ")"
197 }
198
199
200
201 func (d *Decoder) unmarshalInterface(val Unmarshaler, start *StartElement) error {
202
203 d.pushEOF()
204
205 d.unmarshalDepth++
206 err := val.UnmarshalXML(d, *start)
207 d.unmarshalDepth--
208 if err != nil {
209 d.popEOF()
210 return err
211 }
212
213 if !d.popEOF() {
214 return fmt.Errorf("xml: %s.UnmarshalXML did not consume entire <%s> element", receiverType(val), start.Name.Local)
215 }
216
217 return nil
218 }
219
220
221
222
223 func (d *Decoder) unmarshalTextInterface(val encoding.TextUnmarshaler) error {
224 var buf []byte
225 depth := 1
226 for depth > 0 {
227 t, err := d.Token()
228 if err != nil {
229 return err
230 }
231 switch t := t.(type) {
232 case CharData:
233 if depth == 1 {
234 buf = append(buf, t...)
235 }
236 case StartElement:
237 depth++
238 case EndElement:
239 depth--
240 }
241 }
242 return val.UnmarshalText(buf)
243 }
244
245
246 func (d *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
247 if val.Kind() == reflect.Pointer {
248 if val.IsNil() {
249 val.Set(reflect.New(val.Type().Elem()))
250 }
251 val = val.Elem()
252 }
253 if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) {
254
255
256 return val.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
257 }
258 if val.CanAddr() {
259 pv := val.Addr()
260 if pv.CanInterface() && pv.Type().Implements(unmarshalerAttrType) {
261 return pv.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
262 }
263 }
264
265
266 if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
267
268
269 return val.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
270 }
271 if val.CanAddr() {
272 pv := val.Addr()
273 if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
274 return pv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
275 }
276 }
277
278 if val.Type().Kind() == reflect.Slice && val.Type().Elem().Kind() != reflect.Uint8 {
279
280
281 n := val.Len()
282 val.Set(reflect.Append(val, reflect.Zero(val.Type().Elem())))
283
284
285 if err := d.unmarshalAttr(val.Index(n), attr); err != nil {
286 val.SetLen(n)
287 return err
288 }
289 return nil
290 }
291
292 if val.Type() == attrType {
293 val.Set(reflect.ValueOf(attr))
294 return nil
295 }
296
297 return copyValue(val, []byte(attr.Value))
298 }
299
300 var (
301 attrType = reflect.TypeOf(Attr{})
302 unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
303 unmarshalerAttrType = reflect.TypeOf((*UnmarshalerAttr)(nil)).Elem()
304 textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
305 )
306
307
308 func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
309
310 if start == nil {
311 for {
312 tok, err := d.Token()
313 if err != nil {
314 return err
315 }
316 if t, ok := tok.(StartElement); ok {
317 start = &t
318 break
319 }
320 }
321 }
322
323
324
325 if val.Kind() == reflect.Interface && !val.IsNil() {
326 e := val.Elem()
327 if e.Kind() == reflect.Pointer && !e.IsNil() {
328 val = e
329 }
330 }
331
332 if val.Kind() == reflect.Pointer {
333 if val.IsNil() {
334 val.Set(reflect.New(val.Type().Elem()))
335 }
336 val = val.Elem()
337 }
338
339 if val.CanInterface() && val.Type().Implements(unmarshalerType) {
340
341
342 return d.unmarshalInterface(val.Interface().(Unmarshaler), start)
343 }
344
345 if val.CanAddr() {
346 pv := val.Addr()
347 if pv.CanInterface() && pv.Type().Implements(unmarshalerType) {
348 return d.unmarshalInterface(pv.Interface().(Unmarshaler), start)
349 }
350 }
351
352 if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
353 return d.unmarshalTextInterface(val.Interface().(encoding.TextUnmarshaler))
354 }
355
356 if val.CanAddr() {
357 pv := val.Addr()
358 if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
359 return d.unmarshalTextInterface(pv.Interface().(encoding.TextUnmarshaler))
360 }
361 }
362
363 var (
364 data []byte
365 saveData reflect.Value
366 comment []byte
367 saveComment reflect.Value
368 saveXML reflect.Value
369 saveXMLIndex int
370 saveXMLData []byte
371 saveAny reflect.Value
372 sv reflect.Value
373 tinfo *typeInfo
374 err error
375 )
376
377 switch v := val; v.Kind() {
378 default:
379 return errors.New("unknown type " + v.Type().String())
380
381 case reflect.Interface:
382
383
384
385 return d.Skip()
386
387 case reflect.Slice:
388 typ := v.Type()
389 if typ.Elem().Kind() == reflect.Uint8 {
390
391 saveData = v
392 break
393 }
394
395
396
397 n := v.Len()
398 v.Set(reflect.Append(val, reflect.Zero(v.Type().Elem())))
399
400
401 if err := d.unmarshal(v.Index(n), start); err != nil {
402 v.SetLen(n)
403 return err
404 }
405 return nil
406
407 case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.String:
408 saveData = v
409
410 case reflect.Struct:
411 typ := v.Type()
412 if typ == nameType {
413 v.Set(reflect.ValueOf(start.Name))
414 break
415 }
416
417 sv = v
418 tinfo, err = getTypeInfo(typ)
419 if err != nil {
420 return err
421 }
422
423
424 if tinfo.xmlname != nil {
425 finfo := tinfo.xmlname
426 if finfo.name != "" && finfo.name != start.Name.Local {
427 return UnmarshalError("expected element type <" + finfo.name + "> but have <" + start.Name.Local + ">")
428 }
429 if finfo.xmlns != "" && finfo.xmlns != start.Name.Space {
430 e := "expected element <" + finfo.name + "> in name space " + finfo.xmlns + " but have "
431 if start.Name.Space == "" {
432 e += "no name space"
433 } else {
434 e += start.Name.Space
435 }
436 return UnmarshalError(e)
437 }
438 fv := finfo.value(sv, initNilPointers)
439 if _, ok := fv.Interface().(Name); ok {
440 fv.Set(reflect.ValueOf(start.Name))
441 }
442 }
443
444
445 for _, a := range start.Attr {
446 handled := false
447 any := -1
448 for i := range tinfo.fields {
449 finfo := &tinfo.fields[i]
450 switch finfo.flags & fMode {
451 case fAttr:
452 strv := finfo.value(sv, initNilPointers)
453 if a.Name.Local == finfo.name && (finfo.xmlns == "" || finfo.xmlns == a.Name.Space) {
454 if err := d.unmarshalAttr(strv, a); err != nil {
455 return err
456 }
457 handled = true
458 }
459
460 case fAny | fAttr:
461 if any == -1 {
462 any = i
463 }
464 }
465 }
466 if !handled && any >= 0 {
467 finfo := &tinfo.fields[any]
468 strv := finfo.value(sv, initNilPointers)
469 if err := d.unmarshalAttr(strv, a); err != nil {
470 return err
471 }
472 }
473 }
474
475
476 for i := range tinfo.fields {
477 finfo := &tinfo.fields[i]
478 switch finfo.flags & fMode {
479 case fCDATA, fCharData:
480 if !saveData.IsValid() {
481 saveData = finfo.value(sv, initNilPointers)
482 }
483
484 case fComment:
485 if !saveComment.IsValid() {
486 saveComment = finfo.value(sv, initNilPointers)
487 }
488
489 case fAny, fAny | fElement:
490 if !saveAny.IsValid() {
491 saveAny = finfo.value(sv, initNilPointers)
492 }
493
494 case fInnerXML:
495 if !saveXML.IsValid() {
496 saveXML = finfo.value(sv, initNilPointers)
497 if d.saved == nil {
498 saveXMLIndex = 0
499 d.saved = new(bytes.Buffer)
500 } else {
501 saveXMLIndex = d.savedOffset()
502 }
503 }
504 }
505 }
506 }
507
508
509
510 Loop:
511 for {
512 var savedOffset int
513 if saveXML.IsValid() {
514 savedOffset = d.savedOffset()
515 }
516 tok, err := d.Token()
517 if err != nil {
518 return err
519 }
520 switch t := tok.(type) {
521 case StartElement:
522 consumed := false
523 if sv.IsValid() {
524 consumed, err = d.unmarshalPath(tinfo, sv, nil, &t)
525 if err != nil {
526 return err
527 }
528 if !consumed && saveAny.IsValid() {
529 consumed = true
530 if err := d.unmarshal(saveAny, &t); err != nil {
531 return err
532 }
533 }
534 }
535 if !consumed {
536 if err := d.Skip(); err != nil {
537 return err
538 }
539 }
540
541 case EndElement:
542 if saveXML.IsValid() {
543 saveXMLData = d.saved.Bytes()[saveXMLIndex:savedOffset]
544 if saveXMLIndex == 0 {
545 d.saved = nil
546 }
547 }
548 break Loop
549
550 case CharData:
551 if saveData.IsValid() {
552 data = append(data, t...)
553 }
554
555 case Comment:
556 if saveComment.IsValid() {
557 comment = append(comment, t...)
558 }
559 }
560 }
561
562 if saveData.IsValid() && saveData.CanInterface() && saveData.Type().Implements(textUnmarshalerType) {
563 if err := saveData.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
564 return err
565 }
566 saveData = reflect.Value{}
567 }
568
569 if saveData.IsValid() && saveData.CanAddr() {
570 pv := saveData.Addr()
571 if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
572 if err := pv.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
573 return err
574 }
575 saveData = reflect.Value{}
576 }
577 }
578
579 if err := copyValue(saveData, data); err != nil {
580 return err
581 }
582
583 switch t := saveComment; t.Kind() {
584 case reflect.String:
585 t.SetString(string(comment))
586 case reflect.Slice:
587 t.Set(reflect.ValueOf(comment))
588 }
589
590 switch t := saveXML; t.Kind() {
591 case reflect.String:
592 t.SetString(string(saveXMLData))
593 case reflect.Slice:
594 if t.Type().Elem().Kind() == reflect.Uint8 {
595 t.Set(reflect.ValueOf(saveXMLData))
596 }
597 }
598
599 return nil
600 }
601
602 func copyValue(dst reflect.Value, src []byte) (err error) {
603 dst0 := dst
604
605 if dst.Kind() == reflect.Pointer {
606 if dst.IsNil() {
607 dst.Set(reflect.New(dst.Type().Elem()))
608 }
609 dst = dst.Elem()
610 }
611
612
613 switch dst.Kind() {
614 case reflect.Invalid:
615
616 default:
617 return errors.New("cannot unmarshal into " + dst0.Type().String())
618 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
619 if len(src) == 0 {
620 dst.SetInt(0)
621 return nil
622 }
623 itmp, err := strconv.ParseInt(strings.TrimSpace(string(src)), 10, dst.Type().Bits())
624 if err != nil {
625 return err
626 }
627 dst.SetInt(itmp)
628 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
629 if len(src) == 0 {
630 dst.SetUint(0)
631 return nil
632 }
633 utmp, err := strconv.ParseUint(strings.TrimSpace(string(src)), 10, dst.Type().Bits())
634 if err != nil {
635 return err
636 }
637 dst.SetUint(utmp)
638 case reflect.Float32, reflect.Float64:
639 if len(src) == 0 {
640 dst.SetFloat(0)
641 return nil
642 }
643 ftmp, err := strconv.ParseFloat(strings.TrimSpace(string(src)), dst.Type().Bits())
644 if err != nil {
645 return err
646 }
647 dst.SetFloat(ftmp)
648 case reflect.Bool:
649 if len(src) == 0 {
650 dst.SetBool(false)
651 return nil
652 }
653 value, err := strconv.ParseBool(strings.TrimSpace(string(src)))
654 if err != nil {
655 return err
656 }
657 dst.SetBool(value)
658 case reflect.String:
659 dst.SetString(string(src))
660 case reflect.Slice:
661 if len(src) == 0 {
662
663 src = []byte{}
664 }
665 dst.SetBytes(src)
666 }
667 return nil
668 }
669
670
671
672
673
674
675 func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
676 recurse := false
677 Loop:
678 for i := range tinfo.fields {
679 finfo := &tinfo.fields[i]
680 if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) || finfo.xmlns != "" && finfo.xmlns != start.Name.Space {
681 continue
682 }
683 for j := range parents {
684 if parents[j] != finfo.parents[j] {
685 continue Loop
686 }
687 }
688 if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
689
690 return true, d.unmarshal(finfo.value(sv, initNilPointers), start)
691 }
692 if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
693
694
695
696 recurse = true
697
698
699
700 parents = finfo.parents[:len(parents)+1]
701 break
702 }
703 }
704 if !recurse {
705
706 return false, nil
707 }
708
709
710
711 for {
712 var tok Token
713 tok, err = d.Token()
714 if err != nil {
715 return true, err
716 }
717 switch t := tok.(type) {
718 case StartElement:
719 consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t)
720 if err != nil {
721 return true, err
722 }
723 if !consumed2 {
724 if err := d.Skip(); err != nil {
725 return true, err
726 }
727 }
728 case EndElement:
729 return true, nil
730 }
731 }
732 }
733
734
735
736
737
738
739
740 func (d *Decoder) Skip() error {
741 for {
742 tok, err := d.Token()
743 if err != nil {
744 return err
745 }
746 switch tok.(type) {
747 case StartElement:
748 if err := d.Skip(); err != nil {
749 return err
750 }
751 case EndElement:
752 return nil
753 }
754 }
755 }
756
View as plain text