diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go index 133503fa2d..ac3440916a 100644 --- a/src/encoding/xml/marshal.go +++ b/src/encoding/xml/marshal.go @@ -580,6 +580,15 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat // marshalAttr marshals an attribute with the given name and value, adding to start.Attr. func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value) error { + // Dereference or skip nil pointer, interface values. + switch val.Kind() { + case reflect.Pointer, reflect.Interface: + if val.IsNil() { + return nil + } + val = val.Elem() + } + if val.CanInterface() && val.Type().Implements(marshalerAttrType) { attr, err := val.Interface().(MarshalerAttr).MarshalXMLAttr(name) if err != nil { @@ -626,15 +635,6 @@ func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value) } } - // Dereference or skip nil pointer, interface values. - switch val.Kind() { - case reflect.Pointer, reflect.Interface: - if val.IsNil() { - return nil - } - val = val.Elem() - } - // Walk slices. if val.Kind() == reflect.Slice && val.Type().Elem().Kind() != reflect.Uint8 { n := val.Len() diff --git a/src/encoding/xml/marshal_test.go b/src/encoding/xml/marshal_test.go index b8bce7170a..c99147ef54 100644 --- a/src/encoding/xml/marshal_test.go +++ b/src/encoding/xml/marshal_test.go @@ -343,6 +343,10 @@ type MarshalerStruct struct { Foo MyMarshalerAttrTest `xml:",attr"` } +type IMarshalerStruct struct { + Foo interface{} `xml:",attr"` +} + type InnerStruct struct { XMLName Name `xml:"testns outer"` } @@ -1252,6 +1256,11 @@ var marshalTests = []struct { ExpectXML: ``, Value: &MarshalerStruct{}, }, + { + ExpectXML: ``, + Value: &IMarshalerStruct{Foo: &MyMarshalerAttrTest{}}, + MarshalOnly: true, + }, { ExpectXML: ``, Value: &OuterStruct{IntAttr: 10},