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"