Extracting HTML nodes using Jsoup - html-parsing

This is the html code:
<!DOCTYPE html>
<html>
<title>Instructor's Page</title>
<body>
<h1>Instructor's Page</h1>
<div class="check1"> <div id="check2">
<span id="check3" class="check4"> <strong class="check5"><link href="http://schema.org/t"/>Instructor-1 name</strong>
</span>
</div>
<div class="check1"> <div id="check2">
<span id="check3" class="check4"> <strong class="check6">Instructor-2 name</strong>
</span>
</body>
</html>
I am very new to Jsoup. How to extract Instructor's name from the given html page?
Currently, I know only printing the title.
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.IOException;
public class crawl {
public static void main(String[] args) {
Document doc1;
try {
File input = new File("t.html");
doc1 = Jsoup.parse(input, "UTF-8");
// get page title
String title1 = doc1.title();
System.out.println("title : " + title1);
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}

Use the select-method to select those elements in the HTML page you want.
It takes a pattern as an argument to what objects you want to select, such as a specific tag with a certain id or class.
//Creates a collection of Element objects for all span tags
Elements names = doc.select("span");
//Returns a collection of the first cells of each row
Elements names = doc.select("td:eq(0)");
Use this to select what you are looking for. Using a tool in your web browser that helps you identify tags in the HTML source can be helpful.
As to your original question on how to select instructor names, see below.
If the structure of the HTML always is the same and you are certain that the instructors name will be inside a span-tag, then you can simply parse the text in the
Elements names = doc.select("span");
for (Element e : names) {
System.out.println("Name is: " + e.text());
}
Will print out
Name is: Instructor-1 name
Name is: Instructor-2 name

Related

Could not parse as expression: "#{email.getUrl()}" (template: "test" - line 10, col 8)

I want to access url of other server from thymeleaf page. How to do this?
Have a look to my controller.
#GetMapping("/getJSPage")
public String getJSP(Model theModel)
{
// String url = "https://test-node-api-test.herokuapp.com/";
Email email = new Email();
theModel.addAttribute("email", email);
return "test";
}
My Email class
class Email
{
private String mail;
public String getURL(){
return "https://test-node-api-test.herokuapp.com/";
}
}
and here is my test.HTML file
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Send HTML Email using JSP</title>
</head>
<body>
<h1>Send Email using JSP</h1>
<p>
<a th:href="#{email.getUrl()}"> clickable</a>
<a th:href="#{https://test-node-api-test.herokuapp.com/}"> clickable</a>
</p>
</body>
</html>
Below link <a th:href="#{https://test-node-api-test.herokuapp.com/}"> clickable</a> is hard-code, it's working but <a th:href="#{email.getUrl()}"> clickable</a> is generating error
org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "#{email.getUrl()}" (template: "test" - line 10, col 8)
How Can i solve this ?
As per the Standard URL Syntax, if you want to use an expression when creating a url, you have to surround it with ${...}.
<a th:href="#{${email.getURL()}}"> clickable</a>
Also, getURL() should match the getter exactly. You have getURL() and getUrl() in your example code.

How to use core-list-dart with paper-action-dialog

I would like to
display a list with core-list-dart
show a modal (paper-action-dialog) when I click on an element of the list
the modal will hold form fields in order to update the list item selected. What I have for now is the modal displaying bad information like if you click on the second item of the list it's the information of the first item displayed in the modal
Here is the code:
<core-list-dart data="{{data}}">
<template>
<div>
<div on-click="{{showModal}}">{{model.name}}</div>
<paper-action-dialog heading="edit exercise: {{model.name}}" backdrop autoCloseDisabled>
<paper-input label="name" floatingLabel></paper-input>
<paper-button dismissive>Cancel</paper-button>
<paper-button on-click="{{updateExercise}}" data-ex-id="{{index}}" affirmative>Ok</paper-button>
</paper-action-dialog>
</div>
</template>
</core-list-dart>
and the dart code
#CustomTag('exercise-list')
class ExerciseList extends PolymerElement {
#observable ObservableList data;
ExerciseList.created() : super.created();
// lifecycle method
void ready() {
data = toObservable([new Person('Bob'), new Person('Tim')]);
}
showModal(event, detail, target){
shadowRoot.querySelector('paper-action-dialog').toggle();
}
updateExercise(event, detail, target){
String id = target.dataset['ex-id'];
print(id);
}
}
class Person extends Observable {
// mandatory field
#observable int index;
// mandatory field
#observable bool selected;
//model
#observable String name;
Person(this.name);
}
how can I bind the good information ?
Thank you !
Complete Code here
shadowRoot.querySelector('paper-action-dialog').toggle();
finds the first 'paper-action-dialog' within exercise-list (which is the first item as long as you don't scroll down and items are not virtualized) and shows it.
A solution could be to create an attribute on the dialog with the index bound to it.
<core-list-dart data="{{data}}">
<template>
<div index="{{index}}">
<div index="{{index}}" on-click="{{showModal}}">{{model.name}}</div>
<paper-action-dialog heading="edit exercise: {{model.name}}" backdrop autoCloseDisabled>
<paper-input label="name" floatingLabel></paper-input>
<paper-button dismissive>Cancel</paper-button>
<paper-button on-click="{{updateExercise}}" data-ex-id="{{index}}" affirmative>Ok</paper-button>
</paper-action-dialog>
</div>
</template>
</core-list-dart>
and change your code to
var index = target.attributes['index'];
shadowRoot.querySelector('div[index="$index"] paper-action-dialog').toggle();

dart-polymer update polymer dom elements

I am using this Templates to create a list of notice entries which works fine the first time.
NoticeList nle = querySelector('#noticeList');
nle.notices = notices;
But the second time I call this code gets executed the site doesn't change at all.
Am i missing something?
Thank you
<polymer-element name="notice-list">
<template>
<ul id = "noticeEntrys">
<template repeat="{{notice in notices}}">
<li>
<notice-element notice={{notice}}></notice-element>
</li>
</template>
</ul>
</template>
<script type="application/dart" src="notice_list.dart"></script>
</polymer-element>
<polymer-element name="notice-element">
<template>
<div class="notice">
<textarea rows="8" readonly>{{notice.getText()}}</textarea>
<div class="controlls">
<button type="button" name="delete" on-click={{delete}}>Delete</button>
<button type="button" name="change" on-click={{change}}>Change</button>
</div>
</div>
</template>
<script type="application/dart" src="notice_element.dart"></script>
</polymer-element>
#CustomTag('notice-list')
class NoticeList extends PolymerElement {
NoticeList.created() : super.created() {
}
#published List<Notice> notices;
}
#CustomTag('notice-element')
class NoticeElement extends PolymerElement {
NoticeElement.created() : super.created() {
}
#published Notice notice;
void delete(Event e, var detail, Node target) {
Datamanager.removeNotice(notice);
Controller.updateListe();
}
void change(Event e, var detail, Node target) {
Controller.updateActiveElement(notice);
}
void setNotice(Notice n) {
notice = n;
}
}
Edit: I update the code the same as i set the list in the first time
I get the new data via a webservice and the new data is correct
static void noticesLoadedPolymerList(List<Notice> notices) {
NoticeList nle = querySelector('#noticeList');
nle.setNotices(notices);
}
Edit2: I added a simple integer to display the listsize
#observable int listSize;
The value changes if i assign the new list but the displayed content doesn't.
If you set notices in NoticeList to a new List instance it should recognize the change.
If you assign notices in your first attempt and only modify in you second attempt you have to make your notices list observable var notices = toObservable([new Notice('notice1'), new Notice('notice2'), ...]).
You haven't provided code of your Notice class.
It may be necessary to make your Notice class observable like:
class Notice extends Object with Observable {
#observable String text;
}
This way Polymer recognizes if only a property of a notice instance changes (without changing (add/remove) the notices list.
Finally hat time to solve the problem.
My problem was that i would start polymer like this
initPolymer();
when i should have started it like this
initPolymer().run(() {
//initialization and other stuff
}
More about this you can find here https://code.google.com/p/dart/issues/detail?id=15379

Adding dynamic WebComponent divs

I'm trying to dynamically add a number of divs using Dart. The divs contain a custom web component, and I'm trying to pass in a variable. I want to be able to specify n number of variables, pass them to n number of components, and insert those into an HTML document. What's happening, however, is I'm getting the inserted divs without the variables. I wonder if this is a case of Dart trying to pass something into a an already loaded DOM and therefore doing nothing...? Here's some code:
product_elem.dart:
import 'package:web_ui/web_ui.dart';
import 'dart:html';
class ProductComponent extends WebComponent {
var productId;
}
product_elem.html:
<!DOCTYPE html>
<html>
<body>
<element name="product-elem" constructor="ProductComponent" extends="div">
<template>
<div style="width:335px;margin:10px;">
<h3>
{{productId}}
</h3>
</div>
</template>
<script type="application/dart" src="product_elem.dart"></script>
</element>
</body>
</html>
testcase_component.dart:
import 'dart:html';
import 'package:web_ui/web_ui.dart';
var productId;
void main() {
List myList = new List();
myList.addAll(["Foo", "Bar", "Baz"]);
for (var i = 0; i < myList.length; i++) {
productId = myList[i];
query('#products').innerHtml +=
"<div is='product-elem' id='product_elem' product-id='{{productId}}'></div>";
}
}
testcase_component.html:
<!DOCTYPE html>
<html>
<head>
<link rel="import" href="product_elem.html">
</head>
<body>
<div id="products">
<!-- Insert dynamic divs here -->
</div>
<script type="application/dart" src="testcase_component.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
You can't just add WebComponents like that. WebUI doesn't know that anything was added, so you just end up with a normal div.
Here is the current (slightly messy) way to dynamically add WebComponents:
void main() {
List myList = new List();
myList.addAll(["Foo", "Bar", "Baz"]);
for (var i = 0; i < myList.length; i++) {
productId = myList[i];
var product = new ProductComponent(productId);
product.host = new DivElement();
var lifecycleCaller = new ComponentItem(product)..create();
query('#products').append(product.host);
lifecycleCaller.insert();
}
}
This way the proper WebUI lifecycles are called.
Also make sure to add a constructor for ProductElem so that productId can be externally set:
class ProductComponent extends WebComponent {
var productId;
ProductComponent(this.productId);
}

Making a Map or a List observable in Web UI

I can make a String or a num type observable by using the #observable declaration in the Dart code:
#observable
var x = '';
and {{ }} syntax in the html:
<div>x = {{x}}</div>
But #observable does not work with Lists and Maps. How do I make those observable?
Use toObservable() with the List or Map as an argument. This creates a
binding between the List or Map object and its representation in the UI.
The following example uses toObservable(). Notice that the List and Map
objects have data added to them every second. With toObservable() creating
the proper binding, the UI for these objects auto-magically updates to show
the added items.
When the List or Map are clear()ed, the the UI once again reflects this.
For instructions on how to build and run a script such as this one, see
http://www.dartlang.org/articles/web-ui/tools.html.
Here is the main.dart file:
import 'dart:async';
import 'package:web_ui/web_ui.dart';
#observable
num x = 0; // #observable works fine with a number.
List list = toObservable(new List());
Map<String, num> map = toObservable(new Map());
void main() {
new Timer.periodic(new Duration(seconds: 1), (_) {
x += 1;
list.add(x);
map[x.toString()] = x;
if (x % 4 == 0) {
list.clear();
map.clear();
}
return x;
});
}
And here is the accompanying dart.html file:
<!DOCTYPE html>
<html>
<body>
<p>x = {{ x }}</p>
<ul>
<template iterate='item in list'>
<li>list item = {{item}}</li>
</template>
</ul>
<ul>
<template iterate='key in map.keys'>
<li>map key = {{key}}, map value = {{map[key]}}</li>
</template>
</ul>
<script type="application/dart" src="main.dart"></script>
</body>
</html>

Resources