github.com/go-spring/spring-base@v1.1.3/log/log_reader.go (about)

     1  /*
     2   * Copyright 2012-2019 the original author or authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *      https://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package log
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/xml"
    22  	"errors"
    23  	"io"
    24  )
    25  
    26  var (
    27  	readers = map[string]Reader{}
    28  )
    29  
    30  func init() {
    31  	RegisterReader(new(XMLReader), ".xml")
    32  }
    33  
    34  type Node struct {
    35  	Label      string
    36  	Children   []*Node
    37  	Attributes map[string]string
    38  }
    39  
    40  func (node *Node) child(label string) *Node {
    41  	for _, c := range node.Children {
    42  		if c.Label == label {
    43  			return c
    44  		}
    45  	}
    46  	return nil
    47  }
    48  
    49  // Reader 配置项解析器。
    50  type Reader interface {
    51  	Read(b []byte) (*Node, error)
    52  }
    53  
    54  // RegisterReader 注册配置项解析器。
    55  func RegisterReader(r Reader, ext ...string) {
    56  	for _, s := range ext {
    57  		readers[s] = r
    58  	}
    59  }
    60  
    61  type XMLReader struct{}
    62  
    63  func (r *XMLReader) Read(b []byte) (*Node, error) {
    64  	stack := []*Node{{Label: "<<STACK>>"}}
    65  	d := xml.NewDecoder(bytes.NewReader(b))
    66  	for {
    67  		token, err := d.Token()
    68  		if err == io.EOF {
    69  			break
    70  		}
    71  		if err != nil {
    72  			return nil, err
    73  		}
    74  		switch t := token.(type) {
    75  		case xml.StartElement:
    76  			curr := &Node{
    77  				Label:      t.Name.Local,
    78  				Attributes: make(map[string]string),
    79  			}
    80  			for _, attr := range t.Attr {
    81  				curr.Attributes[attr.Name.Local] = attr.Value
    82  			}
    83  			stack = append(stack, curr)
    84  		case xml.EndElement:
    85  			curr := stack[len(stack)-1]
    86  			parent := stack[len(stack)-2]
    87  			parent.Children = append(parent.Children, curr)
    88  			stack = stack[:len(stack)-1]
    89  		}
    90  	}
    91  	if len(stack[0].Children) == 0 {
    92  		return nil, errors.New("error xml config file")
    93  	}
    94  	return stack[0].Children[0], nil
    95  }