PureHTML.Query (PureHTML v0.5.0)

View Source

CSS selector querying for PureHTML documents.

Provides functions for finding and traversing HTML nodes using CSS selectors.

Summary

Functions

Extracts an attribute value from a single node.

Extracts attribute values from a list of nodes.

Finds elements matching a selector and extracts an attribute from them.

Returns the immediate children of a node.

Finds all nodes matching the CSS selector.

Like find/2, but raises ArgumentError on an invalid selector.

Finds the first node matching the CSS selector.

Like find_one/2, but raises ArgumentError on an invalid selector.

Extracts text content from an HTML tree or node.

Types

html_node()

@type html_node() :: PureHTML.html_node()

html_tree()

@type html_tree() :: [html_node()]

Functions

attr(node, name)

@spec attr(html_node(), String.t()) :: String.t() | nil

Extracts an attribute value from a single node.

Returns the attribute value as a string, or nil if the attribute doesn't exist or the input is not an element.

Examples

iex> node = {"a", [{"href", "/home"}, {"class", "link"}], ["Home"]}
iex> PureHTML.attr(node, "href")
"/home"

iex> node = {"a", [{"href", "/home"}], ["Home"]}
iex> PureHTML.attr(node, "title")
nil

attribute(html, name)

@spec attribute(html_tree() | html_node(), String.t()) :: [String.t()]

Extracts attribute values from a list of nodes.

Returns a list of attribute values. Nodes without the attribute are skipped.

Examples

iex> "<a href='/one'>One</a><a href='/two'>Two</a>"
...> |> PureHTML.parse()
...> |> PureHTML.query("a")
...> |> PureHTML.attribute("href")
["/one", "/two"]

attribute(html, selector, name)

@spec attribute(html_tree() | html_node(), String.t(), String.t()) :: [String.t()]

Finds elements matching a selector and extracts an attribute from them.

Combines find/2 and attribute/2 into a single call for convenience.

Examples

iex> "<nav><a href='/'>Home</a><a href='/about'>About</a></nav>"
...> |> PureHTML.parse()
...> |> PureHTML.attribute("a", "href")
["/", "/about"]

iex> "<div><img src='a.png'><img src='b.png'></div>"
...> |> PureHTML.parse()
...> |> PureHTML.attribute("img", "src")
["a.png", "b.png"]

children(node, opts \\ [])

@spec children(
  html_node(),
  keyword()
) :: html_tree() | nil

Returns the immediate children of a node.

Options

  • :include_text - Include text nodes (default: true)

Examples

iex> node = {"div", [], [{"p", [], ["Hello"]}, "Some text"]}
iex> PureHTML.Query.children(node)
[{"p", [], ["Hello"]}, "Some text"]

iex> node = {"div", [], [{"p", [], ["Hello"]}, "Some text"]}
iex> PureHTML.Query.children(node, include_text: false)
[{"p", [], ["Hello"]}]

find(html, selector)

Finds all nodes matching the CSS selector.

Supported Selectors

  • Tag: div, p, a
  • Universal: *
  • Class: .class
  • ID: #id
  • Attribute: [attr], [attr=value], [attr^=prefix], [attr$=suffix], [attr*=substring]
  • Combinators: div p (descendant), div > p (child), h1 + p (adjacent sibling), h1 ~ p (general sibling)
  • Selector list: .a, .b

An invalid selector represents, and therefore matches, nothing: the result is []. find!/2 raises instead.

Examples

iex> html = PureHTML.parse("<div><p class='intro'>Hello</p><p>World</p></div>")
iex> PureHTML.Query.find(html, "p.intro")
[{"p", [{"class", "intro"}], ["Hello"]}]

iex> html = PureHTML.parse("<ul><li>A</li><li>B</li></ul>")
iex> PureHTML.Query.find(html, "li")
[{"li", [], ["A"]}, {"li", [], ["B"]}]

iex> PureHTML.Query.find(PureHTML.parse("<p>x</p>"), "div >")
[]

find!(html, selector)

@spec find!(html_tree() | html_node(), String.t()) :: html_tree()

Like find/2, but raises ArgumentError on an invalid selector.

Examples

iex> PureHTML.Query.find!(PureHTML.parse("<p>x</p>"), "p")
[{"p", [], ["x"]}]

find_one(html, selector)

Finds the first node matching the CSS selector.

Returns the first matching node in document order, or nil if no match is found. Stops walking the tree at the first match, so it is cheaper than find/2 when you only need one result. An invalid selector matches nothing: the result is nil. find_one!/2 raises instead.

Examples

iex> "<ul><li>A</li><li>B</li></ul>"
...> |> PureHTML.parse()
...> |> PureHTML.query_one("li")
{"li", [], ["A"]}

iex> "<div><p>Hello</p></div>"
...> |> PureHTML.parse()
...> |> PureHTML.query_one(".missing")
nil

find_one!(html, selector)

@spec find_one!(html_tree() | html_node(), String.t()) :: html_node() | nil

Like find_one/2, but raises ArgumentError on an invalid selector.

text(html, opts \\ [])

@spec text(
  html_tree() | html_node(),
  keyword()
) :: String.t()

Extracts text content from an HTML tree or node.

Options

  • :deep - Traverse all descendants (default: true). When false, only direct text children.
  • :separator - String to insert between text segments (default: "")
  • :strip - Strip whitespace from each segment and remove empty segments (default: false)
  • :include_script - Include text from <script> tags (default: false)
  • :include_style - Include text from <style> tags (default: false)
  • :include_inputs - Include value from <input> and <textarea> (default: false)

Examples

iex> html = PureHTML.parse("<p>Hello <strong>World</strong></p>")
iex> PureHTML.text(html)
"Hello World"

iex> html = PureHTML.parse("<ul><li>A</li><li>B</li></ul>")
iex> PureHTML.text(html, separator: ", ")
"A, B"

iex> html = PureHTML.parse("<ul>\n  <li>One</li>\n  <li>Two</li>\n</ul>")
iex> PureHTML.text(html, strip: true, separator: ", ")
"One, Two"