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