How to get only div with not style attribute? - c#

Suppose I have the following html structure:
<div class="table-container"></div>
<div class="table-container" style="display: none;"></div>
<div class="table-container" style="display: none;"></div>
<div class="table-container"></div>
how can I get only the div with no style attribute? I did this:
HtmlNodeCollection containers = doc.DocumentNode.SelectNodes("//div[#class='table-container']");
there is a property that allow me to do that?

Your'e close. Just add a Where:
var nodes = doc
.DocumentNode
.ChildNodes
.Where(n => n.Attributes.Count == 1 &&
n.Attributes[0].Name == "class")
.ToList();

Related

How to count nested div using selenium c#?

<div class="bodyCells">
<div style="position:absolute;left:0;">
<div style="overflow:hidden;">
<div title="AAA" class="pivotTableCellWrap">AAA</div>
<div title="BBB" class="pivotTableCellWrap">BBB</div>
</div>
<div>
<div title="AAA-123" class="pivotTableCellWrap">AAA-123</div>
<div title="BBB-123" class="pivotTableCellWrap">BBB-123</div>
</div>
</div>
</div>
I have two bodycells div in my page and I want the count the nested div inside the second one.
Required output :- I want the count=2
Tried Approach :-
int rowCount = driver.FindElements(By.XPath("//div[#class='bodyCells[2]']//div").Count());
Console.WriteLine(rowCount);
you can use the below modified XPath inorder to get the count of second nested div
XPath: //div[#class='bodyCells']/div/div[2]/div
Code:
var rowCount = _driver.FindElements(By.XPath("//div[#class='bodyCells']/div/div[2]/div")).Count;
Console.WriteLine(rowCount);
As per the HTML you have provided to count the nested child <divs> inside the second (parent) <div> you can use either of the following solution:
CssSelector:
List<string> elements = driver.FindElements(By.CssSelector("div.bodyCells div.pivotTableCellWrap[title*='-']"));
Console.WriteLine(elements.Count);
XPath:
List<string> elements = driver.FindElements(By.XPath("//div[#class='bodyCells']//div[#class='pivotTableCellWrap' and contains(#title,'-')]"));
Console.WriteLine(elements.Count);

Cannot find specific XML elements in XML Document

I just ran into a head scratcher, I'm not quite sure why this does not work. I want to find all the elements with the attribute "video".
My XML document looks like this:
<MainMenu>
<div id="BroughtInMenu">
<div class="menuItem0">
Menu Item
<div class="subMenu0">
<div class="menuItem1">
Dictation
<div class="subMenu1">
<div class="menuItem2" video="1">Fee Earner</div>
<div class="menuItem2" video="1">Secretary</div>
<div class="menuItem2" video="1">View File History</div>
</div>
</div>
<div class="menuItem1">
PM Advanced Agenda
<div class="subMenu1">
<div class="menuItem2">
Help
<div class="subMenu2">
<div class="menuItem3" video="1">Release Notes</div>
</div>
</div>
<div class="menuItem2">
System Maintenance
<div class="subMenu2">
<div class="menuItem3" video="1">Additional Field Setup</div>
<div class="menuItem3" video="1">Role Permission Maintenance</div>
<div class="menuItem3" video="1">Shared Diary Permissions</div>
</div>
</div>
<div class="menuItem2">
Utilities
<div class="subMenu2">
<div class="menuItem3" video="1">Change Entity Subtype</div>
<div class="menuItem3" video="1">Field Maintenance</div>
<div class="menuItem3" video="1">Move Client and Files to Fee Earner</div>
<div class="menuItem3" video="1">Reallocate Files</div>
</div>
</div>
</div>
</div> . . . . . . . . . . . . . . . . ..
This is very the same as HTML. This is for a website, so at the end I want to get all the elements with the attribute "video".
If I can do this, then I will only grab the div elements with the attribute "video", and then I will be able to use that for something else, like in a search, where I actually search the xml document and return the div, etc etc... hope you see my drift here...
Because the video attribute is going to point to a location, it will be very useful for html purposes to just jump to the video when the div is clicked.
So far I have tried this, but i am not getting the elements at all:
XElement xDoc = XElement.Load(Server.MapPath("automation/xml/mainMenu.xml"));
IEnumerable<XElement> list = from el in xDoc.Elements("div") where el.Attribute("video") != null select el;
foreach (XElement element in list)
{
//Nothing found?
}
I also thought about REGEX... maybe regex will be able to pull the divs i want, already in text format so that i can just push it into an html element in the website?
Any help will be greatly appreceiated!
Use Descendands instead of Elements. Elements returns just immediate children.
var xDoc = XElement.Load(Server.MapPath("automation/xml/mainMenu.xml"));
var list = from el in xDoc.Descendants("div")
where el.Attribute("video") != null
select el;
foreach (XElement element in list)
{
//Nothing found?
}
You can select elements where a particular attribute is present with XPath. To use the XPath extension methods, you need to include the namespace.
using System.Xml.XPath;
An XPath such as "//div[#video]" will include all "div" tags at any level, but filter the selected elements to only those with a "video" attribute, so you're not looping unnecessarily through lots of elements checking for the presence of an attribute.
var xDoc = XElement.Load(Server.MapPath("automation/xml/mainMenu.xml"));
foreach (var divWithVideo in xDoc.XPathSelectElements ("//div[#video]")) {
Console.WriteLine (divWithVideo);
}
Here you are only iterating on the elements with a "video" attribute.

