1# cascadia
2
3[](https://travis-ci.org/andybalholm/cascadia)
4
5The Cascadia package implements CSS selectors for use with the parse trees produced by the html package.
6
7To test CSS selectors without writing Go code, check out [cascadia](https://github.com/suntong/cascadia) the command line tool, a thin wrapper around this package.
8
9[Refer to godoc here](https://godoc.org/github.com/andybalholm/cascadia).
10
11## Example
12
13The following is an example of how you can use Cascadia.
14
15```go
16package main
17
18import (
19 "fmt"
20 "log"
21 "strings"
22
23 "github.com/andybalholm/cascadia"
24 "golang.org/x/net/html"
25)
26
27var pricingHtml string = `
28<div class="card mb-4 box-shadow">
29 <div class="card-header">
30 <h4 class="my-0 font-weight-normal">Free</h4>
31 </div>
32 <div class="card-body">
33 <h1 class="card-title pricing-card-title">$0/mo</h1>
34 <ul class="list-unstyled mt-3 mb-4">
35 <li>10 users included</li>
36 <li>2 GB of storage</li>
37 <li><a href="https://example.com">See more</a></li>
38 </ul>
39 </div>
40</div>
41
42<div class="card mb-4 box-shadow">
43 <div class="card-header">
44 <h4 class="my-0 font-weight-normal">Pro</h4>
45 </div>
46 <div class="card-body">
47 <h1 class="card-title pricing-card-title">$15/mo</h1>
48 <ul class="list-unstyled mt-3 mb-4">
49 <li>20 users included</li>
50 <li>10 GB of storage</li>
51 <li><a href="https://example.com">See more</a></li>
52 </ul>
53 </div>
54</div>
55
56<div class="card mb-4 box-shadow">
57 <div class="card-header">
58 <h4 class="my-0 font-weight-normal">Enterprise</h4>
59 </div>
60 <div class="card-body">
61 <h1 class="card-title pricing-card-title">$29/mo</h1>
62 <ul class="list-unstyled mt-3 mb-4">
63 <li>30 users included</li>
64 <li>15 GB of storage</li>
65 <li><a>See more</a></li>
66 </ul>
67 </div>
68</div>
69`
70
71func Query(n *html.Node, query string) *html.Node {
72 sel, err := cascadia.Parse(query)
73 if err != nil {
74 return &html.Node{}
75 }
76 return cascadia.Query(n, sel)
77}
78
79func QueryAll(n *html.Node, query string) []*html.Node {
80 sel, err := cascadia.Parse(query)
81 if err != nil {
82 return []*html.Node{}
83 }
84 return cascadia.QueryAll(n, sel)
85}
86
87func AttrOr(n *html.Node, attrName, or string) string {
88 for _, a := range n.Attr {
89 if a.Key == attrName {
90 return a.Val
91 }
92 }
93 return or
94}
95
96func main() {
97 doc, err := html.Parse(strings.NewReader(pricingHtml))
98 if err != nil {
99 log.Fatal(err)
100 }
101 fmt.Printf("List of pricing plans:\n\n")
102 for i, p := range QueryAll(doc, "div.card.mb-4.box-shadow") {
103 planName := Query(p, "h4").FirstChild.Data
104 price := Query(p, ".pricing-card-title").FirstChild.Data
105 usersIncluded := Query(p, "li:first-child").FirstChild.Data
106 storage := Query(p, "li:nth-child(2)").FirstChild.Data
107 detailsUrl := AttrOr(Query(p, "li:last-child a"), "href", "(No link available)")
108 fmt.Printf(
109 "Plan #%d\nName: %s\nPrice: %s\nUsers: %s\nStorage: %s\nDetails: %s\n\n",
110 i+1,
111 planName,
112 price,
113 usersIncluded,
114 storage,
115 detailsUrl,
116 )
117 }
118}
119```
120The output is:
121```
122List of pricing plans:
123
124Plan #1
125Name: Free
126Price: $0/mo
127Users: 10 users included
128Storage: 2 GB of storage
129Details: https://example.com
130
131Plan #2
132Name: Pro
133Price: $15/mo
134Users: 20 users included
135Storage: 10 GB of storage
136Details: https://example.com
137
138Plan #3
139Name: Enterprise
140Price: $29/mo
141Users: 30 users included
142Storage: 15 GB of storage
143Details: (No link available)
144```