package xml_test import ( "bytes" "log" "sort" "testing" "github.com/aws/smithy-go/encoding/xml" ) var root = xml.StartElement{Name: xml.Name{Local: "root"}} func TestEncoder(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { root := encoder.RootElement(root) defer root.Close() stringKey := xml.StartElement{Name: xml.Name{Local: "stringKey"}} integerKey := xml.StartElement{Name: xml.Name{Local: "integerKey"}} floatKey := xml.StartElement{Name: xml.Name{Local: "floatKey"}} foo := xml.StartElement{Name: xml.Name{Local: "foo"}} byteSlice := xml.StartElement{Name: xml.Name{Local: "byteSlice"}} root.MemberElement(stringKey).String("stringValue") root.MemberElement(integerKey).Integer(1024) root.MemberElement(floatKey).Float(3.14) ns := root.MemberElement(foo) defer ns.Close() ns.MemberElement(byteSlice).String("Zm9vIGJhcg==") }() e := []byte(`stringValue10243.14Zm9vIGJhcg==`) verify(t, encoder, e) } func TestEncodeAttribute(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := xml.StartElement{ Name: xml.Name{Local: "payload", Space: "baz"}, Attr: []xml.Attr{ xml.NewAttribute("attrkey", "value"), }, } obj := encoder.RootElement(r) obj.String("") }() expect := `` verify(t, encoder, []byte(expect)) } func TestEncodeNamespace(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { root := encoder.RootElement(root) defer root.Close() key := xml.StartElement{ Name: xml.Name{Local: "namespace"}, Attr: []xml.Attr{ xml.NewNamespaceAttribute("prefix", "https://example.com"), }, } n := root.MemberElement(key) defer n.Close() prefix := xml.StartElement{Name: xml.Name{Local: "user"}} n.MemberElement(prefix).String("abc") }() e := []byte(`abc`) verify(t, encoder, e) } func TestEncodeEmptyNamespacePrefix(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { root := encoder.RootElement(root) defer root.Close() key := xml.StartElement{ Name: xml.Name{Local: "namespace"}, Attr: []xml.Attr{ xml.NewNamespaceAttribute("", "https://example.com"), }, } n := root.MemberElement(key) defer n.Close() prefix := xml.StartElement{Name: xml.Name{Local: "user"}} n.MemberElement(prefix).String("abc") }() e := []byte(`abc`) verify(t, encoder, e) } func verify(t *testing.T, encoder *xml.Encoder, e []byte) { if a := encoder.Bytes(); bytes.Compare(e, a) != 0 { t.Errorf("expected %+q, but got %+q", e, a) } if a := encoder.String(); string(encoder.Bytes()) != a { t.Errorf("expected %s, but got %s", e, a) } } func TestEncodeNestedShape(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // nested `nested` shape nested := xml.StartElement{Name: xml.Name{Local: "nested"}} n1 := r.MemberElement(nested) defer n1.Close() // nested `value` shape value := xml.StartElement{Name: xml.Name{Local: "value"}} n1.MemberElement(value).String("expected value") }() e := []byte(`expected value`) defer verify(t, encoder, e) } func TestEncodeMapString(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // nested `mapStr` shape mapstr := xml.StartElement{Name: xml.Name{Local: "mapstr"}} mapElement := r.MemberElement(mapstr) defer mapElement.Close() m := mapElement.Map() key := xml.StartElement{Name: xml.Name{Local: "key"}} value := xml.StartElement{Name: xml.Name{Local: "value"}} e := m.Entry() defer e.Close() e.MemberElement(key).String("abc") e.MemberElement(value).Integer(123) }() ex := []byte(`abc123`) verify(t, encoder, ex) } func TestEncodeMapFlatten(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // nested `mapStr` shape mapstr := xml.StartElement{Name: xml.Name{Local: "mapstr"}} flatElement := r.FlattenedElement(mapstr) m := flatElement.Map() e := m.Entry() defer e.Close() key := xml.StartElement{Name: xml.Name{Local: "key"}} e.MemberElement(key).String("abc") value := xml.StartElement{Name: xml.Name{Local: "value"}} e.MemberElement(value).Integer(123) }() ex := []byte(`abc123`) verify(t, encoder, ex) } func TestEncodeMapNamed(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // nested `mapStr` shape mapstr := xml.StartElement{Name: xml.Name{Local: "mapNamed"}} mapElement := r.MemberElement(mapstr) defer mapElement.Close() m := mapElement.Map() e := m.Entry() defer e.Close() key := xml.StartElement{Name: xml.Name{Local: "namedKey"}} e.MemberElement(key).String("abc") value := xml.StartElement{Name: xml.Name{Local: "namedValue"}} e.MemberElement(value).Integer(123) }() ex := []byte(`abc123`) verify(t, encoder, ex) } func TestEncodeMapShape(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // nested `mapStr` shape mapstr := xml.StartElement{Name: xml.Name{Local: "mapShape"}} mapElement := r.MemberElement(mapstr) defer mapElement.Close() m := mapElement.Map() e := m.Entry() defer e.Close() key := xml.StartElement{Name: xml.Name{Local: "key"}} e.MemberElement(key).String("abc") value := xml.StartElement{Name: xml.Name{Local: "value"}} n1 := e.MemberElement(value) defer n1.Close() shapeVal := xml.StartElement{Name: xml.Name{Local: "shapeVal"}} n1.MemberElement(shapeVal).Integer(1) }() ex := []byte(`abc1`) verify(t, encoder, ex) } func TestEncodeMapFlattenShape(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // nested `mapStr` shape mapstr := xml.StartElement{Name: xml.Name{Local: "mapShape"}} flatElement := r.FlattenedElement(mapstr) m := flatElement.Map() e := m.Entry() defer e.Close() key := xml.StartElement{Name: xml.Name{Local: "key"}} e.MemberElement(key).String("abc") value := xml.StartElement{Name: xml.Name{Local: "value"}} n1 := e.MemberElement(value) defer n1.Close() shapeVal := xml.StartElement{Name: xml.Name{Local: "shapeVal"}} n1.MemberElement(shapeVal).Integer(1) }() ex := []byte(`abc1`) verify(t, encoder, ex) } func TestEncodeMapNamedShape(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // nested `mapStr` shape mapstr := xml.StartElement{Name: xml.Name{Local: "mapNamedShape"}} mapElement := r.MemberElement(mapstr) defer mapElement.Close() m := mapElement.Map() e := m.Entry() defer e.Close() key := xml.StartElement{Name: xml.Name{Local: "namedKey"}} e.MemberElement(key).String("abc") value := xml.StartElement{Name: xml.Name{Local: "namedValue"}} n1 := e.MemberElement(value) defer n1.Close() shapeVal := xml.StartElement{Name: xml.Name{Local: "shapeVal"}} n1.MemberElement(shapeVal).Integer(1) }() ex := []byte(`abc1`) verify(t, encoder, ex) } func TestEncodeListString(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // Object key `liststr` liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}} m := r.MemberElement(liststr) defer m.Close() a := m.Array() a.Member().String("abc") a.Member().Integer(123) }() ex := []byte(`abc123`) verify(t, encoder, ex) } func TestEncodeListFlatten(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // Object key `liststr` liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}} m := r.FlattenedElement(liststr) a := m.Array() a.Member().String("abc") a.Member().Integer(123) }() ex := []byte(`abc123`) verify(t, encoder, ex) } func TestEncodeListNamed(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // Object key `liststr` liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}} namedMember := xml.StartElement{Name: xml.Name{Local: "namedMember"}} m := r.MemberElement(liststr) defer m.Close() a := m.ArrayWithCustomName(namedMember) a.Member().String("abc") a.Member().Integer(123) }() ex := []byte(`abc123`) verify(t, encoder, ex) } // func TestEncodeListShape(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // Object key `liststr` liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}} m := r.MemberElement(liststr) defer m.Close() a := m.Array() value := xml.StartElement{Name: xml.Name{Local: "value"}} m1 := a.Member() m1.MemberElement(value).String("abc") m1.Close() m2 := a.Member() m2.MemberElement(value).Integer(123) m2.Close() }() ex := []byte(`abc123`) verify(t, encoder, ex) } // func TestEncodeListFlattenShape(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // Object key `liststr` liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}} m := r.FlattenedElement(liststr) a := m.Array() value := xml.StartElement{Name: xml.Name{Local: "value"}} m1 := a.Member() m1.MemberElement(value).String("abc") m1.Close() m2 := a.Member() m2.MemberElement(value).Integer(123) m2.Close() }() ex := []byte(`abc123`) verify(t, encoder, ex) } // func TestEncodeListNamedShape(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() // Object key `liststr` liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}} namedMember := xml.StartElement{Name: xml.Name{Local: "namedMember"}} // member element m := r.MemberElement(liststr) defer m.Close() // Build array a := m.ArrayWithCustomName(namedMember) value := xml.StartElement{Name: xml.Name{Local: "value"}} m1 := a.Member() m1.MemberElement(value).String("abc") m1.Close() m2 := a.Member() m2.MemberElement(value).Integer(123) m2.Close() }() ex := []byte(`abc123`) verify(t, encoder, ex) } func TestEncodeEscaping(t *testing.T) { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) func() { r := encoder.RootElement(root) defer r.Close() cases := map[string]rune{ "quote": '"', "apos": '\'', "amp": '&', "lt": '<', "gt": '>', "tab": '\t', "newLine": '\n', "carriageReturn": '\r', "nextLine": '\u0085', "lineSeparator": '\u2028', } var sortedKeys []string for name := range cases { sortedKeys = append(sortedKeys, name) } sort.Strings(sortedKeys) for _, name := range sortedKeys { rr := cases[name] st := xml.StartElement{Name: xml.Name{Local: name}} st.Attr = append(st.Attr, xml.Attr{ Name: xml.Name{ Local: "key", }, Value: name + string(rr) + name, }) value := r.MemberElement(st) value.String(name + string(rr) + name) } }() ex := []byte(`amp&ampapos'aposcarriageReturn carriageReturngt>gtlineSeparator
lineSeparatorlt<ltnewLine newLinenextLine…nextLinequote"quotetab tab`) verify(t, encoder, ex) } // ExampleEncoder is the example function on how to use an encoder func ExampleEncoder() { b := bytes.NewBuffer(nil) encoder := xml.NewEncoder(b) // expected encoded xml document is : // `abc123` defer log.Printf("Encoded xml document: %v", encoder.String()) r := encoder.RootElement(root) defer r.Close() // Object key `liststr` liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}} namedMember := xml.StartElement{Name: xml.Name{Local: "namedMember"}} // member element m := r.MemberElement(liststr) defer m.Close() // Build array a := m.ArrayWithCustomName(namedMember) value := xml.StartElement{Name: xml.Name{Local: "value"}} m1 := a.Member() m1.MemberElement(value).String("abc") m1.Close() m2 := a.Member() m2.MemberElement(value).Integer(123) m2.Close() }