################################ Parsing a document into a tree ################################ A token stream is flat. To see which element contains which, you need the *structure*: a tree. Go from a string of HTML to a navigable tree of nodes. .. important:: The one rule worth learning first: turbohtml models text as real **child nodes** (the WHATWG DOM shape), not `lxml `_'s ``text``/``tail`` or `BeautifulSoup `_'s ``.string``. So ``node[i]`` indexes a node's children, and attributes are reached through ``node.attrs``, never ``node["attr"]``. Hand a whole document to :func:`turbohtml.parse`. It applies the full WHATWG tree-construction algorithm (the same one browsers run, including the error recovery that inserts the missing ``html``, ``head`` and ``body``) and returns a :class:`turbohtml.Document`: .. testcode:: import turbohtml doc = turbohtml.parse("

Hello

Tom & Jerry

") print(doc.root) .. testoutput:: Element('html') The recovery is not silent: each WHATWG parse error turbohtml recovered from is on :attr:`~turbohtml.Document.errors`, a list of :class:`~turbohtml.ParseError` with the spec ``code`` and source position. A clean document leaves it empty; malformed input fills it (and ``parse(..., strict=True)`` raises :class:`~turbohtml.HTMLParseError` on the first one): .. testcode:: print(doc.errors) print(turbohtml.parse("").errors[0].code) .. testoutput:: [] duplicate-attribute By default turbohtml parses ``