jamietre / CsQuery

CsQuery is a complete CSS selector engine, HTML parser, and jQuery port for C# and .NET 4.
Other
1.16k stars 249 forks source link

Difference between Select and Find #183

Closed marcselman closed 9 years ago

marcselman commented 9 years ago

I don't understand the inner workings of Select and Find. Take the following example:

var dom = CQ.Create("<div><p><a>hoi</a></p></div>");

// Selection1
var div = dom.Select("div");
div.Count().Dump();

// Selection 2
var div2 = dom.Find("div");
div2.Count().Dump();

// Selection 3
var p = div.Select("> p");
p.Count().Dump();

// Selection 4
var p2 = div.Find("> p");
p2.Count().Dump();

I would expect all selections to return one element. But that is not the case. Why do selection 2 and selection 3 return 0 elements?

Thanks, Marc

jamietre commented 9 years ago

Select operates against the whole dom. x.Select("div') is like $('div') it will find any div elements in the entire dom regardless of the current selection. (In CsQuery unlike jQuery there are any number of possible "doms" - you can create a new CQ object that's a selection from an existing dom, and it will inherit the dom of its source, or you can create a new one from HTML which is a new dom unrelated to any other)

Find is the same as jquery find, it operates only against the children of the selection. When you create a new dom, by default, the selection is only the top-level element(s) in your case it is just <div>. So Find will only find children of the root div. In "selection 2" you are looking for "div" children of the root div and there are no such children.

In selection 3, the first child combinator will look for things that are the first children of the root of the dom, e.g. the single "div" element. So that doesn't match anything.

In selection 4, it is looking for things that are the first child of the current selection (the root div) so it matches.

This should all work the same as jquery with the exception that the word "Select" is parlance for "$('x') in my dom". In jQuery $('> html') will return the root HTML element. $('<div><p><a>hoi</a></p></div>') will create a fragment with just the top div element selected, e.g. in chrome console:

> $('<div><p><a>hoi</a></p></div>')
< [▶<div>...</div>]
marcselman commented 9 years ago

Hi Jamietre,

Thank you for your explanation. In jQuery you can't do something (weird) like: $('div').find('> p').$('a') But in CsQuery you can do this: dom.Select("div").Find("> p").Select("a") That's what threw me off. I guess I should just use Select only for the initial select and Find for all subsequent child searches.

One more question though: Like you said in jQuery $('> html') returns the root HTML element but why does dom.Select("> div") on my dom not return the root div element?

marcselman commented 9 years ago

Thanks Jamietre!