1// Copyright (c) 2012 - Cloud Instruments Co., Ltd. 2// 3// All rights reserved. 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are met: 7// 8// 1. Redistributions of source code must retain the above copyright notice, this 9// list of conditions and the following disclaimer. 10// 2. Redistributions in binary form must reproduce the above copyright notice, 11// this list of conditions and the following disclaimer in the documentation 12// and/or other materials provided with the distribution. 13// 14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 25package seelog 26 27import ( 28 "encoding/xml" 29 "errors" 30 "fmt" 31 "io" 32 "strings" 33) 34 35type xmlNode struct { 36 name string 37 attributes map[string]string 38 children []*xmlNode 39 value string 40} 41 42func newNode() *xmlNode { 43 node := new(xmlNode) 44 node.children = make([]*xmlNode, 0) 45 node.attributes = make(map[string]string) 46 return node 47} 48 49func (node *xmlNode) String() string { 50 str := fmt.Sprintf("<%s", node.name) 51 52 for attrName, attrVal := range node.attributes { 53 str += fmt.Sprintf(" %s=\"%s\"", attrName, attrVal) 54 } 55 56 str += ">" 57 str += node.value 58 59 if len(node.children) != 0 { 60 for _, child := range node.children { 61 str += fmt.Sprintf("%s", child) 62 } 63 } 64 65 str += fmt.Sprintf("</%s>", node.name) 66 67 return str 68} 69 70func (node *xmlNode) unmarshal(startEl xml.StartElement) error { 71 node.name = startEl.Name.Local 72 73 for _, v := range startEl.Attr { 74 _, alreadyExists := node.attributes[v.Name.Local] 75 if alreadyExists { 76 return errors.New("tag '" + node.name + "' has duplicated attribute: '" + v.Name.Local + "'") 77 } 78 node.attributes[v.Name.Local] = v.Value 79 } 80 81 return nil 82} 83 84func (node *xmlNode) add(child *xmlNode) { 85 if node.children == nil { 86 node.children = make([]*xmlNode, 0) 87 } 88 89 node.children = append(node.children, child) 90} 91 92func (node *xmlNode) hasChildren() bool { 93 return node.children != nil && len(node.children) > 0 94} 95 96//============================================= 97 98func unmarshalConfig(reader io.Reader) (*xmlNode, error) { 99 xmlParser := xml.NewDecoder(reader) 100 101 config, err := unmarshalNode(xmlParser, nil) 102 if err != nil { 103 return nil, err 104 } 105 if config == nil { 106 return nil, errors.New("xml has no content") 107 } 108 109 nextConfigEntry, err := unmarshalNode(xmlParser, nil) 110 if nextConfigEntry != nil { 111 return nil, errors.New("xml contains more than one root element") 112 } 113 114 return config, nil 115} 116 117func unmarshalNode(xmlParser *xml.Decoder, curToken xml.Token) (node *xmlNode, err error) { 118 firstLoop := true 119 for { 120 var tok xml.Token 121 if firstLoop && curToken != nil { 122 tok = curToken 123 firstLoop = false 124 } else { 125 tok, err = getNextToken(xmlParser) 126 if err != nil || tok == nil { 127 return 128 } 129 } 130 131 switch tt := tok.(type) { 132 case xml.SyntaxError: 133 err = errors.New(tt.Error()) 134 return 135 case xml.CharData: 136 value := strings.TrimSpace(string([]byte(tt))) 137 if node != nil { 138 node.value += value 139 } 140 case xml.StartElement: 141 if node == nil { 142 node = newNode() 143 err := node.unmarshal(tt) 144 if err != nil { 145 return nil, err 146 } 147 } else { 148 childNode, childErr := unmarshalNode(xmlParser, tok) 149 if childErr != nil { 150 return nil, childErr 151 } 152 153 if childNode != nil { 154 node.add(childNode) 155 } else { 156 return 157 } 158 } 159 case xml.EndElement: 160 return 161 } 162 } 163} 164 165func getNextToken(xmlParser *xml.Decoder) (tok xml.Token, err error) { 166 if tok, err = xmlParser.Token(); err != nil { 167 if err == io.EOF { 168 err = nil 169 return 170 } 171 return 172 } 173 174 return 175} 176