fetching ul li items under div class using html agility pack

<div class="outer">
<div class="divOne"></div>
<div class="divContent">
<h3>SomeTitle</h3>
<h4>SomeSubtitle</h4>
<ul>
<li>SomeUrl
<span> Nr of records under this url </span>
</li>
</ul>
<h4>Some Other Subtitle</h4>
<ul>
<li>SomeUrl
<span> Nr of records under this url </span>
</li>
</ul>
</div>
</div>
Once more, I want to fetch all unordered list items under above html structure
I'm able to fetch divContent class content using
var regs = htmlDoc.DocumentNode.SelectSingleNode(#"//div[#class='outer']");
var descendant = regs.Descendants()
.Where(x => x.Name == "div" && x.Attributes["class"].Value == "divContent")
.Select(x => x.OuterHtml);
now I need expression to fetch ul li items.
This should work fine:
IEnumerable<string> listItemHtml = htmlDoc.DocumentNode.SelectNodes(
#"//div[#class='outer']/div[#class='divContent']/ul/li")
.Select(li => li.OuterHtml);
Example: https://dotnetfiddle.net/fnDPLB
Update based on comments below:
If you want to find only <li> elements belonging to <ul> elements that are direct siblings of an <h4> element with the value "SomeSubtitle", here's an XPath expression that should work:
//div[#class='outer'] // Get div.outer
/div[#class='divContent'] // under that div, find div.divContent
/h4[text()='SomeSubtitle'] // under div.divContent, find an h4 with the value 'SomeSubtitle'
/following::ul[1]/li // Get the first ul following the h4 and then get its li elements.
Example: https://dotnetfiddle.net/AfinpV

XPath query not working(need find by text)

Hello sow i working with HtmlAgilityPack and i have this problem all elemnts that i need have the same stractior and the same class exept the text of the span like in the code i have span with text Amount and Date sow i need to build link like this
"//span(with text=Amount)[div and contains(#class,'detailsValue ')]");
I need to get data 1,700,000.00 from the div that in the span with text 'Amount' and 14.04.2014 from the div that in the span with text 'Date'
Any ideas?
This what i have now
List<string> OriginalAmount = GetListDataFromHtmlSourse(PageData, "//span[div and contains(#class,'detailsValue ')]");
private static List<string> GetListDataFromHtmlSourse(string HtmlSourse, string link)
{
List<string> data = new List<string>();
HtmlAgilityPack.HtmlDocument DocToParse = new HtmlAgilityPack.HtmlDocument();
DocToParse.LoadHtml(HtmlSourse);
foreach (HtmlNode node in DocToParse.DocumentNode.SelectNodes(link))
{
if (node.InnerText != null) data.Add(node.InnerText);
}
return data;
}
<div class=" depositDetails cellHeight float " style="height: 37px;">
<span class=" detailsName darkgray ">Amount</span>
<br>
<div class="detailsValue float" style="direction:rtl">1,700,000.00 </div>
</div>
</div>
<div class="BoxCellHeight float">
<div class="cellHeight separatorvertical float" style="height: 46px;"> </div>
<div class=" depositDetails cellHeight float " style="height: 40px;">
<span class=" detailsName darkgray ">Date</span>
<br>
<div class="detailsValue float">14.04.2014</div>
</div>
</div>
Actually, the question is not very clear. How about this :
//span[.='Amount']/following-sibling::div[contains(#class,'detailsValue')]]
Above XPath will search for <span> element with text equals "Amount", then get it's following <div> sibling having class contains "detailsValue"
UPDATE :
According to your comment, if I don't misunderstand it, you want both value (div after Amount span and div after Date span). Try this XPath :
//span[.='Amount' or .='Date']/following-sibling::div[contains(#class, 'detailsValue')]

Find the node that has no children. If it has any <span> children, just ignore it

I'm using HTMLAgilityPack. I have something like this:
<div class="address">
<h3>Postadress</h3>
<div class="box-address">Box 27 </div>
<div class="post-address">
16493 KISTA
</div>
</div>
The problem is there are other <div class="address">s.
So I have to find the one that has a <h3> child with the text "Postaddress".
What I need to extract is the value of <div class="post-address"> that is "16493 KISTA".
There are other records returned for <div class="post-address"> that have children and I don't want those to be returned. I'm only looking for <div class="post-address"> that has no children and only contains naked text.
My solution so far is:
var postAddressdiv = doc.DocumentNode.SelectNodes("//div[#class='address']");
if (postAddressdiv != null)
{
foreach (HtmlAgilityPack.HtmlNode node in postAddressdiv)
{
HtmlNode postAddress;
var h3 = node.Descendants("h3");
if (h3 != null)
{
if (h3.First().LastChild.InnerHtml == "Postadress")
{
MessageBox.Show("right place you are.");
postAddress = node.SelectSingleNode("//div[#class='post-address']");
var postAddressChildren = postAddress.Descendants();
if (postAddressChildren == null)
MessageBox.Show("found one!!!!");
}
}
}
}
But it's not working. What am I doing wrong? Thanks.
var nodes = doc.DocumentNode
.SelectNodes("//div[#class='address' and h3='Postadress']/div[#class='post-address']");

Categories