views:

50

answers:

2

From a table element, I would like to select all rows that have the class even or the class odd.

I tried the jQuery syntax:

report.css("table.data tr[class~=odd even]").each{|line| parse_line_item(line)}

but it threw an error, any help is appreciated, thanks.

+1  A: 

Use two selectors: report.css("table.data tr.odd, table.data tr.even")

The ~= operator in a CSS attribute selector checks that the value matches a space-delimited list of classes. For instance, tr[class~=odd] would match <tr class="odd"> and <tr class="odd ball">. However, in the specific case of the class attribute, the better selector is simply tr.odd.

If you use the ~= operator with a space in the value (as in tr[class~="odd even"], the selector will never match anything.

Ron DeVera
this works, however it gives it to me as `1,3,5,7,9,2,4,6,8` rather than sequentially. is there a way to get it sequentially?
Russ Bradberry
If the order matters, you could select `table.data tr[class]` to find every `tr` with any `class` attribute, then check for an exact `class` value in Ruby. It's not as succinct, but far more flexible than CSS selectors.
Ron DeVera
ill look into that, thanks!
Russ Bradberry
A: 

The CSS selector you have there is not even a syntactically valid selector:

[class~=odd even]

Values that contain whitespace must always be quoted, so the correct way to write this selector would be:

[class~="odd even"]

However, this selector actually cannot ever match anything: the [attr~=val] attribute value selector matches ...

an element with the att attribute whose value is a whitespace-separated list of words, one of which is exactly "val". If "val" contains whitespace, it will never represent anything (since the words are separated by spaces)

Since the words are separated by whitespace, this means they cannot ever contain whitespace themselves. But the word you are looking for ("odd even"), does contain whitespace, therefore it cannot ever match anything.

Presumably, what you are looking for is an OR combinator, but it doesn't exist. So, what you are looking for cannot be expressed with CSS selectors.

Well, actually, that's not true: it can be expressed with CSS selectors. You can simply use selector groups, which give you set union of the matches, which is equivalent to using an OR combinator:

table.data tr.odd, table.data tr.even

Remember: CSS is set-based, therefore order doesn't matter. In your case, order does matter, which means that CSS is really the wrong tool for the job:

report.xpath('//table[@class="data"]//tr[@class="odd" or @class="even"')

Although I must admit that I am not sure why you don't just use something like this:

report.css('table.data tr')

After all, isn't selecting all odd and all even rows the same as selecting all rows? I mean, what else have you got in there, irrational rows?

Jörg W Mittag