Get the nested nodes in a string with Xpath or HtmlAgilityPack - sql

On the server, I am getting back a HTML snippet as a string via AJAX from the client JS. The contents are a nested DIV with ul, li items. HTML DIv snippet
<div> //please see link above
<ul class="tree" id="ulID" name="input">
<li><span class="vertical..."></span>
<div></span>1</div>
<ul>..
</div>
I am using C# HtmlAgilityPack, but I am not able to get the nested contents to extract the data, and add data back.
Below is some of the code.
HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
// nested
htmlDoc.OptionFixNestedTags=true;
bool failed = false;
// Use: htmlDoc.LoadHtml(htmlString);
// ParseErrors is an ArrayList
if (htmlDoc.ParseErrors != null && htmlDoc.ParseErrors.Count() > 0)
{
// Handle any parse errors as required
// check if string was JSON formatted
if (htmlDoc.LoadHtml(JSONdeserialize(htmlString)).ParseErrors.Count() > 0) failed = true;
}
else
{
if (htmlDoc.DocumentNode != null)
{
HtmlAgilityPack.HtmlNode bodyNode = htmlDoc.DocumentNode.SelectSingleNode("//ulID");
if (bodyNode != null)
{
// **how can I get the contents of the node here??****
// what is the xpath to get all the structured contents so I can walk the tree
// If option walk tree
// How can I build foreach(HTMLnode node in nodes) nested array
}
}
}
What is the Xpath to select all content in DOM string, when I don't have body, but simple Div enclosed string.
How can I extract all the nodes, and their contents at their nested levels
Any recommendations on how to save this structure? so I can easily recover it?

I am not sure the Xpath you have now is correct.
I am also unsure when the first ul tag ends. If it ends just before the div closes. Then you can just use this xpath.
"//ul[#id='ulID']"
Then you get the first ul htmlnode. Then you can iterate through its children.
I highly recommend you take a look at some xpath examples.

Related

Aurelia repeat.for generating an extra element

