| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
parent directory.. | ||||
XSD schemas for eXist-db configuration and descriptor files.
Each native schema declares an independent semver on <xs:schema version="…">. Schema version is not tied to the eXist-db product release.
| Change type | Version bump |
|---|---|
| Breaking change for existing instance documents | MAJOR |
| Backward-compatible addition (new optional element/attribute) | MINOR |
| Documentation or non-semantics XSD-only change | PATCH (optional) |
CI fails if a schema or canonical template changes without bumping the paired xs:schema/@version.
Canonical templates may declare an optional schemaVersion attribute on the root element. When present, its value should match the paired xs:schema/@version (native schema semver — not the eXist product release, and not expath package @version). Legacy documents without the attribute remain valid; runtime code logs a debug message when it is missing and warns when it differs from the version this build expects.
| Schema @version | schemaVersion on template |
|---|---|
| conf.xsd | <exist schemaVersion="…"> |
| collection.xconf.xsd | <collection schemaVersion="…"> |
| descriptor.xsd | <xquery-app schemaVersion="…"> |
| mime-types.xsd | <mime-types schemaVersion="…"> |
| controller-config.xsd | <configuration schemaVersion="…"> |
All five schemas xs:include the schemaVersionType simple type from schema-version-type.xsd rather than each declaring their own copy (it has no targetNamespace, so it is pulled in as a chameleon component and inherits each includer's namespace).
SchemaVersion.java's version constants are generated at build time from xs:schema/@version on the paired XSDs (see generate-schema-version.xsl, wired as exist-core/pom.xml's schema-version-codegen execution) — never hand-edit them. SchemaVersionSyncTest is a tautology now that the constants can't drift by construction, kept as a guard against the codegen wiring itself silently breaking. ci-schema-checks.yml still triggers on edits to SchemaVersion.java itself.
Templates vs schemas — root pom.xml binds xml-maven-plugin:validate at the validate phase. This also runs on every full build via ci-test.yml (mvn test runs validate first).
ci-schema-checks.yml re-runs mvn validate on PRs that touch schemas or canonical templates (fast, path-filtered).
Schemas vs the W3C meta-schema — the same validate-canonical-instances execution also validates every schema/**/*.xsd as an instance document against the W3C XSD 1.1 meta-schema, catching malformed schema authoring (e.g. a misplaced xs:assert, an unresolvable xsi:type in xs:appinfo) before it ships. Resolution is fully offline: catalogHandling is set to strict and a catalogs entry points at catalog.xml, so the meta-schema's own xs:import of the xml: namespace never reaches the network — a live fetch would fail the build rather than silently succeeding. Idea borrowed from #5541, where the same catalog trick lets a user validate the well-formedness of their own XSD against the meta-schema.
The meta-schema files are vendored, not generated:
| File | Source | Fetched |
|---|---|---|
| entities/XMLSchema.xsd | https://www.w3.org/2009/XMLSchema/XMLSchema.xsd (XSD 1.1 structures schema — supersedes the older 2001/2004 XSD 1.0 revision previously bundled here, which had no xs:assert/vc: support and was otherwise unused) | 2026-06-20 |
| entities/XMLSchema.dtd, entities/datatypes.dtd | https://www.w3.org/2009/XMLSchema/XMLSchema.dtd, .../datatypes.dtd — internal-subset companions XMLSchema.xsd's DOCTYPE/parameter entities pull in | 2026-06-20 |
| entities/xml.xsd | https://www.w3.org/2001/xml.xsd — the xml: namespace schema XMLSchema.xsd itself imports | 2026-06-20 |
Published under the W3C Document License (permissive, redistribution allowed). Each file is byte-identical to its upstream source — kept that way deliberately so future re-syncs are a clean diff against W3C's copy, with no local patching. Duplicated under exist-core/src/test/resources/org/exist/validation/entities/ to mirror that module's own test catalog, matching this repo's existing pattern for the other bundled DTDs/XSDs.
Version bumps — a single Saxon XSLT 2.0 transform, governance.xsl, does the whole check in one pass: it reads the schema/template pairs straight from pom.xml's validate-canonical-instances validationSets, reads changed paths and BASE-revision copies of each XSD via unparsed-text()/document()/doc-available(), and fails the build directly with xsl:message terminate="yes" (which also prints the GitHub Actions ::error:: annotations) when a paired schema/template changed without its xs:schema/@version moving. .github/scripts/prepare-governance-context.sh is pure git plumbing — it resolves the diff base, dumps each schema's BASE-revision content to disk, and writes a small context.xml — everything else is XSLT, run via mvn -N xml:transform@schema-governance.
That execution is bound to phase=none in pom.xml, so it never runs on an ordinary mvn install/mvn test/mvn validate — only ci-schema-checks.yml invokes it directly, after running the shim script. Saxon-HE (XSLT 2.0/3.0) is already a xml-maven-plugin dependency via exist-parent/pom.xml's pluginManagement — no extra CI dependency installation needed (no more xmllint/xsltproc).
Other schemas (users.xsd, server.xsd, expath-pkg.xsd, …) apply to runtime or package files, not shipped templates.
Schemas ship at $EXIST_HOME/schema/ (#6189).
Four touch points, in order:
Add the XSD to schema/. The schema/** path trigger in ci-schema-checks.yml fires automatically on any change there. Governance reads schema/template pairs from pom.xml's validate-canonical-instances validationSets, not by scanning schema/ directly, so the XSD alone is not enough.
Register the schema/template pair in pom.xml's validate-canonical-instances execution. This is the single source of truth that both validation and drift-detection read. Add a <validationSet> entry pairing the new XSD with its canonical instance.
Add the canonical instance path to the drift-detection scope — but only if it lives outside the paths already covered. Currently covered: everything under exist-distribution/src/main/config/, plus controller-config.xml and mime-types.xml explicitly. If the new instance is outside these, add its path to the git diff --name-only call in .github/scripts/prepare-governance-context.sh and to both paths: blocks in ci-schema-checks.yml. In practice any new eXist-db config schema will land under exist-distribution/src/main/config/ and step 3 does not apply.
Wire SchemaVersion codegen in the consumer module's pom.xml (modelled on exist-core/pom.xml's schema-version-codegen execution) if you want the version constant auto-generated at build time rather than maintained by hand.
Hand-rolling separate conf.xml / controller-config.xml copies for every test module means they drift. Two shared base stylesheets in this directory generate the module-specific test fixtures from the canonical templates at build time:
| Base stylesheet | Canonical source | Generated file |
|---|---|---|
| generate-conf-fixture.xsl | exist-distribution/src/main/config/conf.xml | conf.xml |
| generate-controller-config-fixture.xsl | exist-jetty-config/…/standalone-webapp/WEB-INF/controller-config.xml | controller-config.xml |
Each test module that needs a custom conf.xml has a thin src/test/resources-filtered/conf-fixture.xsl that imports the base stylesheet and redeclares whichever xsl:param defaults need changing. XSLT import precedence means the per-fixture param value wins over the base default without requiring any template overrides. xml-maven-plugin runs the transformation in the generate-test-resources phase; the output lands in target/generated-test-resources/ and is listed as a filtered testResource so Maven's ${...} token substitution still applies.
| Param | Type | Default | Purpose |
|---|---|---|---|
| keep-modules | xs:string* | () | @uri values of builtin XQuery modules to keep |
| keep-indexes | xs:string* | () | @id values of indexer modules to keep |
| data-path | xs:string | ${basedir}/target/test-data | Rewrites db-connection/@files and recovery/@journal-dir |
| catalog-uri | xs:string? | () | Overrides validation/catalog/@uri; empty = keep canonical's |
| content-file-pool-size | xs:string? | () | Overrides content file pool size; empty = keep canonical's |
| extra-triggers | element()* | () | Appended to db-connection/startup/triggers |
| extra-index-modules | element()* | () | Appended to indexer/modules |
| extra-modules | element()* | () | Appended to xquery/builtin-modules |
The base stylesheet also strips RestXqStartupTrigger and AutoDeploymentTrigger from canonical (they assume a full webapp deployment); restore them per-fixture via $extra-triggers if a test needs them.
| Param | Type | Default | Purpose |
|---|---|---|---|
| keep-forwards | xs:string* | all 4 | forward/@pattern values to keep |
| rest-forward-pattern | xs:string? | () | Override @pattern on the /rest forward; empty = keep as-is |
| root-elements | element()* | () | Replace the entire <root> group; empty = keep template's roots |
keep-modules and keep-indexes operate on live elements only. If a <module> entry is commented out in the canonical template, it is invisible to the XPath match and cannot be "kept" this way. Use the corresponding extra-* param instead:
<!-- WRONG: spatial-index is commented out in canonical — keep-indexes silently produces nothing -->
<xsl:param name="keep-indexes" as="xs:string*" select="('sort-index', 'spatial-index')"/>
<!-- CORRECT: inject the live element directly -->
<xsl:param name="extra-index-modules" as="element()*">
<module xmlns="" id="spatial-index" file="spatial.dbx"
class="org.exist.indexing.spatial.GMLHSQLIndex"/>
</xsl:param>Modules that are commented out in canonical by default: spatial-index, xqsuite, vector.
The same rule applies to $extra-modules for builtin modules with child <parameter> elements — if the canonical entry is self-closing and your fixture needs parameter children, keep $keep-modules empty for that module (so the bare canonical entry is not also kept) and supply the parameterised element via $extra-modules:
<!-- SQL module needs pool parameters not present in the canonical self-closing entry -->
<xsl:param name="extra-modules" as="element()*">
<module xmlns="" uri="http://exist-db.org/xquery/sql" class="org.exist.xquery.modules.sql.SQLModule">
<parameter name="pool.1.name" value="pool-1"/>
…
</module>
</xsl:param>The generated conf.xml goes through Maven's testResource filtering, so ${basedir} in string parameters expands correctly. However, if you write a ${…} token inside a literal-result-element attribute that is also an XSLT AVT ({…}), you must double the curly braces so XSLT does not try to evaluate the inner braces as an XPath expression:
<!-- WRONG: XSLT tries to evaluate ${project.build.testOutputDirectory} as XPath -->
<parameter name="dir" value="${project.build.testOutputDirectory}/functx"/>
<!-- CORRECT: doubled braces → XSLT emits ${...} as literal text → Maven expands it -->
<parameter name="dir" value="${{project.build.testOutputDirectory}}/functx"/>Plain attribute content (not inside {…}) passes through unchanged and needs no escaping.
Create src/test/resources-filtered/conf-fixture.xsl importing the base stylesheet via its stable URN — no depth-counting required:
<xsl:import href="urn:exist-db:codegen:generate-conf-fixture"/>The URN is resolved by the schema/catalog.xml OASIS catalog, which xml-maven-plugin picks up automatically from exist-parent's pluginManagement (no per-module config needed).
Override only the params that differ from the base defaults; leave everything else out.
No xml-maven-plugin boilerplate needed in pom.xml — the conf-fixture-codegen profile in exist-parent/pom.xml activates automatically when src/test/resources-filtered/conf-fixture.xsl is present.
Add target/generated-test-resources as a filtered testResource and exclude **/*-fixture.xsl from src/test/resources-filtered so the stylesheet itself is not copied to target/test-classes.
exist-parent/pom.xml contains a conf-fixture-codegen profile activated automatically whenever src/test/resources-filtered/conf-fixture.xsl is present in a module. The profile runs the standard single-conf-xml transformation (canonical conf.xml → fixture → output in target/generated-test-resources/conf.xml).
Note: the profile must live in exist-parent (the actual inheritance parent of all modules), not the reactor root pom.xml — Maven evaluates <file> activation relative to the pom that defines the profile, so a profile in the reactor root would check the root's own basedir, where no module's src/test/resources-filtered/conf-fixture.xsl ever exists.
Most modules can remove their individual xml-maven-plugin conf-fixture-codegen execution from pom.xml entirely and rely on the profile; only modules with multiple fixtures (e.g. exist-core's four per-package conf-fixture.xsl files) or non-standard output paths (e.g. expathrepo) keep their own explicit execution alongside the profile.
schema/catalog.xml provides OASIS catalog entries mapping stable URNs to the two base stylesheets. Both the Maven build and IDE tooling use these URN aliases — per-fixture xsl:import hrefs use the URN form, resolved by schema/catalog.xml in both contexts:
<xsl:import href="urn:exist-db:codegen:generate-conf-fixture"/>
<xsl:import href="urn:exist-db:codegen:generate-controller-config-fixture"/>Maven wiring: exist-parent/pom.xml's pluginManagement registers schema/catalog.xml as a <catalog> for xml-maven-plugin; the plugin's Resolver (which implements javax.xml.transform.URIResolver) is set on the Saxon TransformerFactory, so URN hrefs resolve through the catalog at XSLT compile time.
| Back | FazBrowse Home | New Git URL |