-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathelement.go
More file actions
90 lines (73 loc) · 2.34 KB
/
element.go
File metadata and controls
90 lines (73 loc) · 2.34 KB
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
package libxml
// Element type declares XML tree element data to use during parse.
type Element struct {
parent *Element
tagName TagName
enter EnterFunc
data DataFunc
exit ExitFunc
structure TagElementMapping
}
// MakeElement creates new instance of Element.
func MakeElement(parent *Element, tag TagName, enter EnterFunc, data DataFunc, out ExitFunc) *Element {
return &Element{
parent: parent,
tagName: tag,
enter: enter,
data: data,
exit: out,
structure: make(TagElementMapping),
}
}
// Tag defines element using direct tag name of child or chain of children lead to target element.
func (elem *Element) Tag(names ...TagName) *Element {
firstTag := names[0]
if existed, ok := elem.structure[firstTag]; ok {
if len(names) > 1 {
return existed.Tag(names[1:]...)
}
return existed
}
newElement := MakeElement(elem, firstTag, nil, nil, nil)
elem.structure[firstTag] = newElement
if len(names) > 1 {
return newElement.Tag(names[1:]...)
}
return newElement
}
// Root returns root element of current element tree.
func (elem *Element) Root() *Element {
if elem.parent == nil {
return elem
}
return elem.parent.Root()
}
// Path returns tag names chain to arrive into current element from root.
func (elem *Element) Path() string {
prefix := ""
if elem.parent != nil {
prefix = elem.parent.Path() + "/"
}
return prefix + string(elem.tagName)
}
// Parse adds current element child specified by tag name
// as well as functions to execute when child enter, child data processing and child exit.
// Returns created child element.
func (elem *Element) Parse(tag TagName, enter EnterFunc, data DataFunc, out ExitFunc) *Element {
child := elem.Tag(tag)
child.OnData(data)
child.OnEnter(enter)
child.OnExit(out)
return child
}
// HasChild returns true if element has child with specified tag name.
func (elem Element) HasChild(tag TagName) bool {
_, ok := elem.structure[tag]
return ok
}
// OnEnter set function to execute on entering current element during parse.
func (elem *Element) OnEnter(fun EnterFunc) { elem.enter = fun }
// OnData set function to process current element data during parse.
func (elem *Element) OnData(fun DataFunc) { elem.data = fun }
// OnExit set function to execute on exiting current element during parse.
func (elem *Element) OnExit(fun ExitFunc) { elem.exit = fun }