toml_path_equals
Query a structured document with a JSONPath expression and assert every match deep-equals the supplied value.
Semantics:
- Multiple matches — every match must equal the expected value.
- Zero matches — counts as a violation (the key the rule is enforcing doesn’t exist).
- Unparseable files — one violation per file (not silently skipped).
XML mapping applies to every XML surface: xml_path_*, json_schema_passes format: xml, and the xml: extract used by cross_file / file_graph / registry_paths_resolve. XML is mapped to the queryable tree with the xmltodict-style convention so the JSONPath reads like the XML — the document is { <root-element>: … } ($.Project…, $.project…); attributes are @name keys (['@Version'], in bracket notation, since .@Version is not valid JSONPath); a leaf element collapses to its text (<TargetFramework>net8.0</TargetFramework> → "net8.0"); namespaces flatten to the local name (Maven’s default pom.xml namespace just works). Two properties of XML’s data model to keep in mind:
- Every XML leaf value is a string. Quote expected values (
equals: "4.0.0", notequals: 4.0.0), reach for*_path_matches, and in ajson_schema_passesschema type XML fields asstringwith apattern—type: integer/boolean/numberalways fail against XML (every leaf is a string);type: array/objectadditionally depend on cardinality (next point). - Cardinality is data-dependent. A single
<dependency>is an object (a string for a leaf element); two or more become an array. A[*]wildcard therefore does not normalize cardinality —dependency[*]reads nothing for one element but every element for many, and a leaf query flips the same way (an attribute such as MSBuild’sCondition=also turns a would-be leaf string into a{ "@Condition": …, "#text": … }object). When a rule must handle both one and many, use recursive descent:$.Project.ItemGroup.ProjectReference..['@Include']reads the@Includeof one or many. Scope the..under a parent element so it does not over-match a same-named key elsewhere.
Full rationale and edge cases: docs/design/v0.10/xml_path.md.
Options
Section titled “Options”| Option | Type | Required | Default | Description |
|---|---|---|---|---|
equals | any value | yes | Expected value. Any JSON type (string, number, boolean, null, array, object). | |
if_present | boolean | false | When true, a query returning zero matches is silently OK - only real matches that fail the op produce violations. | |
path | string | yes | JSONPath expression rooted at $. Supports dot-access ($.foo.bar), array index ($.deps[0]), wildcards ($.deps[*]), filters, and every other RFC 9535 construct. |
Plus the common paths, level, id, and when fields. This table is generated from the JSON Schema; option types and defaults are authoritative.
Example
Section titled “Example”A crate pinned to an older Rust edition
Section titled “A crate pinned to an older Rust edition”The rule fires on this repository:
crates/crates/bad/crates/bad/Cargo.tomlcrates/ok/crates/ok/Cargo.toml[package]name = "bad"edition = "2021"[package]name = "ok"edition = "2024"With this .alint.yml:
version: 1rules: - id: rust-edition-2024 kind: toml_path_equals paths: "crates/*/Cargo.toml" path: "$.package.edition" equals: "2024" level: warningalint check reports:
--- crates/bad/Cargo.toml ------------------------------------------------------ ! warning rust-edition-2024 value at path does not equal expected: expected "2024", got "2021"
Summary (1 violation): ! 1 warning 0 passing * 1 failingEvery crate targets the 2024 edition
Section titled “Every crate targets the 2024 edition”This repository is compliant:
crates/crates/a/crates/a/Cargo.tomlcrates/b/crates/b/Cargo.toml[package]name = "a"edition = "2024"[package]name = "b"edition = "2024"With this .alint.yml:
version: 1rules: - id: rust-edition-2024 kind: toml_path_equals paths: "crates/*/Cargo.toml" path: "$.package.edition" equals: "2024" level: warningalint check reports:
v All 1 rule(s) passed.