]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/xml: Marshal ",any" fields
authorChris Jones <chris@cjones.org>
Sat, 22 Dec 2012 15:00:36 +0000 (10:00 -0500)
committerRuss Cox <rsc@golang.org>
Sat, 22 Dec 2012 15:00:36 +0000 (10:00 -0500)
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

src/pkg/encoding/xml/marshal.go
src/pkg/encoding/xml/marshal_test.go
src/pkg/encoding/xml/read.go
src/pkg/encoding/xml/typeinfo.go

index 17134c5eb4d75f73e6591d43e1a3154588b2e85f..8b2f4173f3a2b1b9885fe50d3d72a0e33e8481a5 100644 (file)
@@ -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() {
index 668fea6f85e5e5877aa270755e68858cf376ca7b..2ce7721abd106af09b367fb0464fe9acb7a90fc9 100644 (file)
@@ -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: &#34;; squote: &#39;; ampersand: &amp;; less: &lt;; greater: &gt;;</value></nested></a>`,
+               ExpectXML: `<a><nested><value>dquote: &#34;; squote: &#39;; ampersand: &amp;; less: &lt;; greater: &gt;;</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: &#xA;; cr: &#xD;; tab: &#x9;;</value></nested></a>`,
+               ExpectXML: `<a><nested><value>newline: &#xA;; cr: &#xD;; tab: &#x9;;</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"}},
                },
        },
        {
index 0e6761d66adac7916ea3b7be8fff331142c1c0f6..7a06a29b95af94b2e4af4a6cb57fbeb247a32d31 100644 (file)
@@ -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)
                                }
index 970d1701932d4a1eea02cf35ddefb914eb413a7c..bbeb28d87eaa35239687fa8a170332606614b519 100644 (file)
@@ -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
                }