forked from gocolly/colly
-
Notifications
You must be signed in to change notification settings - Fork 0
/
xmlelement.go
131 lines (121 loc) · 3.34 KB
/
xmlelement.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
131
package colly
import (
"encoding/xml"
"strings"
"github.com/antchfx/htmlquery"
"github.com/antchfx/xmlquery"
"golang.org/x/net/html"
)
// XMLElement is the representation of a XML tag.
type XMLElement struct {
// Name is the name of the tag
Name string
Text string
attributes interface{}
// Request is the request object of the element's HTML document
Request *Request
// Response is the Response object of the element's HTML document
Response *Response
// DOM is the DOM object of the page. DOM is relative
// to the current XMLElement and is either a html.Node or xmlquery.Node
// based on how the XMLElement was created.
DOM interface{}
isHTML bool
}
// NewXMLElementFromHTMLNode creates a XMLElement from a html.Node.
func NewXMLElementFromHTMLNode(resp *Response, s *html.Node) *XMLElement {
return &XMLElement{
Name: s.Data,
Request: resp.Request,
Response: resp,
Text: htmlquery.InnerText(s),
DOM: s,
attributes: s.Attr,
isHTML: true,
}
}
// NewXMLElementFromXMLNode creates a XMLElement from a xmlquery.Node.
func NewXMLElementFromXMLNode(resp *Response, s *xmlquery.Node) *XMLElement {
return &XMLElement{
Name: s.Data,
Request: resp.Request,
Response: resp,
Text: s.InnerText(),
DOM: s,
attributes: s.Attr,
isHTML: false,
}
}
// Attr returns the selected attribute of a HTMLElement or empty string
// if no attribute found
func (h *XMLElement) Attr(k string) string {
if h.isHTML {
for _, a := range h.attributes.([]html.Attribute) {
if a.Key == k {
return a.Val
}
}
} else {
for _, a := range h.attributes.([]xml.Attr) {
if a.Name.Local == k {
return a.Value
}
}
}
return ""
}
// ChildText returns the concatenated and stripped text content of the matching
// elements.
func (h *XMLElement) ChildText(xpathQuery string) string {
if h.isHTML {
return strings.TrimSpace(htmlquery.InnerText(htmlquery.FindOne(h.DOM.(*html.Node), xpathQuery)))
}
return strings.TrimSpace(xmlquery.FindOne(h.DOM.(*xmlquery.Node), xpathQuery).InnerText())
}
// ChildAttr returns the stripped text content of the first matching
// element's attribute.
func (h *XMLElement) ChildAttr(xpathQuery, attrName string) string {
if h.isHTML {
child := htmlquery.FindOne(h.DOM.(*html.Node), xpathQuery)
if child != nil {
for _, attr := range child.Attr {
if attr.Key == attrName {
return strings.TrimSpace(attr.Val)
}
}
}
} else {
child := xmlquery.FindOne(h.DOM.(*xmlquery.Node), xpathQuery)
if child != nil {
for _, attr := range child.Attr {
if attr.Name.Local == attrName {
return strings.TrimSpace(attr.Value)
}
}
}
}
return ""
}
// ChildAttrs returns the stripped text content of all the matching
// element's attributes.
func (h *XMLElement) ChildAttrs(xpathQuery, attrName string) []string {
res := make([]string, 0)
if h.isHTML {
htmlquery.FindEach(h.DOM.(*html.Node), xpathQuery, func(i int, child *html.Node) {
for _, attr := range child.Attr {
if attr.Key == attrName {
res = append(res, strings.TrimSpace(attr.Val))
}
}
})
} else {
xmlquery.FindEach(h.DOM.(*xmlquery.Node), xpathQuery, func(i int, child *xmlquery.Node) {
for _, attr := range child.Attr {
if attr.Name.Local == attrName {
res = append(res, strings.TrimSpace(attr.Value))
}
}
})
}
return res
}