diff options
Diffstat (limited to 'libgo/go/encoding/xml/marshal.go')
-rw-r--r-- | libgo/go/encoding/xml/marshal.go | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/libgo/go/encoding/xml/marshal.go b/libgo/go/encoding/xml/marshal.go index 7a05a1bb10e..a96c523d553 100644 --- a/libgo/go/encoding/xml/marshal.go +++ b/libgo/go/encoding/xml/marshal.go @@ -12,6 +12,7 @@ import ( "reflect" "strconv" "strings" + "time" ) const ( @@ -52,6 +53,10 @@ const ( // - a field with tag ",comment" is written as an XML comment, not // subject to the usual marshalling procedure. It must not contain // the "--" string within it. +// - a field with a tag including the "omitempty" option is omitted +// if the field value is empty. The empty values are false, 0, any +// nil pointer or interface value, and any array, slice, map, or +// string of length zero. // // If a field uses a tag "a>b>c", then the element c will be nested inside // parent elements a and b. Fields that appear next to each other that name @@ -63,6 +68,8 @@ const ( // FirstName string `xml:"person>name>first"` // LastName string `xml:"person>name>last"` // Age int `xml:"person>age"` +// Height float `xml:"person>height,omitempty"` +// Married bool `xml:"person>married"` // } // // xml.Marshal(&Result{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}) @@ -76,6 +83,7 @@ const ( // <last>Doe</last> // </name> // <age>42</age> +// <married>false</married> // </person> // </result> // @@ -116,6 +124,9 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error { if !val.IsValid() { return nil } + if finfo != nil && finfo.flags&fOmitEmpty != 0 && isEmptyValue(val) { + return nil + } kind := val.Kind() typ := val.Type() @@ -183,12 +194,8 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error { continue } fv := val.FieldByIndex(finfo.idx) - switch fv.Kind() { - case reflect.String, reflect.Array, reflect.Slice: - // TODO: Should we really do this once ,omitempty is in? - if fv.Len() == 0 { - continue - } + if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) { + continue } p.WriteByte(' ') p.WriteString(finfo.name) @@ -217,7 +224,14 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error { return nil } +var timeType = reflect.TypeOf(time.Time{}) + func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error { + // Normally we don't see structs, but this can happen for an attribute. + if val.Type() == timeType { + p.WriteString(val.Interface().(time.Time).Format(time.RFC3339Nano)) + return nil + } switch val.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p.WriteString(strconv.FormatInt(val.Int(), 10)) @@ -249,6 +263,10 @@ func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error { var ddBytes = []byte("--") func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error { + if val.Type() == timeType { + p.WriteString(val.Interface().(time.Time).Format(time.RFC3339Nano)) + return nil + } s := parentStack{printer: p} for i := range tinfo.fields { finfo := &tinfo.fields[i] @@ -378,3 +396,21 @@ type UnsupportedTypeError struct { func (e *UnsupportedTypeError) Error() string { return "xml: unsupported type: " + e.Type.String() } + +func isEmptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + return false +} |