diff --git a/src/soup.ml b/src/soup.ml index a79fe12..992edd1 100644 --- a/src/soup.ml +++ b/src/soup.ml @@ -596,8 +596,11 @@ struct | OnlyOfType -> element_count_with_name (name node) node = 1 | Empty -> no_children node | Content s -> texts node |> String.concat "" |> has_substring s - | Has selector -> - let matching_nodes = filter (fun n -> matches_simple_selector n selector) (descendants node) in count matching_nodes > 0 + | Has selector -> + descendants node + |> filter (fun descendant -> matches_simple_selector descendant selector) + |> count + |> fun count -> count > 0 | Not selector -> not (matches_simple_selector node selector) and matches_simple_selector node = function @@ -924,7 +927,7 @@ struct let s = parse_parenthesized_value parse_quoted_string stream in Content s | "empty" -> Empty - | "has" -> + | "has" -> let selector = parse_parenthesized_value parse_simple_selector stream in Has selector | "not" -> diff --git a/test/performance/performance.ml b/test/performance/performance.ml index b303db6..f290bca 100644 --- a/test/performance/performance.ml +++ b/test/performance/performance.ml @@ -31,16 +31,20 @@ let () = let selector = ":has([id=mngb])" in assert (soup $$ selector |> count = 2); - measure 1000 ("select_all " ^ selector) (fun () -> soup $$ selector |> count |> ignore); + measure 1000 ("select_all " ^ selector) + (fun () -> soup $$ selector |> count |> ignore); let selector = ":has([action*=search])" in assert (soup $$ selector |> count = 3); - measure 1000 ("select_all " ^ selector) (fun () -> soup $$ selector |> count |> ignore); + measure 1000 ("select_all " ^ selector) + (fun () -> soup $$ selector |> count |> ignore); let selector = ":has([name=gbv])" in assert (soup $$ selector |> count = 4); - measure 1000 ("select_all " ^ selector) (fun () -> soup $$ selector |> count |> ignore); + measure 1000 ("select_all " ^ selector) + (fun () -> soup $$ selector |> count |> ignore); let selector = "*" in assert (soup $$ selector |> count > 10); - measure 1000 ("select_all " ^ selector) (fun () -> soup $$ selector |> count |> ignore) + measure 1000 ("select_all " ^ selector) + (fun () -> soup $$ selector |> count |> ignore) diff --git a/test/test.ml b/test/test.ml index ac7e693..c3abcb3 100644 --- a/test/test.ml +++ b/test/test.ml @@ -123,6 +123,9 @@ let suites = [ test "ul li:not(:nth-child(1))" 2; test ":not(ul) > li" 2; test ":has([id=one])" 3; + test "ul:has([id=one])" 1; + test "ol:has([id=one])" 0; + test "li:has([id=one])" 0; test ":has(.odd)" 4; test ("html:root > body.lists[class~=lists] > ul > li#one:nth-child(1) " ^