Get all elements in a NodeCollections - c#

I have an html file :
<div class="form-wrapper">
<div></div>
<div class="Clearfix">
<div></div>
<div></div>
<span></span><span class="time">Time</span>
</div>
<div></div>
<div class="Clearfix">
<div></div>
<div></div>
<span></span><span class="time">Time1</span>
</div>
<div></div>
<div class="Clearfix">
<div></div>
<div></div>
<span></span><span class="time">Time2</span>
</div><div></div>
<div class="Clearfix">
<div></div>
<div></div>
<span></span><span class="time">Time3</span>
</div>
I'm using the c# code below to get all the times items :
var node_1 = htmlDocument.DocumentNode.SelectNodes("//div[#class='form-wrapper']").First();
var ITEM = node_1.SelectNodes("//div[#class='clearfix']");
for (int Node = 0; Node < ITEM.Count; Node++)
{
Console.WriteLine(ITEM[Node].SelectNodes("//span[#class='time']")[1].InnerText.Trim());
}
Console.ReadKey();
I'm taking the First() "Form-wrapper" since they're many .
I tried to use this too :
foreach (var Node in node_1.SelectNodes("//div[#class='clearfix']"))
{
//
}
Issue is : as you can see I have 4 Clearfix Classes so i need to get the result :
Time
Time1
Time2
Time3
but for some reasons i only get :
Time
Time
Time
Time

When you are querying over some node you don't need // at the beginning, if you are adding it query will be executed over whole document.
You need to take first node after selecting, so you need to take node with index 0 not 1
This 2 points will solve your problem, but there are some improvements you can do
Instead of SelecNodes().First() you can user SelectSingleNode()
If you don't need any information about parent nodes you can directly query
for child nodes - htmlDocument.SelectNodes("\\span[#class='time']") will do all the work

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);

Selenium C# unable to get the list using FindElements

0 ,C# and NUnit.
The problem I am facing is that I need to fetch out the value from a span and store into an arraylist.
I am Using the below code to fetch the price list
var productprice = driver.FindElements(By.CssSelector(".price.mb-10.text-right "));
from the HTML given below
<div class="pl-sec">
<ul>
<li class="row-fluid">
<li class="row-fluid">
<div class="span2">
<div class="span7 disc-content">
<div class="span3 price-content">
<div class="price mb-10 text-right"> £14.99</div>
<div class="full-width mb-20">
</div>
</li>
<li class="row-fluid">
<div class="span2">
<div class="span7 disc-content">
<div class="span3 price-content">
<div class="price mb-10 text-right"> £16.99</div>
<div class="full-width mb-20">
</div>
</li>
I do get the list but am unable to fetch the text from the elements I got using the css selector.
Below is the watch from visual studio.
- [0] {OpenQA.Selenium.Firefox.FirefoxWebElement} OpenQA.Selenium.IWebElement {OpenQA.Selenium.Firefox.FirefoxWebElement}
+ [OpenQA.Selenium.Firefox.FirefoxWebElement] {OpenQA.Selenium.Firefox.FirefoxWebElement} OpenQA.Selenium.Firefox.FirefoxWebElement
Displayed true bool
Enabled true bool
+ Location {X = 802 Y = 793} System.Drawing.Point
Selected false bool
+ Size {Width = 164 Height = 14} System.Drawing.Size
TagName "div" string
Text "£16.99" string
I need to fetch the 'Text' with price given in the above watch.
Sorry if its unclear .I am a bit new to this.
Finally Fixed it.
The issue was that the var used to store elements stored elements as an arraylist and had to find the position and then dig into the Text property.
Below is the corrected code-
driver.FindElement(By.XPath("//div[4]/div[2]/ul/li[2]/label")).Click();
//This below codes gets the count of product displayed by checking the prince.
var productprice = driver.FindElements(By.CssSelector(".price.mb-10.text-right "));
//var productprice = driver.FindElement(By.XPath("//div[#class='price.mb-10.text-right']")).Text;
string strval = "";
strval = productprice[5].Text;

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.

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')]

how to get html div element innertext by id using regular expression in C#

I'm getting full html code using WebClient. But i need to get specified div from full html using regular expression.
for example:
<body>
<div id="main">
<div id="left" style="float:left">this is a <b>left</b> side:<div style='color:red'> 1 </div>
</div>
<div id="right" style="float:left"> main side</div>
<div>
</body>
if i need div named 'main', function return
<div id="left" style="float:left">this is a <b>left</b> side:<div style='color:red'> 1 </div>
</div>
<div id="right" style="float:left"> main side</div>
If i need div named 'left', function return
this is a <b>left</b> side:<div style='color:red'> 1 </div>
If i need div named 'right', function return
main side
How can i do?
Why do people insist on trying to use regex to parse html? You can probably do it if you exclude a whole host of edge-cases... but just use HTML Agility Pack and you're done:
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(...); // or Load
string main = doc.DocumentNode.SelectSingleNode("//div[#id='main']").InnerHtml;
(note I'm assuming it is not xhtml; if it is xhtml, use XmlDocument or XDocument, and very similar code to the above)
string divname = "somename";
Match m = RegEx.Match(htmlContent, "<div[^>]*id="+divname+".*?>(.*?)</div");
string contenct = m.Groups[1].Tostring();
won't work if you have nested divs inside the desired div

Categories