-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathhtml_parser.ail
More file actions
56 lines (49 loc) · 1.93 KB
/
Copy pathhtml_parser.ail
File metadata and controls
56 lines (49 loc) · 1.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
-- HTML5 parsing with std/html
-- Demonstrates the lenient HTML5 parser handling real-world quirks:
-- unclosed tags, boolean attributes, mixed-case tags. The XmlNode tree
-- returned by std/html is interchangeable with std/xml — same findAll,
-- findFirst, getText, getAttr, getTag accessors.
--
-- Usage: ailang run --caps IO --entry main html_parser.ail
module examples/runnable/html_parser
import std/result (Result, Ok, Err)
import std/option (Option, Some, None)
import std/html (parse, parseFragment)
import std/xml (findAll, findFirst, getText, getTag, getAttr)
import std/list as List (length)
import std/io (println)
export func main() -> int ! {IO} {
-- Real-world HTML5 with unclosed paragraphs, mixed-case tags,
-- and a boolean attribute. A strict XML parser would reject this.
let html = "<!DOCTYPE html><HTML><body><p>first<p>second<input type=\"checkbox\" checked><a href=\"https://example.com\">link</a></body></HTML>";
match parse(html) {
Ok(root) => {
-- Root is the <html> element (lower-cased by HTML5 parser).
println("root tag: ${getTag(root)}");
-- Lenient parse splits <p>first<p>second into two siblings.
let paragraphs = findAll(root, "p");
println("paragraphs: ${show(List.length(paragraphs))}");
-- Find the link and extract its href.
match findFirst(root, "a") {
Some(a) => match getAttr(a, "href") {
Some(href) => println("href: ${href}"),
None => println("no href")
},
None => println("no link found")
};
-- Find the boolean attribute on <input>. HTML5 emits value "" for it.
match findFirst(root, "input") {
Some(inp) => match getAttr(inp, "checked") {
Some(_) => println("checked: yes (boolean attr present)"),
None => println("not checked")
},
None => println("no input")
};
0
},
Err(msg) => {
println("parse error: ${msg}");
1
}
}
}