From: Chris Jones Date: Sat, 22 Dec 2012 15:00:36 +0000 (-0500) Subject: encoding/xml: Marshal ",any" fields X-Git-Tag: go1.1rc2~1563 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=a9121a19f0a2904e1b7a62d4bb07eb82093bb93a;p=gostls13.git encoding/xml: Marshal ",any" fields Fixes #3559. This makes Marshal handle fields marked ",any" instead of ignoring them. That makes Marshal more symmetrical with Unmarshal, which seems to have been a design goal. Note some test cases were changed, because this patch changes marshalling behavior. I think the previous behavior was buggy, but there's still a backward-compatibility question to consider. R=rsc CC=golang-dev, n13m3y3r https://golang.org/cl/6938068 --- diff --git a/src/pkg/encoding/xml/marshal.go b/src/pkg/encoding/xml/marshal.go index 17134c5eb4..8b2f4173f3 100644 --- a/src/pkg/encoding/xml/marshal.go +++ b/src/pkg/encoding/xml/marshal.go @@ -273,7 +273,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error { s := parentStack{printer: p} for i := range tinfo.fields { finfo := &tinfo.fields[i] - if finfo.flags&(fAttr|fAny) != 0 { + if finfo.flags&(fAttr) != 0 { continue } vf := finfo.value(val) @@ -340,7 +340,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error { continue } - case fElement: + case fElement, fElement | fAny: s.trim(finfo.parents) if len(finfo.parents) > len(s.stack) { if vf.Kind() != reflect.Ptr && vf.Kind() != reflect.Interface || !vf.IsNil() { diff --git a/src/pkg/encoding/xml/marshal_test.go b/src/pkg/encoding/xml/marshal_test.go index 668fea6f85..2ce7721abd 100644 --- a/src/pkg/encoding/xml/marshal_test.go +++ b/src/pkg/encoding/xml/marshal_test.go @@ -188,6 +188,18 @@ type AnyTest struct { AnyField AnyHolder `xml:",any"` } +type AnyOmitTest struct { + XMLName struct{} `xml:"a"` + Nested string `xml:"nested>value"` + AnyField *AnyHolder `xml:",any,omitempty"` +} + +type AnySliceTest struct { + XMLName struct{} `xml:"a"` + Nested string `xml:"nested>value"` + AnyField []AnyHolder `xml:",any"` +} + type AnyHolder struct { XMLName Name XML string `xml:",innerxml"` @@ -652,12 +664,43 @@ var marshalTests = []struct { XML: "unknown", }, }, - UnmarshalOnly: true, }, { - Value: &AnyTest{Nested: "known", AnyField: AnyHolder{XML: ""}}, - ExpectXML: `known`, - MarshalOnly: true, + Value: &AnyTest{Nested: "known", + AnyField: AnyHolder{ + XML: "", + XMLName: Name{Local: "AnyField"}, + }, + }, + ExpectXML: `known`, + }, + { + ExpectXML: `b`, + Value: &AnyOmitTest{ + Nested: "b", + }, + }, + { + ExpectXML: `bei`, + Value: &AnySliceTest{ + Nested: "b", + AnyField: []AnyHolder{ + { + XMLName: Name{Local: "c"}, + XML: "e", + }, + { + XMLName: Name{Space: "f", Local: "g"}, + XML: "i", + }, + }, + }, + }, + { + ExpectXML: `b`, + Value: &AnySliceTest{ + Nested: "b", + }, }, // Test recursive types. @@ -690,15 +733,17 @@ var marshalTests = []struct { // Test escaping. { - ExpectXML: `dquote: "; squote: '; ampersand: &; less: <; greater: >;`, + ExpectXML: `dquote: "; squote: '; ampersand: &; less: <; greater: >;`, Value: &AnyTest{ - Nested: `dquote: "; squote: '; ampersand: &; less: <; greater: >;`, + Nested: `dquote: "; squote: '; ampersand: &; less: <; greater: >;`, + AnyField: AnyHolder{XMLName: Name{Local: "empty"}}, }, }, { - ExpectXML: `newline: ; cr: ; tab: ;`, + ExpectXML: `newline: ; cr: ; tab: ;`, Value: &AnyTest{ - Nested: "newline: \n; cr: \r; tab: \t;", + Nested: "newline: \n; cr: \r; tab: \t;", + AnyField: AnyHolder{XMLName: Name{Local: "AnyField"}}, }, }, { diff --git a/src/pkg/encoding/xml/read.go b/src/pkg/encoding/xml/read.go index 0e6761d66a..7a06a29b95 100644 --- a/src/pkg/encoding/xml/read.go +++ b/src/pkg/encoding/xml/read.go @@ -279,7 +279,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error { saveComment = finfo.value(sv) } - case fAny: + case fAny, fAny | fElement: if !saveAny.IsValid() { saveAny = finfo.value(sv) } diff --git a/src/pkg/encoding/xml/typeinfo.go b/src/pkg/encoding/xml/typeinfo.go index 970d170193..bbeb28d87e 100644 --- a/src/pkg/encoding/xml/typeinfo.go +++ b/src/pkg/encoding/xml/typeinfo.go @@ -154,6 +154,9 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro // This will also catch multiple modes in a single field. valid = false } + if finfo.flags&fMode == fAny { + finfo.flags |= fElement + } if finfo.flags&fOmitEmpty != 0 && finfo.flags&(fElement|fAttr) == 0 { valid = false }