From f696fbf5bb5834337e5ea6921eed8b386c2568be Mon Sep 17 00:00:00 2001 From: Martin Angers Date: Wed, 29 Aug 2012 11:31:25 -0400 Subject: [PATCH] add local html doc for tests --- README.md | 11 +---- goquery.go | 57 +++++++++++++++++++++++++ goquery_test.go | 22 ++++++++-- testdata/page.html | 102 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 12 deletions(-) create mode 100644 testdata/page.html diff --git a/README.md b/README.md index 26df93c..cb21137 100644 --- a/README.md +++ b/README.md @@ -18,16 +18,9 @@ Once this is done, install GoQuery: GoQuery exposes two classes, `Document` and `Selection`. Unlike jQuery, which is loaded as part of a DOM document, and thus acts on its containing document, GoQuery doesn't know which HTML document to act upon. So it needs to be told, and that's what the `Document` class is for. It holds the root document node to manipulate, and can make selections on this document. -### Document constructors - -A `*Document` can be created by one of these methods: - -* **NewDocument(url string) (*Document, error)** : loads the HTML document specified by the URL as a string, parses it to its in-memory node representation (using the experimental HTML package) and returns the document reference, or an error. -* **&Document{rootNode, nil}** : creates a document and sets its root node. Useful if you already parsed an HTML document and want to manipulate it using GoQuery. - -### .Add(string), .AddFromSelection(*Selection) - +Please note that Cascadia's selectors do NOT necessarily match all supported selectors of jQuery (Sizzle). See the [cascadia project][cascadia] for details. +(reference coming soon) ## License diff --git a/goquery.go b/goquery.go index 2ac8731..7873819 100644 --- a/goquery.go +++ b/goquery.go @@ -3,17 +3,28 @@ package goquery import ( "code.google.com/p/cascadia" "exp/html" + //"fmt" "net/http" "net/url" ) // TODO : Ensure no node is added more than once in a selection (especially with Add...) +// TODO : Add the following methods: +// - Closest() +// - Parents() +// - Fix ChildrenFiltered, by forking Cascadia and adding a MatchSingle() method? type Document struct { Root *html.Node Url *url.URL } +func NewDocumentFromNode(root *html.Node) (d *Document) { + // Create and fill the document + d = &Document{root, nil} + return +} + func NewDocument(url string) (d *Document, e error) { // Load the URL res, e := http.Get(url) @@ -55,6 +66,32 @@ func findWithContext(selector string, nodes ...*html.Node) []*html.Node { return matches } +func childrenWithContext(selector string, nodes ...*html.Node) []*html.Node { + var matches []*html.Node + //var allChildren bool + //var sel *cascadia.Selector + /* + if selector == "*" || selector == "" { + // Get all children + allChildren = true + } else { + if sel, e := cascadia.Compile(selector); e != nil { + // Selector doesn't compile, empty selection + return nil + } + } + */ + for _, n := range nodes { + for _, nchild := range n.Child { + // TODO : At the moment, given Cascadia's API, cannot call Children with a selector string + //if allChildren /*|| sel(nchild)*/ { + matches = append(matches, nchild) + //} + } + } + return matches +} + // Returns a new Selection object func (this *Document) Find(selector string) *Selection { return &Selection{findWithContext(selector, this.Root), this} @@ -101,3 +138,23 @@ func (this *Selection) Attr(attrName string) (val string, exists bool) { } return } + +// Returns a new Selection object. +func (this *Document) Children() *Selection { + return this.ChildrenFiltered("") +} + +// Returns a new Selection object. +func (this *Selection) Children() *Selection { + return this.ChildrenFiltered("") +} + +// Returns a new Selection object. +func (this *Document) ChildrenFiltered(selector string) *Selection { + return &Selection{childrenWithContext(selector, this.Root), this} +} + +// Returns a new Selection object. +func (this *Selection) ChildrenFiltered(selector string) *Selection { + return &Selection{childrenWithContext(selector, this.Nodes...), this.document} +} diff --git a/goquery_test.go b/goquery_test.go index 519e231..8345d51 100644 --- a/goquery_test.go +++ b/goquery_test.go @@ -2,16 +2,22 @@ package goquery import ( "exp/html" + "os" "testing" ) var doc *Document func TestNewDocument(t *testing.T) { - var e error - doc, e = NewDocument("http://provok.in") - if e != nil { + if f, e := os.Open("./testdata/page.html"); e != nil { t.Error(e.Error()) + } else { + defer f.Close() + if node, e := html.Parse(f); e != nil { + t.Error(e.Error()) + } else { + doc = NewDocumentFromNode(node) + } } } @@ -92,3 +98,13 @@ func TestAttrNotExist(t *testing.T) { t.Errorf("Expected no value for the href attribute, got %v.", val) } } + +func TestChildren(t *testing.T) { + sel := doc.Find(".pvk-content").Children() + if len(sel.Nodes) != 13 { + t.Errorf("Expected 13 child nodes, got %v.", len(sel.Nodes)) + for _, n := range sel.Nodes { + t.Logf("%+v", n) + } + } +} diff --git a/testdata/page.html b/testdata/page.html new file mode 100644 index 0000000..de2b3af --- /dev/null +++ b/testdata/page.html @@ -0,0 +1,102 @@ + + + + + + + Provok.in + + + + + + + + + +
+
+
+   +
+
+
+
+
+
+

+ Provok.in +

+

+ Prove your point. +

+
+
+
+
+ Beta Version. Things may change. Or disappear. Or fail miserably. If it's the latter, please file an issue. +
+
+ +
+ Welcome, {{getUserName()}} ( logout ) +
+
+
+
+
+   +
+
+
+
+   +
+
+
+
+
+
+ × +

+ {{ title }} +

+

+ {{ message }} +

+
+
+
+
+
+
+
+
+
+
+   +
+
+
+
+   +
+
+ +
+
+   +
+
+
+ + \ No newline at end of file