Href attribute empty when selecting anchor with xpath - html

I have a number of links in a page that look like so :
<a class="plant_detail_link" href="plants/O7-01111"><h3>O7-01111</h3></a>
I can select all these link in my page with the following xpath :
//a[#class='plant_detail_link']
I can extract attributes like the class of each link in the usual manner :
//a[#class='plant_detail_link']/#class
But when I attempt to use the same technique to extract the href attribute values I get an empty list :
//a[#class='plant_detail_link']/#href
Does anyone have any ideas why this may be the case?
image detailing chrome developer console xpath execution
EDIT:
See full page html here - http://pastebin.com/MAjTt86V

it's a chrome bug, I believe. You can add the [index].value to get the result. In other words, the $x for href did work but it doesn't return the result in the output for some reason.
For example, I ran these $x queries in the console on this page for the 'Questions' button and got the following output:
$x("//a[#id='nav-questions']/#href")
> []
$x("//a[#id='nav-questions']/#href")[0].value
> "/questions"
You can use something like this to get a usable array of values:
var links = $x("//a[#target='_blank']/#href");
var linkArr = [];
for (i in links) { linkArr.push(links[i].value)}
or to put it in a function:
function getHref(selector, value, $x) {
var links = $x("//a[#"+selector+"='"+value+"']/#href");
var linkArr = [];
for (i in links) { linkArr.push(links[i].value)};
return linkArr; }
getHref("target","_blank", $x);
EDIT
Not sure if this will help you but in chrome adding a comma like this returns the output without the [index].value:
$x,("//a[#id='nav-questions']/#href")
> "//a[#id='nav-questions']/#href"
you could try adding a comma to the xpath selector but I'm not sure if it will help in your case.

Related

Check <head> contains specific <link> without JQuery

