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