Skip to content

Instantly share code, notes, and snippets.

@ivankravchenko
Created April 24, 2016 03:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ivankravchenko/036f68e671e33179b636bd58f6ebc9d0 to your computer and use it in GitHub Desktop.
Save ivankravchenko/036f68e671e33179b636bd58f6ebc9d0 to your computer and use it in GitHub Desktop.
diff --git a/src/pkg/encoding/xml/read.go b/src/pkg/encoding/xml/read.go
index c216824..09f0d85 100644
--- a/src/pkg/encoding/xml/read.go
+++ b/src/pkg/encoding/xml/read.go
@@ -451,6 +451,51 @@ func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []str
Loop:
for i := range tinfo.fields {
finfo := &tinfo.fields[i]
+ if finfo.flags&fAttr != 0 {
+ if len(finfo.parents) > len(parents) + 1 {
+ recurse = true
+ parents = finfo.parents[:len(parents)+1]
+ } else if len(finfo.parents) == len(parents) + 1 {
+ for _, a := range start.Attr {
+ if a.Name.Local == finfo.name {
+ v := sv.FieldByIndex(finfo.idx)
+ switch v.Kind() {
+ case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.String:
+ copyValue(v, []byte(a.Value))
+ continue Loop
+ case reflect.Slice:
+ typ := v.Type()
+ if typ.Elem().Kind() == reflect.Uint8 {
+ // []byte
+ copyValue(v, []byte(a.Value))
+ continue Loop
+ }
+
+ // Slice of element values.
+ // Grow slice.
+ n := v.Len()
+ if n >= v.Cap() {
+ ncap := 2 * n
+ if ncap < 4 {
+ ncap = 4
+ }
+ new := reflect.MakeSlice(typ, n, ncap)
+ reflect.Copy(new, v)
+ v.Set(new)
+ }
+ v.SetLen(n + 1)
+
+ // Recur to read element into slice.
+ copyValue(v.Index(n), []byte(a.Value))
+ continue Loop
+
+ default:
+ return false, errors.New("unknown type " + v.Type().String())
+ }
+ }
+ }
+ }
+ }
if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) {
continue
}
diff --git a/src/pkg/encoding/xml/xml_test.go b/src/pkg/encoding/xml/xml_test.go
index 1d0696c..f016507 100644
--- a/src/pkg/encoding/xml/xml_test.go
+++ b/src/pkg/encoding/xml/xml_test.go
@@ -576,3 +576,92 @@ func TestProcInstEncoding(t *testing.T) {
}
}
}
+
+func TestNestedAttr(t *testing.T) {
+ type NestedAttr struct {
+ Version string `xml:"version,attr"`
+ AbName string `xml:"configuration>ab>name,attr"`
+ AbVariations int `xml:"configuration>ab>variations,attr"`
+ Example string `xml:"configuration>example"`
+ }
+ var a NestedAttr
+ err := Unmarshal([]byte(`
+ <rules version="1.0.1">
+ <configuration>
+ <ab name="ab test name" variations="5"/>
+ <example>example content</example>
+ </configuration>
+ </rules>
+ `), &a)
+ expectedNestedAttr := NestedAttr{
+ Version: "1.0.1",
+ AbName: "ab test name",
+ AbVariations: 5,
+ Example: "example content",
+ }
+
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(a, expectedNestedAttr) {
+ t.Errorf("have %+v want %+v", a, expectedNestedAttr)
+ }
+}
+
+func TestNestedList(t *testing.T) {
+ type NestedList struct {
+ Example string `xml:"example"`
+ Members []int `xml:"members>member"`
+ }
+ var a NestedList
+ err := Unmarshal([]byte(`
+ <output>
+ <example>example content</example>
+ <members>
+ <member>1</member>
+ <member>13</member>
+ <member>5</member>
+ </members>
+ </output>
+ `), &a)
+ expectedNestedList := NestedList{
+ Example: "example content",
+ Members: []int{1, 13, 5},
+ }
+
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(a, expectedNestedList) {
+ t.Errorf("have %+v want %+v", a, expectedNestedList)
+ }
+}
+
+func TestNestedAttrList(t *testing.T) {
+ type NestedAttrList struct {
+ Example string `xml:"example"`
+ Members []int `xml:"members>member>id,attr"`
+ }
+ var a NestedAttrList
+ err := Unmarshal([]byte(`
+ <output>
+ <example>example content</example>
+ <members>
+ <member id="1"/>
+ <member id="13"/>
+ <member id="5"/>
+ </members>
+ </output>
+ `), &a)
+ expectedNestedAttrList := NestedAttrList{
+ Example: "example content",
+ Members: []int{1, 13, 5},
+ }
+
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(a, expectedNestedAttrList) {
+ t.Errorf("have %+v want %+v", a, expectedNestedAttrList)
+ }
+}
@inancgumus
Copy link

They should have added your pull request into the core. As I see, they didn't review it yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment