README.md

  1# cascadia
  2
  3[![](https://travis-ci.org/andybalholm/cascadia.svg)](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```