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