A total, left-to-right scan of an XML source binary that produces the positions Saxy does not.
Saxy 1.6.1 passes handlers no position data of any kind and has no option
to enable it (deps/saxy/lib/saxy/handler.ex), so positions are produced
by this independent scan and zipped against the SAX event stream by index
in Statifier.Parser.Handler - the Nth start-tag record this scanner
finds is the Nth :start_element Saxy emits.
The scan only ever answers "is this a markup construct, and where does it
start and end". It classifies each < by the bytes that follow it -
<!-- comment (skipped to -->), <![CDATA[ (skipped to ]]>),
<!DOCTYPE (skipped to >, honoring an internal [...] subset), <? PI
or the XML declaration (skipped to ?>), </ an end tag, anything else a
start tag - and never interprets content, expands entities, or validates.
A self-closing <b/> emits two records, a :start and an :end with
identical spans, so the record stream stays 1:1 with Saxy's element events
by construction.
It is a total function: it never raises, on any binary, including
malformed or truncated XML. On a malformed document, Saxy's own error is
what surfaces to Statifier.Parser.parse/1; this scanner's only
obligation on such input is to return a list without crashing, since a
well-formed document is Saxy's job to reject, not this scanner's.
Summary
Functions
Scans source into an ordered list of start/end tag records.
Types
@type attribute() :: %{ name: binary(), location: Statifier.Parser.Location.t(), value_location: Statifier.Parser.Location.t() }
@type t() :: %Statifier.Parser.Markup{ attributes: [attribute()], kind: :start | :end, location: Statifier.Parser.Location.t(), name: binary() }
Functions
Scans source into an ordered list of start/end tag records.
Total over any binary - see the moduledoc. Comments, CDATA sections, DOCTYPE declarations, and processing instructions (including the XML declaration) are skipped without producing a record; only start and end tags do.