func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
	if !value.IsValid() {
		return nil
	}
	if payload := tag.Get("payload"); payload != "" {
		field, _ := value.Type().FieldByName(payload)
		tag = field.Tag
		value = elemOf(value.FieldByName(payload))
		if !value.IsValid() {
			return nil
		}
	}
	child := NewXMLElement(xml.Name{Local: tag.Get("locationName")})
	if prefix, uri := tag.Get("xmlPrefix"), tag.Get("xmlURI"); uri != "" {
		ns := xml.Attr{
			Name:  xml.Name{Local: "xmlns"},
			Value: uri,
		}
		if prefix != "" {
			b.namespaces[prefix] = uri  
			ns.Name.Local = "xmlns:" + prefix
		}
		child.Attr = append(child.Attr, ns)
	}
	var payloadFields, nonPayloadFields int
	t := value.Type()
	for i := 0; i < value.NumField(); i++ {
		member := elemOf(value.Field(i))
		field := t.Field(i)
		if field.PkgPath != "" {
			continue  
		}
		if field.Tag.Get("ignore") != "" {
			continue
		}
		mTag := field.Tag
		if mTag.Get("location") != "" {  
			nonPayloadFields++
			continue
		}
		payloadFields++
		if protocol.CanSetIdempotencyToken(value.Field(i), field) {
			token := protocol.GetIdempotencyToken()
			member = reflect.ValueOf(token)
		}
		memberName := mTag.Get("locationName")
		if memberName == "" {
			memberName = field.Name
			mTag = reflect.StructTag(string(mTag) + ` locationName:"` + memberName + `"`)
		}
		if err := b.buildValue(member, child, mTag); err != nil {
			return err
		}
	}
	if !(payloadFields == 0 && nonPayloadFields > 0) {
		current.AddChild(child)
	}
	return nil
}
buildStruct adds a struct and its fields to the current XMLNode. All fields and any nested
types are converted to XMLNodes also.
package xmlutil
import (
	"encoding/base64"
	"encoding/xml"
	"fmt"
	"reflect"
	"sort"
	"strconv"
	"strings"
	"time"
	"github.com/aws/aws-sdk-go/private/protocol"
)
func BuildXML(params interface{}, e *xml.Encoder) error {
	return buildXML(params, e, false)
}
func buildXML(params interface{}, e *xml.Encoder, sorted bool) error {
	b := xmlBuilder{encoder: e, namespaces: map[string]string{}}
	root := NewXMLElement(xml.Name{})
	if err := b.buildValue(reflect.ValueOf(params), root, ""); err != nil {
		return err
	}
	for _, c := range root.Children {
		for _, v := range c {
			return StructToXML(e, v, sorted)
		}
	}
	return nil
}
func elemOf(value reflect.Value) reflect.Value {
	for value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	return value
}
type xmlBuilder struct {
	encoder    *xml.Encoder
	namespaces map[string]string
}
func (b *xmlBuilder) buildValue(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
	value = elemOf(value)
	if !value.IsValid() {  
		return nil
	} else if tag.Get("location") != "" {  
		return nil
	}
	xml := tag.Get("xml")
	if len(xml) != 0 {
		name := strings.SplitAfterN(xml, ",", 2)[0]
		if name == "-" {
			return nil
		}
	}
	t := tag.Get("type")
	if t == "" {
		switch value.Kind() {
		case reflect.Struct:
			t = "structure"
		case reflect.Slice:
			t = "list"
		case reflect.Map:
			t = "map"
		}
	}
	switch t {
	case "structure":
		if field, ok := value.Type().FieldByName("_"); ok {
			tag = tag + reflect.StructTag(" ") + field.Tag
		}
		return b.buildStruct(value, current, tag)
	case "list":
		return b.buildList(value, current, tag)
	case "map":
		return b.buildMap(value, current, tag)
	default:
		return b.buildScalar(value, current, tag)
	}
}