mirror of
https://github.com/PuerkitoBio/goquery.git
synced 2024-04-21 12:31:36 +00:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1271ee34c | ||
|
|
f5c5de8530 | ||
|
|
46c32cef0e | ||
|
|
755fd592bb | ||
|
|
3cb3b86568 | ||
|
|
2ee2e49ac5 | ||
|
|
c0b805c7dc | ||
|
|
152b1a2c8f | ||
|
|
9043fe2599 | ||
|
|
56a198aba8 |
@@ -7,4 +7,5 @@ go:
|
|||||||
- 1.4
|
- 1.4
|
||||||
- 1.5
|
- 1.5
|
||||||
- 1.6
|
- 1.6
|
||||||
|
- 1.7
|
||||||
- tip
|
- tip
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Please note that because of the net/html dependency, goquery requires Go1.1+.
|
|||||||
$ go get github.com/PuerkitoBio/goquery
|
$ go get github.com/PuerkitoBio/goquery
|
||||||
|
|
||||||
(optional) To run unit tests:
|
(optional) To run unit tests:
|
||||||
|
|
||||||
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
|
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
|
||||||
$ go test
|
$ go test
|
||||||
|
|
||||||
@@ -26,6 +26,8 @@ Please note that because of the net/html dependency, goquery requires Go1.1+.
|
|||||||
|
|
||||||
**Note that goquery's API is now stable, and will not break.**
|
**Note that goquery's API is now stable, and will not break.**
|
||||||
|
|
||||||
|
* **2017-02-12 (v1.1.0)** : Add `SetHtml` and `SetText` (thanks to @glebtv).
|
||||||
|
* **2016-12-29 (v1.0.2)** : Optimize allocations for `Selection.Text` (thanks to @radovskyb).
|
||||||
* **2016-08-28 (v1.0.1)** : Optimize performance for large documents.
|
* **2016-08-28 (v1.0.1)** : Optimize performance for large documents.
|
||||||
* **2016-07-27 (v1.0.0)** : Tag version 1.0.0.
|
* **2016-07-27 (v1.0.0)** : Tag version 1.0.0.
|
||||||
* **2016-06-15** : Invalid selector strings internally compile to a `Matcher` implementation that never matches any node (instead of a panic). So for example, `doc.Find("~")` returns an empty `*Selection` object.
|
* **2016-06-15** : Invalid selector strings internally compile to a `Matcher` implementation that never matches any node (instead of a panic). So for example, `doc.Find("~")` returns an empty `*Selection` object.
|
||||||
@@ -84,7 +86,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func ExampleScrape() {
|
func ExampleScrape() {
|
||||||
doc, err := goquery.NewDocument("http://metalsucks.net")
|
doc, err := goquery.NewDocument("http://metalsucks.net")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -13,7 +13,7 @@ and then:
|
|||||||
```
|
```
|
||||||
// Load the URL
|
// Load the URL
|
||||||
res, err := http.Get(url)
|
res, err := http.Get(url)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
// handle error
|
// handle error
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
@@ -65,4 +65,4 @@ Thanks to github user @jmoiron.
|
|||||||
[otto]: https://github.com/robertkrimen/otto
|
[otto]: https://github.com/robertkrimen/otto
|
||||||
[exotto]: https://gist.github.com/cryptix/87127f76a94183747b53
|
[exotto]: https://gist.github.com/cryptix/87127f76a94183747b53
|
||||||
[iconv]: http://godoc.org/?q=iconv
|
[iconv]: http://godoc.org/?q=iconv
|
||||||
[text]: http://godoc.org/code.google.com/p/go.text/encoding
|
[text]: https://godoc.org/golang.org/x/text/encoding
|
||||||
|
|||||||
@@ -270,6 +270,17 @@ func (s *Selection) ReplaceWithNodes(ns ...*html.Node) *Selection {
|
|||||||
return s.Remove()
|
return s.Remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the html content of each element in the selection to specified html string.
|
||||||
|
func (s *Selection) SetHtml(html string) *Selection {
|
||||||
|
return setHtmlNodes(s, parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the content of each element in the selection to specified content. The
|
||||||
|
// provided text string is escaped.
|
||||||
|
func (s *Selection) SetText(text string) *Selection {
|
||||||
|
return s.SetHtml(html.EscapeString(text))
|
||||||
|
}
|
||||||
|
|
||||||
// Unwrap removes the parents of the set of matched elements, leaving the matched
|
// Unwrap removes the parents of the set of matched elements, leaving the matched
|
||||||
// elements (and their siblings, if any) in their place.
|
// elements (and their siblings, if any) in their place.
|
||||||
// It returns the original selection.
|
// It returns the original selection.
|
||||||
@@ -481,6 +492,18 @@ func parseHtml(h string) []*html.Node {
|
|||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setHtmlNodes(s *Selection, ns ...*html.Node) *Selection {
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
for c := n.FirstChild; c != nil; c = n.FirstChild {
|
||||||
|
n.RemoveChild(c)
|
||||||
|
}
|
||||||
|
for _, c := range ns {
|
||||||
|
n.AppendChild(cloneNode(c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
// Get the first child that is an ElementNode
|
// Get the first child that is an ElementNode
|
||||||
func getFirstChildEl(n *html.Node) *html.Node {
|
func getFirstChildEl(n *html.Node) *html.Node {
|
||||||
c := n.FirstChild
|
c := n.FirstChild
|
||||||
|
|||||||
@@ -278,6 +278,66 @@ func TestReplaceWithHtml(t *testing.T) {
|
|||||||
printSel(t, doc.Selection)
|
printSel(t, doc.Selection)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSetHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
q := doc.Find("#main, #foot")
|
||||||
|
q.SetHtml(`<div id="replace">test</div>`)
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#replace").Nodes, 2)
|
||||||
|
assertLength(t, doc.Find("#main, #foot").Nodes, 2)
|
||||||
|
|
||||||
|
if q.Text() != "testtest" {
|
||||||
|
t.Errorf("Expected text to be %v, found %v", "testtest", q.Text())
|
||||||
|
}
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetHtmlNoMatch(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
q := doc.Find("#notthere")
|
||||||
|
q.SetHtml(`<div id="replace">test</div>`)
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#replace").Nodes, 0)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetHtmlEmpty(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
q := doc.Find("#main")
|
||||||
|
q.SetHtml(``)
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("#main").Children().Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetText(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
q := doc.Find("#main, #foot")
|
||||||
|
repl := "<div id=\"replace\">test</div>"
|
||||||
|
q.SetText(repl)
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#replace").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main, #foot").Nodes, 2)
|
||||||
|
|
||||||
|
if q.Text() != (repl + repl) {
|
||||||
|
t.Errorf("Expected text to be %v, found %v", (repl + repl), q.Text())
|
||||||
|
}
|
||||||
|
|
||||||
|
h, err := q.Html()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error: %v", err)
|
||||||
|
}
|
||||||
|
esc := "<div id="replace">test</div>"
|
||||||
|
if h != esc {
|
||||||
|
t.Errorf("Expected html to be %v, found %v", esc, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
func TestReplaceWithSelection(t *testing.T) {
|
func TestReplaceWithSelection(t *testing.T) {
|
||||||
doc := Doc2Clone()
|
doc := Doc2Clone()
|
||||||
sel := doc.Find("#nf6").ReplaceWithSelection(doc.Find("#nf5"))
|
sel := doc.Find("#nf6").ReplaceWithSelection(doc.Find("#nf5"))
|
||||||
|
|||||||
+15
-18
@@ -63,9 +63,22 @@ func (s *Selection) Text() string {
|
|||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
// Slightly optimized vs calling Each: no single selection object created
|
// Slightly optimized vs calling Each: no single selection object created
|
||||||
for _, n := range s.Nodes {
|
var f func(*html.Node)
|
||||||
buf.WriteString(getNodeText(n))
|
f = func(n *html.Node) {
|
||||||
|
if n.Type == html.TextNode {
|
||||||
|
// Keep newlines and spaces, like jQuery
|
||||||
|
buf.WriteString(n.Data)
|
||||||
|
}
|
||||||
|
if n.FirstChild != nil {
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
f(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
f(n)
|
||||||
|
}
|
||||||
|
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,22 +205,6 @@ func (s *Selection) ToggleClass(class ...string) *Selection {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the specified node's text content.
|
|
||||||
func getNodeText(node *html.Node) string {
|
|
||||||
if node.Type == html.TextNode {
|
|
||||||
// Keep newlines and spaces, like jQuery
|
|
||||||
return node.Data
|
|
||||||
} else if node.FirstChild != nil {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for c := node.FirstChild; c != nil; c = c.NextSibling {
|
|
||||||
buf.WriteString(getNodeText(c))
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAttributePtr(attrName string, n *html.Node) *html.Attribute {
|
func getAttributePtr(attrName string, n *html.Node) *html.Attribute {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user