xml_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 project file targeting the wrong .NET framework
Section titled “A project file targeting the wrong .NET framework”The rule fires on this repository:
src/src/Bad/src/Bad/Bad.csprojsrc/Ok/src/Ok/Ok.csproj<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFramework>net6.0</TargetFramework></PropertyGroup></Project><Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFramework>net8.0</TargetFramework></PropertyGroup></Project>With this .alint.yml:
version: 1rules: - id: csproj-net8 kind: xml_path_equals paths: "src/*/*.csproj" path: "$.Project.PropertyGroup.TargetFramework" equals: "net8.0" level: erroralint check reports:
--- src/Bad/Bad.csproj --------------------------------------------------------- x error csproj-net8 value at path does not equal expected: expected "net8.0", got "net6.0"
Summary (1 violation): x 1 error 0 passing * 1 failingEvery project file targets net8.0
Section titled “Every project file targets net8.0”This repository is compliant:
src/src/App/src/App/App.csproj<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFramework>net8.0</TargetFramework><Nullable>enable</Nullable></PropertyGroup></Project>With this .alint.yml:
version: 1rules: - id: csproj-net8 kind: xml_path_equals paths: "src/*/*.csproj" path: "$.Project.PropertyGroup.TargetFramework" equals: "net8.0" level: erroralint check reports:
v All 1 rule(s) passed.