summaryrefslogtreecommitdiff
path: root/libgo/go/encoding/xml/marshal.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/encoding/xml/marshal.go')
-rw-r--r--libgo/go/encoding/xml/marshal.go48
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
+}