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