GlyphGryph
GlyphGryph

Reputation: 4794

Find cells under a column in an HTML table with xpath?

I want to be able to extract all cells under a certain column with xpath.

There are/may be occasionally colspans.

Is there any way to do this, by which I suppose I'm asking, is there any inherent relationship between a table header and the cells below it? Or is there no inherent relationship and despite being fairly easy to do visually, its outside the ability of pure xpath?

Scenario: We have an HTML table with a dozen columns and several rows. The columns have headers, and some of the column headers span more than one column.

One of those column headers (we don't know which one) has the textual content "Pick Me".

I want to be able to select all the cells under that cell in the table.

Upvotes: 0

Views: 4293

Answers (3)

Web Ted
Web Ted

Reputation: 1

In case you need to grab specific column for example the first:

//tr/td[1]

Upvotes: 0

John Tobey
John Tobey

Reputation: 41

You can do it in XPath 1. I assume that only one column has the desired header and the rowspan attribute does not occur.

tbody/tr/td[
      count(preceding-sibling::td[not(@colspan)])
      + sum(preceding-sibling::td/@colspan)
    = count(../../tr[1]/th[.='Pick Me']/preceding-sibling::th[not(@colspan)])
      + sum(../../tr[1]/th[.='Pick Me']/preceding-sibling::th/@colspan)]

The above expression yields all cells starting in the leftmost column of the Pick Me header. By duplicating a lot of the logic, you can get the cells starting in any column spanned by Pick Me or the cells sharing a column with Pick Me, perhaps the broadest interpretation of your question:

tbody/tr/td[
      count(preceding-sibling::td[not(@colspan)])
      + sum(preceding-sibling::td/@colspan)
    < count(../../tr[1]/th[.='Pick Me']/preceding-sibling::th[not(@colspan)])
      + sum(../../tr[1]/th[.='Pick Me']/preceding-sibling::th/@colspan)
      + count(../../tr[1]/th[.='Pick Me'][not(@colspan)])
      + sum(../../tr[1]/th[.='Pick Me']/@colspan)
  and count(preceding-sibling::td[not(@colspan)])
      + sum(preceding-sibling::td/@colspan)
      + not(@colspan)
      + sum(@colspan)
    > count(../../tr[1]/th[.='Pick Me']/preceding-sibling::th[not(@colspan)])
      + sum(../../tr[1]/th[.='Pick Me']/preceding-sibling::th/@colspan)]

The strategy here is to compute the "position" of both the left and right side of each cell and the Pick Me header, where "position" means the number of columns to something's left. The cell overlaps the header's column(s) if, and only if, the cell's left is left of the header's right and the cell's right is right of the header's left. That is the meaning of the numeric comparisons.

Upvotes: 4

GlyphGryph
GlyphGryph

Reputation: 4794

No, there is no association in xpath between column headers in a table and the column they fall within.

The only way to find cells that fall beneath a specific column header is, using some other code, to count the columns (account for colspans) until the desired table header is found, and then count that many columns in each row to extract the cells.

Upvotes: 1

Related Questions