Parse HTML using Xpath? - html

I want to help my problem is: I get the data but the data obtained in duplicate. Thank you.
HTML
<div id="items" style="width: 940px; height: 2176px; position: relative;">
<div class="item masonry-brick" style="top: 0px; right: 0px; position: absolute;">
<div class="picture">
<a title="bikini" class="image" href="...-bikini.html">
<img alt="bikini" src="...13508.jpg">
</a>
<div class="item-content">
<h2>bikini</h2>
<div class="item_social">
<ul>
<li><i class="fa fa-eye"></i><span>6</span></li>
<li><i class="fa fa-thumbs-o-up"></i><span>0</span></li>
<li><i class="fa fa-comments"></i><span>0</span></li>
</ul>
</div>
<div class="author-post">
<a class="author" href="....nuong" rel="nofollow">
<img class="author_avatar" alt="nương" src="....ae3c3d8a6a.png">
<span class="author_name">nương</span>
<ul class="author_item">
<li><span>13 giờ trước </span></li>
</ul>
</a>
</div>
</div>
</div>
</div>
//..... more item masonry-brick
</div>
My code C# parsing "but the data obtained in duplicate image and text!",but full item number.
HtmlDocument htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml(htmlPage);
List<Data> datas = new List<Data>();
foreach (var div in htmlDocument.DocumentNode.SelectNodes("//div[starts-with(#class, 'item')]"))
{
Data newdata = new Data();
newdata.Imgsrc = div.SelectSingleNode("//div[#class='picture']//img").Attributes["src"].Value;
newdata.Title = div.SelectSingleNode("//div[#class='item-content']//h2").InnerText.Trim();
newdata.Summary = div.SelectSingleNode("//div[#class='author-post']//span").InnerText.Trim();
datas.Add(newdata);
}
lstDatas.ItemsSource = datas;
Thanks you!

You need to add period/dot (.) at the beginning of your XPath to indicate that the XPath searching scope is local within current div context :
foreach (var div in htmlDocument.DocumentNode.SelectNodes("//div[starts-with(#class, 'item')]"))
{
Data newdata = new Data();
newdata.Imgsrc = div.SelectSingleNode(".//div[#class='picture']//img").Attributes["src"].Value;
newdata.Title = div.SelectSingleNode(".//div[#class='item-content']//h2").InnerText.Trim();
newdata.Summary = div.SelectSingleNode(".//div[#class='author-post']//span").InnerText.Trim();
datas.Add(newdata);
}
Otherwise, the XPath will search within entire HtmlDocument and return the first matched node again and again in every iteration, that's why you got those duplicates.

Related

Angular Emptying A Shopping Cart

