diff --git a/README.md b/README.md index 78a45cc..0f971b1 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Syntax-wise, it is as close as possible to jQuery, with the same function names ## 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.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). diff --git a/type.go b/type.go index 0a1d2c1..0fffad8 100644 --- a/type.go +++ b/type.go @@ -2,6 +2,7 @@ package goquery import ( "code.google.com/p/go.net/html" + "io" "net/http" "net/url" ) @@ -35,6 +36,19 @@ func NewDocument(url string) (d *Document, e error) { 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. // It loads the specified response's document, parses it, and stores the root Document // node, ready to be manipulated. @@ -48,16 +62,15 @@ func NewDocumentFromResponse(res *http.Response) (d *Document, e error) { } // Create and fill the document - d = newDocument(root, res.Request.URL) - return + return newDocument(root, res.Request.URL), nil } // 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 - d = &Document{nil, url, root} + d := &Document{nil, url, root} d.Selection = newSingleSelection(root, d) - return + return d } // Selection represents a collection of nodes matching some criteria. The diff --git a/type_test.go b/type_test.go index 2a20999..84be9b8 100644 --- a/type_test.go +++ b/type_test.go @@ -1,6 +1,7 @@ package goquery import ( + "bytes" "code.google.com/p/go.net/html" "fmt" "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: ` + +
+