github.com/alibabacloud-go/tea@v1.3.10/dara/xml.go (about)

     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  }