mirror of
https://github.com/PuerkitoBio/goquery
synced 2025-09-27 13:12:23 +08:00
add NewDocumentFromReader, closes #20
This commit is contained in:
@@ -22,6 +22,7 @@ Syntax-wise, it is as close as possible to jQuery, with the same function names
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
* **v0.3.2** : Add `NewDocumentFromReader()` (thanks jweir) which allows creating a goquery document from an io.Reader.
|
||||||
* **v0.3.1** : Add `NewDocumentFromResponse()` (thanks assassingj) which allows creating a goquery document from an http response.
|
* **v0.3.1** : Add `NewDocumentFromResponse()` (thanks assassingj) which allows creating a goquery document from an http response.
|
||||||
* **v0.3.0** : Add `EachWithBreak()` which allows to break out of an `Each()` loop by returning false. This function was added instead of changing the existing `Each()` to avoid breaking compatibility.
|
* **v0.3.0** : Add `EachWithBreak()` which allows to break out of an `Each()` loop by returning false. This function was added instead of changing the existing `Each()` to avoid breaking compatibility.
|
||||||
* **v0.2.1** : Make go-getable, now that [go.net/html is Go1.0-compatible][gonet] (thanks to @matrixik for pointing this out).
|
* **v0.2.1** : Make go-getable, now that [go.net/html is Go1.0-compatible][gonet] (thanks to @matrixik for pointing this out).
|
||||||
|
23
type.go
23
type.go
@@ -2,6 +2,7 @@ package goquery
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/go.net/html"
|
"code.google.com/p/go.net/html"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
)
|
)
|
||||||
@@ -35,6 +36,19 @@ func NewDocument(url string) (d *Document, e error) {
|
|||||||
return NewDocumentFromResponse(res)
|
return NewDocumentFromResponse(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDocumentFromReader() returns a Document from a generic reader.
|
||||||
|
// It returns an error as second value if the reader's data cannot be parsed
|
||||||
|
// as html. It does *not* check if the reader is also an io.Closer, so the
|
||||||
|
// provided reader is never closed by this call, it is the responsibility
|
||||||
|
// of the caller to close it if required.
|
||||||
|
func NewDocumentFromReader(r io.Reader) (d *Document, e error) {
|
||||||
|
root, e := html.Parse(r)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return newDocument(root, nil), nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewDocumentFromResponse() is another Document constructor that takes an http resonse as argument.
|
// NewDocumentFromResponse() is another Document constructor that takes an http resonse as argument.
|
||||||
// It loads the specified response's document, parses it, and stores the root Document
|
// It loads the specified response's document, parses it, and stores the root Document
|
||||||
// node, ready to be manipulated.
|
// node, ready to be manipulated.
|
||||||
@@ -48,16 +62,15 @@ func NewDocumentFromResponse(res *http.Response) (d *Document, e error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create and fill the document
|
// Create and fill the document
|
||||||
d = newDocument(root, res.Request.URL)
|
return newDocument(root, res.Request.URL), nil
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private constructor, make sure all fields are correctly filled.
|
// Private constructor, make sure all fields are correctly filled.
|
||||||
func newDocument(root *html.Node, url *url.URL) (d *Document) {
|
func newDocument(root *html.Node, url *url.URL) *Document {
|
||||||
// Create and fill the document
|
// Create and fill the document
|
||||||
d = &Document{nil, url, root}
|
d := &Document{nil, url, root}
|
||||||
d.Selection = newSingleSelection(root, d)
|
d.Selection = newSingleSelection(root, d)
|
||||||
return
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selection represents a collection of nodes matching some criteria. The
|
// Selection represents a collection of nodes matching some criteria. The
|
||||||
|
49
type_test.go
49
type_test.go
@@ -1,6 +1,7 @@
|
|||||||
package goquery
|
package goquery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"code.google.com/p/go.net/html"
|
"code.google.com/p/go.net/html"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@@ -99,3 +100,51 @@ func TestNewDocument(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewDocumentFromReader(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
src string
|
||||||
|
err bool
|
||||||
|
sel string
|
||||||
|
cnt int
|
||||||
|
}{
|
||||||
|
0: {
|
||||||
|
src: `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test</title>
|
||||||
|
<body>
|
||||||
|
<h1>Hi</h1>
|
||||||
|
</body>
|
||||||
|
</html>`,
|
||||||
|
sel: "h1",
|
||||||
|
cnt: 1,
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
// Actually pretty hard to make html.Parse return an error
|
||||||
|
// based on content...
|
||||||
|
src: `<html><body><aef<eqf>>>qq></body></ht>`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
|
for i, c := range cases {
|
||||||
|
buf.Reset()
|
||||||
|
buf.WriteString(c.src)
|
||||||
|
|
||||||
|
d, e := NewDocumentFromReader(buf)
|
||||||
|
if (e != nil) != c.err {
|
||||||
|
if c.err {
|
||||||
|
t.Errorf("[%d] - expected error, got none", i)
|
||||||
|
} else {
|
||||||
|
t.Errorf("[%d] - expected no error, got %s", i, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.sel != "" {
|
||||||
|
s := d.Find(c.sel)
|
||||||
|
if s.Length() != c.cnt {
|
||||||
|
t.Errorf("[%d] - expected %d nodes, found %d", i, c.cnt, s.Length())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user