Hello I have a shopping cart which I am able to add products as well as delete products using a api . When deleting an item from cart it has to be deleted using a button click on each item by id, one by one. which is fine for that purpose, but I am trying to do empty all items in cart url from a function not a button which has not worked for me because id will be undefined.
My question is, if this is even possible? I have tried clearing the array of items such as cartItems.length = 0 or cartItems = [] this only empties a copy of the array from my understanding, so therefore the items will still exist in the cart from what I have tried.
I'm reaching out to see if anyone can answer this and point me in the right direction it will be greatly appreciated. I have included a snippet of of html and the cart service for the delete item.
cart service
RemoveProductFromCart(id:number):Observable<void>{
return this.http.delete<CartItem[]>(`${this.cartUrl}/${id}`)
.pipe(catchError(_err => of (null))
);
}
cartitem.ts
handleRemoveFromCart(){
alert("hit remove from cart");
this.cartService.RemoveProductFromCart(this.cartItem.id)
.subscribe(() =>
console.log("Product with Id deleted",
this.cartItem.id),
(err) => console.log(err)
);
}
html for cartitem
<div class="container-md" >
<div>
<img class="img-fluid" [src]="cartItem.imageUrl" style="padding-bottom:5px; padding-top:50px" alt="Cart">
<div class="text-nowrap" style="font-size:13px; width: 400px">{{cartItem.productName}}</div>
{{cartItem?.size}}{{Valuesize}}
<div style="font-size:13px;"><strong>{{ (cartItem.price) | currency}}</strong></div>
<div class=" float-right">
<span><i class="fa-solid fa-trash-can" style="color:#D30169; cursor: pointer;" (click)="handleRemoveFromCart();handleReload()"></i></span>
</div>
</div>
</div>
cart html
<div *ngIf="cartItems.length === 0"class="alert alert-
info">Your Cart is Empty</div>
<div *ngIf="product">
<div>{{product.name}}</div>
<input type="number" [(ngModel)]="product.num"
min="0"/>
</div>
<div *ngFor="let item of cartItems; let i = index">
<app-cart-item [cartItem]="item"></app-cart-item>
</div>
<li class="list-group-item" style="margin-top:30px;">
<strong>Total Items {{itemTotal}}</strong>
</li>
<li class="list-group-item active">
<strong>Total: {{ cartTotal | currency}}</strong>
</li>
<li class="btn btn-primary" style="height: 40px;
width:210px; margin-top:20px; color:ffffff">
<a class="" routerLink="/clothing" style="color:
#ffffff; cursor: pointer;">Continue
Shopping</a>
</li>
<li class= "btn" style="height: 40px; width:210px;
margin-top: 20px; background-color:#D30169">
<a class="" routerLink="/checkout" style="color:
#ffffff">Go To Checkout</a>
</li>
</div>
</div>
</div
Have a look into Rxjs
cart.service.ts
Create a behavior subject of cart items
cartItems$ = new BehaviorSubject<CartItem>([]);
To clear all the items
clearCart() {
this.cartItems$.next([]);
}
To add or remove an item
addToCart(cartItem: CartItem) {
this.cartItems$.next([cartItem, ...this.cartItems.getValue()]);
}
removeFromCart(cartItemId: string) {
this.cartItems$.next([this.cartItems.getValue().filter((cartItem) => cartItem.id !== cartItemId)]);
}
cartItem.ts
To subscribe to cartItems
cartItems:CartItem[] = []
constructor(private cartService: CartService) {
this.cartService.cartItems$.subscribe((v) => (this.cartItems = v));
}
Don't forget to unsubscribe

Using Element.insertAdjacentHTML to add 'Blocks' of HTML

