HTML & Document Parsing ​
HTTPX provides high-performance, structured HTML and XML document parsing, DOM manipulation, and CSS selector inspection.
NOTE
HTTPX parses HTML/XML with its native DOM engine (parsing/html.zig, parsing/xml.zig); Tree-sitter is used for the JSON Feed syntax layer, the template syntax layer, plus the shared incremental-edit vocabulary (Point/SourceRange/TextEdit). Applications normally interact only with HTTPX's HTML/document APIs (httpx.Parser, response.html(), doc.select()). Applications do not need to install or import Tree-sitter directly.
Parsing Documents ​
Parse HTML directly from an HTTP response or from a string using httpx.Parser:
const std = @import("std");
const httpx = @import("httpx");
pub fn main() !void {
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const html_content =
\\<!DOCTYPE html>
\\<html>
\\<head><title>My Website</title></head>
\\<body>
\\ <div class="container">
\\ <h1 id="header">Welcome to HTTPX</h1>
\\ <a href="https://github.com" class="link">GitHub</a>
\\ </div>
\\</body>
\\</html>
;
var parser = httpx.Parser.init(allocator, .{});
var doc = try parser.parseHtml(html_content);
defer doc.deinit();
// Query title, body text, or links
const title = try doc.title();
std.debug.print("Title: {s}\n", .{title});
// CSS Selector query
const headers = try doc.select("#header");
defer allocator.free(headers);
for (headers) |h| {
std.debug.print("Header text: {s}\n", .{h.text()});
}
const links = try doc.select("a.link");
defer allocator.free(links);
for (links) |l| {
std.debug.print("Href: {s}\n", .{l.attr("href") orelse ""});
}
}Direct Response Parsing ​
When executing HTTP requests, responses can be parsed directly into an HTML document with response.html():
var client = httpx.Client.init(allocator, io, .{});
defer client.deinit();
var response = try client.get("http://httpbun.com/html", .{});
defer response.deinit();
var doc = try response.html();
defer doc.deinit();
std.debug.print("Title: {s}\n", .{try doc.title()});
const links = try doc.links();
for (links) |link| {
std.debug.print("Link: {s} -> {s}\n", .{ link.text, link.href });
}Supported Selectors ​
- Tag names:
div,p,h1 - Class names:
.card,.button-primary,div.container - IDs:
#main-nav,#submit-button,h1#header - Attribute matching:
[target="_blank"],[href],[class*="active"] - Descendant combinator:
div.container p - Child combinator:
ul > li - Selector lists:
h1, h2, h3
Incremental Document Updates ​
For live-reloading and development mode, HTTPX runs Tree-sitter incremental reparses (htmlLanguage in parsing/html.zig) to obtain structurally changed ranges; Document.incrementalUpdate rebuilds the DOM from the new syntax tree. The file watcher (web/watcher) uses the same incremental analysis plus template dependency tracking for targeted cache invalidation.
