1
2
3
4
5
6
7
8
9 package mxj
10
11 import (
12 "bytes"
13 "encoding/json"
14 "encoding/xml"
15 "errors"
16 "fmt"
17 "io"
18 "reflect"
19 "sort"
20 "strconv"
21 "strings"
22 "time"
23 )
24
25 var (
26 textK = "#text"
27 seqK = "#seq"
28 commentK = "#comment"
29 attrK = "#attr"
30 directiveK = "#directive"
31 procinstK = "#procinst"
32 targetK = "#target"
33 instK = "#inst"
34 )
35
36
37
38 func SetGlobalKeyMapPrefix(s string) {
39 textK = strings.ReplaceAll(textK, textK[0:1], s)
40 seqK = strings.ReplaceAll(seqK, seqK[0:1], s)
41 commentK = strings.ReplaceAll(commentK, commentK[0:1], s)
42 directiveK = strings.ReplaceAll(directiveK, directiveK[0:1], s)
43 procinstK = strings.ReplaceAll(procinstK, procinstK[0:1], s)
44 targetK = strings.ReplaceAll(targetK, targetK[0:1], s)
45 instK = strings.ReplaceAll(instK, instK[0:1], s)
46 attrK = strings.ReplaceAll(attrK, attrK[0:1], s)
47 }
48
49
50
51
52
53
54
55
56
57
58
59
60
61 var XmlCharsetReader func(charset string, input io.Reader) (io.Reader, error)
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 func NewMapXml(xmlVal []byte, cast ...bool) (Map, error) {
86 var r bool
87 if len(cast) == 1 {
88 r = cast[0]
89 }
90 return xmlToMap(xmlVal, r)
91 }
92
93
94
95
96
97
98
99
100 func NewMapXmlReader(xmlReader io.Reader, cast ...bool) (Map, error) {
101 var r bool
102 if len(cast) == 1 {
103 r = cast[0]
104 }
105
106
107
108
109 if _, ok := xmlReader.(io.ByteReader); !ok {
110 xmlReader = myByteReader(xmlReader)
111 }
112
113
114 return xmlReaderToMap(xmlReader, r)
115 }
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130 func NewMapXmlReaderRaw(xmlReader io.Reader, cast ...bool) (Map, []byte, error) {
131 var r bool
132 if len(cast) == 1 {
133 r = cast[0]
134 }
135
136 buf := make([]byte, 0)
137 wb := bytes.NewBuffer(buf)
138 trdr := myTeeReader(xmlReader, wb)
139
140 m, err := xmlReaderToMap(trdr, r)
141
142
143 b := wb.Bytes()
144
145 if err != nil {
146 return nil, b, err
147 }
148
149 return m, b, nil
150 }
151
152
153 func xmlReaderToMap(rdr io.Reader, r bool) (map[string]interface{}, error) {
154
155 p := xml.NewDecoder(rdr)
156 if CustomDecoder != nil {
157 useCustomDecoder(p)
158 } else {
159 p.CharsetReader = XmlCharsetReader
160 }
161 return xmlToMapParser("", nil, p, r)
162 }
163
164
165 func xmlToMap(doc []byte, r bool) (map[string]interface{}, error) {
166 b := bytes.NewReader(doc)
167 p := xml.NewDecoder(b)
168 if CustomDecoder != nil {
169 useCustomDecoder(p)
170 } else {
171 p.CharsetReader = XmlCharsetReader
172 }
173 return xmlToMapParser("", nil, p, r)
174 }
175
176
177
178
179
180
181
182
183 func PrependAttrWithHyphen(v bool) {
184 if v {
185 attrPrefix = "-"
186 lenAttrPrefix = len(attrPrefix)
187 return
188 }
189 attrPrefix = ""
190 lenAttrPrefix = len(attrPrefix)
191 }
192
193
194 var includeTagSeqNum bool
195
196
197
198
199
200
201
236 func IncludeTagSeqNum(b ...bool) {
237 if len(b) == 0 {
238 includeTagSeqNum = !includeTagSeqNum
239 } else if len(b) == 1 {
240 includeTagSeqNum = b[0]
241 }
242 }
243
244
245 var lowerCase bool
246
247
248
249
250
251
252
253
254
255 func CoerceKeysToLower(b ...bool) {
256 if len(b) == 0 {
257 lowerCase = !lowerCase
258 } else if len(b) == 1 {
259 lowerCase = b[0]
260 }
261 }
262
263
264 var disableTrimWhiteSpace bool
265 var trimRunes = "\t\r\b\n "
266
267
268
269 func DisableTrimWhiteSpace(b ...bool) {
270 if len(b) == 0 {
271 disableTrimWhiteSpace = true
272 } else {
273 disableTrimWhiteSpace = b[0]
274 }
275
276 if disableTrimWhiteSpace {
277 trimRunes = "\t\r\b\n"
278 } else {
279 trimRunes = "\t\r\b\n "
280 }
281 }
282
283
284
285
286
287 var attrPrefix string = `-`
288 var lenAttrPrefix int = 1
289
290
291
292
293 func SetAttrPrefix(s string) {
294 attrPrefix = s
295 lenAttrPrefix = len(attrPrefix)
296 }
297
298
299
300 var snakeCaseKeys bool
301
302
303
304
305 func CoerceKeysToSnakeCase(b ...bool) {
306 if len(b) == 0 {
307 snakeCaseKeys = !snakeCaseKeys
308 } else if len(b) == 1 {
309 snakeCaseKeys = b[0]
310 }
311 }
312
313
314
315 var castToInt bool
316
317
318
319
320 func CastValuesToInt(b ...bool) {
321 if len(b) == 0 {
322 castToInt = !castToInt
323 } else if len(b) == 1 {
324 castToInt = b[0]
325 }
326 }
327
328
329 var handleXMPPStreamTag bool
330
331
332
333
334
335
336
337
338
339
340
341 func HandleXMPPStreamTag(b ...bool) {
342 if len(b) == 0 {
343 handleXMPPStreamTag = !handleXMPPStreamTag
344 } else if len(b) == 1 {
345 handleXMPPStreamTag = b[0]
346 }
347 }
348
349
350 var decodeSimpleValuesAsMap bool
351
352
353
354
355
356
357
358 func DecodeSimpleValuesAsMap(b ...bool) {
359 if len(b) == 0 {
360 decodeSimpleValuesAsMap = !decodeSimpleValuesAsMap
361 } else if len(b) == 1 {
362 decodeSimpleValuesAsMap = b[0]
363 }
364 }
365
366
367
368
369 func xmlToMapParser(skey string, a []xml.Attr, p *xml.Decoder, r bool) (map[string]interface{}, error) {
370 if lowerCase {
371 skey = strings.ToLower(skey)
372 }
373 if snakeCaseKeys {
374 skey = strings.Replace(skey, "-", "_", -1)
375 }
376
377
378
379 var n, na map[string]interface{}
380 var seq int
381
382
383
384
385
386 if skey != "" {
387 n = make(map[string]interface{})
388 na = make(map[string]interface{})
389 if len(a) > 0 {
390 for _, v := range a {
391 if snakeCaseKeys {
392 v.Name.Local = strings.Replace(v.Name.Local, "-", "_", -1)
393 }
394 var key string
395 key = attrPrefix + v.Name.Local
396 if lowerCase {
397 key = strings.ToLower(key)
398 }
399 if xmlEscapeCharsDecoder {
400 v.Value = escapeChars(v.Value)
401 }
402 na[key] = cast(v.Value, r, key)
403 }
404 }
405 }
406
407 if handleXMPPStreamTag && skey == "stream" {
408 n[skey] = na
409 return n, nil
410 }
411
412 for {
413 t, err := p.Token()
414 if err != nil {
415 if err != io.EOF {
416 return nil, errors.New("xml.Decoder.Token() - " + err.Error())
417 }
418 return nil, err
419 }
420 switch t.(type) {
421 case xml.StartElement:
422 tt := t.(xml.StartElement)
423
424
425
426
427
428
429
430
431 if skey == "" {
432 return xmlToMapParser(tt.Name.Local, tt.Attr, p, r)
433 }
434
435
436
437 nn, err := xmlToMapParser(tt.Name.Local, tt.Attr, p, r)
438 if err != nil {
439 return nil, err
440 }
441
442
443
444
445
446
447
448
449 var key string
450 var val interface{}
451 for key, val = range nn {
452 break
453 }
454
455
456
457
458
459
460 if includeTagSeqNum {
461 switch val.(type) {
462 case []interface{}:
463
464 case map[string]interface{}:
465 val.(map[string]interface{})["_seq"] = seq
466 seq++
467 case interface{}:
468 v := map[string]interface{}{textK: val}
469 v["_seq"] = seq
470 seq++
471 val = v
472 }
473 }
474
475
476
477
478 if v, ok := na[key]; ok {
479 var a []interface{}
480 switch v.(type) {
481 case []interface{}:
482 a = v.([]interface{})
483 default:
484 a = []interface{}{v}
485 }
486 a = append(a, val)
487 na[key] = a
488 } else {
489 na[key] = val
490 }
491 case xml.EndElement:
492
493 if len(n) == 0 {
494
495
496
497
498 if len(na) > 0 {
499 n[skey] = na
500 } else {
501 n[skey] = ""
502 }
503 } else if len(n) == 1 && len(na) > 0 {
504
505 for _, v := range n {
506 na[textK] = v
507 }
508 n[skey] = na
509 }
510 return n, nil
511 case xml.CharData:
512
513 tt := strings.Trim(string(t.(xml.CharData)), trimRunes)
514 if xmlEscapeCharsDecoder {
515 tt = escapeChars(tt)
516 }
517 if len(tt) > 0 {
518 if len(na) > 0 || decodeSimpleValuesAsMap {
519 na[textK] = cast(tt, r, textK)
520 } else if skey != "" {
521 n[skey] = cast(tt, r, skey)
522 } else {
523
524
525
526
527
528 continue
529 }
530 }
531 default:
532
533 }
534 }
535 }
536
537 var castNanInf bool
538
539
540
541 func CastNanInf(b ...bool) {
542 if len(b) == 0 {
543 castNanInf = !castNanInf
544 } else if len(b) == 1 {
545 castNanInf = b[0]
546 }
547 }
548
549
550
551 func cast(s string, r bool, t string) interface{} {
552 if checkTagToSkip != nil && t != "" && checkTagToSkip(t) {
553
554
555 return s
556 }
557
558 if r {
559
560 if !castNanInf {
561 switch strings.ToLower(s) {
562 case "nan", "inf", "-inf":
563 return s
564 }
565 }
566
567
568 if castToInt {
569 if f, err := strconv.ParseInt(s, 10, 64); err == nil {
570 return f
571 }
572 if f, err := strconv.ParseUint(s, 10, 64); err == nil {
573 return f
574 }
575 }
576
577 if castToFloat {
578 if f, err := strconv.ParseFloat(s, 64); err == nil {
579 return f
580 }
581 }
582
583
584
585
586 if castToBool {
587 if len(s) > 0 && len(s) < 6 {
588 switch s[:1] {
589 case "t", "T", "f", "F":
590 if b, err := strconv.ParseBool(s); err == nil {
591 return b
592 }
593 }
594 }
595 }
596 }
597 return s
598 }
599
600
601 var castToFloat = true
602
603
604
605
606 func CastValuesToFloat(b ...bool) {
607 if len(b) == 0 {
608 castToFloat = !castToFloat
609 } else if len(b) == 1 {
610 castToFloat = b[0]
611 }
612 }
613
614 var castToBool = true
615
616
617
618
619 func CastValuesToBool(b ...bool) {
620 if len(b) == 0 {
621 castToBool = !castToBool
622 } else if len(b) == 1 {
623 castToBool = b[0]
624 }
625 }
626
627
628
629 var checkTagToSkip func(string) bool
630
631
632
633
634
635
636
637 func SetCheckTagToSkipFunc(fn func(string) bool) {
638 checkTagToSkip = fn
639 }
640
641
642
643
644
645 const (
646 DefaultRootTag = "doc"
647 )
648
649 var useGoXmlEmptyElemSyntax bool
650
651
652
653
654
655 func XmlGoEmptyElemSyntax() {
656 useGoXmlEmptyElemSyntax = true
657 }
658
659
660
661
662 func XmlDefaultEmptyElemSyntax() {
663 useGoXmlEmptyElemSyntax = false
664 }
665
666
667
668
669 var xmlCheckIsValid bool
670
671
672 func XmlCheckIsValid(b ...bool) {
673 if len(b) == 1 {
674 xmlCheckIsValid = b[0]
675 return
676 }
677 xmlCheckIsValid = !xmlCheckIsValid
678 }
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696 func (mv Map) Xml(rootTag ...string) ([]byte, error) {
697 m := map[string]interface{}(mv)
698 var err error
699 b := new(bytes.Buffer)
700 p := new(pretty)
701
702 if len(m) == 1 && len(rootTag) == 0 {
703 for key, value := range m {
704
705
706
707 switch value.(type) {
708 case []interface{}:
709 for _, v := range value.([]interface{}) {
710 switch v.(type) {
711 case map[string]interface{}:
712 default:
713 err = marshalMapToXmlIndent(false, b, DefaultRootTag, m, p)
714 goto done
715 }
716 }
717 }
718 err = marshalMapToXmlIndent(false, b, key, value, p)
719 }
720 } else if len(rootTag) == 1 {
721 err = marshalMapToXmlIndent(false, b, rootTag[0], m, p)
722 } else {
723 err = marshalMapToXmlIndent(false, b, DefaultRootTag, m, p)
724 }
725 done:
726 if xmlCheckIsValid {
727 d := xml.NewDecoder(bytes.NewReader(b.Bytes()))
728 for {
729 _, err = d.Token()
730 if err == io.EOF {
731 err = nil
732 break
733 } else if err != nil {
734 return nil, err
735 }
736 }
737 }
738 return b.Bytes(), err
739 }
740
741
742
743
744
745
746 func (mv Map) XmlWriter(xmlWriter io.Writer, rootTag ...string) error {
747 x, err := mv.Xml(rootTag...)
748 if err != nil {
749 return err
750 }
751
752 _, err = xmlWriter.Write(x)
753 return err
754 }
755
756
757
758
769
770
771
772 func (mv Map) XmlIndentWriter(xmlWriter io.Writer, prefix, indent string, rootTag ...string) error {
773 x, err := mv.XmlIndent(prefix, indent, rootTag...)
774 if err != nil {
775 return err
776 }
777
778 _, err = xmlWriter.Write(x)
779 return err
780 }
781
782
783
784
795
796
797
798
799
800
801
802 var xhandlerPollInterval = time.Millisecond
803
804
805
806
807
808
809
810
811 func HandleXmlReader(xmlReader io.Reader, mapHandler func(Map) bool, errHandler func(error) bool) error {
812 var n int
813 for {
814 m, merr := NewMapXmlReader(xmlReader)
815 n++
816
817
818 if merr != nil && merr != io.EOF {
819 merr = fmt.Errorf("[xmlReader: %d] %s", n, merr.Error())
820 if ok := errHandler(merr); !ok {
821
822 return merr
823 }
824 continue
825 }
826
827
828 if len(m) != 0 {
829 if ok := mapHandler(m); !ok {
830 break
831 }
832 } else if merr != io.EOF {
833 time.Sleep(xhandlerPollInterval)
834 }
835
836 if merr == io.EOF {
837 break
838 }
839 }
840 return nil
841 }
842
843
844
845
846
847
848
849
850
851 func HandleXmlReaderRaw(xmlReader io.Reader, mapHandler func(Map, []byte) bool, errHandler func(error, []byte) bool) error {
852 var n int
853 for {
854 m, raw, merr := NewMapXmlReaderRaw(xmlReader)
855 n++
856
857
858 if merr != nil && merr != io.EOF {
859 merr = fmt.Errorf("[xmlReader: %d] %s", n, merr.Error())
860 if ok := errHandler(merr, raw); !ok {
861
862 return merr
863 }
864 continue
865 }
866
867
868 if len(m) != 0 {
869 if ok := mapHandler(m, raw); !ok {
870 break
871 }
872 } else if merr != io.EOF {
873 time.Sleep(xhandlerPollInterval)
874 }
875
876 if merr == io.EOF {
877 break
878 }
879 }
880 return nil
881 }
882
883
884
885
886
887
888
889
890
891
892
893
894 type teeReader struct {
895 r io.Reader
896 w io.Writer
897 b []byte
898 }
899
900 func myTeeReader(r io.Reader, w io.Writer) io.Reader {
901 b := make([]byte, 1)
902 return &teeReader{r, w, b}
903 }
904
905
906 func (t *teeReader) Read(p []byte) (int, error) {
907 return 0, nil
908 }
909
910 func (t *teeReader) ReadByte() (byte, error) {
911 n, err := t.r.Read(t.b)
912 if n > 0 {
913 if _, err := t.w.Write(t.b[:1]); err != nil {
914 return t.b[0], err
915 }
916 }
917 return t.b[0], err
918 }
919
920
921 type byteReader struct {
922 r io.Reader
923 b []byte
924 }
925
926 func myByteReader(r io.Reader) io.Reader {
927 b := make([]byte, 1)
928 return &byteReader{r, b}
929 }
930
931
932
933 func (b *byteReader) Read(p []byte) (int, error) {
934 return b.r.Read(p)
935 }
936
937 func (b *byteReader) ReadByte() (byte, error) {
938 _, err := b.r.Read(b.b)
939 if len(b.b) > 0 {
940
941 return b.b[0], err
942 }
943 var c byte
944 return c, err
945 }
946
947
948
949
950
951
952
953 func (mv Map) XmlIndent(prefix, indent string, rootTag ...string) ([]byte, error) {
954 m := map[string]interface{}(mv)
955
956 var err error
957 b := new(bytes.Buffer)
958 p := new(pretty)
959 p.indent = indent
960 p.padding = prefix
961
962 if len(m) == 1 && len(rootTag) == 0 {
963
964
965 for key, value := range m {
966 if _, ok := value.([]interface{}); ok {
967 err = marshalMapToXmlIndent(true, b, DefaultRootTag, m, p)
968 } else {
969 err = marshalMapToXmlIndent(true, b, key, value, p)
970 }
971 }
972 } else if len(rootTag) == 1 {
973 err = marshalMapToXmlIndent(true, b, rootTag[0], m, p)
974 } else {
975 err = marshalMapToXmlIndent(true, b, DefaultRootTag, m, p)
976 }
977 if xmlCheckIsValid {
978 d := xml.NewDecoder(bytes.NewReader(b.Bytes()))
979 for {
980 _, err = d.Token()
981 if err == io.EOF {
982 err = nil
983 break
984 } else if err != nil {
985 return nil, err
986 }
987 }
988 }
989 return b.Bytes(), err
990 }
991
992 type pretty struct {
993 indent string
994 cnt int
995 padding string
996 mapDepth int
997 start int
998 }
999
1000 func (p *pretty) Indent() {
1001 p.padding += p.indent
1002 p.cnt++
1003 }
1004
1005 func (p *pretty) Outdent() {
1006 if p.cnt > 0 {
1007 p.padding = p.padding[:len(p.padding)-len(p.indent)]
1008 p.cnt--
1009 }
1010 }
1011
1012
1013
1014
1015 func marshalMapToXmlIndent(doIndent bool, b *bytes.Buffer, key string, value interface{}, pp *pretty) error {
1016 var err error
1017 var endTag bool
1018 var isSimple bool
1019 var elen int
1020 p := &pretty{pp.indent, pp.cnt, pp.padding, pp.mapDepth, pp.start}
1021
1022
1023
1024 if reflect.ValueOf(value).Kind() == reflect.Map {
1025 switch value.(type) {
1026 case map[string]interface{}:
1027 default:
1028 val := make(map[string]interface{})
1029 vv := reflect.ValueOf(value)
1030 keys := vv.MapKeys()
1031 for _, k := range keys {
1032 val[fmt.Sprint(k)] = vv.MapIndex(k).Interface()
1033 }
1034 value = val
1035 }
1036 }
1037
1038
1039
1040
1041 switch value.(type) {
1042
1043 case map[string]interface{}, []byte, string, float64, bool, int, int32, int64, float32, json.Number:
1044 case []map[string]interface{}, []string, []float64, []bool, []int, []int32, []int64, []float32, []json.Number:
1045 case []interface{}:
1046 case nil:
1047 value = ""
1048 default:
1049
1050 if reflect.ValueOf(value).Kind() == reflect.Struct {
1051 if v, err := xml.Marshal(value); err != nil {
1052 return err
1053 } else {
1054 value = string(v)
1055 }
1056 } else {
1057
1058 value = fmt.Sprint(value)
1059 }
1060 }
1061
1062
1063 if doIndent {
1064 switch value.(type) {
1065 case []interface{}, []string:
1066
1067 default:
1068 if _, err = b.WriteString(p.padding); err != nil {
1069 return err
1070 }
1071 }
1072 }
1073 switch value.(type) {
1074 case []interface{}:
1075 default:
1076 if _, err = b.WriteString(`<` + key); err != nil {
1077 return err
1078 }
1079 }
1080
1081 switch value.(type) {
1082 case map[string]interface{}:
1083 vv := value.(map[string]interface{})
1084 lenvv := len(vv)
1085
1086 attrlist := make([][2]string, len(vv))
1087 var n int
1088 var ss string
1089 for k, v := range vv {
1090 if lenAttrPrefix > 0 && lenAttrPrefix < len(k) && k[:lenAttrPrefix] == attrPrefix {
1091 switch v.(type) {
1092 case string:
1093 if xmlEscapeChars {
1094 ss = escapeChars(v.(string))
1095 } else {
1096 ss = v.(string)
1097 }
1098 attrlist[n][0] = k[lenAttrPrefix:]
1099 attrlist[n][1] = ss
1100 case float64, bool, int, int32, int64, float32, json.Number:
1101 attrlist[n][0] = k[lenAttrPrefix:]
1102 attrlist[n][1] = fmt.Sprintf("%v", v)
1103 case []byte:
1104 if xmlEscapeChars {
1105 ss = escapeChars(string(v.([]byte)))
1106 } else {
1107 ss = string(v.([]byte))
1108 }
1109 attrlist[n][0] = k[lenAttrPrefix:]
1110 attrlist[n][1] = ss
1111 default:
1112 return fmt.Errorf("invalid attribute value for: %s:<%T>", k, v)
1113 }
1114 n++
1115 }
1116 }
1117 if n > 0 {
1118 attrlist = attrlist[:n]
1119 sort.Sort(attrList(attrlist))
1120 for _, v := range attrlist {
1121 if _, err = b.WriteString(` ` + v[0] + `="` + v[1] + `"`); err != nil {
1122 return err
1123 }
1124 }
1125 }
1126
1127 if n == lenvv {
1128 if useGoXmlEmptyElemSyntax {
1129 if _, err = b.WriteString(`</` + key + ">"); err != nil {
1130 return err
1131 }
1132 } else {
1133 if _, err = b.WriteString(`/>`); err != nil {
1134 return err
1135 }
1136 }
1137 break
1138 }
1139
1140
1141 isComplex := false
1142 if v, ok := vv[textK]; ok && n+1 == lenvv {
1143
1144 switch v.(type) {
1145 case string:
1146 if xmlEscapeChars {
1147 v = escapeChars(v.(string))
1148 } else {
1149 v = v.(string)
1150 }
1151 case []byte:
1152 if xmlEscapeChars {
1153 v = escapeChars(string(v.([]byte)))
1154 } else {
1155 v = string(v.([]byte))
1156 }
1157 }
1158 if _, err = b.WriteString(">" + fmt.Sprintf("%v", v)); err != nil {
1159 return err
1160 }
1161 endTag = true
1162 elen = 1
1163 isSimple = true
1164 break
1165 } else if ok {
1166
1167
1168 switch v.(type) {
1169 case string:
1170 if xmlEscapeChars {
1171 v = escapeChars(v.(string))
1172 } else {
1173 v = v.(string)
1174 }
1175 case []byte:
1176 if xmlEscapeChars {
1177 v = escapeChars(string(v.([]byte)))
1178 } else {
1179 v = string(v.([]byte))
1180 }
1181 }
1182 if _, err = b.WriteString(">" + fmt.Sprintf("%v", v)); err != nil {
1183 return err
1184 }
1185 isComplex = true
1186 }
1187
1188
1189 if !isComplex {
1190 if _, err = b.WriteString(">"); err != nil {
1191 return err
1192 }
1193 }
1194 if doIndent {
1195
1196 if _, err = b.WriteString("\n"); err != nil {
1197 return err
1198 }
1199 }
1200
1201 p.mapDepth++
1202
1203 elemlist := make([][2]interface{}, len(vv))
1204 n = 0
1205 for k, v := range vv {
1206 if k == textK {
1207
1208 continue
1209 }
1210 if lenAttrPrefix > 0 && lenAttrPrefix < len(k) && k[:lenAttrPrefix] == attrPrefix {
1211 continue
1212 }
1213 elemlist[n][0] = k
1214 elemlist[n][1] = v
1215 n++
1216 }
1217 elemlist = elemlist[:n]
1218 sort.Sort(elemList(elemlist))
1219 var i int
1220 for _, v := range elemlist {
1221 switch v[1].(type) {
1222 case []interface{}:
1223 default:
1224 if i == 0 && doIndent {
1225 p.Indent()
1226 }
1227 }
1228 i++
1229 if err := marshalMapToXmlIndent(doIndent, b, v[0].(string), v[1], p); err != nil {
1230 return err
1231 }
1232 switch v[1].(type) {
1233 case []interface{}:
1234 default:
1235 if doIndent {
1236 p.Outdent()
1237 }
1238 }
1239 i--
1240 }
1241 p.mapDepth--
1242 endTag = true
1243 elen = 1
1244 case []interface{}:
1245
1246 if len(value.([]interface{})) == 0 {
1247 if doIndent {
1248 if _, err = b.WriteString(p.padding + p.indent); err != nil {
1249 return err
1250 }
1251 }
1252 if _, err = b.WriteString("<" + key); err != nil {
1253 return err
1254 }
1255 elen = 0
1256 endTag = true
1257 break
1258 }
1259 for _, v := range value.([]interface{}) {
1260 if doIndent {
1261 p.Indent()
1262 }
1263 if err := marshalMapToXmlIndent(doIndent, b, key, v, p); err != nil {
1264 return err
1265 }
1266 if doIndent {
1267 p.Outdent()
1268 }
1269 }
1270 return nil
1271 case []string:
1272
1273
1274
1275
1276
1277
1278 if len(value.([]string)) == 0 {
1279 if doIndent {
1280 if _, err = b.WriteString(p.padding + p.indent); err != nil {
1281 return err
1282 }
1283 }
1284 if _, err = b.WriteString("<" + key); err != nil {
1285 return err
1286 }
1287 elen = 0
1288 endTag = true
1289 break
1290 }
1291 for _, v := range value.([]string) {
1292 if doIndent {
1293 p.Indent()
1294 }
1295 if err := marshalMapToXmlIndent(doIndent, b, key, v, p); err != nil {
1296 return err
1297 }
1298 if doIndent {
1299 p.Outdent()
1300 }
1301 }
1302 return nil
1303 case nil:
1304
1305 if doIndent {
1306
1307 if _, err = b.WriteString(p.padding); err != nil {
1308 return err
1309 }
1310 }
1311 if _, err = b.WriteString("<" + key); err != nil {
1312 return err
1313 }
1314 endTag, isSimple = true, true
1315 break
1316 default:
1317 elen = 0
1318 switch value.(type) {
1319 case string:
1320 v := value.(string)
1321 if xmlEscapeChars {
1322 v = escapeChars(v)
1323 }
1324 elen = len(v)
1325 if elen > 0 {
1326
1327 if _, err = b.WriteString(">" + v); err != nil {
1328 return err
1329 }
1330 }
1331 case float64, bool, int, int32, int64, float32, json.Number:
1332 v := fmt.Sprintf("%v", value)
1333 elen = len(v)
1334 if _, err = b.WriteString(">" + v); err != nil {
1335 return err
1336 }
1337 case []byte:
1338
1339 v := string(value.([]byte))
1340 if xmlEscapeChars {
1341 v = escapeChars(v)
1342 }
1343 elen = len(v)
1344 if elen > 0 {
1345
1346 if _, err = b.WriteString(">" + v); err != nil {
1347 return err
1348 }
1349 }
1350 default:
1351 if _, err = b.WriteString(">"); err != nil {
1352 return err
1353 }
1354 var v []byte
1355 var err error
1356 if doIndent {
1357 v, err = xml.MarshalIndent(value, p.padding, p.indent)
1358 } else {
1359 v, err = xml.Marshal(value)
1360 }
1361 if err != nil {
1362 if _, err = b.WriteString(">UNKNOWN"); err != nil {
1363 return err
1364 }
1365 } else {
1366 elen = len(v)
1367 if elen > 0 {
1368 if _, err = b.Write(v); err != nil {
1369 return err
1370 }
1371 }
1372 }
1373 }
1374 isSimple = true
1375 endTag = true
1376 }
1377 if endTag {
1378 if doIndent {
1379 if !isSimple {
1380 if _, err = b.WriteString(p.padding); err != nil {
1381 return err
1382 }
1383 }
1384 }
1385 if elen > 0 || useGoXmlEmptyElemSyntax {
1386 if elen == 0 {
1387 if _, err = b.WriteString(">"); err != nil {
1388 return err
1389 }
1390 }
1391 if _, err = b.WriteString(`</` + key + ">"); err != nil {
1392 return err
1393 }
1394 } else {
1395 if _, err = b.WriteString(`/>`); err != nil {
1396 return err
1397 }
1398 }
1399 }
1400 if doIndent {
1401 if p.cnt > p.start {
1402 if _, err = b.WriteString("\n"); err != nil {
1403 return err
1404 }
1405 }
1406 p.Outdent()
1407 }
1408
1409 return nil
1410 }
1411
1412
1413
1414 type attrList [][2]string
1415
1416 func (a attrList) Len() int {
1417 return len(a)
1418 }
1419
1420 func (a attrList) Swap(i, j int) {
1421 a[i], a[j] = a[j], a[i]
1422 }
1423
1424 func (a attrList) Less(i, j int) bool {
1425 return a[i][0] <= a[j][0]
1426 }
1427
1428 type elemList [][2]interface{}
1429
1430 func (e elemList) Len() int {
1431 return len(e)
1432 }
1433
1434 func (e elemList) Swap(i, j int) {
1435 e[i], e[j] = e[j], e[i]
1436 }
1437
1438 func (e elemList) Less(i, j int) bool {
1439 return e[i][0].(string) <= e[j][0].(string)
1440 }
1441
View as plain text