I'm trying to insert the following 'block' of HTML using Element.insertAdjacentHTML()
<div class="content-wrapper">
<ul>
<li class="go-back-environment">
<a href="/environment">
<p>Back to Environment</p>
</a>
</li>
<li class="back-home">
<a href="/home">
<p>Back to home</p>
</a>
</li>
</ul>
</div>
However, I'm not sure it is possible to add divs with classes and lists. I've been trying to find (unsuccessfully) articles with examples where more than one 'p' or 'span' was added.
I started with the following but I don't know how to continue building:
var footer = document.getElementById ('environment');
footer.insertAdjacentHTML('afterend','')
I tried the following:
<script>
var footer = document.getElementById ('environment');
footer.insertAdjacentHTML('afterend',
'<div class="content-wrapper">
<ul>
<li class="go-back-environment">
<a href="/environment">
<p>Back to Environment</p>
</a>
</li>
<li class="back-home">
<a href="/home">
<p>Back to home</p>
</a>
</li>
</ul>
</div> ');
</script>
Is it even possible ?
Thanks !
Yes, it is. Try using template literals for longer html strings:
var footer = document.getElementById('footer');
var html = `
<div class="content-wrapper">
<ul>
<li class="go-back-environment">
<a href="/environment">
<p>Back to Environment</p>
</a>
</li>
<li class="back-home">
<a href="/home">
<p>Back to home</p>
</a>
</li>
</ul>
</div>
`;
footer.insertAdjacentHTML('afterend', html);
<main>Main</main>
<footer id="footer">Footer</footer>
Looks like you have done some mistake in string
Check for this
var footer = document.getElementById('environment');
var appendHtml = ['<div class="content-wrapper">',
'<ul>',
'<li class = "go-back-environment">',
'<a href = "/environment">',
'<p> Back to Environment </p>',
'</a>',
'</li>',
'<li class = "back-home">',
'<a href = "/home">',
'<p> Back to home </p>',
'</a>',
'</li>',
'</ul>',
'</div>'].join("");
footer.insertAdjacentHTML('afterend', appendHtml);
<div id=environment>Footer Div</div>

Bootstrap, foreach in view

I have a little problem. I have some products in shop ( I don't know how many products there will be ). In the main site I would like to print only 3 products in one row. And I don't know how to do loop to work this. Now in my code I have only one row and I doesn't look nice. I designed my row t contain only 3 products.
<div class="row-fluid">
<ul class="thumbnails">
#if (count($subcategoryProducts)==0)
There's no products
#else
#foreach($subcategoryProducts as $product)
<li class="span4">
<div class="thumbnail">
<a class="zoomTool" href="/product/{{$product->id}}" title="add to cart"><span
class="icon-search"></span> Details</a>
<a href="/product/{{$product->id}}"><img src="{{$product->getImageURL()}}"
alt=""></a>
<div class="caption cntr">
<p>{{$product->name}}</p>
<p><strong> {{$product->price}}</strong></p>
<h4><a class="shopBtn" href="#/{{$product->id}}" title="add to cart"> Add to cart </a>
</h4>
<br class="clr">
</div>
</div>
</li>
#endforeach
#endif
</ul>
</div>
Where's my mistake? Shoul I put this loop in another maybe?
Approach 2 here by JERRIE PELSER was the answer to my prayers today.
Use a simple extension method
public static class ArrayExtensions
{
/// <summary>
/// Splits an array into several smaller arrays.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
/// <param name="array">The array to split.</param>
/// <param name="size">The size of the smaller arrays.</param>
/// <returns>An array containing smaller arrays.</returns>
public static IEnumerable<IEnumerable<T>> Split<T>(this T[] array, int size)
{
for (var i = 0; i < (float)array.Length / size; i++)
{
yield return array.Skip(i * size).Take(size);
}
}
}
Use the extension method in foreach to split the rows by the number of columns required
#model IEnumerable<BootstrapGridLayout.Models.Article>
#using BootstrapGridLayout;
#{
ViewBag.Title = "Home Page";
}
#foreach (var row in Model.ToArray().Split(3))
{
<div class="row">
#foreach (var article in row)
{
<div class="col-md-4">
<div class="thumbnail">
<img src="#article.Thumbnail" data-holder-rendered="true" style="height: 200px; width: 100%; display: block;">
<div class="caption">
<h3 id="thumbnail-label">#article.Name</h3>
<p>#article.Description</p>
</div>
</div>
</div>
}
</div>
}

handlebars don't operate data output

My problem is handlebars don't operate Json data output. I don't understand this problem. How can i handle it???
This is my JSON data
{
"boardInfo":
[
{"no":1,"title":"히히","url":null,"writerNick":"cheolhan","contents":"하하","createdDate":"2016-10-24","createdDate2":"2016-10-24","like":0,"viewCount":19,"email":null,"userNo":"1","categoryNo":2,"category":"스포츠","linkTitle":null,"linkURL":null,"linkDetailUrl":null,"linkImage":null,"linkDesc":null,"userProfilePath":null},
{"no":2,"title":"히히","url":null,"writerNick":"cheolhan","contents":"하하","createdDate":"2016-10-24","createdDate2":"2016-10-24","like":0,"viewCount":15,"email":null,"userNo":"1","categoryNo":2,"category":"스포츠","linkTitle":null,"linkURL":null,"linkDetailUrl":null,"linkImage":null,"linkDesc":null,"userProfilePath":null},
{"no":3,"title":"후후","url":null,"writerNick":"cheolhan","contents":"후후","createdDate":"2016-10-24","createdDate2":"2016-10-24","like":0,"viewCount":276,"email":null,"userNo":"1","categoryNo":2,"category":"스포츠","linkTitle":null,"linkURL":null,"linkDetailUrl":null,"linkImage":null,"linkDesc":null,"userProfilePath":null}
]
}
This is script code
var source = $('#liTemplateText').html();
var template = Handlebars.compile(source);
var data = result.data.boardInfo
data.stringify = JSON.stringify(data);
console.log(data)
var boards = template(data);
$("#post_wrapper").append(boards);
{{#each data}}
<li id="each_post_wrap">
<div id="each_post">
<div id="user_Nick">
<img class="user_Nonepht userInfoLink" src="/TeamProject/upload/{{userProfilePath}}" alt="userImg" data-userNo="{{userNo}}" data-userNick="{{writerNick}}">
<span class="userInfoLink" data-userNo="{{userNo}}" data-userNick="{{writerNick}}">{{writerNick}}</span>
</div>
<div class="post_photoWrap titleLink" data-no="{{no}}" data-userNo="{{userNo}}">
<a href="#">
<img src="{{linkImage}}" alt="Image File">
</a>
</div>
<a class="post_contsWrap">
<span class="each_post_title titleLink" data-no="{{no}}" data-userNo="{{userNo}}">{{title}}</span>
<span class="each_post_contents titleLink" data-no="{{no}}" data-userNo="{{userNo}}"><p>{{{contents}}}</p></span>
</a>
<div class="post_ctgWrap">
<span class="categoryLink" data-ctgNo="{{categoryNo}}">{{category}}</span>
</div>
<div class="post_BtnWrap">
<div class="post_leftBtn">
<img class="viewCount" src="/TeamProject/mainpage/mainpage_images/viewCount.png" alt="view">
<span>{{viewCount}}</span>
</div>
<div class="post_rightBtn">
<img class="like_Onclick" src="/TeamProject/mainpage/mainpage_images/likeOnClick.png" alt="like">
<span>{{like}}</span>
</div>
<div>
</div>
</li>
{{/each}}
This is HTML code
<div id="tabs" class="all_post_wrap">
<ul id="post_wrapper" class="tabs-1-contents">
</ul>
</div>
Any help much appreciated.

Scraping using codeigniter and i need title and custom link

<div id="archive_content_block">
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="archive_cat_caption">
<h4>অর্থনীতি</h4>
</div>
<ul>
<li><i class="fa fa-square-o"></i>
<a href="http://67.227.189.112/~rtvnews24/economy/2126/বাধ্যতামূলক-করারোপের-প্রস্তাব-অর্থমন্ত্রীর">
<font style="color:rgb(33, 33, 33)">বাধ্যতামূলক করারোপের প্রস্তাব অর্থমন্ত্রীর</font>
</a>
</li>
</ul>
</div>
<div class="col-md-6 col-sm-6">
<div class="archive_cat_caption">
<h4>খেলাধুলা</h4>
</div>
<ul>
<li><i class="fa fa-square-o"></i> <font style="color:rgb(33, 33, 33)">অস্ট্রেলিয়া রেকর্ড</font></li>
</ul>
</div>
</div>
</div>
[this is my scraping html page code]
here i have a function which for get scraping title and link. but not work
public function get_dom()
{
$this->load->library('scraping');
$date = date('Y/m/d'); // custom date
$url = "http://67.227.189.112/~rtvnews24/archive/$date"; //my link
$html = file_get_html($url);
$row = $html->find('div.archive_content_block',0); // select content
foreach($row->find('div.archive_cat_caption', 0) as $title) {
echo $title->find('h4', 0)->plaintext.'</br>'; //title
foreach($row->find('ul',0) as $link) {
echo $link->find('li',0)->find('a', 0)->href.'</br>'; //link
}
}
}
here i am try to get title and link. please help me. Thanks in advance