mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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
This commit is contained in:
parent
9622f5032e
commit
a9121a19f0
4 changed files with 59 additions and 11 deletions
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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: "<sub>unknown</sub>",
|
||||
},
|
||||
},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
Value: &AnyTest{Nested: "known", AnyField: AnyHolder{XML: "<unknown/>"}},
|
||||
ExpectXML: `<a><nested><value>known</value></nested></a>`,
|
||||
MarshalOnly: true,
|
||||
Value: &AnyTest{Nested: "known",
|
||||
AnyField: AnyHolder{
|
||||
XML: "<unknown/>",
|
||||
XMLName: Name{Local: "AnyField"},
|
||||
},
|
||||
},
|
||||
ExpectXML: `<a><nested><value>known</value></nested><AnyField><unknown/></AnyField></a>`,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<a><nested><value>b</value></nested></a>`,
|
||||
Value: &AnyOmitTest{
|
||||
Nested: "b",
|
||||
},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<a><nested><value>b</value></nested><c><d>e</d></c><g xmlns="f"><h>i</h></g></a>`,
|
||||
Value: &AnySliceTest{
|
||||
Nested: "b",
|
||||
AnyField: []AnyHolder{
|
||||
{
|
||||
XMLName: Name{Local: "c"},
|
||||
XML: "<d>e</d>",
|
||||
},
|
||||
{
|
||||
XMLName: Name{Space: "f", Local: "g"},
|
||||
XML: "<h>i</h>",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<a><nested><value>b</value></nested></a>`,
|
||||
Value: &AnySliceTest{
|
||||
Nested: "b",
|
||||
},
|
||||
},
|
||||
|
||||
// Test recursive types.
|
||||
|
|
@ -690,15 +733,17 @@ var marshalTests = []struct {
|
|||
|
||||
// Test escaping.
|
||||
{
|
||||
ExpectXML: `<a><nested><value>dquote: "; squote: '; ampersand: &; less: <; greater: >;</value></nested></a>`,
|
||||
ExpectXML: `<a><nested><value>dquote: "; squote: '; ampersand: &; less: <; greater: >;</value></nested><empty></empty></a>`,
|
||||
Value: &AnyTest{
|
||||
Nested: `dquote: "; squote: '; ampersand: &; less: <; greater: >;`,
|
||||
Nested: `dquote: "; squote: '; ampersand: &; less: <; greater: >;`,
|
||||
AnyField: AnyHolder{XMLName: Name{Local: "empty"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<a><nested><value>newline: 
; cr: 
; tab: 	;</value></nested></a>`,
|
||||
ExpectXML: `<a><nested><value>newline: 
; cr: 
; tab: 	;</value></nested><AnyField></AnyField></a>`,
|
||||
Value: &AnyTest{
|
||||
Nested: "newline: \n; cr: \r; tab: \t;",
|
||||
Nested: "newline: \n; cr: \r; tab: \t;",
|
||||
AnyField: AnyHolder{XMLName: Name{Local: "AnyField"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue