How to convert Xpath to CSS - css

My xpath is: /html/body/div/table/tbody/tr[2]/td[4]
I need to get an CSS to use it in jsoup selector.
I found a comparison between xpath and css: here, and it's said in their example (Second <E> element anywhere on page) that I can't do it. Xpath xpath=(//E)[2] CSS N\A.
Maybe I can't find what I'm looking for. Any ideas?
Here's the html I'm trying to parse (I need to get values: 1 and 3):
<div class=tablecont>
<table width=100%>
<tr>
<td class=header align=center>Panel Color</td>
<td class=header align=center>Locked</td>
<td class=header align=center>Unqualified</td>
<td class=header align=center>Qualified</td>
<td class=header align=center>Finished</td>
<td class=header align=center>TOTAL</td>
</tr>
<tr>
<td align=center>
<div class=packagecode>ONE</div>
<div>
<div class=packagecolor style=background-color:#FC0;></div>
</div>
</td>
<td align=center>0</td>
<td align=center>0</td>
<td align=center>1</td>
<td align=center>12</td>
<td align=center class=rowhead>53</td>
</tr>
<tr>
<td align=center>
<div class=packagecode>two</div>
<div>
<div class=packagecolor style=background-color:#C3F;></div>
</div>
</td>
<td align=center>0</td>
<td align=center>0</td>
<td align=center>3</td>
<td align=center>42</td>
<td align=center class=rowhead>26</td>
</tr>
</table>
</div>

While an expression like (//E)[2] can't be represented with a CSS selector, an expression like E[2] can be emulated using the :nth-of-type() pseudo-class:
html > body > div > table > tbody > tr:nth-of-type(2) > td:nth-of-type(4)

Works good for me.
//Author: Oleksandr Knyga
function xPathToCss(xpath) {
return xpath
.replace(/\[(\d+?)\]/g, function(s,m1){ return '['+(m1-1)+']'; })
.replace(/\/{2}/g, '')
.replace(/\/+/g, ' > ')
.replace(/#/g, '')
.replace(/\[(\d+)\]/g, ':eq($1)')
.replace(/^\s+/, '');
}

Are you looking for something like this:
http://jsfiddle.net/YZu8D/
.tablecont tr:nth-child(2) td:nth-child(4) {background-color: yellow; }
.tablecont tr:nth-child(3) td:nth-child(4) {background-color: yellow; }

One should learn how to write css selectors, but a for a quick fix, try: cssify
For example, I put in your xpath and it spit out: html > body > div > table > tbody > tr:nth-of-type(2) > td:nth-of-type(4)
Try it out.

Related

Apply CSS style to all columns of a table

In my CSS, I have an entry:
.isenabled {
font-weight:bold;
background-color:lightyellow
}
In the HTML, I have:
<table>
<tr>
<td class="isenabled">This is enabled</td>
<td>This isn't</td>
</tr>
</table>
This works as intended. What I'd like to do is:
<table>
<tr class="isenabled">
<td>This is enabled</td>
<td>So is this</td>
</tr>
<tr>
<td class="isenabled">This is enabled</td>
<td>This isn't</td>
</tr>
</table>
But this doesn't work as it stands (both the cells have the default background). What should I do instead?
[EDIT]
I've made the desired behaviour more explicit.
Use following style
tr.isenabled > td, td.isenabled {
font-weight: bold;
background-color: lightyellow
}
<table>
<tr class="isenabled">
<td>This is enabled</td>
<td>So is this</td>
</tr>
</table>
.isenabled is catching the element with class "isenabled".
that's why when you add class to 'td' it works.
<table>
<tr>
<td class="isenabled">This is enabled</td>
<td>This isn't</td>
</tr>
</table>
if you are adding class to 'tr' element the css properties will be applied to 'tr' but you want it to be applied on 'td'.
'>' is used for immediate child after the the selected element
so if you write "tr > td" as selected it will select all 'td' which are immediate child of any 'tr' in html document.
so you can do like this
tr.isenabled > td {
font-weight: bold;
background-color: lightyellow
}
it will select all 'td' which is immediate child of any element with class "isenabled".
Here is the more information about css selectors https://www.w3schools.com/cssref/css_selectors.asp.

Remove all tr elements unless tr>td>input has a class 'DontRemoveMe'

Sorry for the very specific title, couldn't think of how to say it in more general terms.
Assume you have a table and each row contains a cell that has an input, but some input fields have a class of 'DontRemoveMe'. How do you target every row except the 'DontRemoveMe' rows?
Manipulation of DOM Elements requires JavaScript. One way to achieve this is with jQuery:
function remove() {
$('tr:not(.dontRemoveMe)').remove();
}
.dontRemoveMe td {
background-color: green;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr class="dontRemoveMe">
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Jon</td>
<td>Jones</td>
<td>33</td>
</tr>
</table>
<button onclick="remove()">Remove rows</button>
CSS (Not Yet Implemented):
Using CSS level 4 selectors, I believe it would be
tr:has(td>input:not(>>.DontRemoveMe))
However, those aren't implemented in any browser. So you would want to use javascript.
Javascript:
// Select all rows that don't contain a input.DontRemoveMe
let rows = Array.from(document.querySelectorAll("tr")).filter(x => !(x.querySelector("input.DontRemoveMe")));
// Add a special class to these rows so we can target them with CSS
rows.forEach(x => x.classList.add("selected"));
td {
padding: 8px; /* Padding for all rows to make background visible */
}
.selected {
background: red;
}
<table>
<tr>
<td><input type="text" value="selected" />
</td>
</tr>
<tr>
<td><input class="DontRemoveMe" type="text" value="not selected" />
</td>
</tr>
<tr>
<td>
<input type="text" value="selected" />
</td>
</tr>
</table>
Here is an old school javascript way.
Find all the tr tags then find any children with class DontRemoveMe, if it doesn't find any add a .hide class to the current row.
But, honestly I'd question the reason you want to do it like this, chances are there is a more sensible way.
var tr = document.getElementsByTagName('tr');
var i = 0;
var length = tr.length
for (; i < length; i++) {
var dontRemove = tr[i].getElementsByClassName('DontRemoveMe')
if (!dontRemove.length) {
tr[i].classList.add('hide')
}
}
td {
color: #ededed;
}
.red {
background-color: #ff3030;
}
.blue {
background-color: #6495ED;
}
.hide {
display: none;
}
<table>
<tr class="red">
<td>Normal</td>
<td>Normal</td>
<td class="DontRemoveMe">Don't Remove Me</td>
</tr>
<tr class="blue">
<td>Can't see me</td>
<td>Can't see me</td>
<td>Can't see me</td>
</tr>
<tr class="red">
<td class="DontRemoveMe">Don't Remove Me</td>
<td>Normal</td>
<td class="DontRemoveMe">Don't Remove Me</td>
</tr>
</table>

Can I select the children of a pseudo class in CSS?

I'd like to select all of the child td elements of the second child of a tbody element. Here is the selection I am trying to achieve:
<table>
<thead></thead>
<tbody>
<tr></tr>
<tr>
<td>I want to select this td</td>
<td>And this one</td>
</tr>
</tbody>
</table>
tbody:nth-child(2) > td
{
//insert rules
}
However this is not working. Does CSS3 support selecting children of pseudoclasses? If not, any advice on how to achieve the above selection would be greatly appreciated.
Thanks for you input.
tr:nth-child(2) does what you asked for:
tr:nth-child(2) {
color: red;
<table>
<thead></thead>
<tbody>
<tr>
<td>not me</td>
<td>And not me</td>
</tr>
<tr>
<td>I want to select this td</td>
<td>And this one</td>
</tr>
</tbody>
</table>
tbody:nth-child(2) > td won't work because only <tr> elements can be children of <tbody> elements.
to select all second td try it:
td:nth-child(2)
{
//
}
but if you wan't to select all td in the second child you can try :
tr:nth-child(2)
{
//
}
Yes you can mix pseudo-selectors and the child selector (did you notice your typo on child?):
.a-class:nth-child(2n) > .child-class

CSS selector if previous element has child with different className

Having the following table, is it possible to set a particular style for tr:first-child, when :first-child of previous tr has a different class? On the example table I want round corners on rows 2 and 4, but not on row 5 (since row 4 first child has the same class that row 5 first child).
<html>
<head>
<style type="text/css">
table { width: 100%; }
.a { background-color: red; }
table > tbody > tr:first-child > td.a:first-child {
border-top-left-radius: 10px;
}
</style>
</head>
<body>
<table>
<tr><td colspan=2>title</td></tr>
<tr><td class=a>sadsf</td><td class=a>adsfs</td></tr>
<tr><td class=b>sadsf</td><td class=b>adsfs</td></tr>
<tr><td class=a>sadsf</td><td class=a>adsfs</td></tr>
<tr><td class=a>sadsf</td><td class=a>adsfs</td></tr>
</table>
</body>
</html>
Short answer: No
You can reference CSS Selectors here.
Long Answer:
Let's simplify your title first:
I want to style an element, but only if that elements immediate preceding neighbor’s first child does not have the same class.
This is easily accomplishable with javascript, but let’s pretend you can’t use javascript and you have a little freedom with your class declarations.
The first thing you should do is give each parent element a unique class name (I would choose the same as the children). So in this example it would be <tr class=“a”> and so forth.
Then we can style every :first-child with the effect you want (in this case, border-radius).
Later we can use css selectors to target every element, that has an adjacent sibling with the same class name (see docs) and we will revert or remove the style just placed on it.
Here's a fiddle using li elements as demo and below in the snippet you will see another example using table elements.
tr {
color: orange;
}
tr.a > td.a:first-child,
tr.b > td.b:first-child,
tr.c > td.c:first-child {
color: aqua; /* style all first-children*/
}
tr.a + tr.a > td.a:first-child,
tr.b + tr.b > td.b:first-child,
tr.c + tr.c > td.c:first-child {
color: orange; /*revert the styling on select elemets*/
}
<table>
<tr class="a">
<td colspan="2">class-a</td><!--should be styled-->
</tr>
<tr class="b">
<td class="b">class-b</td><!--should be styled-->
<td class="b">class-b</td>
</tr>
<tr class="c">
<td class="c">class-c</td><!--should be styled-->
<td class="c">class-c</td>
</tr>
<tr class="b">
<td class="b">class-b</td><!--should be styled-->
<td class="b">class-b</td>
</tr>
<tr class="b">
<td class="b">class-b</td><!--should NOT be styled-->
<td class="b">class-b</td>
</tr>
<tr class="c">
<td class="c">class-c</td><!--should be styled-->
<td class="c">class-c</td>
</tr>
<tr class="b">
<td class="b">class-b</td><!--should be styled-->
<td class="b">class-b</td>
</tr>
<tr class="c">
<td class="c">class-c</td><!--should be styled-->
<td class="c">class-c</td>
</tr>
<tr class="c">
<td class="c">class-c</td><!--should NOT be styled-->
<td class="c">class-c</td>
</tr>
</table>

I want a different color only for first row of a html table

I used a table. I applied CSS ID table-4.
Following the html code:
<table border='0' width='100%' id='table-4'>
<tr><td>Date</td><td>Headline</td></tr>
<tr><td>29 DEC</td><td>Dead</td></tr>
<tr><td>30 DEC</td><td>Hit</td></tr>
<tr><td>02 JAN</td><td>Leg</td></tr>
</table>
Here is the style.css:
#table-4 { background-color: #F2F2F2;}
So the whole table's background color is #F2F2F2, but I want a different color for the first row where Date and Headline goes, so how could I modify my CSS for this thing?
You can use :first-child for this. Write like this:
#table-4 tr:first-child{
background:red;
}
Check this http://jsfiddle.net/cbK8J/
#JonathandeM.'s comment is correct. Pop <thead> and <tbody> tags in there, and change the <td> tags in the <thead> row to <th> tags (because HTML says what things are, and they're headings):
<table border='0' width='100%' id='table-4'>
<thead>
<tr><th scope="col">Date</th><th scope="col">Headline</th></tr>
</thead>
<tbody>
<tr><td>29 DEC</td><td>Dead</td></tr>
<tr><td>30 DEC</td><td>Hit</td></tr>
<tr><td>02 JAN</td><td>Leg</td></tr>
</tbody>
</table>
Then the CSS to make the heading row have a different background colour is:
#table-4 thead tr {
background-color: green;
}
you can do this:
HTML:
<td class="whatever">Date</td><td class="whatever">Headline</td>
css:
.whatever { color: #a9a9a9 }
<tr> will do the row, <td> will do the cells.
You have to add id to first tr tag:
<table border='0' width='100%' id='table-4'>
<tr id ="r1" ><td>Date</td><td>Headline</td></tr>
<tr><td>29 DEC</td><td>Dead</td></tr>
<tr><td>30 DEC</td><td>Hit</td></tr>
<tr><td>02 JAN</td><td>Leg</td></tr>
</table>
and then add another css line:
#table-4 #r1 { background-color: blue;}
it will give you blue color
Or you can simply modify only the Html file, no change in css
<table border='0' width='100%' id='table-4'>
<tr><td bgcolor='red' >Date</td><td bgcolor='red'>Headline</td></tr>
<tr><td>29 DEC</td><td>Dead</td></tr>
<tr><td>30 DEC</td><td>Hit</td></tr>
<tr><td>02 JAN</td><td>Leg</td></tr>
</table>

Resources