Problem
I have a repeat.for in my html markup bound to an array on my viewmodel. The array only has one element. However, the generation of the HTML always produces one extra undefined element.
This behavior only appears in one section of my code which makes it very hard to duplicate -- repeat.for is working everywhere else in my code.
Proof
So before you label me crazy and try to insist that my array must have more items than I think, have a look at my code and at the output from the Aurelia Inspector.
client.js
export class Client {
months = []
activate(id) {
...
this.loadData()
}
loadData(){
this.months.push("Item1")
}
client.html
<section class="scrollable">
${months.length}
<div repeat.for="month of months">
Index = ${$index}
</div>
</section>
My output looks like this:
1
Index = 0
Index = 1
If I use Aurelia Inspector, here is what I see:
Inspecting '1' = ${months.length}
Inspecting 'Index = 0' = ${$index}
Inspecting 'Index = 1' = ${$index}
Has anyone seen similar behavior with repeat.for? Any ideas as to what I might be doing wrong?

Getting error while inserting Customized String in xpath in Webdriver

Iam trying to locate elements in a webpage. Elements are arranged in rows. For all the rows(or elements), the common attribute is "pfobj". With the help of list interface i have listed out all the elements having attribute pfobj. While finding element with xpath iam getting error. I tried to insert srting pfobj inside xpath argument.
code for a particular element:
WebElement eachelement = driver.findElement(By.xpath("//*[#pfobj=\"pfobj1\"]"));
I want to run for all elements by using loop. so i need to insert "pfobj"(which will iterate by increasing the value) in the place of "pfobj1".
I have tried the several ways but iam getting error:
String slash1 = "\\";
String pfobj = pfobj1;
String slash2 = "\\";
String final = slash1 + pfobj + slash2
Can someone please help me out with this issue
You can try this code :
for ( WebElement element: List) {
if (element.getAttribute("pfobj").equals("pfobj")){
// do what you want
}
}
List is your element list
From what I take from this question is that there are several elements in your HTML having value of pfobj attribute as pfobj1, pfobj2, and so on.
If you want to compare all such elements in a loop, you can do like -
List<WebElement> your_list = driver.findElements(By.xpath("//input[contains(#pfobj,'pfobj')]"))
int counter = 1;
for(WebElement your_element : your_list )
{
if(your_element.getAttribute("pfobj").equals("pfobj" + counter))
{
//do whatever you want
}
counter++;
}

click only visible element selenium webdriverjs

I have multiple div like below
<div class="one">send Message</div>
<div class="one">send Message</div>
<div class="one">send Message</div>
I have a web page where there is send Message buttons like above, in which only one button is visible at a time.Other two buttons are hidden via some javascript codes.So for example if 2nd button is visible , I should be able to click only that element.But in my selenium code , its trying to click first hidden div and its failing
driver.findElements(by.className(".one")).then((els) => {
var element = els[index];
element.click();
});
So basically I wanna convert below javascript code to Selenium nodejs code,If some one guide me that will be helpful
var all = document.getElementsByTagName("*");
for (var i = 0, max = all.length; i < max; i++) {
if (isHidden(all[i]))
// hidden
else
// visible
}
function isHidden(el) {
var style = window.getComputedStyle(el);
return ((style.display === 'none') || (style.visibility === 'hidden'))
}
Do you want to click the button ( basically a div as far as code is concerned ) which is visible ?
If that is your main agenda, then the code you've written will fail to find desired element. As you are selecting the element by it's classname not its visibility.
Your code will find all the matched class element. As it's a basic element selector and all your buttons have the same class, so they are basically rendered on the page.
Approach 1
driver.findElements(by.className(".one")).then((els) => {
for(var key in els){
var element = els[key];
if(element.isDisplayed()){ //if visible element
element.click();
}
}
});
The Key here is to check if the element you are trying to click is visible on the page.
Approach 2
By giving a unique class to the target button. Some class for eg 'clickable' or 'active'. So it will be a more optimized solution to select the target element using the Css selector. The Key here is to give uniqueness to your target element to be more identifiable.
Usually many Java Scripts are run in the node Js without the convert.
Have you try it in the node Js without converting ???
** Remember to import selenium

Locating Element with same class in Selenium using c#

I am trying to access ABC. I know that simple By.ClassName("bb") will not work here. How else can I access this content.
<body>
<div id="Frame">
<div class="bb"></div>
<div class="bb">ABC</div>
</div>
</body>
You can use the below css selector to get the value of "ABC".
.bb:nth-child(2)
You can use "XPath" Expression to find or locating your element.
Example : element = findElement(By.xpath("Your xpath expression");
For your XML use following line.
element = findElement(By.xpath("/body/div/div[#class='bb'][node()]");
There is a way to do this in the search using XPath but I am not an XPath expert. I can give you a solution using CSS Selectors. Basically you grab all the DIVs with class bb and then search their text to find the desired text.
String searchText = "ABC";
IReadOnlyCollection<IWebElement> divs = driver.FindElements(By.CssSelector("div.bb"));
foreach (IWebElement div in divs)
{
if (div.Text == searchText)
{
break; // exit the for and use the variable 'div' which contains the desired DIV
}
}

Dojo disable all input fields in div container

Is there any way to disable all input fields in an div container with dojo?
Something like:
dijit.byId('main').disable -> Input
That's how I do it:
dojo.query("input, button, textarea, select", container).attr("disabled", true);
This one-liner disables all form elements in the given container.
Sure there is. Open up this form test page for example, launch FireBug and execute in the console:
var container = dojo.query('div')[13];
console.log(container);
dojo.query('input', container).forEach(
function(inputElem){
console.log(inputElem);
inputElem.disabled = 'disabled';
}
)
Notes:
On that test page form elements are actually dijit form widgets, but in this sample I'm treating them as if they were normal input tags
The second dojo.query selects all input elements within the container element. If the container had some unique id, you could simplify the sample by having only one dojo.query: dojo.query('#containerId input').forEach( ...
forEach loops through all found input elements and applies the given function on them.
Update: There's also a shortcut for setting an attribute value using NodeList's attr function instead of forEach. attr takes first the attribute name and then the value or an object with name/value pairs:
var container = dojo.query('div')[13];
dojo.query('input', container).attr('disabled', 'disabled');
Something else to keep in mind is the difference between A Dijit and a regular DomNode. If you want all Dijit's within a DomNode, you can convert them from Nodes -> Dijit refs with query no problem:
// find all widget-dom-nodes in a div, convert them to dijit reference:
var widgets = dojo.query("[widgetId]", someDiv).map(dijit.byNode);
// now iterate over that array making each disabled in dijit-land:
dojo.forEach(widgets, function(w){ w.attr("disabled", "disabled"); }
It really just depends on if your inputs are regular Dom input tags or have been converted into the rich Dijit templates (which all do have a regular input within them, just controlled by the widget reference instead)
I would do it like this:
var widgets;
require(["dijit/registry", "dojo/dom"], function(registry, dom){
widgets = registry.findWidgets(dom.byId(domId));
});
require(["dojo/_base/array"], function(array){
array.forEach(widgets, function(widget, index) {
widget.set("disabled", true);
});
});
Method findWidgets is essential to get all widgets underneath a specific DOM.