Package xmlutil provides XML serialization of AWS requests and responses.
package xmlutil

import (
	
	
	
	
	
	
	
	

	
)
BuildXML will serialize params into an xml.Encoder. Error will be returned if the serialization of any of the params or nested values fails.
func ( interface{},  *xml.Encoder) error {
	return buildXML(, , false)
}

func ( interface{},  *xml.Encoder,  bool) error {
	 := xmlBuilder{encoder: , namespaces: map[string]string{}}
	 := NewXMLElement(xml.Name{})
	if  := .buildValue(reflect.ValueOf(), , "");  != nil {
		return 
	}
	for ,  := range .Children {
		for ,  := range  {
			return StructToXML(, , )
		}
	}
	return nil
}
Returns the reflection element of a value, if it is a pointer.
func ( reflect.Value) reflect.Value {
	for .Kind() == reflect.Ptr {
		 = .Elem()
	}
	return 
}
A xmlBuilder serializes values from Go code to XML
buildValue generic XMLNode builder for any type. Will build value for their specific type struct, list, map, scalar. Also takes a "type" tag value to set what type a value should be converted to XMLNode as. If type is not provided reflect will be used to determine the value's type.
func ( *xmlBuilder) ( reflect.Value,  *XMLNode,  reflect.StructTag) error {
	 = elemOf()
	if !.IsValid() { // no need to handle zero values
		return nil
	} else if .Get("location") != "" { // don't handle non-body location values
		return nil
	}

	 := .Get("xml")
	if len() != 0 {
		 := strings.SplitAfterN(, ",", 2)[0]
		if  == "-" {
			return nil
		}
	}

	 := .Get("type")
	if  == "" {
		switch .Kind() {
		case reflect.Struct:
			 = "structure"
		case reflect.Slice:
			 = "list"
		case reflect.Map:
			 = "map"
		}
	}

	switch  {
	case "structure":
		if ,  := .Type().FieldByName("_");  {
			 =  + reflect.StructTag(" ") + .Tag
		}
		return .buildStruct(, , )
	case "list":
		return .buildList(, , )
	case "map":
		return .buildMap(, , )
	default:
		return .buildScalar(, , )
	}
}
buildStruct adds a struct and its fields to the current XMLNode. All fields and any nested types are converted to XMLNodes also.
func ( *xmlBuilder) ( reflect.Value,  *XMLNode,  reflect.StructTag) error {
	if !.IsValid() {
		return nil
	}
unwrap payloads
	if  := .Get("payload");  != "" {
		,  := .Type().FieldByName()
		 = .Tag
		 = elemOf(.FieldByName())

		if !.IsValid() {
			return nil
		}
	}

	 := NewXMLElement(xml.Name{Local: .Get("locationName")})
there is an xmlNamespace associated with this struct
	if ,  := .Get("xmlPrefix"), .Get("xmlURI");  != "" {
		 := xml.Attr{
			Name:  xml.Name{Local: "xmlns"},
			Value: ,
		}
		if  != "" {
			.namespaces[] =  // register the namespace
			.Name.Local = "xmlns:" + 
		}

		.Attr = append(.Attr, )
	}

	var ,  int

	 := .Type()
	for  := 0;  < .NumField(); ++ {
		 := elemOf(.Field())
		 := .Field()

		if .PkgPath != "" {
			continue // ignore unexported fields
		}
		if .Tag.Get("ignore") != "" {
			continue
		}

		 := .Tag
		if .Get("location") != "" { // skip non-body members
			++
			continue
		}
		++

		if protocol.CanSetIdempotencyToken(.Field(), ) {
			 := protocol.GetIdempotencyToken()
			 = reflect.ValueOf()
		}

		 := .Get("locationName")
		if  == "" {
			 = .Name
			 = reflect.StructTag(string() + ` locationName:"` +  + `"`)
		}
		if  := .buildValue(, , );  != nil {
			return 
		}
	}
Only case where the child shape is not added is if the shape only contains non-payload fields, e.g headers/query.
	if !( == 0 &&  > 0) {
		.AddChild()
	}

	return nil
}
buildList adds the value's list items to the current XMLNode as children nodes. All nested values in the list are converted to XMLNodes also.
func ( *xmlBuilder) ( reflect.Value,  *XMLNode,  reflect.StructTag) error {
	if .IsNil() { // don't build omitted lists
		return nil
	}
check for unflattened list member
	 := .Get("flattened") != ""

	 := xml.Name{Local: .Get("locationName")}
	if  {
		for  := 0;  < .Len(); ++ {
			 := NewXMLElement()
			.AddChild()
			if  := .buildValue(.Index(), , "");  != nil {
				return 
			}
		}
	} else {
		 := NewXMLElement()
		.AddChild()

		for  := 0;  < .Len(); ++ {
			 := .Get("locationNameList")
			if  == "" {
				 = "member"
			}

			 := NewXMLElement(xml.Name{Local: })
			.AddChild()
			if  := .buildValue(.Index(), , "");  != nil {
				return 
			}
		}
	}

	return nil
}
buildMap adds the value's key/value pairs to the current XMLNode as children nodes. All nested values in the map are converted to XMLNodes also. Error will be returned if it is unable to build the map's values into XMLNodes
func ( *xmlBuilder) ( reflect.Value,  *XMLNode,  reflect.StructTag) error {
	if .IsNil() { // don't build omitted maps
		return nil
	}

	 := NewXMLElement(xml.Name{Local: .Get("locationName")})
	.AddChild()
	 = 

	,  := "key", "value"
	if  := .Get("locationNameKey");  != "" {
		 = 
	}
	if  := .Get("locationNameValue");  != "" {
		 = 
	}
sorting is not required for compliance, but it makes testing easier
	 := make([]string, .Len())
	for ,  := range .MapKeys() {
		[] = .String()
	}
	sort.Strings()

	for ,  := range  {
		 := .MapIndex(reflect.ValueOf())

		 := 
		if .Get("flattened") == "" { // add "entry" tag to non-flat maps
			 := NewXMLElement(xml.Name{Local: "entry"})
			.AddChild()
			 = 
		}

		 := NewXMLElement(xml.Name{Local: })
		.Text = 
		 := NewXMLElement(xml.Name{Local: })
		.AddChild()
		.AddChild()

		if  := .buildValue(, , "");  != nil {
			return 
		}
	}

	return nil
}
buildScalar will convert the value into a string and append it as a attribute or child of the current XMLNode. The value will be added as an attribute if tag contains a "xmlAttribute" attribute value. Error will be returned if the value type is unsupported.
func ( *xmlBuilder) ( reflect.Value,  *XMLNode,  reflect.StructTag) error {
	var  string
	switch converted := .Interface().(type) {
	case string:
		 = 
	case []byte:
		if !.IsNil() {
			 = base64.StdEncoding.EncodeToString()
		}
	case bool:
		 = strconv.FormatBool()
	case int64:
		 = strconv.FormatInt(, 10)
	case int:
		 = strconv.Itoa()
	case float64:
		 = strconv.FormatFloat(, 'f', -1, 64)
	case float32:
		 = strconv.FormatFloat(float64(), 'f', -1, 32)
	case time.Time:
		 := .Get("timestampFormat")
		if len() == 0 {
			 = protocol.ISO8601TimeFormatName
		}

		 = protocol.FormatTime(, )
	default:
		return fmt.Errorf("unsupported value for param %s: %v (%s)",
			.Get("locationName"), .Interface(), .Type().Name())
	}

	 := xml.Name{Local: .Get("locationName")}
	if .Get("xmlAttribute") != "" { // put into current node's attribute list
		 := xml.Attr{Name: , Value: }
		.Attr = append(.Attr, )
	} else { // regular text node
		.AddChild(&XMLNode{Name: , Text: })
	}
	return nil