package main import ( "bufio" "bytes" "io" "os" "unicode" ) const ( stat_none = iota stat_group stat_key stat_value stat_comment ) type Attr struct { Name string Value string Comment string next *Attr } type Element struct { Element string Attr *Attr next *Element } type Decoder struct { state int b byte t bytes.Buffer r io.ByteReader err error m *Element n string } func (d *Decoder) getAttr(m *Element, e string) string { for n := m.Attr; nil != n; n = n.next { if e == n.Name { return n.Value } } return "" } func (d *Decoder) GetElement(e string, a string) string { for n := d.m; nil != n; n = n.next { if e == n.Element { return d.getAttr(n, a) } } return "" } func (d *Decoder) newAttrNextComment(value string) { d.m.Attr.Comment = value println(value) } func (d *Decoder) newAttrNext(name string, value string) { attr := new(Attr) attr.Name = name attr.Value = value if nil == d.m.Attr { attr.next = nil } else { attr.next = d.m.Attr } d.m.Attr = attr } func (d *Decoder) newElement(name string) { element := new(Element) element.Element = name element.Attr = nil if nil == d.m { element.next = nil } else { element.next = d.m } d.m = element } func (d *Decoder) switchToMap() { for { d.b, d.err = d.r.ReadByte() if d.err != nil { break } switch d.state { case stat_none: if d.b == '[' { d.state = stat_group } else if d.b == ';' { d.state = stat_comment } else if !unicode.IsSpace(rune(d.b)) { d.state = stat_key d.t.WriteByte(byte(d.b)) } break case stat_group: if d.b == ']' { d.state = stat_none d.newElement(d.t.String()) d.t.Reset() } else if !unicode.IsSpace(rune(d.b)) { d.t.WriteByte(byte(d.b)) } break case stat_key: if d.b == '=' { d.state = stat_value d.n = d.t.String() d.t.Reset() } else if !unicode.IsSpace(rune(d.b)) { d.t.WriteByte(byte(d.b)) } break case stat_value: if !unicode.IsSpace(rune(d.b)) { d.t.WriteByte(byte(d.b)) } else { d.state = stat_none d.newAttrNext(d.n, d.t.String()) d.t.Reset() } break case stat_comment: if !unicode.IsSpace(rune(d.b)) { d.t.WriteByte(byte(d.b)) } else { d.state = stat_none d.newAttrNextComment(d.t.String()) d.t.Reset() } break default: d.state = stat_none break } } } func (d *Decoder) switchToReader(r io.Reader) { if rb, ok := r.(io.ByteReader); ok { d.r = rb } else { d.r = bufio.NewReader(r) } d.switchToMap() } func NewDecoder(r io.Reader) *Decoder { d := &Decoder{} d.switchToReader(r) return d } func main() { xmlFile, err := os.Open("hh.ini") if nil != err { return } defer xmlFile.Close() d := NewDecoder(xmlFile) println(d.GetElement("aaaa", "ac")) }
有疑问加站长微信联系(非本文作者)
![](https://static.golangjob.cn/static/img/footer.png?imageView2/2/w/280)