1// Copyright 2014 beego Author. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// Package xml for config provider. 16// 17// depend on github.com/beego/x2j. 18// 19// go install github.com/beego/x2j. 20// 21// Usage: 22// import( 23// _ "github.com/astaxie/beego/config/xml" 24// "github.com/astaxie/beego/config" 25// ) 26// 27// cnf, err := config.NewConfig("xml", "config.xml") 28// 29//More docs http://beego.me/docs/module/config.md 30package xml 31 32import ( 33 "encoding/xml" 34 "errors" 35 "fmt" 36 "io/ioutil" 37 "os" 38 "strconv" 39 "strings" 40 "sync" 41 42 "github.com/astaxie/beego/config" 43 "github.com/beego/x2j" 44) 45 46// Config is a xml config parser and implements Config interface. 47// xml configurations should be included in <config></config> tag. 48// only support key/value pair as <key>value</key> as each item. 49type Config struct{} 50 51// Parse returns a ConfigContainer with parsed xml config map. 52func (xc *Config) Parse(filename string) (config.Configer, error) { 53 context, err := ioutil.ReadFile(filename) 54 if err != nil { 55 return nil, err 56 } 57 58 return xc.ParseData(context) 59} 60 61// ParseData xml data 62func (xc *Config) ParseData(data []byte) (config.Configer, error) { 63 x := &ConfigContainer{data: make(map[string]interface{})} 64 65 d, err := x2j.DocToMap(string(data)) 66 if err != nil { 67 return nil, err 68 } 69 70 x.data = config.ExpandValueEnvForMap(d["config"].(map[string]interface{})) 71 72 return x, nil 73} 74 75// ConfigContainer A Config represents the xml configuration. 76type ConfigContainer struct { 77 data map[string]interface{} 78 sync.Mutex 79} 80 81// Bool returns the boolean value for a given key. 82func (c *ConfigContainer) Bool(key string) (bool, error) { 83 if v := c.data[key]; v != nil { 84 return config.ParseBool(v) 85 } 86 return false, fmt.Errorf("not exist key: %q", key) 87} 88 89// DefaultBool return the bool value if has no error 90// otherwise return the defaultval 91func (c *ConfigContainer) DefaultBool(key string, defaultval bool) bool { 92 v, err := c.Bool(key) 93 if err != nil { 94 return defaultval 95 } 96 return v 97} 98 99// Int returns the integer value for a given key. 100func (c *ConfigContainer) Int(key string) (int, error) { 101 return strconv.Atoi(c.data[key].(string)) 102} 103 104// DefaultInt returns the integer value for a given key. 105// if err != nil return defaultval 106func (c *ConfigContainer) DefaultInt(key string, defaultval int) int { 107 v, err := c.Int(key) 108 if err != nil { 109 return defaultval 110 } 111 return v 112} 113 114// Int64 returns the int64 value for a given key. 115func (c *ConfigContainer) Int64(key string) (int64, error) { 116 return strconv.ParseInt(c.data[key].(string), 10, 64) 117} 118 119// DefaultInt64 returns the int64 value for a given key. 120// if err != nil return defaultval 121func (c *ConfigContainer) DefaultInt64(key string, defaultval int64) int64 { 122 v, err := c.Int64(key) 123 if err != nil { 124 return defaultval 125 } 126 return v 127 128} 129 130// Float returns the float value for a given key. 131func (c *ConfigContainer) Float(key string) (float64, error) { 132 return strconv.ParseFloat(c.data[key].(string), 64) 133} 134 135// DefaultFloat returns the float64 value for a given key. 136// if err != nil return defaultval 137func (c *ConfigContainer) DefaultFloat(key string, defaultval float64) float64 { 138 v, err := c.Float(key) 139 if err != nil { 140 return defaultval 141 } 142 return v 143} 144 145// String returns the string value for a given key. 146func (c *ConfigContainer) String(key string) string { 147 if v, ok := c.data[key].(string); ok { 148 return v 149 } 150 return "" 151} 152 153// DefaultString returns the string value for a given key. 154// if err != nil return defaultval 155func (c *ConfigContainer) DefaultString(key string, defaultval string) string { 156 v := c.String(key) 157 if v == "" { 158 return defaultval 159 } 160 return v 161} 162 163// Strings returns the []string value for a given key. 164func (c *ConfigContainer) Strings(key string) []string { 165 v := c.String(key) 166 if v == "" { 167 return nil 168 } 169 return strings.Split(v, ";") 170} 171 172// DefaultStrings returns the []string value for a given key. 173// if err != nil return defaultval 174func (c *ConfigContainer) DefaultStrings(key string, defaultval []string) []string { 175 v := c.Strings(key) 176 if v == nil { 177 return defaultval 178 } 179 return v 180} 181 182// GetSection returns map for the given section 183func (c *ConfigContainer) GetSection(section string) (map[string]string, error) { 184 if v, ok := c.data[section].(map[string]interface{}); ok { 185 mapstr := make(map[string]string) 186 for k, val := range v { 187 mapstr[k] = config.ToString(val) 188 } 189 return mapstr, nil 190 } 191 return nil, fmt.Errorf("section '%s' not found", section) 192} 193 194// SaveConfigFile save the config into file 195func (c *ConfigContainer) SaveConfigFile(filename string) (err error) { 196 // Write configuration file by filename. 197 f, err := os.Create(filename) 198 if err != nil { 199 return err 200 } 201 defer f.Close() 202 b, err := xml.MarshalIndent(c.data, " ", " ") 203 if err != nil { 204 return err 205 } 206 _, err = f.Write(b) 207 return err 208} 209 210// Set writes a new value for key. 211func (c *ConfigContainer) Set(key, val string) error { 212 c.Lock() 213 defer c.Unlock() 214 c.data[key] = val 215 return nil 216} 217 218// DIY returns the raw value by a given key. 219func (c *ConfigContainer) DIY(key string) (v interface{}, err error) { 220 if v, ok := c.data[key]; ok { 221 return v, nil 222 } 223 return nil, errors.New("not exist key") 224} 225 226func init() { 227 config.Register("xml", &Config{}) 228} 229