open Bytesrw
(* CSS selector query example *)
let html = {|
Products
Product List
-
Widget A
$10.00
-
Widget B
$15.00
-
Widget C
$20.00
|}
let () =
let result = Html5rw.parse (Bytes.Reader.of_string html) in
(* Find element by ID *)
Printf.printf "=== ID Selector (#title) ===\n";
let titles = Html5rw.query result "#title" in
List.iter (fun node ->
Printf.printf "Found: %s\n" (Html5rw.get_text_content node)
) titles;
(* Find elements by class *)
Printf.printf "\n=== Class Selector (.product) ===\n";
let products = Html5rw.query result ".product" in
Printf.printf "Found %d products\n" (List.length products);
(* Find elements by tag *)
Printf.printf "\n=== Tag Selector (span) ===\n";
let spans = Html5rw.query result "span" in
Printf.printf "Found %d span elements\n" (List.length spans);
(* Find with attribute presence *)
Printf.printf "\n=== Attribute Presence ([data-id]) ===\n";
let with_data_id = Html5rw.query result "[data-id]" in
List.iter (fun node ->
match Html5rw.get_attr node "data-id" with
| Some id -> Printf.printf "Found element with data-id=%s\n" id
| None -> ()
) with_data_id;
(* Find with attribute value *)
Printf.printf "\n=== Attribute Value ([data-id=\"3\"]) ===\n";
let featured = Html5rw.query result "[data-id=\"3\"]" in
List.iter (fun node ->
Printf.printf "Found: %s\n" (Html5rw.get_text_content node)
) featured;
(* Find with multiple classes *)
Printf.printf "\n=== Multiple Classes (.product.featured) ===\n";
let featured_products = Html5rw.query result ".featured" in
List.iter (fun node ->
Printf.printf "Featured: %s\n" (Html5rw.get_text_content node)
) featured_products;
(* Check if a node matches a selector *)
Printf.printf "\n=== Match Check (.featured) ===\n";
List.iter (fun node ->
if Html5rw.matches node ".featured" then
Printf.printf "This product is featured!\n"
) products;
(* Pseudo-class: first-child *)
Printf.printf "\n=== Pseudo-class (:first-child) ===\n";
let first = Html5rw.query result "li:first-child" in
List.iter (fun node ->
Printf.printf "First li: %s\n" (String.trim (Html5rw.get_text_content node))
) first;
(* Pseudo-class: last-child *)
Printf.printf "\n=== Pseudo-class (:last-child) ===\n";
let last = Html5rw.query result "li:last-child" in
List.iter (fun node ->
Printf.printf "Last li: %s\n" (String.trim (Html5rw.get_text_content node))
) last;
(* Universal selector *)
Printf.printf "\n=== Universal Selector (*) ===\n";
let all = Html5rw.query result "*" in
Printf.printf "Total elements: %d\n" (List.length all);
(* Combining queries: find products then filter *)
Printf.printf "\n=== Combined: Products with price > $15 ===\n";
List.iter (fun product ->
(* Find price span within this product *)
let price_spans = List.filter (fun node ->
Html5rw.matches node ".price"
) (Html5rw.descendants product) in
List.iter (fun price_span ->
let price_text = Html5rw.get_text_content price_span in
(* Parse price - remove $ and convert *)
let price_str = String.sub price_text 1 (String.length price_text - 1) in
let price = float_of_string price_str in
if price > 15.0 then begin
let name_spans = List.filter (fun node ->
Html5rw.matches node ".name"
) (Html5rw.descendants product) in
match name_spans with
| name :: _ ->
Printf.printf " %s: %s\n" (Html5rw.get_text_content name) price_text
| [] -> ()
end
) price_spans
) products