summaryrefslogtreecommitdiffstats
path: root/libgo/go/encoding/xml
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-03-02 16:38:43 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-03-02 16:38:43 +0000
commit2d2d80b8bd963f59534897b3d51ef8bd546cb4bc (patch)
treeefa0c55763b34cbc633bc494c2743d1b5d9aaff3 /libgo/go/encoding/xml
parent2ad2700dbf70b2e49575f3f2307839a45cf2f71c (diff)
downloadppe42-gcc-2d2d80b8bd963f59534897b3d51ef8bd546cb4bc.tar.gz
ppe42-gcc-2d2d80b8bd963f59534897b3d51ef8bd546cb4bc.zip
libgo: Update to weekly.2012-02-14 release.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184798 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/encoding/xml')
-rw-r--r--libgo/go/encoding/xml/atom_test.go13
-rw-r--r--libgo/go/encoding/xml/marshal.go48
-rw-r--r--libgo/go/encoding/xml/marshal_test.go93
-rw-r--r--libgo/go/encoding/xml/read.go13
-rw-r--r--libgo/go/encoding/xml/read_test.go41
-rw-r--r--libgo/go/encoding/xml/typeinfo.go17
6 files changed, 183 insertions, 42 deletions
diff --git a/libgo/go/encoding/xml/atom_test.go b/libgo/go/encoding/xml/atom_test.go
index 8d003aade07..a71284312af 100644
--- a/libgo/go/encoding/xml/atom_test.go
+++ b/libgo/go/encoding/xml/atom_test.go
@@ -4,6 +4,8 @@
package xml
+import "time"
+
var atomValue = &Feed{
XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
Title: "Example Feed",
@@ -24,11 +26,10 @@ var atomValue = &Feed{
}
var atomXml = `` +
- `<feed xmlns="http://www.w3.org/2005/Atom">` +
+ `<feed xmlns="http://www.w3.org/2005/Atom" updated="2003-12-13T18:30:02Z">` +
`<title>Example Feed</title>` +
`<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>` +
`<link href="http://example.org/"></link>` +
- `<updated>2003-12-13T18:30:02Z</updated>` +
`<author><name>John Doe</name><uri></uri><email></email></author>` +
`<entry>` +
`<title>Atom-Powered Robots Run Amok</title>` +
@@ -40,8 +41,12 @@ var atomXml = `` +
`</entry>` +
`</feed>`
-func ParseTime(str string) Time {
- return Time(str)
+func ParseTime(str string) time.Time {
+ t, err := time.Parse(time.RFC3339, str)
+ if err != nil {
+ panic(err)
+ }
+ return t
}
func NewText(text string) Text {
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
+}
diff --git a/libgo/go/encoding/xml/marshal_test.go b/libgo/go/encoding/xml/marshal_test.go
index 0f6c0f0795d..9170fccd243 100644
--- a/libgo/go/encoding/xml/marshal_test.go
+++ b/libgo/go/encoding/xml/marshal_test.go
@@ -9,6 +9,7 @@ import (
"strconv"
"strings"
"testing"
+ "time"
)
type DriveType int
@@ -38,14 +39,14 @@ type NamedType string
type Port struct {
XMLName struct{} `xml:"port"`
- Type string `xml:"type,attr"`
+ Type string `xml:"type,attr,omitempty"`
Comment string `xml:",comment"`
Number string `xml:",chardata"`
}
type Domain struct {
XMLName struct{} `xml:"domain"`
- Country string `xml:",attr"`
+ Country string `xml:",attr,omitempty"`
Name []byte `xml:",chardata"`
Comment []byte `xml:",comment"`
}
@@ -149,11 +150,33 @@ type NameInField struct {
type AttrTest struct {
Int int `xml:",attr"`
- Lower int `xml:"int,attr"`
+ Named int `xml:"int,attr"`
Float float64 `xml:",attr"`
Uint8 uint8 `xml:",attr"`
Bool bool `xml:",attr"`
Str string `xml:",attr"`
+ Bytes []byte `xml:",attr"`
+}
+
+type OmitAttrTest struct {
+ Int int `xml:",attr,omitempty"`
+ Named int `xml:"int,attr,omitempty"`
+ Float float64 `xml:",attr,omitempty"`
+ Uint8 uint8 `xml:",attr,omitempty"`
+ Bool bool `xml:",attr,omitempty"`
+ Str string `xml:",attr,omitempty"`
+ Bytes []byte `xml:",attr,omitempty"`
+}
+
+type OmitFieldTest struct {
+ Int int `xml:",omitempty"`
+ Named int `xml:"int,omitempty"`
+ Float float64 `xml:",omitempty"`
+ Uint8 uint8 `xml:",omitempty"`
+ Bool bool `xml:",omitempty"`
+ Str string `xml:",omitempty"`
+ Bytes []byte `xml:",omitempty"`
+ Ptr *PresenceTest `xml:",omitempty"`
}
type AnyTest struct {
@@ -234,6 +257,12 @@ var marshalTests = []struct {
{Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
{Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+ // Test time.
+ {
+ Value: &Plain{time.Unix(1e9, 123456789).UTC()},
+ ExpectXML: `<Plain><V>2001-09-09T01:46:40.123456789Z</V></Plain>`,
+ },
+
// A pointer to struct{} may be used to test for an element's presence.
{
Value: &PresenceTest{new(struct{})},
@@ -549,13 +578,65 @@ var marshalTests = []struct {
{
Value: &AttrTest{
Int: 8,
- Lower: 9,
+ Named: 9,
+ Float: 23.5,
+ Uint8: 255,
+ Bool: true,
+ Str: "str",
+ Bytes: []byte("byt"),
+ },
+ ExpectXML: `<AttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
+ ` Bool="true" Str="str" Bytes="byt"></AttrTest>`,
+ },
+ {
+ Value: &AttrTest{Bytes: []byte{}},
+ ExpectXML: `<AttrTest Int="0" int="0" Float="0" Uint8="0"` +
+ ` Bool="false" Str="" Bytes=""></AttrTest>`,
+ },
+ {
+ Value: &OmitAttrTest{
+ Int: 8,
+ Named: 9,
+ Float: 23.5,
+ Uint8: 255,
+ Bool: true,
+ Str: "str",
+ Bytes: []byte("byt"),
+ },
+ ExpectXML: `<OmitAttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
+ ` Bool="true" Str="str" Bytes="byt"></OmitAttrTest>`,
+ },
+ {
+ Value: &OmitAttrTest{},
+ ExpectXML: `<OmitAttrTest></OmitAttrTest>`,
+ },
+
+ // omitempty on fields
+ {
+ Value: &OmitFieldTest{
+ Int: 8,
+ Named: 9,
Float: 23.5,
Uint8: 255,
Bool: true,
- Str: "s",
+ Str: "str",
+ Bytes: []byte("byt"),
+ Ptr: &PresenceTest{},
},
- ExpectXML: `<AttrTest Int="8" int="9" Float="23.5" Uint8="255" Bool="true" Str="s"></AttrTest>`,
+ ExpectXML: `<OmitFieldTest>` +
+ `<Int>8</Int>` +
+ `<int>9</int>` +
+ `<Float>23.5</Float>` +
+ `<Uint8>255</Uint8>` +
+ `<Bool>true</Bool>` +
+ `<Str>str</Str>` +
+ `<Bytes>byt</Bytes>` +
+ `<Ptr></Ptr>` +
+ `</OmitFieldTest>`,
+ },
+ {
+ Value: &OmitFieldTest{},
+ ExpectXML: `<OmitFieldTest></OmitFieldTest>`,
},
// Test ",any"
diff --git a/libgo/go/encoding/xml/read.go b/libgo/go/encoding/xml/read.go
index bde875a0123..b5a3426a328 100644
--- a/libgo/go/encoding/xml/read.go
+++ b/libgo/go/encoding/xml/read.go
@@ -10,6 +10,7 @@ import (
"reflect"
"strconv"
"strings"
+ "time"
)
// BUG(rsc): Mapping between XML elements and data structures is inherently flawed:
@@ -270,6 +271,10 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
v.Set(reflect.ValueOf(start.Name))
break
}
+ if typ == timeType {
+ saveData = v
+ break
+ }
sv = v
tinfo, err = getTypeInfo(typ)
@@ -473,6 +478,14 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
src = []byte{}
}
t.SetBytes(src)
+ case reflect.Struct:
+ if t.Type() == timeType {
+ tv, err := time.Parse(time.RFC3339, string(src))
+ if err != nil {
+ return err
+ }
+ t.Set(reflect.ValueOf(tv))
+ }
}
return nil
}
diff --git a/libgo/go/encoding/xml/read_test.go b/libgo/go/encoding/xml/read_test.go
index 833eafc9a58..8df09b3ccee 100644
--- a/libgo/go/encoding/xml/read_test.go
+++ b/libgo/go/encoding/xml/read_test.go
@@ -7,6 +7,7 @@ package xml
import (
"reflect"
"testing"
+ "time"
)
// Stripped down Atom feed data structures.
@@ -24,7 +25,7 @@ func TestUnmarshalFeed(t *testing.T) {
// hget http://codereview.appspot.com/rss/mine/rsc
const atomFeedString = `
<?xml version="1.0" encoding="utf-8"?>
-<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us"><title>Code Review - My issues</title><link href="http://codereview.appspot.com/" rel="alternate"></link><link href="http://codereview.appspot.com/rss/mine/rsc" rel="self"></link><id>http://codereview.appspot.com/</id><updated>2009-10-04T01:35:58+00:00</updated><author><name>rietveld&lt;&gt;</name></author><entry><title>rietveld: an attempt at pubsubhubbub
+<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us" updated="2009-10-04T01:35:58+00:00"><title>Code Review - My issues</title><link href="http://codereview.appspot.com/" rel="alternate"></link><link href="http://codereview.appspot.com/rss/mine/rsc" rel="self"></link><id>http://codereview.appspot.com/</id><author><name>rietveld&lt;&gt;</name></author><entry><title>rietveld: an attempt at pubsubhubbub
</title><link href="http://codereview.appspot.com/126085" rel="alternate"></link><updated>2009-10-04T01:35:58+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:134d9179c41f806be79b3a5f7877d19a</id><summary type="html">
An attempt at adding pubsubhubbub support to Rietveld.
http://code.google.com/p/pubsubhubbub
@@ -78,26 +79,26 @@ not being used from outside intra_region_diff.py.
</summary></entry></feed> `
type Feed struct {
- XMLName Name `xml:"http://www.w3.org/2005/Atom feed"`
- Title string `xml:"title"`
- Id string `xml:"id"`
- Link []Link `xml:"link"`
- Updated Time `xml:"updated"`
- Author Person `xml:"author"`
- Entry []Entry `xml:"entry"`
+ XMLName Name `xml:"http://www.w3.org/2005/Atom feed"`
+ Title string `xml:"title"`
+ Id string `xml:"id"`
+ Link []Link `xml:"link"`
+ Updated time.Time `xml:"updated,attr"`
+ Author Person `xml:"author"`
+ Entry []Entry `xml:"entry"`
}
type Entry struct {
- Title string `xml:"title"`
- Id string `xml:"id"`
- Link []Link `xml:"link"`
- Updated Time `xml:"updated"`
- Author Person `xml:"author"`
- Summary Text `xml:"summary"`
+ Title string `xml:"title"`
+ Id string `xml:"id"`
+ Link []Link `xml:"link"`
+ Updated time.Time `xml:"updated"`
+ Author Person `xml:"author"`
+ Summary Text `xml:"summary"`
}
type Link struct {
- Rel string `xml:"rel,attr"`
+ Rel string `xml:"rel,attr,omitempty"`
Href string `xml:"href,attr"`
}
@@ -109,12 +110,10 @@ type Person struct {
}
type Text struct {
- Type string `xml:"type,attr"`
+ Type string `xml:"type,attr,omitempty"`
Body string `xml:",chardata"`
}
-type Time string
-
var atomFeed = Feed{
XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
Title: "Code Review - My issues",
@@ -123,7 +122,7 @@ var atomFeed = Feed{
{Rel: "self", Href: "http://codereview.appspot.com/rss/mine/rsc"},
},
Id: "http://codereview.appspot.com/",
- Updated: "2009-10-04T01:35:58+00:00",
+ Updated: ParseTime("2009-10-04T01:35:58+00:00"),
Author: Person{
Name: "rietveld<>",
InnerXML: "<name>rietveld&lt;&gt;</name>",
@@ -134,7 +133,7 @@ var atomFeed = Feed{
Link: []Link{
{Rel: "alternate", Href: "http://codereview.appspot.com/126085"},
},
- Updated: "2009-10-04T01:35:58+00:00",
+ Updated: ParseTime("2009-10-04T01:35:58+00:00"),
Author: Person{
Name: "email-address-removed",
InnerXML: "<name>email-address-removed</name>",
@@ -181,7 +180,7 @@ the top of feeds.py marked NOTE(rsc).
Link: []Link{
{Rel: "alternate", Href: "http://codereview.appspot.com/124106"},
},
- Updated: "2009-10-03T23:02:17+00:00",
+ Updated: ParseTime("2009-10-03T23:02:17+00:00"),
Author: Person{
Name: "email-address-removed",
InnerXML: "<name>email-address-removed</name>",
diff --git a/libgo/go/encoding/xml/typeinfo.go b/libgo/go/encoding/xml/typeinfo.go
index 5475f290d18..8e2e4508b10 100644
--- a/libgo/go/encoding/xml/typeinfo.go
+++ b/libgo/go/encoding/xml/typeinfo.go
@@ -36,8 +36,7 @@ const (
fComment
fAny
- // TODO:
- //fOmitEmpty
+ fOmitEmpty
fMode = fElement | fAttr | fCharData | fInnerXml | fComment | fAny
)
@@ -133,20 +132,28 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
finfo.flags |= fComment
case "any":
finfo.flags |= fAny
+ case "omitempty":
+ finfo.flags |= fOmitEmpty
}
}
// Validate the flags used.
+ valid := true
switch mode := finfo.flags & fMode; mode {
case 0:
finfo.flags |= fElement
case fAttr, fCharData, fInnerXml, fComment, fAny:
- if f.Name != "XMLName" && (tag == "" || mode == fAttr) {
- break
+ if f.Name == "XMLName" || tag != "" && mode != fAttr {
+ valid = false
}
- fallthrough
default:
// This will also catch multiple modes in a single field.
+ valid = false
+ }
+ if finfo.flags&fOmitEmpty != 0 && finfo.flags&(fElement|fAttr) == 0 {
+ valid = false
+ }
+ if !valid {
return nil, fmt.Errorf("xml: invalid tag in field %s of type %s: %q",
f.Name, typ, f.Tag.Get("xml"))
}
OpenPOWER on IntegriCloud