-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathquerying.go
More file actions
148 lines (128 loc) · 4.08 KB
/
querying.go
File metadata and controls
148 lines (128 loc) · 4.08 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
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package GoHtml
import (
"iter"
"strings"
)
// GetElementByTagName returns the first node that match with the given tagName by advancing from the node.
func (node *Node) GetElementByTagName(tagName string) *Node {
tagName = strings.ToLower(strings.TrimSpace(tagName))
traverser := NewTraverser(node)
var returnNode *Node
traverser.Walkthrough(func(node *Node) TraverseCondition {
if node.GetTagName() == tagName {
returnNode = node
return StopWalkthrough
}
return ContinueWalkthrough
})
return returnNode
}
// GetElementByClassName returns the first node that match with the given className by advancing from the node.
func (node *Node) GetElementByClassName(className string) *Node {
traverser := NewTraverser(node)
var returnNode *Node
traverser.Walkthrough(func(node *Node) TraverseCondition {
classList := NewClassList()
classList.DecodeFrom(node)
if classList.Contains(className) {
returnNode = node
return StopWalkthrough
}
return ContinueWalkthrough
})
return returnNode
}
// GetElementByID returns the first node that match with the given idName by advancing from the node.
func (node *Node) GetElementByID(idName string) *Node {
traverser := NewTraverser(node)
var returnNode *Node
traverser.Walkthrough(func(node *Node) TraverseCondition {
id, _ := node.GetAttribute("id")
if id == idName {
returnNode = node
return StopWalkthrough
}
return ContinueWalkthrough
})
return returnNode
}
// GetElementsByClassName returns a NodeList containing nodes that have the given className from the node.
func (node *Node) GetElementsByClassName(className string) NodeList {
traverser := NewTraverser(node)
nodeList := NewNodeList()
traverser.Walkthrough(func(node *Node) TraverseCondition {
classList := NewClassList()
classList.DecodeFrom(node)
if classList.Contains(className) {
nodeList.Append(node)
}
return ContinueWalkthrough
})
return nodeList
}
// GetElementsByTagName returns a NodeList containing nodes that have the given tagName from the node.
func (node *Node) GetElementsByTagName(tagName string) NodeList {
traverser := NewTraverser(node)
nodeList := NewNodeList()
traverser.Walkthrough(func(node *Node) TraverseCondition {
if node.GetTagName() == tagName {
nodeList.Append(node)
}
return ContinueWalkthrough
})
return nodeList
}
// GetElementsByClassName returns a NodeList containing nodes that have the given idName from the node.
func (node *Node) GetElementsById(idName string) NodeList {
traverser := NewTraverser(node)
nodeList := NewNodeList()
traverser.Walkthrough(func(node *Node) TraverseCondition {
id, _ := node.GetAttribute("id")
if id == idName {
nodeList.Append(node)
}
return ContinueWalkthrough
})
return nodeList
}
/*
QuerySearch search returns a iterator that traverse through the node tree from given node and passes nodes that matches the given selector.
*/
func QuerySearch(node *Node, selector string) iter.Seq[*Node] {
traverser := NewTraverser(node)
return func(yield func(node *Node) bool) {
selectorTokens := TokenizeSelectorsAndCombinators(selector)
for node := range traverser.Walkthrough {
if matchFromRightMostSelectors(node, selectorTokens) && !yield(node) {
return
}
}
}
}
// matchFromRightMostQueryToken tries to match query tokens from right to left and return the index at which point query token last matched.
func matchFromRightMostSelectors(node *Node, selectorTokens []CombinatorEl) bool {
for i := len(selectorTokens) - 1; i >= 0; i-- {
if node == nil {
break
}
node = selectorTokens[i].getMatchingNode(node)
}
return node != nil
}
// QuerySelector returns the first node that matches with the selector from the node.
func (node *Node) QuerySelector(selector string) *Node {
iter := QuerySearch(node, selector)
for node := range iter {
return node
}
return nil
}
// QuerySelectorAll returns a NodeList that has node that matches the selector form the node.
func (node *Node) QuerySelectorAll(selector string) NodeList {
iter := QuerySearch(node, selector)
nodeList := NewNodeList()
for node := range iter {
nodeList.Append(node)
}
return nodeList
}