Permalink
Browse files

add NewDocumentFromReader, closes #20

  • Loading branch information...
1 parent e8c0a63 commit f065786d418c9d22a33cad33decd59277af31471 @mna mna committed Sep 7, 2013
Showing with 68 additions and 5 deletions.
  1. +1 −0 README.md
  2. +18 −5 type.go
  3. +49 −0 type_test.go
View
@@ -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).
View
23 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
View
@@ -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: `
+<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())
+ }
+ }
+ }
+}

0 comments on commit f065786

Please sign in to comment.