Is it possible to check that the <head> contains a specific <link> tag?
For example I would add a link to the head:
let link = document.createElement('link');
link.href = 'https://my.path.css';
link.type = 'text/css';
link.rel = 'stylesheet';
document.head.append(link);
Is it then possible to check that it is present within the head?
I know that I can get an HTMLCollection with
const headChildren = document.getElementsByTagName('head')[0].children;
But I can't seem to navigate this to check...
The reason you can't "navigate" headChildren is because it's an 'iterable' but not officially an array.
Use Array.from to convert it then you can treat it like a normal array.
let actualArray = Array.from(headChildren)
You can also iterate over 'iterables' with a for of loop:
for (let child of headChildren) {
console.log(child)
}
I would use querySelectorAll and not children. I would convert the HTML collection to an array and use some to loop over the collection to find a match with the href.
const exist = Array.from(
document.querySelectorAll('link[rel="stylesheet"]')
).some(link => link.href === 'https://my.path.css')
The suggestions for the loop were only half of the solution I required.
I wanted a simple way to check that the exact tag that I had created and pushed into the was present.
I attempted all the different types of equality to no avail. '==' and '===' wouldn't work I'm assuming because of referring to object identities etc like Strings suffer from.
I found the solution with `.isEqualNode' which equates two nodes.
Therefore my solution in the end was:
const headChildren = document.getElementsByTagName('head')[0].children;
for (let child or headChildren) {
if (child.isEqualNode(myLinkNode) {
// Do something
}
}

How to access html element text in chrome devtools console

I have a page with a whole bunch of blackquote tags.
In dev console I am typing document.getElementsByTagName("blockquote") that giving me an array.
But if I do document.getElementsByTagName("blockquote").innerText document.getElementsByTagName("blockquote").innerHTML document.getElementsByTagName("blockquote").textContent
document.getElementsByTagName("blockquote").outerText document.getElementsByTagName("blockquote").outerHTML
All return undefined
However if I inspect elements of the array document.getElementsByTagName("blockquote") I can see all above properties in place.
How to access at least one of them (innerText, outerHTLM, innerText, outerHTML, textContent) ?
Or if you want to access any specific element you can use index in array
for (var i=0; i <document.getElementsByTagName("blockquote").length; i++ ){
var singleElement = document.getElementsByTagName("blockquote")[i];
console.log(singleElement.innerHTML);
}
You need to iterate the array in order to access those properties. Something like this will work for them:
var elements = document.getElementsByTagName("blockquote");
for (var prop in elements)
{
if(elements.hasOwnProperty(prop)) {
console.log(elements[prop].innerHTML);
}
}
You can also try the following commands:
var elements = document.getElementsByTagName("blockquote");.This will return the list of elements.To access the text of your required element at i index
elements[i].value.

Jsoup filter out only some tags from html to text

can any master of jsoup tell me some suggestions to filter html to text/string? I've tried calling text() of Document. But all tags/elements will be filtered. My aim is to filter some specified tags.
i.e: I've html text like:
<div>hello<p>world</div>,<table><tr><td>xxx</td></tr>
to get result:
<div>hello<p>world</div>,xxx
which has filtered tags.
I can't test this right now but I think you want to write a recursive function that steps through the tree and prints each node based on a condition. The following is an example of what it might look like but I expect that you will have to modify it to suit your needs more precisely.
Document doc = JSoup.parse(page_text);
recursive_print(doc.head());
recursive_print(doc.body());
...
private static Set<String> ignore = new HashSet<String>(){{
add("table");
...
}};
public static void recursive_print(Element el){
if(!ignore.contains(el.className()))
System.out.println(el.html());
for(Element child : el.children())
recursive_print(child);
}
You can use Whitelist to achieve this goal. For example:
Whitelist whiteList = new Whitelist();
whiteList.addTags("div", "p", "td");
It means that all other tags will be removed.

GetJSON and using a Show More link

I'm using getJSON to get data from the facebook pages api, and it works just fine, using this code:
$(document).ready(function(){
$.getJSON('url',function(json){
$.each(json.data,function(i,fb){
var output='';
//here I add to output, as this example line:
output += '<div"><a href="http://www.facebook.com/profile.php?id='+fb.from.id+'>'+fb.from.name+'</a>';
$("#results").append(output);
});
});
However, what I'd like to do is similar to what facebook does in it's social plug in where it starts off with 5 entries and has a Show More link, which when clicked, brings in 5 more entries.
Is there a way to do this by altering the code I have?
Thanks
Well, sure there is. Do you want to fetch the other results when a user clicks the "more link" to save bandwidth or is it OK to fetch it at the same time? (async vs sync)
This answer considers the bold text:
output += '<div' + (i >= 5 ? ' style="display: none;"' : '') + '><a href="http://www.facebook.com/profile.php?id=' + fb.from.id +'>'+fb.from.name+'</a></div>';
Oh, and check that line in your code, you had a syntax error and an unmatched div. Also you should have quotation marks around your HTML element's attributes.
For showing the links when the more link is clicked you could do something like:
$('.more').click(function() {
$(this).hide();
// Find the closest ancestor which is a parent of both
// the more link and the actual results list
var $parent = $(this).closest('.parentSelector');
$('.listSelector', $parent).children().show();
return false; // Don't follow the link
});
The parts with the parent stuff above is for the case when you have multiple such results list on the same page and you need to separate them. If you don't need it, here is a simpler variant:
$('.more').click(function() {
$(this).hide();
$('#results').children().show(); // Show all other list items
return false; // Don't follow the link
});

Sending values through links

Here is the situation: I have 2 pages.
What I want is to have a number of text links(<a href="">) on page 1 all directing to page 2, but I want each link to send a different value.
On page 2 I want to show that value like this:
Hello you clicked {value}
Another point to take into account is that I can't use any php in this situation, just html.
Can you use any scripting? Something like Javascript. If you can, then pass the values along in the query string (just add a "?ValueName=Value") to the end of your links. Then on the target page retrieve the query string value. The following site shows how to parse it out: Parsing the Query String.
Here's the Javascript code you would need:
var qs = new Querystring();
var v1 = qs.get("ValueName")
From there you should be able to work with the passed value.
Javascript can get it. Say, you're trying to get the querystring value from this url: http://foo.com/default.html?foo=bar
var tabvalue = getQueryVariable("foo");
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++)
{
var pair = vars[i].split("=");
if (pair[0] == variable)
{
return pair[1];
}
}
}
** Not 100% certain if my JS code here is correct, as I didn't test it.
You might be able to accomplish this using HTML Anchors.
http://www.w3schools.com/HTML/html_links.asp
Append your data to the HREF tag of your links ad use javascript on second page to parse the URL and display wathever you want
http://java-programming.suite101.com/article.cfm/how_to_get_url_parts_in_javascript
It's not clean, but it should work.
Use document.location.search and split()
http://www.example.com/example.html?argument=value
var queryString = document.location.search();
var parts = queryString.split('=');
document.write(parts[0]); // The argument name
document.write(parts[1]); // The value
Hope it helps
Well this is pretty basic with javascript, but if you want more of this and more advanced stuff you should really look into php for instance. Using php it's easy to get variables from one page to another, here's an example:
the url:
localhost/index.php?myvar=Hello World
You can then access myvar in index.php using this bit of code:
$myvar =$_GET['myvar'];
Ok thanks for all your replies, i'll take a look if i can find a way to use the scripts.
It's really annoying since i have to work around a CMS, because in the CMS, all pages are created with a Wysiwyg editor which tend to filter out unrecognized tags/scripts.
Edit: Ok it seems that the damn wysiwyg editor only recognizes html tags... (as expected)
Using php
<?
$passthis = "See you on the other side";
echo '<form action="whereyouwantittogo.php" target="_blank" method="post">'.
'<input type="text" name="passthis1" value="'.
$passthis .' " /> '.
'<button type="Submit" value="Submit" >Submit</button>'.
'</form>';
?>
The script for the page you would like to pass the info to:
<?
$thispassed = $_POST['passthis1'];
echo '<textarea>'. $thispassed .'</textarea>';
echo $thispassed;
?>
Use this two codes on seperate pages with the latter at whereyouwantittogo.php and you should be in business.