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