Skip to content

Commit bceb0e7

Browse files
authored
Add Floki.get_by_id/2 (#548)
1 parent 8709bd7 commit bceb0e7

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

lib/floki.ex

+26
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,32 @@ defmodule Floki do
289289
Finder.find(html_tree_as_tuple, selector)
290290
end
291291

292+
@doc """
293+
Finds the first element in an HTML tree by id.
294+
295+
Returns `nil` if no element is found.
296+
297+
This is useful when there are IDs that contain special characters that
298+
are invalid when passed as is as a CSS selector.
299+
It is similar to the `getElementById` method in the browser.
300+
301+
## Examples
302+
303+
iex> {:ok, html} = Floki.parse_fragment(~s[<p><span class="hint" id="id?foo_special:chars">hello</span></p>])
304+
iex> Floki.get_by_id(html, "id?foo_special:chars")
305+
{"span", [{"class", "hint"}, {"id", "id?foo_special:chars"}], ["hello"]}
306+
iex> Floki.get_by_id(html, "does-not-exist")
307+
nil
308+
309+
"""
310+
@spec get_by_id(html_tree() | html_node(), String.t()) :: html_tree
311+
def get_by_id(html_tree_as_tuple, id)
312+
when is_list(html_tree_as_tuple) or is_html_node(html_tree_as_tuple) do
313+
html_tree_as_tuple
314+
|> Finder.find(%Floki.Selector{id: id})
315+
|> List.first()
316+
end
317+
292318
@doc """
293319
Changes the attribute values of the elements matched by `selector`
294320
with the function `mutation` and returns the whole element tree.

test/floki_test.exs

+16
Original file line numberDiff line numberDiff line change
@@ -1594,6 +1594,22 @@ defmodule FlokiTest do
15941594
Floki.Finder.find(html_tree, [selector_struct_1, selector_struct_2])
15951595
end
15961596

1597+
# Floki.get_by_id/2
1598+
1599+
test "get_by_id finds element with special characters" do
1600+
html =
1601+
document!(
1602+
html_body(~s"""
1603+
<div id="my-id?with_special!char:acters">Hello</div>
1604+
""")
1605+
)
1606+
1607+
assert {"div", [{"id", "my-id?with_special!char:acters"}], ["Hello"]} =
1608+
Floki.get_by_id(html, "my-id?with_special!char:acters")
1609+
1610+
refute Floki.get_by_id(html, "doesn't exist")
1611+
end
1612+
15971613
# Floki.children/2
15981614

15991615
test "returns the children elements of an element including the text" do

0 commit comments

Comments
 (0)