Validate XML from xml-model processing instructions with a GitHub Action and
CLI designed for Relax NG and Schematron-heavy repositories.
This repository provides:
- a Java CLI
- a self-contained GitHub Action ready for GitHub Marketplace
Release artifacts are published on GitHub Releases as:
xml-model-validator.jarxml-model-validator.jar.sha256
The validator:
- parses
xml-modelprocessing instructions with a proper XML parser - validates Relax NG schemas with Jing
- validates Schematron with Saxon and SchXslt2
- supports Relax NG and Schematron
xml-modeldeclarations in the same file - supports Relax NG XML syntax (
.rng) and RELAX NG Compact Syntax (.rnc) - supports standalone Schematron files and embedded Schematron inside Relax NG XML syntax schemas
- supports Schematron
phaseselection from thexml-modelprocessing instruction - recognizes common schema hints from
schematypens,type, and schema file extensions - follows remote schema URLs and caches downloaded schemas in the workspace
- supports optional schema alias overrides for repositories that need to pin a remote schema URL to a local file
- resolves XML paths, caches, and optional aliases against the consuming repository when run as a GitHub Action
- emits GitHub annotations for validation failures and warnings
Minimal usage:
- uses: actions/checkout@v6
- uses: adunning/xml-model-validator@v1Version tag semantics:
@v1is a floating major tag that tracks the latest1.x.yrelease.@v1.0.0is an immutable exact release tag.- This repository publishes releases from
vX.Y.Ztags and then updates the matching major tag (vX) automatically.
Validate a directory recursively:
- uses: adunning/xml-model-validator@v1
with:
directory: collectionsValidate only the XML files changed by the current push or pull request:
- uses: adunning/xml-model-validator@v1
with:
changed_only: trueChoose how changed files are discovered:
- uses: adunning/xml-model-validator@v1
with:
changed_only: true
changed_source: auto # auto | api | gitValidate explicit files and stop on the first failure:
- uses: adunning/xml-model-validator@v1
with:
files: docs/a.xml docs/b.xml
fail_fast: truefiles: space-separated list of XML filesfile_list: newline-delimited file list pathdirectory: directory to scan recursivelychanged_only: validate only XML files changed by the current push or pull requestchanged_source: source forchanged_onlyfile discovery (auto,api,git)jobs: number of workers,0means automaticschema_aliases: optional TSV file mapping remote schema URLs to local filesfail_fast: stop after the first failing file
If you do not provide files, file_list, directory, or changed_only,
the action validates all XML files in the repository by default.
Selection precedence is directory, then file_list, then files, then
changed_only, then the repository-wide default.
When changed_only: true:
changed_source: auto(default) tries the GitHub API for pull request and push events, then falls back to git diff if API discovery is unavailable.changed_source: apirequires GitHub event context and API access.changed_source: gituses local git diff logic.- If no changed XML files are found, the action reports that validation was skipped and exits successfully.
The validator follows xml-model directly by default. If a repository needs an
override, provide a TSV file with:
remote-url<TAB>local-path
Relative alias paths are resolved from the alias file location.
The action is intentionally focused on the schema types most commonly used with
xml-model in editorial workflows:
- Relax NG XML syntax
- RELAX NG Compact Syntax
- standalone Schematron
- embedded Schematron in Relax NG XML syntax schemas
It does not currently attempt to validate every schema language that xml-model
can theoretically reference.
The GitHub Action sets up Java internally, builds the shaded jar from the
action source when needed, then runs it with java -jar.
The built jar is cached under ~/.cache/xml-model-validator/jar, and its cache
key is derived from the action's build inputs so a cached binary is only reused
when the jar-producing contents match.
The action also caches Maven's local repository and wrapper directories under
~/.m2, keyed from Maven dependency inputs so dependency downloads are reused
until those inputs change.
Remote schema downloads and prepared Schematron artifacts are cached under
~/.cache/xml-model-validator/schema-downloads and
~/.cache/xml-model-validator/schematron. The action restores the latest
runtime cache and saves a fresh one at the end of each run so those artifacts
can accumulate safely over time.
The changed_only mode expects the repository to be available in the runner,
which normally means using actions/checkout@v6 earlier in the job.
If you use changed_source: git, fetch-depth: 0 is recommended for reliable
diffs on push and pull request events.
Build the runnable jar:
./mvnw -q -DskipTests packageRun:
java -jar target/xml-model-validator.jar --directory path/to/xml -j 0Show CLI usage:
java -jar target/xml-model-validator.jar --helpShow CLI version:
java -jar target/xml-model-validator.jar --versionVerify a published release artifact:
VERSION=v1.0.0 # replace with the release tag you want to verify
curl -LO "https://github.com/adunning/xml-model-validator/releases/download/${VERSION}/xml-model-validator.jar"
curl -LO "https://github.com/adunning/xml-model-validator/releases/download/${VERSION}/xml-model-validator.jar.sha256"
shasum -a 256 -c xml-model-validator.jar.sha256- Ensure
pom.xmlandCITATION.cffuse the target version. - Ensure
CITATION.cffdate-releasedmatches the planned release date. - Run checks locally:
./mvnw -B verify- Tag and push a strict SemVer tag (
vX.Y.Z):
git tag -a vX.Y.Z -m "Release vX.Y.Z"
git push origin vX.Y.Z- The release workflow creates the GitHub Release automatically from that tag,
and then force-updates the major tag (
vX) to the same commit.
Example: pushing v1.0.0 publishes the release and updates v1.
- Do not manually create or push
v1,v2, etc.; those tags are managed by the release workflow to stay synchronized with the latest patch/minor in each major line.
The release workflow validates version metadata, verifies the jar runtime version, builds the project, and publishes the runnable jar plus SHA-256 checksum as GitHub Release assets.