= Exercise 5.8
// Refs:
:url-base: https://github.com/fenegroni/TGPL-exercise-solutions
:workflow: workflows/Exercise 5.8
:action: actions/workflows/ch5ex8.yml
:url-workflow: {url-base}/{workflow}
:url-action: {url-base}/{action}
:badge-exercise: image:{url-workflow}/badge.svg?branch=main[link={url-action}]
{badge-exercise}
Modify `forEachNode`
so that the `pre` and `post` functions return a boolean result
indicating whether to continue the traversal.
Use it to write a function `ElementByID`
with the following signature
that finds the first HTML element with the specified `id` attribute.
The function should stop the traversal as soon as a match is found.
[source,go]
----
func ElementByID(doc *html.Node, id string) *html.Node
----
== Test
The test will have a few HTML elements
with the `id` attribute in several combinations
to validate the implementation is robust.
== Implementation
We had to modify `forEachNode` to return a boolean
to indicate whether to continue traversing the tree
as a result of a `pre` or `post` function
returning `false`.
`elementWithID` uses package level variables
`idToFind` and `nodeFound`
which are set and returned by `ElementByID`.
It returns `false` to tell `forEachNode` to stop traversing the tree.
== Why not use anonymous functions
Because at this point in the book
anonymous functions have not been introduced yet.
Most solutions I have seen
do not correctly stop traversing sibling nodes.
One of my tests covers this scenario.