I am just learning html agility pack and would like to extract a couple pieces of data from a website.
I want to store the item name and price into strings. I have html source code that contains 25 products
with 1 segment of the code posted below
I have very little xpath and html agility pack experience. and I am working on a class project to compare lowes and home depot prices for a few items.
I want to save string data_price = "14.97"; and string item = "Leaktite 5-Gal. Blue Bucket (Pack of 3)"
below is a portion of the source code I am working with
<div class="pod-inner">
<div class="productlist plp-pod__compare">
<div class="checkbox-btn js-podclick-analytics" data-podaction="compare">
<input type="checkbox" data-img="https://images.homedepot-static.com/productImages/8c1c50a0-e17c-4624-9e9e-35653052c1ce/svn/leaktite-paint-buckets-lids-209334-64_400_compressed.jpg" data-uom=" /package" data-price="$14.97" data-title="Leaktite 5-Gal. Blue Bucket (Pack of 3)" value="203924937" id="compare203924937" name="product" autocomplete="off" class="checkbox-btn__input">
so far I got
HtmlDocument doc = new HtmlDocument();
string home_bucket_url="https://www.homedepot.com/s/5%2520gallon%2520bucket?NCNI-5";
WebClient client = new WebClient();
string home_bucket_raw = client.DownloadString(home_bucket_url);
var findclasses = doc.DocumentNode.Descendants("input type").Where(d => d.Attributes.Contains("checkbox"));
foreach (var x in findclasses)
{
Console.WriteLine(x.ToString());
}
If you successfully selected node that you need (please debug to make sure), what you can do is simply get the attribute values that you need. Something like this:
x.Attributes["data-price"].Value;
x.Attributes["data-title"].Value;
so as you read title, i need help with magento static block, my task is to make static block content different in 2 shops, if it's even possible? ty for answers.
P.S. Sorry for bad english.
FYI the correct Magento way to do this in multi-store is to create 2 static block with the same ID and assign each one to the store view you want it to show on. Magento will load the correct version based on the current store being viewed.
Try this one it works for me. I made it with html/javascript. You can get store name by
var shopName= '{{config path="general/store_information/name"}}';
and then compare by your needs. Paste code into static block editor.
<!DOCTYPE html>
<html>
<body onload="websiteMessage()">
<p>Happy new years !!!</p>
<p id="static_block"></p>
<script>
function websiteMessage() {
var shopName= '{{config path="general/store_information/name"}}';
var string = "";
if(shopName.localeCompare("Leather_shoes_shop") == 0)
{
string = "leather shoes";
}
else if(shopName.localeCompare("Rubber_shoes_shop") == 0)
{
string = "rubber shoes";
}
else
{
string = "other";
}
document.getElementById('static_block').innerHTML = string;
}
</script>
</body>
</html>
I am using code like this to detect the browser and apply a condition to display or not display <label>:
#{
var settings = Model.PartFieldDefinition.Settings.GetModel();
System.Web.HttpBrowserCapabilitiesBase theBrow = Request.Browser;
}
<fieldset>
#{
if ((theBrow.Browser == "IE") && (theBrow.MajorVersion < 10))
{
#:<label>#Model.DisplayName</label>
#://Some Code for inputs
}
else
{
#://Some Code for inputs
}
}
</fieldset>
I have been trying to figure out if I can (and if so, how) I could utilize this logic to detect what path in the website the user is in to display or not display <label>
For example, on any other path I want the label displayed. However, for the pages under ~/Services (the path), I want to be able to hide the label.
It's a little bit more complicated than that. The code is in an editor template that gets used all over the site. If I use CSS in the editor template to "hide" the label I will affect all the pages. I was hoping with the above logic I can avoid that and only apply my logic on certain pages under a path.
Thanks.
Update
I have tried the following:
#{
string CurrentURL = Request.ApplicationPath;
}
<fieldset>
#{
if ((CurrentURL == "Services")) // also tried "/Services"
// rest of code left out for brevity
}
but the labels are hidden on all pages, even outside the path "~/Services". Am stuck on the syntax.
Found answer
I did the following:
#{
string CurrentURL = Request.Url.AbsoluteUri;
}
<fieldset>
#{
if (CurrentURL.Contains("Services"))
}
and it worked. I don't know if anyone can comment, but which would be better to use: Request.Url.AbsoluteUri or Request.Url.ToString() (both of which work)?
I have set of code for updating a password in the table, here I'm using CGI::AJAX module to update the password and get the popup screen on corresponding execution.When using that code with my application it is executing properly but I didn't get the output(means Perl subroutine is not called when JavaScript function to get use.password is not updated into table). I don't get any error either.
#!/usr/bin/perl -w
use strict;
use CGI;
use DBI;
use Data::Dumper;
my $p = new CGI qw(header start_html end_html h1 script link);
use Class::Accessor;
use CGI::Ajax;
my $create_newuser;
my $ajax = new CGI::Ajax('fetch_javaScript' => $create_newuser);
print $ajax->build_html($p,\&Show_html,{-charset=>'UTF-8', -expires=>'-1d'});
sub Show_html
{
my $html = <<EOHTML;
<html>
<body bgcolor="#D2B9D3">
<IMG src="karvy.jpg" ALT="image">
<form name='myForm'>
<center><table><tr><td>
<div style="width:400px;height:250px;border:3px solid black;">
<center><h4>Create New Password's</h4>
<p>  User Name</b>       <INPUT TYPE="text" NAME="user" id = "user" size = "15" maxlength = "15" tabindex = "1"/></p>
<p>  Password:</b>         <INPUT TYPE=PASSWORD NAME="newpassword" id = "newpassword" size = "15" maxlength = "15" tabindex = "1"/></p>
<p>  Re-Password:</b>   <INPUT TYPE=PASSWORD NAME="repassword" id = "repassword" size = "15" maxlength = "15" tabindex = "1"/></p>
<input type="submit" id="val" value="Submit" align="middle" method="GET" onclick="fetch_javaScript(['user','newpassword','repassword']);"/><INPUT TYPE="reset" name = "Reset" value = "Reset"/>
<p>Main Menu <A HREF = login.pl>click here</A>
</center>
</div>
</td></tr></table></center>
</form>
</body>
</html>
EOHTML
return $html;
}
$create_newuser =sub
{
my #input = $p->params('args');
my $user=$input[0];
my $password=$input[1];
my $repassword=$input[2];
my $DSN = q/dbi:ODBC:SQLSERVER/;
my $uid = q/123/;
my $pwd = q/123/;
my $DRIVER = "Freetds";
my $dbh = DBI->connect($DSN,$uid,$pwd) or die "Coudn't Connect SQL";
if ($user ne '')
{
if($password eq $repassword)
{
my $sth=$dbh->do("insert into rpt_account_information (user_id,username,password,user_status,is_admin) values(2,'".$user."','".$password."',1,1)");
my $value=$sth;
print $value,"\n";
if($value == 1)
{
print 'Your pass has benn changed.Return to the main page';
}
}
else
{
print "<script>alert('Password and Re-Password does not match')</script>";
}
}
else
{
print "<script>alert('Please Enter the User Name')</script>";
}
}
my $create_newuser;
my $ajax = new CGI::Ajax('fetch_javaScript' => $create_newuser);
...;
$create_newuser =sub { ... };
At the moment when you create a new CGI::Ajax object, the $create_newuser variable is still undef. Only much later do you assign a coderef to it.
You can either assign the $create_newuser before you create the CGI::Ajax:
my $create_newuser =sub { ... };
my $ajax = new CGI::Ajax('fetch_javaScript' => $create_newuser);
...;
Or you use a normal, named subroutine and pass a coderef.
my $ajax = new CGI::Ajax('fetch_javaScript' => \&create_newuser);
...;
sub create_newuser { ... }
Aside from this main error, your script has many more problems.
You should use strict instead of the -w option.
For debugging purposes only, use CGI::Carp 'fatalsToBrowser' and sometimes even with warningsToBrowser can be extremely helpful. Otherwise, keeping a close eye on the error logs is a must.
my $p = new CGI qw(header start_html end_html h1 script link) doesn't make any sense. my $p = CGI->new should be sufficient.
use Class::Accessor seems a bit random here.
The HTML in Show_html is careless. First, your heredocs allows variable interpolation and escape codes – it has the semantics of a double quoted string. Most of the time, you don't want that. Start a heredoc like <<'END_OF_HTML' to avoid interpolation etc.
Secondly, look at that tag soup you are producing! Here are some snippets that astonish me:
bgcolor="#D2B9D3", align="middle" – because CSS hasn't been invented yet.
<center> – because CSS hasn't been invented yet, and this element isn't deprecated at all.
<table><tr><td><div ... </div></td></tr></table> – because there is nothing wrong with a table containing a single cell. (For what? This isn't even for layout reasons!) This table cell contains a single div …
… which contains another center. Seriously, what is so great about unneccessary DOM elements that CSS isn't even an option.
style="width:400px;height:250px;border:3px solid black;" – because responsive design hasn't been invented yet.
<p> ... </b> – Oh, what delicious tag soup!
        – this isn't a typewriter, you know. Use CSS and proper markup for your layout. There is a difference between text containing whitespace, and empty areas in your layout.
tabindex = "1" … tabindex = "1" … tabindex = "1" – I don't think you know what tabindex does.
<A HREF = login.pl> – LOWERCASING OR QUOTING YOUR ATTRIBUTES IS FOR THE WEAK!!1
onclick="fetch_javaScript(['user','newpassword','repassword']);" – have you read the CGI::Ajax docs? This is not how it works: You need to define another argument with the ID of the element where the answer HTML is displayed.
In your create_newuser, you have an SQL injection vulnerability. Use placeholders to solve that. Instead of $sth->do("INSERT INTO ... VALUES('$foo')") use $sth->do('INSERT INTO ... VALUES(?)', $foo).
print ... – your Ajax handler shouldn't print output, instead it should return a HTML string, which then gets hooked into the DOM at the place your JS function specified. You want something like
use HTML::Entities;
sub create_newuser {
my ($user, $password, $repassword) = $p->params('args');
my ($e_user, $e_password) = map { encode_entities($_) } $user, $password;
# DON'T DO THIS, it is a joke
return "Hello <em>$e_user</em>, your password <code>$e_password</code> has been successfully transmitted in cleartext!";
}
and in your JS:
fetch_javaScript(['user','newpassword','repassword'], ['answer-element'], 'GET');
where your HTML document somewhere has a <div id="answer-element" />.
I have created some Razor code to output images onto a page if the exist. It is detailed below and contains some simple checks to prevent rendering a blank list item. The site has gone live and works fine. The client then deleted the image from the media folder within Umbraco, meaning my node had a valid image assigned but the image just didn't exists. I got the following exception:
'string' does not contain a definition for 'crops'
How do I deal with this?
#using umbraco.MacroEngines;
#inherits umbraco.MacroEngines.DynamicNodeContext
#using umbraco.presentation.nodeFactory
#using umbraco.cms.businesslogic.media
<ul>
#foreach (dynamic client in #Model.Children)
{
var image = Model.MediaById(client.Logo);
var crops = image.imageCropper.crops;
<li>
<h2><span>#client.Name</span></h2>
#if (crops != null || crops.GetType().ToString() != "System.String")
{
<span class="itemImage">
<img src="#crops.Find("#name", "cropname").url" alt="#client.Name" />
</span>
}
</li>
}
</ul>
In this case you'll probably need to do a type check. I believe the MediaById method should return a DynamicNode if it's valid, so something like the following should work:
if(image.GetType() == typeof(DynamicNode))
{
...
}
I was getting this issue. What I found is that the Model.MediaById(imageid) call would throw an exception if the Media had been deleted (and had already been picked in the past).
So I setup my test like this:
dynamic mainMediaImage = new DynamicNull();
try
{
mainMediaImage = Model.MediaById(related.eventMainImage);
}
catch(Exception e)
{
<p style='display: none;'>#e.Message</p>
}
var cropUrl = "";
if(mainMediaImage.GetType() == typeof(DynamicMedia))
{
cropUrl = GetImageCropperUrl(Model.MediaById(related.eventMainImage).crops, "List Image");
}
I still get the error, but it doesn't display to the user.
I found it would never get to my DynamicMedia check so I had to add the try...catch() around the call or else to entire Macro would fail.