xml.go raw
1 package dara
2
3 import (
4 "bytes"
5 "encoding/xml"
6 "fmt"
7 "reflect"
8 "strings"
9
10 v2 "github.com/clbanning/mxj/v2"
11 )
12
13 func ToXML(obj map[string]interface{}) string {
14 return mapToXML(obj)
15 }
16
17 func ParseXml(val string, result interface{}) map[string]interface{} {
18 resp := make(map[string]interface{})
19
20 start := getStartElement([]byte(val))
21 if result == nil {
22 vm, err := v2.NewMapXml([]byte(val))
23 if err != nil {
24 return nil
25 }
26 return vm
27 }
28 out, err := xmlUnmarshal([]byte(val), result)
29 if err != nil {
30 return resp
31 }
32 resp[start] = out
33 return resp
34 }
35
36 func mapToXML(val map[string]interface{}) string {
37 res := ""
38 for key, value := range val {
39 switch value.(type) {
40 case []interface{}:
41 for _, v := range value.([]interface{}) {
42 switch v.(type) {
43 case map[string]interface{}:
44 res += `<` + key + `>`
45 res += mapToXML(v.(map[string]interface{}))
46 res += `</` + key + `>`
47 default:
48 if fmt.Sprintf("%v", v) != `<nil>` {
49 res += `<` + key + `>`
50 res += fmt.Sprintf("%v", v)
51 res += `</` + key + `>`
52 }
53 }
54 }
55 case map[string]interface{}:
56 res += `<` + key + `>`
57 res += mapToXML(value.(map[string]interface{}))
58 res += `</` + key + `>`
59 default:
60 if fmt.Sprintf("%v", value) != `<nil>` {
61 res += `<` + key + `>`
62 res += fmt.Sprintf("%v", value)
63 res += `</` + key + `>`
64 }
65 }
66 }
67 return res
68 }
69
70 func getStartElement(body []byte) string {
71 d := xml.NewDecoder(bytes.NewReader(body))
72 for {
73 tok, err := d.Token()
74 if err != nil {
75 return ""
76 }
77 if t, ok := tok.(xml.StartElement); ok {
78 return t.Name.Local
79 }
80 }
81 }
82
83 func xmlUnmarshal(body []byte, result interface{}) (interface{}, error) {
84 start := getStartElement(body)
85 dataValue := reflect.ValueOf(result).Elem()
86 dataType := dataValue.Type()
87 for i := 0; i < dataType.NumField(); i++ {
88 field := dataType.Field(i)
89 name, containsNameTag := field.Tag.Lookup("xml")
90 name = strings.Replace(name, ",omitempty", "", -1)
91 if containsNameTag {
92 if name == start {
93 realType := dataValue.Field(i).Type()
94 realValue := reflect.New(realType).Interface()
95 err := xml.Unmarshal(body, realValue)
96 if err != nil {
97 return nil, err
98 }
99 return realValue, nil
100 }
101 }
102 }
103 return nil, nil
104 }
105