diff --git a/pkg/infrastructure/config/xml/xml.go b/pkg/infrastructure/config/xml/xml.go index e3e93b01..e5096b9b 100644 --- a/pkg/infrastructure/config/xml/xml.go +++ b/pkg/infrastructure/config/xml/xml.go @@ -26,7 +26,7 @@ // // cnf, err := config.NewConfig("xml", "config.xml") // -//More docs http://beego.me/docs/module/config.md +// More docs http://beego.me/docs/module/config.md package xml import ( @@ -40,7 +40,11 @@ import ( "strings" "sync" + "github.com/mitchellh/mapstructure" + "github.com/astaxie/beego/pkg/infrastructure/config" + "github.com/astaxie/beego/pkg/infrastructure/logs" + "github.com/beego/x2j" ) @@ -75,11 +79,53 @@ func (xc *Config) ParseData(data []byte) (config.Configer, error) { // ConfigContainer is a Config which represents the xml configuration. type ConfigContainer struct { - config.BaseConfiger data map[string]interface{} sync.Mutex } +// Unmarshaler is a little be inconvenient since the xml library doesn't know type. +// So when you use +// 1 +// The "1" is a string, not int +func (c *ConfigContainer) Unmarshaler(ctx context.Context, prefix string, obj interface{}, opt ...config.DecodeOption) error { + sub, err := c.sub(ctx, prefix) + if err != nil { + return err + } + return mapstructure.Decode(sub, obj) +} + +func (c *ConfigContainer) Sub(ctx context.Context, key string) (config.Configer, error) { + sub, err := c.sub(ctx, key) + if err != nil { + return nil, err + } + + return &ConfigContainer{ + data: sub, + }, nil + +} + +func (c *ConfigContainer) sub(ctx context.Context, key string) (map[string]interface{}, error) { + if key == "" { + return c.data, nil + } + value, ok := c.data[key] + if !ok { + return nil, errors.New(fmt.Sprintf("the key is not found: %s", key)) + } + res, ok := value.(map[string]interface{}) + if !ok { + return nil, errors.New(fmt.Sprintf("the value of this key is not a structure: %s", key)) + } + return res, nil +} + +func (c *ConfigContainer) OnChange(ctx context.Context, key string, fn func(value string)) { + logs.Warn("Unsupported operation") +} + // Bool returns the boolean value for a given key. func (c *ConfigContainer) Bool(ctx context.Context, key string) (bool, error) { if v := c.data[key]; v != nil { @@ -155,7 +201,7 @@ func (c *ConfigContainer) String(ctx context.Context, key string) (string, error // DefaultString returns the string value for a given key. // if err != nil return defaultVal func (c *ConfigContainer) DefaultString(ctx context.Context, key string, defaultVal string) string { - v, err := c.String(nil, key) + v, err := c.String(ctx, key) if v == "" || err != nil { return defaultVal } diff --git a/pkg/infrastructure/config/xml/xml_test.go b/pkg/infrastructure/config/xml/xml_test.go index 470280e0..0a3eb313 100644 --- a/pkg/infrastructure/config/xml/xml_test.go +++ b/pkg/infrastructure/config/xml/xml_test.go @@ -15,10 +15,13 @@ package xml import ( + "context" "fmt" "os" "testing" + "github.com/stretchr/testify/assert" + "github.com/astaxie/beego/pkg/infrastructure/config" ) @@ -120,8 +123,36 @@ func TestXML(t *testing.T) { t.Fatal(err) } - res, _ := xmlconf.String(nil, "name") + res, _ := xmlconf.String(context.Background(), "name") if res != "astaxie" { t.Fatal("get name error") } + + sub, err := xmlconf.Sub(context.Background(), "mysection") + assert.Nil(t, err) + assert.NotNil(t, sub) + name, err := sub.String(context.Background(), "name") + assert.Nil(t, err) + assert.Equal(t, "MySection", name) + + id, err := sub.Int(context.Background(), "id") + assert.Nil(t, err) + assert.Equal(t, 1, id) + + sec := &Section{} + + err = sub.Unmarshaler(context.Background(), "", sec) + assert.Nil(t, err) + assert.Equal(t, "MySection", sec.Name) + + sec = &Section{} + + err = xmlconf.Unmarshaler(context.Background(), "mysection", sec) + assert.Nil(t, err) + assert.Equal(t, "MySection", sec.Name) + +} + +type Section struct { + Name string `xml:"name"` }