A simple option is a table as in a 3-column picture, the search consists of two stages:
find the cell column that contains the name "Lois"
.//tr/td[text()[.="Lois"]]
We accept that the table structure is constant and we get the second relative element relative to the column "Lois" and its button
.//tr/td[text()[.="Lois"]]/following-sibling::td[position()=2]/button
The second option is if the length of the table is unlimited (except for the first and last names there will be a bunch of other parameters), but the "Name" will start the line and the "Button" will finish, we can take the last element that corresponds to the button:
.//tr/td[text()[.="Lois"]]/following-sibling::td[last()]/button
The most universal option , when we do not depend on the position of the name cell and the button
.//tr[td[text()[.="Lois"]]]/td/button
An even more universal option pushed the comment lospejos .
We take into account that the name "Lois" corresponds to the column "Firstname", and not to any other. We find the position of the header "Firstname" (position 1) using the query
count(tr/th/text()[.="Firstname"]/preceding-sibling::*)+1
and use it to search for the name "Lois" in the string
.//tr[td[count(tr/th/text()[.="Firstname"]/preceding-sibling::*)+1][text()[.="Lois"]]]/td/button
that, given the calculated count, for the machine looks like
.//tr[td[1][text()[.="Lois"]]]/td/button
that is, our element must meet two conditions - is under the heading "Firstname" and have the name "Lois"