-
Notifications
You must be signed in to change notification settings - Fork 63
/
var_xpath.go
62 lines (53 loc) · 1.25 KB
/
var_xpath.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
package postprocessor
import (
"io"
"net/http"
"github.com/antchfx/htmlquery"
"github.com/antchfx/xpath"
"golang.org/x/net/html"
)
type VarXpathPostprocessor struct {
Mapping map[string]string
}
func (p *VarXpathPostprocessor) ReturnedParams() []string {
result := make([]string, len(p.Mapping))
for k := range p.Mapping {
result = append(result, k)
}
return result
}
func (p *VarXpathPostprocessor) Process(_ *http.Response, body io.Reader) (map[string]any, error) {
if len(p.Mapping) == 0 {
return nil, nil
}
doc, err := html.Parse(body)
if err != nil {
return nil, err
}
result := make(map[string]any, len(p.Mapping))
for k, path := range p.Mapping {
values, err := p.getValuesFromDOM(doc, path)
if err != nil {
return nil, err
}
if len(values) == 1 {
result[k] = values[0]
} else {
result[k] = values
}
}
return result, nil
}
func (p *VarXpathPostprocessor) getValuesFromDOM(doc *html.Node, xpathQuery string) ([]string, error) {
expr, err := xpath.Compile(xpathQuery)
if err != nil {
return nil, err
}
iter := expr.Evaluate(htmlquery.CreateXPathNavigator(doc)).(*xpath.NodeIterator)
var values []string
for iter.MoveNext() {
node := iter.Current()
values = append(values, node.Value())
}
return values, nil
}