github.com/coveo/gotemplate@v2.7.7+incompatible/xml/xml.go (about) 1 package xml 2 3 import ( 4 "encoding/xml" 5 "math" 6 "reflect" 7 8 "github.com/coveo/gotemplate/collections/implementation" 9 ) 10 11 // Expose xml public objects 12 var ( 13 CopyToken = xml.CopyToken 14 Escape = xml.Escape 15 EscapeText = xml.EscapeText 16 Marshal = xml.Marshal 17 MarshalIndent = xml.MarshalIndent 18 NewDecoder = xml.NewDecoder 19 NewEncoder = xml.NewEncoder 20 NativeUnmarshal = xml.Unmarshal 21 ) 22 23 func (l xmlList) String() string { result, _ := Marshal(l.AsArray()); return string(result) } 24 func (d xmlDict) String() string { result, _ := Marshal(d.AsMap()); return string(result) } 25 26 func (l xmlList) PrettyPrint() string { 27 result, _ := MarshalIndent(l.AsArray(), "", " ") 28 return string(result) 29 } 30 func (d xmlDict) PrettyPrint() string { 31 result, _ := MarshalIndent(d.AsMap(), "", " ") 32 return string(result) 33 } 34 35 // TODO activate when Marshall will be enabled on maps 36 // var _ = func() int { 37 // collections.TypeConverters["xml"] = Unmarshal 38 // return 0 39 // }() 40 41 // Unmarshal calls the native Unmarshal but transform the results 42 // to returns Dictionary and GenerecList instead of go native collections. 43 func Unmarshal(data []byte, out interface{}) (err error) { 44 if err = NativeUnmarshal(data, out); err != nil { 45 return 46 } 47 transform(out) 48 return 49 } 50 51 func transform(out interface{}) { 52 result := transformElement(reflect.ValueOf(out).Elem().Interface()) 53 if _, isMap := out.(*map[string]interface{}); isMap { 54 // If the result is expected to be map[string]interface{}, we convert it back from internal dict type. 55 result = result.(xmlIDict).Native() 56 } 57 reflect.ValueOf(out).Elem().Set(reflect.ValueOf(result)) 58 } 59 60 func transformElement(source interface{}) interface{} { 61 if value, err := xmlHelper.TryAsDictionary(source); err == nil { 62 for _, key := range value.KeysAsString() { 63 value.Set(key, transformElement(value.Get(key))) 64 } 65 source = value 66 } else if value, err := xmlHelper.TryAsList(source); err == nil { 67 for i, sub := range value.AsArray() { 68 value.Set(i, transformElement(sub)) 69 } 70 source = value 71 } else if value, ok := source.(float64); ok { 72 // xml.Unmarshal returns all int values as float64 73 if math.Floor(value) == value { 74 source = int(value) 75 } 76 } 77 return source 78 } 79 80 type ( 81 helperBase = implementation.BaseHelper 82 helperList = implementation.ListHelper 83 helperDict = implementation.DictHelper 84 ) 85 86 var needConversionImpl = implementation.NeedConversion 87 88 //go:generate genny -pkg=xml -in=../collections/implementation/generic.go -out=generated_impl.go gen "ListTypeName=List DictTypeName=Dictionary base=xml" 89 //go:generate genny -pkg=xml -in=../collections/implementation/generic_test.go -out=generated_test.go gen "base=xml"