-
Notifications
You must be signed in to change notification settings - Fork 14
/
parser_xml.go
130 lines (109 loc) · 2.2 KB
/
parser_xml.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package gobatis
import (
"encoding/xml"
"io"
"strings"
)
type ElemType string
const (
eleTpText ElemType = "text" // 静态文本节点
eleTpNode ElemType = "node" // 节点子节点
)
type node struct {
Id string
Namespace string
Name string
Attrs map[string]xml.Attr
Elements []element
}
func (n *node) getAttr(attr string) string {
res := ""
at, ok := n.Attrs[attr]
if ok {
res = at.Value
}
return res
}
type element struct {
ElementType ElemType
Val interface{}
}
func parse(r io.Reader) *node {
parser := xml.NewDecoder(r)
var root node
namespace := ""
st := NewStack()
for {
token, err := parser.Token()
if err != nil {
break
}
switch t := token.(type) {
case xml.StartElement: //tag start
elmt := xml.StartElement(t)
name := elmt.Name.Local
attr := elmt.Attr
attrMap := make(map[string]xml.Attr)
for _, val := range attr {
attrMap[val.Name.Local] = val
}
node := node{
Name: name,
Attrs: attrMap,
Elements: make([]element, 0),
}
id := node.getAttr("id")
node.Id = id
if namespace == "" {
namespace = node.getAttr("namespace")
}
st.Push(node)
case xml.EndElement: //tag end
if st.Len() > 0 {
//cur node
n := st.Pop().(node)
// set namespace
if namespace != "" {
n.Namespace = namespace + "."
}
if st.Len() > 0 { //if the root node then append to element
e := element{
ElementType: eleTpNode,
Val: n,
}
pn := st.Pop().(node)
els := pn.Elements
els = append(els, e)
pn.Elements = els
st.Push(pn)
} else { //else root = n
root = n
}
}
case xml.CharData: //tag content
if st.Len() > 0 {
n := st.Pop().(node)
bytes := xml.CharData(t)
content := strings.TrimSpace(string(bytes))
if content != "" {
e := element{
ElementType: eleTpText,
Val: content,
}
els := n.Elements
els = append(els, e)
n.Elements = els
}
st.Push(n)
}
case xml.Comment:
case xml.ProcInst:
case xml.Directive:
default:
}
}
if st.Len() != 0 {
panic("Parse xml error, there is tag no close, please check your xml config!")
}
return &root
}