From 4f2a1520eca2dbf1a46694d0bd1f5940ef49db67 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Tue, 16 Jun 2026 18:40:52 +0200 Subject: [PATCH 1/9] [feature] Add mvn validate for canonical config templates vs native XSDs Wire xml-maven-plugin on the root aggregator to check conf.xml, collection.xconf.init, descriptor.xml, controller-config.xml, and mime-types.xml against schema/*.xsd using XSD 1.1 (Xerces + xpath2). Centralize version pins and plugin classpath in exist-parent; align three schemas with their canonical templates so validation passes. --- exist-core/pom.xml | 5 --- exist-parent/pom.xml | 75 +++++++++++++++++++++++++++++++++++++ pom.xml | 59 +++++++++++++++++++++++++++++ schema/collection.xconf.xsd | 2 +- schema/descriptor.xsd | 1 + schema/mime-types.xsd | 2 +- 6 files changed, 137 insertions(+), 7 deletions(-) diff --git a/exist-core/pom.xml b/exist-core/pom.xml index 94287e0e7e1..2fcdb5ca616 100644 --- a/exist-core/pom.xml +++ b/exist-core/pom.xml @@ -301,7 +301,6 @@ org.exist-db.thirdparty.xerces xercesImpl - 2.12.2 jdk14-xml-schema-1.1 @@ -348,7 +347,6 @@ org.xmlresolver xmlresolver - ${xmlresolver.version} xml-apis @@ -360,7 +358,6 @@ org.xmlresolver xmlresolver - ${xmlresolver.version} data runtime @@ -376,13 +373,11 @@ org.exist-db.thirdparty.org.eclipse.wst.xml xpath2 - 1.2.0 runtime edu.princeton.cup java-cup - 10k runtime diff --git a/exist-parent/pom.xml b/exist-parent/pom.xml index 570df3da812..4cab338385e 100644 --- a/exist-parent/pom.xml +++ b/exist-parent/pom.xml @@ -137,6 +137,9 @@ 10.5.0 2.1.3 12.5 + 2.12.2 + 1.2.0 + 10k 6.0.23 2.12.0 4.13.2 @@ -229,6 +232,56 @@ ${saxon.version} + + org.exist-db.thirdparty.xerces + xercesImpl + ${xerces.version} + jdk14-xml-schema-1.1 + + + xml-apis + xml-apis + + + + + + org.exist-db.thirdparty.org.eclipse.wst.xml + xpath2 + ${xpath2.version} + + + + edu.princeton.cup + java-cup + ${java-cup.version} + + + + org.xmlresolver + xmlresolver + ${xmlresolver.version} + + + xml-apis + xml-apis + + + + + + org.xmlresolver + xmlresolver + ${xmlresolver.version} + data + + + xml-apis + xml-apis + + + + com.evolvedbinary.j8fu j8fu @@ -912,6 +965,28 @@ Saxon-HE ${saxon.version} + + + org.exist-db.thirdparty.xerces + xercesImpl + ${xerces.version} + jdk14-xml-schema-1.1 + + + org.exist-db.thirdparty.org.eclipse.wst.xml + xpath2 + ${xpath2.version} + + + edu.princeton.cup + java-cup + ${java-cup.version} + + + org.xmlresolver + xmlresolver + ${xmlresolver.version} + diff --git a/pom.xml b/pom.xml index 9566e6abc41..64f401511d6 100644 --- a/pom.xml +++ b/pom.xml @@ -67,6 +67,65 @@ true + + + + org.codehaus.mojo + xml-maven-plugin + + + validate-canonical-instances + validate + + validate + + + + + ${project.basedir}/exist-distribution/src/main/config + + conf.xml + + ${project.basedir}/schema/conf.xsd + http://www.w3.org/XML/XMLSchema/v1.1 + + + ${project.basedir}/exist-distribution/src/main/config + + collection.xconf.init + + ${project.basedir}/schema/collection.xconf.xsd + http://www.w3.org/XML/XMLSchema/v1.1 + + + ${project.basedir}/exist-distribution/src/main/config + + descriptor.xml + + ${project.basedir}/schema/descriptor.xsd + http://www.w3.org/XML/XMLSchema/v1.1 + + + ${project.basedir}/exist-jetty-config/src/main/resources/webapp/WEB-INF + + controller-config.xml + + ${project.basedir}/schema/controller-config.xsd + http://www.w3.org/XML/XMLSchema/v1.1 + + + ${project.basedir}/exist-core/src/main/resources/org/exist/util + + mime-types.xml + + ${project.basedir}/schema/mime-types.xsd + http://www.w3.org/XML/XMLSchema/v1.1 + + + + + + diff --git a/schema/collection.xconf.xsd b/schema/collection.xconf.xsd index fcd8eb16ede..c81b2730d76 100644 --- a/schema/collection.xconf.xsd +++ b/schema/collection.xconf.xsd @@ -267,7 +267,7 @@ Trigger Configuration - + diff --git a/schema/descriptor.xsd b/schema/descriptor.xsd index 30d9432d5b6..e2623391c61 100644 --- a/schema/descriptor.xsd +++ b/schema/descriptor.xsd @@ -35,6 +35,7 @@ + \ No newline at end of file diff --git a/schema/mime-types.xsd b/schema/mime-types.xsd index 7c1b78b18eb..6324b469485 100644 --- a/schema/mime-types.xsd +++ b/schema/mime-types.xsd @@ -17,7 +17,7 @@ - + From eddfbcdc28e8e4378d5357949fffbb9352cebec9 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Tue, 16 Jun 2026 20:59:34 +0200 Subject: [PATCH 2/9] [ci] Enforce xs:schema/@version bumps on governed config changes Add path-filtered ci-schema-checks workflow: XSL governance that reads pairs from pom validationSets, compares base @version (xpath via GITHUB_ENV) to head, and fails with PR annotations when a schema or canonical template changes without a version bump. --- .github/scripts/prepare-governance-env.sh | 77 ++++++++++++++++ .github/scripts/run-governance-check.sh | 48 ++++++++++ .github/workflows/ci-schema-checks.yml | 64 +++++++++++++ pom.xml | 2 +- schema/README.md | 39 ++++++++ schema/governance-annotations.xsl | 12 +++ schema/governance-check.xsl | 104 ++++++++++++++++++++++ schema/governance-pairs.xsl | 39 ++++++++ schema/governance-schemas.xsl | 55 ++++++++++++ 9 files changed, 439 insertions(+), 1 deletion(-) create mode 100755 .github/scripts/prepare-governance-env.sh create mode 100755 .github/scripts/run-governance-check.sh create mode 100644 .github/workflows/ci-schema-checks.yml create mode 100644 schema/README.md create mode 100644 schema/governance-annotations.xsl create mode 100644 schema/governance-check.xsl create mode 100644 schema/governance-pairs.xsl create mode 100644 schema/governance-schemas.xsl diff --git a/.github/scripts/prepare-governance-env.sh b/.github/scripts/prepare-governance-env.sh new file mode 100755 index 00000000000..da73be444ec --- /dev/null +++ b/.github/scripts/prepare-governance-env.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# Resolve diff base, export old @version values (xpath) for schemas resolved from pom.xml via XSL. +set -euo pipefail +cd "$(git rev-parse --show-toplevel)" + +WORKSPACE="${1:?workspace required}" +POM="${WORKSPACE}/pom.xml" +SCHEMA_DIR="${WORKSPACE}/schema" +TMP="${2:-$(mktemp -d)}" +mkdir -p "${TMP}" + +if [[ -n "${GITHUB_BASE_REF:-}" ]]; then + git fetch --depth=1 origin "${GITHUB_BASE_REF}" 2>/dev/null || true + BASE="$(git merge-base HEAD "origin/${GITHUB_BASE_REF}")" +elif [[ -n "${GITHUB_EVENT_BEFORE:-}" && "${GITHUB_EVENT_BEFORE}" != "0000000000000000000000000000000000000000" ]]; then + BASE="${GITHUB_EVENT_BEFORE}" +else + BASE="$(git rev-parse HEAD~1 2>/dev/null || git rev-parse HEAD)" +fi + +schema_version_at() { + git show "${BASE}:$1" 2>/dev/null \ + | xmllint --xpath 'string(/*[local-name()="schema"]/@version)' - 2>/dev/null \ + | xargs echo || true +} + +env_key() { + printf '%s' "$1" | tr '/.-' '_' | tr '[:upper:]' '[:lower:]' +} + +{ + echo "GOVERNANCE_WORKSPACE=${WORKSPACE}" + echo "GOVERNANCE_BASE_REF=${BASE}" +} >> "${GITHUB_ENV}" + +CHANGED=() +while IFS= read -r path; do + [[ -n "${path}" ]] || continue + case "${path}" in + *.md|*.xsl) continue ;; + schema/governance-*|schema/normalize-*) continue ;; + esac + CHANGED+=("${path}") +done < <(git diff --name-only "${BASE}" -- \ + schema \ + exist-distribution/src/main/config \ + exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml \ + exist-core/src/main/resources/org/exist/util/mime-types.xml \ + 2>/dev/null || true) + +CHANGED_XML="${TMP}/changed.xml" +{ + echo '' + echo '' + for path in "${CHANGED[@]:-}"; do + printf ' %s\n' "${path}" + done + echo '' +} > "${CHANGED_XML}" + +SCHEMAS=() +while IFS= read -r schema; do + [[ -n "${schema}" ]] && SCHEMAS+=("${schema}") +done < <(xsltproc --path "${SCHEMA_DIR}" --stringparam pom-uri "${POM}" \ + "${SCHEMA_DIR}/governance-schemas.xsl" "${CHANGED_XML}") + +for schema in "${SCHEMAS[@]:-}"; do + ver="$(schema_version_at "${schema}")" + echo "GOVERNANCE_OLD_VERSION_$(env_key "${schema}")=${ver}" >> "${GITHUB_ENV}" +done + +IFS=','; echo "GOVERNANCE_SCHEMAS=${SCHEMAS[*]:-}" >> "${GITHUB_ENV}" +IFS=','; echo "GOVERNANCE_CHANGED=${CHANGED[*]:-}" >> "${GITHUB_ENV}" + +echo "Governance base: ${BASE}" +echo "Changed: ${CHANGED[*]:-(none)}" +echo "Schemas: ${SCHEMAS[*]:-(none)}" diff --git a/.github/scripts/run-governance-check.sh b/.github/scripts/run-governance-check.sh new file mode 100755 index 00000000000..d8527307efe --- /dev/null +++ b/.github/scripts/run-governance-check.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -euo pipefail + +WORKSPACE="${1:?workspace required}" +OUT="${2:?context xml path required}" +POM="${WORKSPACE}/pom.xml" +SCHEMA_DIR="${WORKSPACE}/schema" + +env_key() { + printf '%s' "$1" | tr '/.-' '_' | tr '[:upper:]' '[:lower:]' +} + +mkdir -p "$(dirname "${OUT}")" + +{ + echo '' + echo "" + + if [[ -n "${GOVERNANCE_SCHEMAS:-}" ]]; then + IFS=',' read -ra SCHEMA_LIST <<< "${GOVERNANCE_SCHEMAS}" + for schema in "${SCHEMA_LIST[@]}"; do + [[ -n "${schema}" ]] || continue + key="GOVERNANCE_OLD_VERSION_$(env_key "${schema}")" + ver="${!key-}" + printf ' %s\n' "${schema}" "${ver}" + done + fi + + if [[ -n "${GOVERNANCE_CHANGED:-}" ]]; then + IFS=',' read -ra PATHS <<< "${GOVERNANCE_CHANGED}" + for path in "${PATHS[@]}"; do + [[ -n "${path}" ]] || continue + printf ' \n' "${path}" + done + fi + + echo '' +} > "${OUT}" + +REPORT="${OUT%/*}/governance-report.xml" +xsltproc --path "${SCHEMA_DIR}" --stringparam pom-uri "${POM}" \ + "${SCHEMA_DIR}/governance-check.xsl" "${OUT}" > "${REPORT}" + +cat "${REPORT}" +xsltproc "${SCHEMA_DIR}/governance-annotations.xsl" "${REPORT}" +test "$(xmllint --xpath 'string(/*[local-name()="report"]/@status)' "${REPORT}")" = "passed" diff --git a/.github/workflows/ci-schema-checks.yml b/.github/workflows/ci-schema-checks.yml new file mode 100644 index 00000000000..f82641c46f4 --- /dev/null +++ b/.github/workflows/ci-schema-checks.yml @@ -0,0 +1,64 @@ +name: Schema checks + +on: + pull_request: + paths: + - 'schema/**' + - 'exist-distribution/src/main/config/**' + - 'exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml' + - 'exist-core/src/main/resources/org/exist/util/mime-types.xml' + push: + branches: [develop] + paths: + - 'schema/**' + - 'exist-distribution/src/main/config/**' + - 'exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml' + - 'exist-core/src/main/resources/org/exist/util/mime-types.xml' + workflow_dispatch: + +permissions: + contents: read + +env: + MAVEN_OPTS: -DtrimStackTrace=false + DEV_JDK: '21' + +jobs: + schema: + name: Native XSD checks + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: ${{ env.DEV_JDK }} + + - uses: ./.github/actions/maven-cache + + - name: Install xmllint and xsltproc + run: sudo apt-get update && sudo apt-get install -y libxml2-utils xsltproc + + - name: Validate canonical templates against XSD + run: mvn -V -B --no-transfer-progress validate -Ddependency-check.skip=true -Ddocker=false + + - name: Export base revisions to env + env: + GITHUB_BASE_REF: ${{ github.base_ref }} + GITHUB_EVENT_BEFORE: ${{ github.event.before }} + run: | + chmod +x .github/scripts/prepare-governance-env.sh + .github/scripts/prepare-governance-env.sh \ + "${{ github.workspace }}" \ + "${{ runner.temp }}" + + - name: Run schema governance check + run: | + chmod +x .github/scripts/run-governance-check.sh + .github/scripts/run-governance-check.sh \ + "${{ github.workspace }}" \ + "${{ runner.temp }}/governance-ctx.xml" diff --git a/pom.xml b/pom.xml index 64f401511d6..e9df4bfdfcf 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ - + org.codehaus.mojo xml-maven-plugin diff --git a/schema/README.md b/schema/README.md new file mode 100644 index 00000000000..88729e0bf0c --- /dev/null +++ b/schema/README.md @@ -0,0 +1,39 @@ +# eXist-db native XML schemas + +XSD schemas for eXist-db configuration and descriptor files. + +## Versioning policy + +Each native schema declares an independent semver on ``. 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`. + +## Validation + +**Templates vs schemas** — root [`pom.xml`](../pom.xml) binds `xml-maven-plugin:validate` at the `validate` phase. This also runs on every full build via [`ci-test.yml`](../.github/workflows/ci-test.yml) (`mvn test` runs `validate` first). + +[`ci-schema-checks.yml`](../.github/workflows/ci-schema-checks.yml) re-runs `mvn validate` on PRs that touch schemas or canonical templates (fast, path-filtered). + +**Version bumps** — CI xpath on the base revision exports `GOVERNANCE_OLD_VERSION_*` env vars; schema paths come from [`governance-schemas.xsl`](governance-schemas.xsl) (pairs read from `pom.xml` validationSets). [`governance-check.xsl`](governance-check.xsl) compares old vs current `xs:schema/@version`. + +## Canonical templates + +| Schema | Template | +|--------|----------| +| [`conf.xsd`](conf.xsd) | [`exist-distribution/src/main/config/conf.xml`](../exist-distribution/src/main/config/conf.xml) | +| [`collection.xconf.xsd`](collection.xconf.xsd) | [`collection.xconf.init`](../exist-distribution/src/main/config/collection.xconf.init) | +| [`descriptor.xsd`](descriptor.xsd) | [`descriptor.xml`](../exist-distribution/src/main/config/descriptor.xml) | +| [`controller-config.xsd`](controller-config.xsd) | [`controller-config.xml`](../exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml) | +| [`mime-types.xsd`](mime-types.xsd) | [`mime-types.xml`](../exist-core/src/main/resources/org/exist/util/mime-types.xml) | + +Other schemas (`users.xsd`, `server.xsd`, `expath-pkg.xsd`, …) apply to runtime or package files, not shipped templates. + +## Distribution + +Schemas ship at `$EXIST_HOME/schema/` ([#6189](https://github.com/eXist-db/exist/issues/6189)). diff --git a/schema/governance-annotations.xsl b/schema/governance-annotations.xsl new file mode 100644 index 00000000000..7cf8f9adbf0 --- /dev/null +++ b/schema/governance-annotations.xsl @@ -0,0 +1,12 @@ + + + + + ::error file= + :: + + + diff --git a/schema/governance-check.xsl b/schema/governance-check.xsl new file mode 100644 index 00000000000..47d8436bf41 --- /dev/null +++ b/schema/governance-check.xsl @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema and template + Schema + + + + + + + + + + + + + + + + + + + + + + + failed + passed + + + + + + + + + + + + + + + + + + + + + changed but @version is still " + + ". Bump xs:schema/@version (see schema/README.md). + + + + + + + diff --git a/schema/governance-pairs.xsl b/schema/governance-pairs.xsl new file mode 100644 index 00000000000..d5ae0e71827 --- /dev/null +++ b/schema/governance-pairs.xsl @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/schema/governance-schemas.xsl b/schema/governance-schemas.xsl new file mode 100644 index 00000000000..a09aaadd091 --- /dev/null +++ b/schema/governance-schemas.xsl @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From a02864eb3a314b46ec4feacf27515ef2d47515e7 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Wed, 17 Jun 2026 10:06:33 +0200 Subject: [PATCH 3/9] [bugfix] Bump native XSD @version for post-2023 semantic changes see #6190 --- schema/collection.xconf.xsd | 2 +- schema/conf.xsd | 2 +- schema/controller-config.xsd | 2 +- schema/descriptor.xsd | 2 +- schema/expath-pkg-extensions/cxan.xsd | 3 ++- schema/expath-pkg-extensions/exist.xsd | 3 ++- schema/expath-pkg-extensions/repo.xsd | 3 ++- schema/expath-pkg.xsd | 3 ++- schema/mime-types.xsd | 2 +- 9 files changed, 13 insertions(+), 9 deletions(-) diff --git a/schema/collection.xconf.xsd b/schema/collection.xconf.xsd index c81b2730d76..9cf5c9ea437 100644 --- a/schema/collection.xconf.xsd +++ b/schema/collection.xconf.xsd @@ -6,7 +6,7 @@ xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" targetNamespace="http://exist-db.org/collection-config/1.0" - version="1.0.0"> + version="1.1.0"> Schema for eXist-db Collection Configuration files /db/system/config/db/**/collection.xconf diff --git a/schema/conf.xsd b/schema/conf.xsd index 5b1c0b363d9..92aae7cc076 100644 --- a/schema/conf.xsd +++ b/schema/conf.xsd @@ -8,7 +8,7 @@ + version="2.0.0"> diff --git a/schema/controller-config.xsd b/schema/controller-config.xsd index 7ed505eee78..73f6d2ab53c 100644 --- a/schema/controller-config.xsd +++ b/schema/controller-config.xsd @@ -4,7 +4,7 @@ xmlns:exist="http://exist.sourceforge.net/NS/exist" elementFormDefault="qualified" targetNamespace="http://exist.sourceforge.net/NS/exist" - version="1.0.0"> + version="1.0.1"> diff --git a/schema/descriptor.xsd b/schema/descriptor.xsd index e2623391c61..c607b4dd581 100644 --- a/schema/descriptor.xsd +++ b/schema/descriptor.xsd @@ -6,7 +6,7 @@ + version="1.1.0"> diff --git a/schema/expath-pkg-extensions/cxan.xsd b/schema/expath-pkg-extensions/cxan.xsd index dc2864d613c..613b09d961e 100644 --- a/schema/expath-pkg-extensions/cxan.xsd +++ b/schema/expath-pkg-extensions/cxan.xsd @@ -5,7 +5,8 @@ xmlns:cxan="http://cxan.org/ns/package" xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" - targetNamespace="http://cxan.org/ns/package"> + targetNamespace="http://cxan.org/ns/package" + version="1.0.0"> A schema for the EXPath Packaging CXAN concept. diff --git a/schema/expath-pkg-extensions/exist.xsd b/schema/expath-pkg-extensions/exist.xsd index b72e130e3d3..eb53fa7f4d7 100644 --- a/schema/expath-pkg-extensions/exist.xsd +++ b/schema/expath-pkg-extensions/exist.xsd @@ -5,7 +5,8 @@ xmlns:eepkg="http://exist-db.org/ns/expath-pkg" xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" - targetNamespace="http://exist-db.org/ns/expath-pkg"> + targetNamespace="http://exist-db.org/ns/expath-pkg" + version="1.0.0"> A schema for eXist-db extensions to EXPath Packaging. diff --git a/schema/expath-pkg-extensions/repo.xsd b/schema/expath-pkg-extensions/repo.xsd index 14ee73383a7..c5000cd65cf 100644 --- a/schema/expath-pkg-extensions/repo.xsd +++ b/schema/expath-pkg-extensions/repo.xsd @@ -5,7 +5,8 @@ xmlns:repo="http://exist-db.org/xquery/repo" xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" - targetNamespace="http://exist-db.org/xquery/repo"> + targetNamespace="http://exist-db.org/xquery/repo" + version="1.0.0"> A schema for eXist-db Package Repository extensions to EXPath Packaging. diff --git a/schema/expath-pkg.xsd b/schema/expath-pkg.xsd index c62f50cc315..b962392ac6d 100644 --- a/schema/expath-pkg.xsd +++ b/schema/expath-pkg.xsd @@ -5,7 +5,8 @@ xmlns:pkg="http://expath.org/ns/pkg" xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" - targetNamespace="http://expath.org/ns/pkg"> + targetNamespace="http://expath.org/ns/pkg" + version="1.0.0"> A schema for EXPath Packaging (i.e. expath-pkg.xml) file as per the EXPath Packaging System - Candidate Module 9 May 2012' specification. diff --git a/schema/mime-types.xsd b/schema/mime-types.xsd index 6324b469485..1244e319f96 100644 --- a/schema/mime-types.xsd +++ b/schema/mime-types.xsd @@ -6,7 +6,7 @@ + version="1.1.0"> From 89c7ca6f3cb407564cf6c197bb176dc3c8501eae Mon Sep 17 00:00:00 2001 From: duncdrum Date: Wed, 17 Jun 2026 11:03:59 +0200 Subject: [PATCH 4/9] [feature] Add schemaVersion attribute to canonical config instances Lets eXist detect when a config template (conf.xml, collection.xconf, descriptor.xml, mime-types.xml, controller-config.xml) was authored against an older revision of its paired XSD. Each schema gains an optional schemaVersion attribute mirroring xs:schema/@version; runtime parsers log a debug message for legacy documents that omit it and warn when a declared value doesn't match what the running build expects. see #3062 --- .../collections/CollectionConfiguration.java | 3 + .../main/java/org/exist/http/Descriptor.java | 3 + .../exist/http/urlrewrite/RewriteConfig.java | 2 + .../java/org/exist/util/Configuration.java | 3 + .../main/java/org/exist/util/MimeTable.java | 4 +- .../java/org/exist/util/SchemaVersion.java | 71 +++++++++++++++++++ .../resources/org/exist/util/mime-types.xml | 2 +- .../org/exist/util/SchemaVersionTest.java | 58 +++++++++++++++ .../src/main/config/collection.xconf.init | 2 +- exist-distribution/src/main/config/conf.xml | 2 +- .../src/main/config/descriptor.xml | 2 +- .../webapp/WEB-INF/controller-config.xml | 2 +- schema/README.md | 12 ++++ schema/collection.xconf.xsd | 12 +++- schema/conf.xsd | 12 +++- schema/controller-config.xsd | 11 ++- schema/descriptor.xsd | 11 ++- schema/mime-types.xsd | 11 ++- 18 files changed, 212 insertions(+), 11 deletions(-) create mode 100644 exist-core/src/main/java/org/exist/util/SchemaVersion.java create mode 100644 exist-core/src/test/java/org/exist/util/SchemaVersionTest.java diff --git a/exist-core/src/main/java/org/exist/collections/CollectionConfiguration.java b/exist-core/src/main/java/org/exist/collections/CollectionConfiguration.java index 379eb2e6b90..ffaa06de747 100644 --- a/exist-core/src/main/java/org/exist/collections/CollectionConfiguration.java +++ b/exist-core/src/main/java/org/exist/collections/CollectionConfiguration.java @@ -40,6 +40,7 @@ import org.exist.storage.IndexSpec; import org.exist.util.DatabaseConfigurationException; import org.exist.util.ParametersExtractor; +import org.exist.util.SchemaVersion; import org.exist.util.XMLReaderObjectFactory; import org.exist.xmldb.XmldbURI; import org.w3c.dom.Document; @@ -129,6 +130,8 @@ protected void read(final DBBroker broker, final Document doc, final boolean che "' in configuration document. Got '" + root.getNamespaceURI() + "'", checkOnly); return; } + SchemaVersion.logDocumentVersion(LOG, root, SchemaVersion.COLLECTION_XCONF, + "collection.xconf" + (docName != null ? " (" + docName + ")" : "")); final NodeList childNodes = root.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node node = childNodes.item(i); diff --git a/exist-core/src/main/java/org/exist/http/Descriptor.java b/exist-core/src/main/java/org/exist/http/Descriptor.java index 571aa558276..1f284d76b15 100644 --- a/exist-core/src/main/java/org/exist/http/Descriptor.java +++ b/exist-core/src/main/java/org/exist/http/Descriptor.java @@ -28,6 +28,7 @@ import org.exist.dom.memtree.SAXAdapter; import org.exist.util.ConfigurationHelper; import org.exist.util.ExistSAXParserFactory; +import org.exist.util.SchemaVersion; import org.exist.util.SingleInstanceConfiguration; import org.exist.xquery.Expression; import org.w3c.dom.Document; @@ -138,6 +139,8 @@ private Descriptor() { final Document doc = adapter.getDocument(); + SchemaVersion.logDocumentVersion(LOG, doc.getDocumentElement(), SchemaVersion.DESCRIPTOR, "descriptor.xml"); + //load attribue settings if ("true".equals(doc.getDocumentElement().getAttribute("request-replay-log"))) { final Path logFile = Path.of("request-replay-log.txt"); diff --git a/exist-core/src/main/java/org/exist/http/urlrewrite/RewriteConfig.java b/exist-core/src/main/java/org/exist/http/urlrewrite/RewriteConfig.java index 745dd98d106..a08a016c20b 100644 --- a/exist-core/src/main/java/org/exist/http/urlrewrite/RewriteConfig.java +++ b/exist-core/src/main/java/org/exist/http/urlrewrite/RewriteConfig.java @@ -35,6 +35,7 @@ import net.sf.saxon.str.StringView; import net.sf.saxon.trans.XPathException; import org.exist.util.XMLReaderPool; +import org.exist.util.SchemaVersion; import org.exist.xmldb.XmldbURI; import org.exist.xquery.Constants; import org.exist.xquery.Expression; @@ -199,6 +200,7 @@ private void configure(final String controllerConfig) throws ServletException { private void parse(final Document doc) throws ServletException { final Element root = doc.getDocumentElement(); + SchemaVersion.logDocumentVersion(LOG, root, SchemaVersion.CONTROLLER_CONFIG, "controller-config.xml"); Node child = root.getFirstChild(); while (child != null) { final String ns = child.getNamespaceURI(); diff --git a/exist-core/src/main/java/org/exist/util/Configuration.java b/exist-core/src/main/java/org/exist/util/Configuration.java index 0927f76fc89..bbead109e73 100644 --- a/exist-core/src/main/java/org/exist/util/Configuration.java +++ b/exist-core/src/main/java/org/exist/util/Configuration.java @@ -345,6 +345,9 @@ public Configuration(@Nullable String configFilename, Optional existHomeDi final Document doc = adapter.getDocument(); + SchemaVersion.logDocumentVersion(LOG, doc.getDocumentElement(), SchemaVersion.CONF, + configFilePath.map(p -> "conf.xml (" + p + ")").orElse("conf.xml")); + //indexer settings configureElement(doc, Indexer.CONFIGURATION_ELEMENT_NAME, element -> configureIndexer(doc, element)); //scheduler settings diff --git a/exist-core/src/main/java/org/exist/util/MimeTable.java b/exist-core/src/main/java/org/exist/util/MimeTable.java index 09d303e9ae9..bbac6f5e5b2 100644 --- a/exist-core/src/main/java/org/exist/util/MimeTable.java +++ b/exist-core/src/main/java/org/exist/util/MimeTable.java @@ -264,8 +264,8 @@ private void load(final InputStream stream, final String src) { private void loadFromStream(final InputStream stream, final String sourceDescription) { try (stream) { - loadMimeTypes(stream); this.src = sourceDescription; + loadMimeTypes(stream); } catch (final ParserConfigurationException | SAXException | IOException e) { throw new IllegalStateException("Failed to load mime-type table from " + sourceDescription, e); } @@ -312,6 +312,8 @@ public void startElement(String uri, String localName, String qName, if (MIME_TYPES.equals(qName)) { + SchemaVersion.logDocumentVersion(LOG, attributes.getValue(SchemaVersion.ATTRIBUTE), + SchemaVersion.MIME_TYPES, src != null ? "mime-types.xml (" + src + ")" : "mime-types.xml"); // Check for a default mime type settings final String defaultMimeAttr = attributes.getValue("default-mime-type"); final String defaultTypeAttr = attributes.getValue("default-resource-type"); diff --git a/exist-core/src/main/java/org/exist/util/SchemaVersion.java b/exist-core/src/main/java/org/exist/util/SchemaVersion.java new file mode 100644 index 00000000000..50ea3842f9f --- /dev/null +++ b/exist-core/src/main/java/org/exist/util/SchemaVersion.java @@ -0,0 +1,71 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.util; + +import org.apache.logging.log4j.Logger; +import org.w3c.dom.Element; + +/** + * Optional {@code schemaVersion} on native config instance documents — mirrors + * {@code xs:schema/@version} on the paired XSD (native schema semver, not eXist product version). + */ +public final class SchemaVersion { + + public static final String ATTRIBUTE = "schemaVersion"; + + /** Paired {@code xs:schema/@version} values for canonical templates (keep in sync with {@code schema/*.xsd}). */ + public static final String CONF = "2.1.0"; + public static final String COLLECTION_XCONF = "1.2.0"; + public static final String DESCRIPTOR = "1.2.0"; + public static final String MIME_TYPES = "1.2.0"; + public static final String CONTROLLER_CONFIG = "1.1.0"; + + private SchemaVersion() { + } + + /** + * Log when {@code schemaVersion} is missing (legacy) or differs from the schema version this build expects. + */ + public static void logDocumentVersion(final Logger log, final Element root, + final String expectedVersion, final String documentDescription) { + logDocumentVersion(log, root != null ? root.getAttribute(ATTRIBUTE) : "", expectedVersion, documentDescription); + } + + /** + * SAX variant when only the attribute value is available. + */ + public static void logDocumentVersion(final Logger log, final String declaredVersion, + final String expectedVersion, final String documentDescription) { + if (declaredVersion == null || declaredVersion.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("{} has no {} attribute (legacy document)", documentDescription, ATTRIBUTE); + } + return; + } + if (!declaredVersion.equals(expectedVersion)) { + log.warn("{} declares {}=\"{}\" but this eXist build expects \"{}\"", + documentDescription, ATTRIBUTE, declaredVersion, expectedVersion); + } else if (log.isDebugEnabled()) { + log.debug("{} {}=\"{}\"", documentDescription, ATTRIBUTE, declaredVersion); + } + } +} diff --git a/exist-core/src/main/resources/org/exist/util/mime-types.xml b/exist-core/src/main/resources/org/exist/util/mime-types.xml index 58ba03cf203..adc83c45ecb 100644 --- a/exist-core/src/main/resources/org/exist/util/mime-types.xml +++ b/exist-core/src/main/resources/org/exist/util/mime-types.xml @@ -37,7 +37,7 @@ and then as a classpath resource in org/exist/util . ======================================================= --> - + diff --git a/exist-core/src/test/java/org/exist/util/SchemaVersionTest.java b/exist-core/src/test/java/org/exist/util/SchemaVersionTest.java new file mode 100644 index 00000000000..0e4f51b6dbb --- /dev/null +++ b/exist-core/src/test/java/org/exist/util/SchemaVersionTest.java @@ -0,0 +1,58 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.util; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.junit.Test; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilderFactory; + +import static org.junit.Assert.assertEquals; + +public class SchemaVersionTest { + + private static final Logger LOG = LogManager.getLogger(SchemaVersionTest.class); + + @Test + public void attributeNameIsSchemaVersion() { + assertEquals("schemaVersion", SchemaVersion.ATTRIBUTE); + } + + @Test + public void logDocumentVersionAcceptsMatchingValue() throws Exception { + final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + final var root = doc.createElement("exist"); + root.setAttribute(SchemaVersion.ATTRIBUTE, SchemaVersion.CONF); + doc.appendChild(root); + SchemaVersion.logDocumentVersion(LOG, root, SchemaVersion.CONF, "test conf.xml"); + } + + @Test + public void logDocumentVersionAcceptsMissingAttribute() throws Exception { + final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + final var root = doc.createElement("exist"); + doc.appendChild(root); + SchemaVersion.logDocumentVersion(LOG, root, SchemaVersion.CONF, "legacy conf.xml"); + } +} diff --git a/exist-distribution/src/main/config/collection.xconf.init b/exist-distribution/src/main/config/collection.xconf.init index 8933b884e33..03e31bd6aa8 100644 --- a/exist-distribution/src/main/config/collection.xconf.init +++ b/exist-distribution/src/main/config/collection.xconf.init @@ -1,5 +1,5 @@ - + - + - + + xsi:schemaLocation="http://exist.sourceforge.net/NS/exist file:../../schema/controller-config.xsd" schemaVersion="1.1.0"> diff --git a/schema/README.md b/schema/README.md index 88729e0bf0c..db35530a9fe 100644 --- a/schema/README.md +++ b/schema/README.md @@ -14,6 +14,18 @@ Each native schema declares an independent semver on `` 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` | `` | +| `collection.xconf.xsd` | `` | +| `descriptor.xsd` | `` | +| `mime-types.xsd` | `` | +| `controller-config.xsd` | `` | + +Keep [`SchemaVersion.java`](../exist-core/src/main/java/org/exist/util/SchemaVersion.java) constants in sync with `xs:schema/@version` on the paired XSDs. + ## Validation **Templates vs schemas** — root [`pom.xml`](../pom.xml) binds `xml-maven-plugin:validate` at the `validate` phase. This also runs on every full build via [`ci-test.yml`](../.github/workflows/ci-test.yml) (`mvn test` runs `validate` first). diff --git a/schema/collection.xconf.xsd b/schema/collection.xconf.xsd index 9cf5c9ea437..36adff921d6 100644 --- a/schema/collection.xconf.xsd +++ b/schema/collection.xconf.xsd @@ -6,7 +6,16 @@ xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" targetNamespace="http://exist-db.org/collection-config/1.0" - version="1.1.0"> + version="1.2.0"> + + + + Native XSD semver; mirrors xs:schema/@version on collection.xconf.xsd (not eXist product version). + + + + + Schema for eXist-db Collection Configuration files /db/system/config/db/**/collection.xconf @@ -28,6 +37,7 @@ + diff --git a/schema/conf.xsd b/schema/conf.xsd index 92aae7cc076..829db1044e4 100644 --- a/schema/conf.xsd +++ b/schema/conf.xsd @@ -8,7 +8,16 @@ + version="2.1.0"> + + + + Native XSD semver; mirrors xs:schema/@version on conf.xsd (not eXist product version). + + + + + @@ -1413,6 +1422,7 @@ + diff --git a/schema/controller-config.xsd b/schema/controller-config.xsd index 73f6d2ab53c..5fae9068e82 100644 --- a/schema/controller-config.xsd +++ b/schema/controller-config.xsd @@ -4,13 +4,22 @@ xmlns:exist="http://exist.sourceforge.net/NS/exist" elementFormDefault="qualified" targetNamespace="http://exist.sourceforge.net/NS/exist" - version="1.0.1"> + version="1.1.0"> + + + Native XSD semver; mirrors xs:schema/@version on controller-config.xsd (not eXist product version). + + + + + + diff --git a/schema/descriptor.xsd b/schema/descriptor.xsd index c607b4dd581..c7198ac9e2d 100644 --- a/schema/descriptor.xsd +++ b/schema/descriptor.xsd @@ -6,7 +6,15 @@ + version="1.2.0"> + + + Native XSD semver; mirrors xs:schema/@version on descriptor.xsd (not eXist product version). + + + + + @@ -36,6 +44,7 @@ + \ No newline at end of file diff --git a/schema/mime-types.xsd b/schema/mime-types.xsd index 1244e319f96..39a57a8f8c0 100644 --- a/schema/mime-types.xsd +++ b/schema/mime-types.xsd @@ -6,7 +6,15 @@ + version="1.2.0"> + + + Native XSD semver; mirrors xs:schema/@version on mime-types.xsd (not eXist product version). + + + + + @@ -55,6 +63,7 @@ + \ No newline at end of file From 18f0f94b3f780feed774dead28fc290af01f601d Mon Sep 17 00:00:00 2001 From: duncdrum Date: Wed, 17 Jun 2026 11:40:22 +0200 Subject: [PATCH 5/9] [bugfix] Close silent-failure gaps in schema governance CI mavenize and simplify the whole operation --- .github/scripts/prepare-governance-context.sh | 53 +++++++++ .github/scripts/prepare-governance-env.sh | 77 ------------- .github/scripts/run-governance-check.sh | 48 -------- .github/workflows/ci-schema-checks.yml | 24 ++-- .../main/java/org/exist/util/MimeTable.java | 25 +++-- .../java/org/exist/util/SchemaVersion.java | 16 ++- .../resources/org/exist/util/mime-types.xml | 2 +- .../org/exist/util/SchemaVersionSyncTest.java | 89 +++++++++++++++ .../src/main/config/collection.xconf.init | 2 +- exist-distribution/src/main/config/conf.xml | 2 +- .../src/main/config/descriptor.xml | 2 +- .../webapp/WEB-INF/controller-config.xml | 2 +- pom.xml | 36 +++++- schema/README.md | 8 +- schema/collection.xconf.xsd | 11 +- schema/conf.xsd | 15 +-- schema/controller-config.xsd | 11 +- schema/descriptor.xsd | 11 +- schema/governance-annotations.xsl | 12 -- schema/governance-check.xsl | 104 ----------------- schema/governance-pairs.xsl | 39 ------- schema/governance-schemas.xsl | 55 --------- schema/governance.xsl | 106 ++++++++++++++++++ schema/mime-types.xsd | 11 +- schema/schema-version-type.xsd | 22 ++++ 25 files changed, 361 insertions(+), 422 deletions(-) create mode 100755 .github/scripts/prepare-governance-context.sh delete mode 100755 .github/scripts/prepare-governance-env.sh delete mode 100755 .github/scripts/run-governance-check.sh create mode 100644 exist-core/src/test/java/org/exist/util/SchemaVersionSyncTest.java delete mode 100644 schema/governance-annotations.xsl delete mode 100644 schema/governance-check.xsl delete mode 100644 schema/governance-pairs.xsl delete mode 100644 schema/governance-schemas.xsl create mode 100644 schema/governance.xsl create mode 100644 schema/schema-version-type.xsd diff --git a/.github/scripts/prepare-governance-context.sh b/.github/scripts/prepare-governance-context.sh new file mode 100755 index 00000000000..43b48759644 --- /dev/null +++ b/.github/scripts/prepare-governance-context.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# Pure git plumbing for schema governance — everything else (pairing, +# version comparison, the GitHub annotations, failing the build) happens in +# a single Saxon XSLT 2.0 transform (schema/governance.xsl) driven by +# `mvn xml:transform@schema-governance`. This script's only job is to put +# the git state that transform needs onto disk as plain files/XML, so the +# stylesheet never has to shell out itself. +set -euo pipefail +cd "$(git rev-parse --show-toplevel)" + +WORKSPACE="${1:?workspace required}" +OUT="${2:-${WORKSPACE}/target/governance}" +mkdir -p "${OUT}/base" + +if [[ -n "${GITHUB_BASE_REF:-}" ]]; then + git fetch --depth=1 origin "${GITHUB_BASE_REF}" 2>/dev/null || true + BASE="$(git merge-base HEAD "origin/${GITHUB_BASE_REF}")" +elif [[ -n "${GITHUB_EVENT_BEFORE:-}" && "${GITHUB_EVENT_BEFORE}" != "0000000000000000000000000000000000000000" ]]; then + BASE="${GITHUB_EVENT_BEFORE}" +else + BASE="$(git rev-parse HEAD~1 2>/dev/null || git rev-parse HEAD)" +fi + +# Every tracked schema/*.xsd's content as it existed at BASE, one file per +# schema named after its basename. A missing file at $OUT/base/ means +# "didn't exist at BASE" (new schema) — governance.xsl checks for that with +# doc-available() rather than this script trying to distinguish "new file" +# from "tool failure" itself. +git ls-tree -r --name-only HEAD -- schema | grep '\.xsd$' | while read -r f; do + out="${OUT}/base/$(basename "${f}")" + git show "${BASE}:${f}" > "${out}" 2>/dev/null || rm -f "${out}" +done + +# One path per line; governance.xsl reads this with unparsed-text() + tokenize(), +# so no XML-escaping of path characters is needed anywhere in this pipeline. +git diff --name-only "${BASE}" -- \ + schema \ + exist-distribution/src/main/config \ + exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml \ + exist-core/src/main/resources/org/exist/util/mime-types.xml \ + exist-core/src/main/java/org/exist/util/SchemaVersion.java \ + > "${OUT}/changed.txt" 2>/dev/null || true + +cat > "${OUT}/context.xml" < + +EOF + +echo "Governance context: ${OUT}/context.xml (base ${BASE})" diff --git a/.github/scripts/prepare-governance-env.sh b/.github/scripts/prepare-governance-env.sh deleted file mode 100755 index da73be444ec..00000000000 --- a/.github/scripts/prepare-governance-env.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash -# Resolve diff base, export old @version values (xpath) for schemas resolved from pom.xml via XSL. -set -euo pipefail -cd "$(git rev-parse --show-toplevel)" - -WORKSPACE="${1:?workspace required}" -POM="${WORKSPACE}/pom.xml" -SCHEMA_DIR="${WORKSPACE}/schema" -TMP="${2:-$(mktemp -d)}" -mkdir -p "${TMP}" - -if [[ -n "${GITHUB_BASE_REF:-}" ]]; then - git fetch --depth=1 origin "${GITHUB_BASE_REF}" 2>/dev/null || true - BASE="$(git merge-base HEAD "origin/${GITHUB_BASE_REF}")" -elif [[ -n "${GITHUB_EVENT_BEFORE:-}" && "${GITHUB_EVENT_BEFORE}" != "0000000000000000000000000000000000000000" ]]; then - BASE="${GITHUB_EVENT_BEFORE}" -else - BASE="$(git rev-parse HEAD~1 2>/dev/null || git rev-parse HEAD)" -fi - -schema_version_at() { - git show "${BASE}:$1" 2>/dev/null \ - | xmllint --xpath 'string(/*[local-name()="schema"]/@version)' - 2>/dev/null \ - | xargs echo || true -} - -env_key() { - printf '%s' "$1" | tr '/.-' '_' | tr '[:upper:]' '[:lower:]' -} - -{ - echo "GOVERNANCE_WORKSPACE=${WORKSPACE}" - echo "GOVERNANCE_BASE_REF=${BASE}" -} >> "${GITHUB_ENV}" - -CHANGED=() -while IFS= read -r path; do - [[ -n "${path}" ]] || continue - case "${path}" in - *.md|*.xsl) continue ;; - schema/governance-*|schema/normalize-*) continue ;; - esac - CHANGED+=("${path}") -done < <(git diff --name-only "${BASE}" -- \ - schema \ - exist-distribution/src/main/config \ - exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml \ - exist-core/src/main/resources/org/exist/util/mime-types.xml \ - 2>/dev/null || true) - -CHANGED_XML="${TMP}/changed.xml" -{ - echo '' - echo '' - for path in "${CHANGED[@]:-}"; do - printf ' %s\n' "${path}" - done - echo '' -} > "${CHANGED_XML}" - -SCHEMAS=() -while IFS= read -r schema; do - [[ -n "${schema}" ]] && SCHEMAS+=("${schema}") -done < <(xsltproc --path "${SCHEMA_DIR}" --stringparam pom-uri "${POM}" \ - "${SCHEMA_DIR}/governance-schemas.xsl" "${CHANGED_XML}") - -for schema in "${SCHEMAS[@]:-}"; do - ver="$(schema_version_at "${schema}")" - echo "GOVERNANCE_OLD_VERSION_$(env_key "${schema}")=${ver}" >> "${GITHUB_ENV}" -done - -IFS=','; echo "GOVERNANCE_SCHEMAS=${SCHEMAS[*]:-}" >> "${GITHUB_ENV}" -IFS=','; echo "GOVERNANCE_CHANGED=${CHANGED[*]:-}" >> "${GITHUB_ENV}" - -echo "Governance base: ${BASE}" -echo "Changed: ${CHANGED[*]:-(none)}" -echo "Schemas: ${SCHEMAS[*]:-(none)}" diff --git a/.github/scripts/run-governance-check.sh b/.github/scripts/run-governance-check.sh deleted file mode 100755 index d8527307efe..00000000000 --- a/.github/scripts/run-governance-check.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -WORKSPACE="${1:?workspace required}" -OUT="${2:?context xml path required}" -POM="${WORKSPACE}/pom.xml" -SCHEMA_DIR="${WORKSPACE}/schema" - -env_key() { - printf '%s' "$1" | tr '/.-' '_' | tr '[:upper:]' '[:lower:]' -} - -mkdir -p "$(dirname "${OUT}")" - -{ - echo '' - echo "" - - if [[ -n "${GOVERNANCE_SCHEMAS:-}" ]]; then - IFS=',' read -ra SCHEMA_LIST <<< "${GOVERNANCE_SCHEMAS}" - for schema in "${SCHEMA_LIST[@]}"; do - [[ -n "${schema}" ]] || continue - key="GOVERNANCE_OLD_VERSION_$(env_key "${schema}")" - ver="${!key-}" - printf ' %s\n' "${schema}" "${ver}" - done - fi - - if [[ -n "${GOVERNANCE_CHANGED:-}" ]]; then - IFS=',' read -ra PATHS <<< "${GOVERNANCE_CHANGED}" - for path in "${PATHS[@]}"; do - [[ -n "${path}" ]] || continue - printf ' \n' "${path}" - done - fi - - echo '' -} > "${OUT}" - -REPORT="${OUT%/*}/governance-report.xml" -xsltproc --path "${SCHEMA_DIR}" --stringparam pom-uri "${POM}" \ - "${SCHEMA_DIR}/governance-check.xsl" "${OUT}" > "${REPORT}" - -cat "${REPORT}" -xsltproc "${SCHEMA_DIR}/governance-annotations.xsl" "${REPORT}" -test "$(xmllint --xpath 'string(/*[local-name()="report"]/@status)' "${REPORT}")" = "passed" diff --git a/.github/workflows/ci-schema-checks.yml b/.github/workflows/ci-schema-checks.yml index f82641c46f4..bed3744ff75 100644 --- a/.github/workflows/ci-schema-checks.yml +++ b/.github/workflows/ci-schema-checks.yml @@ -7,6 +7,7 @@ on: - 'exist-distribution/src/main/config/**' - 'exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml' - 'exist-core/src/main/resources/org/exist/util/mime-types.xml' + - 'exist-core/src/main/java/org/exist/util/SchemaVersion.java' push: branches: [develop] paths: @@ -14,6 +15,7 @@ on: - 'exist-distribution/src/main/config/**' - 'exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml' - 'exist-core/src/main/resources/org/exist/util/mime-types.xml' + - 'exist-core/src/main/java/org/exist/util/SchemaVersion.java' workflow_dispatch: permissions: @@ -40,25 +42,19 @@ jobs: - uses: ./.github/actions/maven-cache - - name: Install xmllint and xsltproc - run: sudo apt-get update && sudo apt-get install -y libxml2-utils xsltproc - - name: Validate canonical templates against XSD run: mvn -V -B --no-transfer-progress validate -Ddependency-check.skip=true -Ddocker=false - - name: Export base revisions to env + - name: Prepare governance context env: GITHUB_BASE_REF: ${{ github.base_ref }} GITHUB_EVENT_BEFORE: ${{ github.event.before }} run: | - chmod +x .github/scripts/prepare-governance-env.sh - .github/scripts/prepare-governance-env.sh \ - "${{ github.workspace }}" \ - "${{ runner.temp }}" + chmod +x .github/scripts/prepare-governance-context.sh + .github/scripts/prepare-governance-context.sh "${{ github.workspace }}" - - name: Run schema governance check - run: | - chmod +x .github/scripts/run-governance-check.sh - .github/scripts/run-governance-check.sh \ - "${{ github.workspace }}" \ - "${{ runner.temp }}/governance-ctx.xml" + - name: Run schema governance (XSLT 2.0 / Saxon) + run: mvn -N -B --no-transfer-progress xml:transform@schema-governance -Ddependency-check.skip=true -Ddocker=false + + - name: Verify SchemaVersion.java matches XSD versions + run: mvn -B --no-transfer-progress test -pl exist-core -Dtest=org.exist.util.SchemaVersionSyncTest -Ddependency-check.skip=true -Ddocker=false diff --git a/exist-core/src/main/java/org/exist/util/MimeTable.java b/exist-core/src/main/java/org/exist/util/MimeTable.java index bbac6f5e5b2..87252ceee43 100644 --- a/exist-core/src/main/java/org/exist/util/MimeTable.java +++ b/exist-core/src/main/java/org/exist/util/MimeTable.java @@ -143,8 +143,9 @@ public MimeTable(final Path path) { } try (final InputStream is = Files.newInputStream(path)) { LOG.info("Loading mime table from file: {}", path.toAbsolutePath()); - loadMimeTypes(is); - this.src = path.toUri().toString(); + final String sourceDescription = path.toUri().toString(); + loadMimeTypes(is, sourceDescription); + this.src = sourceDescription; } catch (final ParserConfigurationException | SAXException | IOException e) { throw new IllegalStateException(FILE_LOAD_FAILED_ERR + path.toAbsolutePath(), e); } @@ -264,8 +265,8 @@ private void load(final InputStream stream, final String src) { private void loadFromStream(final InputStream stream, final String sourceDescription) { try (stream) { + loadMimeTypes(stream, sourceDescription); this.src = sourceDescription; - loadMimeTypes(stream); } catch (final ParserConfigurationException | SAXException | IOException e) { throw new IllegalStateException("Failed to load mime-type table from " + sourceDescription, e); } @@ -275,16 +276,17 @@ private void loadFromStream(final InputStream stream, final String sourceDescrip * Load Mime Types * * @param stream input stream. + * @param sourceDescription description of the stream's origin, for diagnostic messages. * * @throws SAXException if an error occurs whilst reading the XML stream * @throws ParserConfigurationException if an error occurs whilst parsing the stream * @throws IOException if an error occurs whilst reading the stream */ - private void loadMimeTypes(final InputStream stream) throws ParserConfigurationException, SAXException, IOException { + private void loadMimeTypes(final InputStream stream, final String sourceDescription) throws ParserConfigurationException, SAXException, IOException { final SAXParserFactory factory = ExistSAXParserFactory.getSAXParserFactory(); factory.setNamespaceAware(true); factory.setValidating(false); - final InputSource src = new InputSource(stream); + final InputSource inputSource = new InputSource(stream); final SAXParser parser = factory.newSAXParser(); final XMLReader reader = parser.getXMLReader(); @@ -292,8 +294,8 @@ private void loadMimeTypes(final InputStream stream) throws ParserConfigurationE reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); reader.setFeature(FEATURE_SECURE_PROCESSING, true); - reader.setContentHandler(new MimeTableHandler()); - reader.parse(src); + reader.setContentHandler(new MimeTableHandler(sourceDescription)); + reader.parse(inputSource); } private class MimeTableHandler extends DefaultHandler { @@ -302,10 +304,15 @@ private class MimeTableHandler extends DefaultHandler { private static final String DESCRIPTION = "description"; private static final String MIME_TYPE = "mime-type"; private static final String MIME_TYPES = "mime-types"; - + + private final String sourceDescription; private MimeType mime = null; private final StringBuilder charBuf = new StringBuilder(64); + MimeTableHandler(final String sourceDescription) { + this.sourceDescription = sourceDescription; + } + @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { @@ -313,7 +320,7 @@ public void startElement(String uri, String localName, String qName, if (MIME_TYPES.equals(qName)) { SchemaVersion.logDocumentVersion(LOG, attributes.getValue(SchemaVersion.ATTRIBUTE), - SchemaVersion.MIME_TYPES, src != null ? "mime-types.xml (" + src + ")" : "mime-types.xml"); + SchemaVersion.MIME_TYPES, sourceDescription != null ? "mime-types.xml (" + sourceDescription + ")" : "mime-types.xml"); // Check for a default mime type settings final String defaultMimeAttr = attributes.getValue("default-mime-type"); final String defaultTypeAttr = attributes.getValue("default-resource-type"); diff --git a/exist-core/src/main/java/org/exist/util/SchemaVersion.java b/exist-core/src/main/java/org/exist/util/SchemaVersion.java index 50ea3842f9f..607f227816b 100644 --- a/exist-core/src/main/java/org/exist/util/SchemaVersion.java +++ b/exist-core/src/main/java/org/exist/util/SchemaVersion.java @@ -33,11 +33,11 @@ public final class SchemaVersion { public static final String ATTRIBUTE = "schemaVersion"; /** Paired {@code xs:schema/@version} values for canonical templates (keep in sync with {@code schema/*.xsd}). */ - public static final String CONF = "2.1.0"; - public static final String COLLECTION_XCONF = "1.2.0"; - public static final String DESCRIPTOR = "1.2.0"; - public static final String MIME_TYPES = "1.2.0"; - public static final String CONTROLLER_CONFIG = "1.1.0"; + public static final String CONF = "2.1.1"; + public static final String COLLECTION_XCONF = "1.2.1"; + public static final String DESCRIPTOR = "1.2.1"; + public static final String MIME_TYPES = "1.2.1"; + public static final String CONTROLLER_CONFIG = "1.1.1"; private SchemaVersion() { } @@ -56,15 +56,13 @@ public static void logDocumentVersion(final Logger log, final Element root, public static void logDocumentVersion(final Logger log, final String declaredVersion, final String expectedVersion, final String documentDescription) { if (declaredVersion == null || declaredVersion.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("{} has no {} attribute (legacy document)", documentDescription, ATTRIBUTE); - } + log.debug("{} has no {} attribute (legacy document)", documentDescription, ATTRIBUTE); return; } if (!declaredVersion.equals(expectedVersion)) { log.warn("{} declares {}=\"{}\" but this eXist build expects \"{}\"", documentDescription, ATTRIBUTE, declaredVersion, expectedVersion); - } else if (log.isDebugEnabled()) { + } else { log.debug("{} {}=\"{}\"", documentDescription, ATTRIBUTE, declaredVersion); } } diff --git a/exist-core/src/main/resources/org/exist/util/mime-types.xml b/exist-core/src/main/resources/org/exist/util/mime-types.xml index adc83c45ecb..142f6a2318b 100644 --- a/exist-core/src/main/resources/org/exist/util/mime-types.xml +++ b/exist-core/src/main/resources/org/exist/util/mime-types.xml @@ -37,7 +37,7 @@ and then as a classpath resource in org/exist/util . ======================================================= --> - + diff --git a/exist-core/src/test/java/org/exist/util/SchemaVersionSyncTest.java b/exist-core/src/test/java/org/exist/util/SchemaVersionSyncTest.java new file mode 100644 index 00000000000..2232eea0508 --- /dev/null +++ b/exist-core/src/test/java/org/exist/util/SchemaVersionSyncTest.java @@ -0,0 +1,89 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.util; + +import org.junit.Test; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilderFactory; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * The CI schema-governance workflow (.github/workflows/ci-schema-checks.yml) + * enforces that {@code xs:schema/@version} is bumped whenever a native XSD or + * its canonical template changes — but it diffs files via git path filters + * and has no visibility into Java source, so a forgotten update to the + * hand-copied constants in {@link SchemaVersion} would otherwise drift + * silently. This test closes that gap directly: it runs on every {@code mvn + * test}, independent of which files a PR happens to touch, and fails loudly + * the moment a constant disagrees with its paired XSD. + */ +public class SchemaVersionSyncTest { + + private static final Map SCHEMA_FILE_TO_CONSTANT = new LinkedHashMap<>(); + static { + SCHEMA_FILE_TO_CONSTANT.put("conf.xsd", SchemaVersion.CONF); + SCHEMA_FILE_TO_CONSTANT.put("collection.xconf.xsd", SchemaVersion.COLLECTION_XCONF); + SCHEMA_FILE_TO_CONSTANT.put("descriptor.xsd", SchemaVersion.DESCRIPTOR); + SCHEMA_FILE_TO_CONSTANT.put("mime-types.xsd", SchemaVersion.MIME_TYPES); + SCHEMA_FILE_TO_CONSTANT.put("controller-config.xsd", SchemaVersion.CONTROLLER_CONFIG); + } + + @Test + public void schemaVersionConstantsMatchXsds() throws Exception { + final Path schemaDir = resolveSchemaDir(); + assertTrue("schema/ directory not found at " + schemaDir + " (run from repo root: mvn test -pl exist-core)", + Files.isDirectory(schemaDir)); + + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + + for (final Map.Entry entry : SCHEMA_FILE_TO_CONSTANT.entrySet()) { + final String fileName = entry.getKey(); + final Path xsdPath = schemaDir.resolve(fileName); + assertTrue("Missing XSD: " + xsdPath, Files.exists(xsdPath)); + + final Document doc = factory.newDocumentBuilder().parse(xsdPath.toFile()); + final String xsdVersion = doc.getDocumentElement().getAttribute("version"); + + assertEquals("SchemaVersion.java is out of sync with schema/" + fileName + + " — update the matching constant in SchemaVersion.java" + + " whenever you bump xs:schema/@version", + xsdVersion, entry.getValue()); + } + } + + private Path resolveSchemaDir() { + final Path base = Path.of(System.getProperty("user.dir")); + Path p = base.resolve("schema"); + if (!Files.isDirectory(p)) { + p = base.getParent().resolve("schema"); + } + return p; + } +} diff --git a/exist-distribution/src/main/config/collection.xconf.init b/exist-distribution/src/main/config/collection.xconf.init index 03e31bd6aa8..ccef02b7aa2 100644 --- a/exist-distribution/src/main/config/collection.xconf.init +++ b/exist-distribution/src/main/config/collection.xconf.init @@ -1,5 +1,5 @@ - + - + - + + xsi:schemaLocation="http://exist.sourceforge.net/NS/exist file:../../schema/controller-config.xsd" schemaVersion="1.1.1"> diff --git a/pom.xml b/pom.xml index e9df4bfdfcf..ea267445539 100644 --- a/pom.xml +++ b/pom.xml @@ -68,11 +68,45 @@ - + org.codehaus.mojo xml-maven-plugin + + + schema-governance + none + + transform + + + + + ${project.build.directory}/governance + + context.xml + + ${project.basedir}/schema/governance.xsl + ${project.build.directory}/governance + + + .report.xml + + + + + + validate-canonical-instances validate diff --git a/schema/README.md b/schema/README.md index db35530a9fe..d02a1900d45 100644 --- a/schema/README.md +++ b/schema/README.md @@ -24,7 +24,9 @@ Canonical templates may declare an optional **`schemaVersion`** attribute on the | `mime-types.xsd` | `` | | `controller-config.xsd` | `` | -Keep [`SchemaVersion.java`](../exist-core/src/main/java/org/exist/util/SchemaVersion.java) constants in sync with `xs:schema/@version` on the paired XSDs. +All five schemas `xs:include` the `schemaVersionType` simple type from [`schema-version-type.xsd`](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). + +Keep [`SchemaVersion.java`](../exist-core/src/main/java/org/exist/util/SchemaVersion.java) constants in sync with `xs:schema/@version` on the paired XSDs — [`SchemaVersionSyncTest`](../exist-core/src/test/java/org/exist/util/SchemaVersionSyncTest.java) fails the build if they drift apart, and [`ci-schema-checks.yml`](../.github/workflows/ci-schema-checks.yml) also triggers on edits to `SchemaVersion.java` itself. ## Validation @@ -32,7 +34,9 @@ Keep [`SchemaVersion.java`](../exist-core/src/main/java/org/exist/util/SchemaVer [`ci-schema-checks.yml`](../.github/workflows/ci-schema-checks.yml) re-runs `mvn validate` on PRs that touch schemas or canonical templates (fast, path-filtered). -**Version bumps** — CI xpath on the base revision exports `GOVERNANCE_OLD_VERSION_*` env vars; schema paths come from [`governance-schemas.xsl`](governance-schemas.xsl) (pairs read from `pom.xml` validationSets). [`governance-check.xsl`](governance-check.xsl) compares old vs current `xs:schema/@version`. +**Version bumps** — a single Saxon XSLT 2.0 transform, [`governance.xsl`](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()`](https://www.w3.org/TR/xpath-functions-30/#func-unparsed-text)/[`document()`](https://www.w3.org/TR/xslt-30/#document)/[`doc-available()`](https://www.w3.org/TR/xpath-functions-30/#func-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`](../.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`](../pom.xml), so it never runs on an ordinary `mvn install`/`mvn test`/`mvn validate` — only [`ci-schema-checks.yml`](../.github/workflows/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`). ## Canonical templates diff --git a/schema/collection.xconf.xsd b/schema/collection.xconf.xsd index 36adff921d6..8e0cd261f31 100644 --- a/schema/collection.xconf.xsd +++ b/schema/collection.xconf.xsd @@ -6,16 +6,9 @@ xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" targetNamespace="http://exist-db.org/collection-config/1.0" - version="1.2.0"> + version="1.2.1"> - - - Native XSD semver; mirrors xs:schema/@version on collection.xconf.xsd (not eXist product version). - - - - - + Schema for eXist-db Collection Configuration files /db/system/config/db/**/collection.xconf diff --git a/schema/conf.xsd b/schema/conf.xsd index 829db1044e4..fe7b7e65922 100644 --- a/schema/conf.xsd +++ b/schema/conf.xsd @@ -8,17 +8,10 @@ - - - - Native XSD semver; mirrors xs:schema/@version on conf.xsd (not eXist product version). - - - - - - + version="2.1.1"> + + + diff --git a/schema/controller-config.xsd b/schema/controller-config.xsd index 5fae9068e82..8bb533c9cae 100644 --- a/schema/controller-config.xsd +++ b/schema/controller-config.xsd @@ -4,15 +4,8 @@ xmlns:exist="http://exist.sourceforge.net/NS/exist" elementFormDefault="qualified" targetNamespace="http://exist.sourceforge.net/NS/exist" - version="1.1.0"> - - - Native XSD semver; mirrors xs:schema/@version on controller-config.xsd (not eXist product version). - - - - - + version="1.1.1"> + diff --git a/schema/descriptor.xsd b/schema/descriptor.xsd index c7198ac9e2d..f5e160a87f3 100644 --- a/schema/descriptor.xsd +++ b/schema/descriptor.xsd @@ -6,15 +6,8 @@ - - - Native XSD semver; mirrors xs:schema/@version on descriptor.xsd (not eXist product version). - - - - - + version="1.2.1"> + diff --git a/schema/governance-annotations.xsl b/schema/governance-annotations.xsl deleted file mode 100644 index 7cf8f9adbf0..00000000000 --- a/schema/governance-annotations.xsl +++ /dev/null @@ -1,12 +0,0 @@ - - - - - ::error file= - :: - - - diff --git a/schema/governance-check.xsl b/schema/governance-check.xsl deleted file mode 100644 index 47d8436bf41..00000000000 --- a/schema/governance-check.xsl +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Schema and template - Schema - - - - - - - - - - - - - - - - - - - - - - - failed - passed - - - - - - - - - - - - - - - - - - - - - changed but @version is still " - - ". Bump xs:schema/@version (see schema/README.md). - - - - - - - diff --git a/schema/governance-pairs.xsl b/schema/governance-pairs.xsl deleted file mode 100644 index d5ae0e71827..00000000000 --- a/schema/governance-pairs.xsl +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/schema/governance-schemas.xsl b/schema/governance-schemas.xsl deleted file mode 100644 index a09aaadd091..00000000000 --- a/schema/governance-schemas.xsl +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/schema/governance.xsl b/schema/governance.xsl new file mode 100644 index 00000000000..f1648fbb6f8 --- /dev/null +++ b/schema/governance.xsl @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + governance.xsl: no xml-maven-plugin execution with + id='validate-canonical-instances' found in — the execution id + has drifted, or $pom-uri is wrong. Schema governance cannot run blind. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema governance failed ( error(s) above). + + + + diff --git a/schema/mime-types.xsd b/schema/mime-types.xsd index 39a57a8f8c0..be05282158b 100644 --- a/schema/mime-types.xsd +++ b/schema/mime-types.xsd @@ -6,15 +6,8 @@ - - - Native XSD semver; mirrors xs:schema/@version on mime-types.xsd (not eXist product version). - - - - - + version="1.2.1"> + diff --git a/schema/schema-version-type.xsd b/schema/schema-version-type.xsd new file mode 100644 index 00000000000..ef64c96a97b --- /dev/null +++ b/schema/schema-version-type.xsd @@ -0,0 +1,22 @@ + + + + + + + + + Native XSD semver; mirrors the paired schema's xs:schema/@version (not eXist product version). See schema/README.md. + + + + + + + From a9f6083d1c53dadfed15f3ef4f140b2c30574ef0 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Wed, 17 Jun 2026 21:15:03 +0200 Subject: [PATCH 6/9] [feature] Ship native schemas in distribution fix instance schema-location paths schema/ now ships at $EXIST_HOME/schema/. Fixed conf.xml/descriptor.xml/controller-config.xml's schema-location hints, which were source-tree-relative and never correct for the assembled layout. Extended catalog.xml with entries for the remaining schemas; see #6189 catalog.xml is not WAI see #5541 see #350 --- exist-distribution/pom.xml | 9 +++++++++ exist-distribution/src/main/config/conf.xml | 2 +- exist-distribution/src/main/config/descriptor.xml | 2 +- exist-docker/src/assembly/dist-assembly-docker.xml | 1 + exist-docker/src/main/resources-filtered/Dockerfile | 1 + .../src/main/resources-filtered/Dockerfile-DEBUG | 1 + exist-installer/src/main/izpack/install.xml | 1 + .../src/main/resources/webapp/WEB-INF/catalog.xml | 11 ++++++++++- .../resources/webapp/WEB-INF/controller-config.xml | 2 +- 9 files changed, 26 insertions(+), 4 deletions(-) diff --git a/exist-distribution/pom.xml b/exist-distribution/pom.xml index 8e4ccf29f7f..37b3267843d 100644 --- a/exist-distribution/pom.xml +++ b/exist-distribution/pom.xml @@ -516,12 +516,21 @@ + + + + + + + + + diff --git a/exist-distribution/src/main/config/conf.xml b/exist-distribution/src/main/config/conf.xml index 5a88a083945..2e3f783af43 100644 --- a/exist-distribution/src/main/config/conf.xml +++ b/exist-distribution/src/main/config/conf.xml @@ -58,7 +58,7 @@ - http://exist-db.org/exist/apps/doc/documentation.xml --> - + - + - + + + + + + diff --git a/exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml b/exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml index 938bc6b593b..8be7eb767ae 100644 --- a/exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml +++ b/exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml @@ -6,7 +6,7 @@ ++ The order of elements within this configuration file is significant. --> + xsi:schemaLocation="http://exist.sourceforge.net/NS/exist file:../../../schema/controller-config.xsd" schemaVersion="1.1.1"> From ab032c13b358039ca2bfd74f5d48987bae149ba9 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Tue, 23 Jun 2026 01:00:51 +0200 Subject: [PATCH 7/9] [bugfix] Fix abrev typo in expath-pkg.xsd, document shipped schema/ abbrev was already the de-facto name everywhere else (#6008). --- AGENTS.md | 24 ++++++++++++++++++++++++ schema/README.md | 2 +- schema/expath-pkg.xsd | 4 ++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b742b4da0e5..f75437ddace 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -144,6 +144,30 @@ ANTLR generates `XQueryParser.java`, `XQueryLexer.java`, `XQueryTreeParser.java` | `org.exist.dom.persistent` | Persistent DOM implementation | | `org.exist.dom.memtree` | In-memory DOM (for constructed nodes) | +### Native config schemas (`schema/`) + +eXist-db's own config-file XSDs (`conf.xsd`, `collection.xconf.xsd`, `descriptor.xsd`, +`controller-config.xsd`, `mime-types.xsd`, plus `users.xsd`/`server.xsd`/`security-manager.xsd`/ +`expath-pkg.xsd` and its extensions) live in [`schema/`](schema/) at the repo root, and are shipped +in every distribution layout as `$EXIST_HOME/schema/` — a sibling of `etc/`, `bin/`, `lib/` (tarball, +zip, Docker image, and the IzPack installer all include it; see `exist-distribution`/`exist-docker`/ +`exist-installer`). External tools (eXide, IDE plugins) can resolve a config file's grammar from +this fixed location instead of vendoring their own copy. + +- Each XSD's `xs:schema/@version` is an independent semver line — see [`schema/README.md`](schema/README.md) + for the versioning policy (CI enforces a version bump on any semantic schema edit, via + `mvn -N xml:transform@schema-governance`, see [`schema/governance.xsl`](schema/governance.xsl)). +- `org.exist.util.SchemaVersion`'s version constants are generated at build time from the XSDs + themselves (`generate-sources` phase, see `exist-core/pom.xml`'s `schema-version-codegen` + execution and [`schema/generate-schema-version.xsl`](schema/generate-schema-version.xsl)) — never + hand-edit `SchemaVersion`'s constants; bump the XSD's `xs:schema/@version` instead and the + constant follows automatically on the next build. +- The 5 canonical instances (the files `pom.xml`'s `validate-canonical-instances` execution + validates on every `mvn validate`) are the only ones checked for drift; the ~39 test/sample + fixture copies scattered across module test resources (e.g. `extensions/*/src/test/resources*/conf.xml`) + are intentionally hand-trimmed per-module subsets, not literal copies — don't try to regenerate + them from canonical. + ### Adding a new `fn:` function 1. Create the class in `org.exist.xquery.functions.fn` extending `BasicFunction` diff --git a/schema/README.md b/schema/README.md index d02a1900d45..6fd76e13942 100644 --- a/schema/README.md +++ b/schema/README.md @@ -26,7 +26,7 @@ Canonical templates may declare an optional **`schemaVersion`** attribute on the All five schemas `xs:include` the `schemaVersionType` simple type from [`schema-version-type.xsd`](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). -Keep [`SchemaVersion.java`](../exist-core/src/main/java/org/exist/util/SchemaVersion.java) constants in sync with `xs:schema/@version` on the paired XSDs — [`SchemaVersionSyncTest`](../exist-core/src/test/java/org/exist/util/SchemaVersionSyncTest.java) fails the build if they drift apart, and [`ci-schema-checks.yml`](../.github/workflows/ci-schema-checks.yml) also triggers on edits to `SchemaVersion.java` itself. +[`SchemaVersion.java`](../exist-core/src/main/java/org/exist/util/SchemaVersion.java)'s version constants are generated at build time from `xs:schema/@version` on the paired XSDs (see [`generate-schema-version.xsl`](generate-schema-version.xsl), wired as `exist-core/pom.xml`'s `schema-version-codegen` execution) — never hand-edit them. [`SchemaVersionSyncTest`](../exist-core/src/test/java/org/exist/util/SchemaVersionSyncTest.java) 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`](../.github/workflows/ci-schema-checks.yml) still triggers on edits to `SchemaVersion.java` itself. ## Validation diff --git a/schema/expath-pkg.xsd b/schema/expath-pkg.xsd index b962392ac6d..a0248bd47ee 100644 --- a/schema/expath-pkg.xsd +++ b/schema/expath-pkg.xsd @@ -6,7 +6,7 @@ xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" targetNamespace="http://expath.org/ns/pkg" - version="1.0.0"> + version="1.1.0"> A schema for EXPath Packaging (i.e. expath-pkg.xml) file as per the EXPath Packaging System - Candidate Module 9 May 2012' specification. @@ -42,7 +42,7 @@ The name of the package. A package is named using an IRI, as defined by [RFC 3987], excepted any IRI using the file: scheme (most frequent choices are http: and urn: scheme URIs). Note that the definition of IRI excludes relative references. - + From dd51fe3b4afeef81dcd77b023c33d11b4c6267e3 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sat, 20 Jun 2026 15:46:20 +0200 Subject: [PATCH 8/9] [feature] Validate native XSDs against the W3C XSD 1.1 meta-schema Extend the existing template-vs-schema validation (pom.xml) to also check every schema/**/*.xsd is itself a legal schema document, per the W3C meta-schema. Idea borrowed from #5541, where the same catalog trick lets a user validate their own XSD's well-formedness. Upgrades the bundled XMLSchema.xsd from the stale, unused 2001/2004 XSD 1.0 revision (no xs:assert/vc: support) to the 2009 XSD 1.1 revision our native schemas actually need, plus its XMLSchema.dtd/ datatypes.dtd dependents and a refreshed xml.xsd. Resolution stays fully offline via catalogHandling=strict and the shipped catalog.xml. Caught immediately: 5 schemas carried an xsi:type="dcterms:W3CDTF" appinfo annotation with no backing schema, never caught before because nothing validated this strictly. Removed (annotation-only, no semantic effect) and bumped the affected xs:schema/@version per the governance policy, syncing SchemaVersion.java and collection.xconf.init accordingly. close #5541 --- .../java/org/exist/util/SchemaVersion.java | 2 +- .../org/exist/util/SchemaVersionTest.java | 95 +- .../exist/validation/entities/XMLSchema.dtd | 513 +++ .../exist/validation/entities/XMLSchema.xsd | 3693 +++++++---------- .../exist/validation/entities/datatypes.dtd | 222 + .../org/exist/validation/entities/xml.xsd | 352 +- .../src/main/config/collection.xconf.init | 2 +- .../webapp/WEB-INF/entities/XMLSchema.dtd | 513 +++ .../webapp/WEB-INF/entities/XMLSchema.xsd | 3693 +++++++---------- .../webapp/WEB-INF/entities/datatypes.dtd | 222 + .../resources/webapp/WEB-INF/entities/xml.xsd | 352 +- pom.xml | 19 + schema/README.md | 12 + schema/collection.xconf.xsd | 4 +- schema/expath-pkg-extensions/cxan.xsd | 4 +- schema/expath-pkg-extensions/exist.xsd | 4 +- schema/expath-pkg-extensions/repo.xsd | 4 +- schema/expath-pkg.xsd | 2 +- 18 files changed, 5279 insertions(+), 4429 deletions(-) create mode 100644 exist-core/src/test/resources/org/exist/validation/entities/XMLSchema.dtd create mode 100644 exist-core/src/test/resources/org/exist/validation/entities/datatypes.dtd create mode 100644 exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/XMLSchema.dtd create mode 100644 exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/datatypes.dtd diff --git a/exist-core/src/main/java/org/exist/util/SchemaVersion.java b/exist-core/src/main/java/org/exist/util/SchemaVersion.java index 607f227816b..9491eec84c2 100644 --- a/exist-core/src/main/java/org/exist/util/SchemaVersion.java +++ b/exist-core/src/main/java/org/exist/util/SchemaVersion.java @@ -34,7 +34,7 @@ public final class SchemaVersion { /** Paired {@code xs:schema/@version} values for canonical templates (keep in sync with {@code schema/*.xsd}). */ public static final String CONF = "2.1.1"; - public static final String COLLECTION_XCONF = "1.2.1"; + public static final String COLLECTION_XCONF = "1.2.2"; public static final String DESCRIPTOR = "1.2.1"; public static final String MIME_TYPES = "1.2.1"; public static final String CONTROLLER_CONFIG = "1.1.1"; diff --git a/exist-core/src/test/java/org/exist/util/SchemaVersionTest.java b/exist-core/src/test/java/org/exist/util/SchemaVersionTest.java index 0e4f51b6dbb..e5db5127cae 100644 --- a/exist-core/src/test/java/org/exist/util/SchemaVersionTest.java +++ b/exist-core/src/test/java/org/exist/util/SchemaVersionTest.java @@ -21,18 +21,61 @@ */ package org.exist.util; -import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.AbstractAppender; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.LoggerConfig; +import org.apache.logging.log4j.core.config.Property; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.w3c.dom.Document; import javax.xml.parsers.DocumentBuilderFactory; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class SchemaVersionTest { - private static final Logger LOG = LogManager.getLogger(SchemaVersionTest.class); + private static final String CAPTURE_LOGGER = "org.exist.util.SchemaVersionTest.capture"; + + private CapturingAppender appender; + + @Before + public void attachAppender() { + appender = new CapturingAppender(); + appender.start(); + // The test log4j2 config sets the root logger to OFF, which would filter these events before + // any appender sees them. Install a dedicated LoggerConfig at level ALL with our capturing + // appender, mirroring DeferredFunctionCallErrorTest's pattern. + final Logger logger = (Logger) LogManager.getLogger(CAPTURE_LOGGER); + final LoggerContext ctx = logger.getContext(); + final Configuration config = ctx.getConfiguration(); + config.addAppender(appender); + final LoggerConfig loggerConfig = LoggerConfig.newBuilder() + .withLoggerName(CAPTURE_LOGGER) + .withLevel(Level.ALL) + .withAdditivity(false) + .withConfig(config) + .build(); + loggerConfig.addAppender(appender, Level.ALL, null); + config.addLogger(CAPTURE_LOGGER, loggerConfig); + ctx.updateLoggers(); + } + + @After + public void detachAppender() { + final Logger logger = (Logger) LogManager.getLogger(CAPTURE_LOGGER); + final LoggerContext ctx = logger.getContext(); + ctx.getConfiguration().removeLogger(CAPTURE_LOGGER); + ctx.updateLoggers(); + appender.stop(); + } @Test public void attributeNameIsSchemaVersion() { @@ -45,7 +88,13 @@ public void logDocumentVersionAcceptsMatchingValue() throws Exception { final var root = doc.createElement("exist"); root.setAttribute(SchemaVersion.ATTRIBUTE, SchemaVersion.CONF); doc.appendChild(root); - SchemaVersion.logDocumentVersion(LOG, root, SchemaVersion.CONF, "test conf.xml"); + + SchemaVersion.logDocumentVersion(LogManager.getLogger(CAPTURE_LOGGER), + root, SchemaVersion.CONF, "test conf.xml"); + + assertEquals(Level.DEBUG, appender.lastLevel); + assertTrue(appender.lastMessage.contains("test conf.xml")); + assertTrue(appender.lastMessage.contains(SchemaVersion.CONF)); } @Test @@ -53,6 +102,44 @@ public void logDocumentVersionAcceptsMissingAttribute() throws Exception { final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); final var root = doc.createElement("exist"); doc.appendChild(root); - SchemaVersion.logDocumentVersion(LOG, root, SchemaVersion.CONF, "legacy conf.xml"); + + SchemaVersion.logDocumentVersion(LogManager.getLogger(CAPTURE_LOGGER), + root, SchemaVersion.CONF, "legacy conf.xml"); + + assertEquals(Level.DEBUG, appender.lastLevel); + assertTrue(appender.lastMessage.contains("legacy conf.xml")); + assertTrue(appender.lastMessage.contains("no " + SchemaVersion.ATTRIBUTE + " attribute")); + } + + @Test + public void logDocumentVersionWarnsOnMismatch() throws Exception { + final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + final var root = doc.createElement("exist"); + root.setAttribute(SchemaVersion.ATTRIBUTE, "0.0.1"); + doc.appendChild(root); + + SchemaVersion.logDocumentVersion(LogManager.getLogger(CAPTURE_LOGGER), + root, SchemaVersion.CONF, "outdated conf.xml"); + + assertEquals(Level.WARN, appender.lastLevel); + assertTrue(appender.lastMessage.contains("outdated conf.xml")); + assertTrue(appender.lastMessage.contains("0.0.1")); + assertTrue(appender.lastMessage.contains(SchemaVersion.CONF)); + } + + private static final class CapturingAppender extends AbstractAppender { + + private volatile Level lastLevel; + private volatile String lastMessage; + + CapturingAppender() { + super("schema-version-capture", null, null, false, Property.EMPTY_ARRAY); + } + + @Override + public void append(final LogEvent event) { + lastLevel = event.getLevel(); + lastMessage = event.getMessage().getFormattedMessage(); + } } } diff --git a/exist-core/src/test/resources/org/exist/validation/entities/XMLSchema.dtd b/exist-core/src/test/resources/org/exist/validation/entities/XMLSchema.dtd new file mode 100644 index 00000000000..64aa2d97019 --- /dev/null +++ b/exist-core/src/test/resources/org/exist/validation/entities/XMLSchema.dtd @@ -0,0 +1,513 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +%xs-datatypes; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/exist-core/src/test/resources/org/exist/validation/entities/XMLSchema.xsd b/exist-core/src/test/resources/org/exist/validation/entities/XMLSchema.xsd index 575975b412e..21c707cd4a4 100644 --- a/exist-core/src/test/resources/org/exist/validation/entities/XMLSchema.xsd +++ b/exist-core/src/test/resources/org/exist/validation/entities/XMLSchema.xsd @@ -1,2163 +1,1558 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]> + + - Part 1 version: Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp - Part 2 version: Id: datatypes.xsd,v 1.3 2004/01/23 18:11:13 ht Exp + Part 1 version: structures.xsd (rec-20120405) + Part 2 version: datatypes.xsd (rec-20120405) - - + + The schema corresponding to this document is normative, with respect to the syntactic constraints it expresses in the - XML Schema language. The documentation (within <documentation> elements) + XML Schema Definition Language. The documentation (within 'documentation' elements) below, is not normative, but rather highlights important aspects of - the W3C Recommendation of which this is a part - + the W3C Recommendation of which this is a part. - - + See below (at the bottom of this document) for information about + the revision and namespace-versioning policy governing this + schema document. + + + + + The simpleType element and all of its members are defined - towards the end of this schema document + towards the end of this schema document. - - - - + + + Get access to the xml: attribute groups for xml:lang as declared on 'schema' and 'documentation' below - - - - - - + + + + + This type is extended by almost all schema types to allow attributes from other namespaces to be added to user schemas. - - - - - - - - - - - + + + + + + + + + + This type is extended by all types which allow annotation - other than <schema> itself + other than <schema> itself - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + This group is for the elements which occur freely at the top level of schemas. All of their types are based on the "annotated" type by extension. - - - - - - - - - - - - + + + + + + + + + + + This group is for the elements which can self-redefine (see <redefine> below). - - - - - - - - - - - - + + + + + + + + + + + A utility type, not for public use - - - - - - - - - - + + + + + + + + + A utility type, not for public use - - - - - - - - - - + + + + + + + + + A utility type, not for public use - + #all or (possibly empty) subset of {extension, restriction} - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + A utility type, not for public use - - - - - - - - - + + + + + + + + - - + + A utility type, not for public use - + #all or (possibly empty) subset of {extension, restriction, list, union} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - for maxOccurs - - - - - - - - - - - - for all particles - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + for maxOccurs + + + + + + + + + + + + + for all particles + + + + + + + for element, group and attributeGroup, - which both define and reference - - - - - - - - 'complexType' uses this - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + which both define and reference + + + + + + + + 'complexType' uses this + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - + + This branch is short for <complexContent> <restriction base="xs:anyType"> ... </restriction> </complexContent> - - - + + + + + - - - - - - - - - - - Will be restricted to required or forbidden - - - - - + + + + + + + + + + Will be restricted to required or prohibited + + + + + Not allowed if simpleContent child is chosen. - May be overriden by setting on complexContent child. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This choice is added simply to - make this a valid restriction per the REC - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Overrides any setting on complexType parent. - - - - + May be overridden by setting on complexContent child. + + + + + + + + - - - - - - - - - - This choice is added simply to - make this a valid restriction per the REC - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This choice is added simply to + make this a valid restriction per the REC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overrides any setting on complexType parent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This choice is added simply to + make this a valid restriction per the REC + + + + + + + + + + + + + + + + No typeDefParticle group reference - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - + + A utility type, not for public use - + #all or (possibly empty) subset of {substitution, extension, restriction} - - - - - - - - - + + + + + + + - - - - - + + + + + + + + + - - - + - - - - + + + The element element can be used either at the top level to define an element-type binding globally, or within a content model to either reference a globally-defined element or type or declare an element-type binding locally. The ref form is not allowed at the top level. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This type is used for 'alternative' elements. + + + + + + + + + + + + + + + + + group type for explicit groups, named top-level groups and group references - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - group type for the three kinds of group - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This choice with min/max is here to - avoid a pblm with the Elt:All/Choice/Seq - Particle derivation constraint - - - - - - - - - - restricted max/min - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - Only elements allowed inside - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + - - - - - simple type for the value of the 'namespace' attr of - 'any' and 'anyAttribute' - - - - Value is - ##any - - any non-conflicting WFXML/attribute at all - - ##other - - any non-conflicting WFXML/attribute from - namespace other than targetNS - - ##local - - any unqualified non-conflicting WFXML/attribute - - one or - - any non-conflicting WFXML/attribute from - more URI the listed namespaces - references - (space separated) - - ##targetNamespace or ##local may appear in the above list, to - refer to the targetNamespace of the enclosing - schema or an absent targetNamespace respectively - - - - - - A utility type, not for public use - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + group type for the three kinds of group + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - A subset of XPath expressions for use -in selectors - A utility type, not for public -use - - - - The following pattern is intended to allow XPath - expressions per the following EBNF: - Selector ::= Path ( '|' Path )* - Path ::= ('.//')? Step ( '/' Step )* - Step ::= '.' | NameTest - NameTest ::= QName | '*' | NCName ':' '*' - child:: is also allowed - - - - - - - - - - - - - - - - - - - - - - - A subset of XPath expressions for use -in fields - A utility type, not for public -use - - + + + + - The following pattern is intended to allow XPath - expressions per the same EBNF as for selector, - with the following change: - Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) - + This choice with min/max is here to + avoid a pblm with the Elt:All/Choice/Seq + Particle derivation constraint - - - - - - - - - - - - - - - - - - - - - - - - - The three kinds of identity constraints, all with - type of or derived from 'keybase'. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A utility type, not for public use - - A public identifier, per ISO 8879 - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + Only elements allowed inside + - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - notations for use within XML Schema schemas - - - - - - - - - Not the real urType, but as close an approximation as we can - get in the XML representation - - - - - - - - - - First the built-in primitive datatypes. These definitions are for - information only, the real built-in definitions are magic. - - - - For each built-in datatype in this schema (both primitive and - derived) can be uniquely addressed via a URI constructed - as follows: - 1) the base URI is the URI of the XML Schema namespace - 2) the fragment identifier is the name of the datatype - - For example, to address the int datatype, the URI is: - - http://www.w3.org/2001/XMLSchema#int - - Additionally, each facet definition element can be uniquely - addressed via a URI constructed as follows: - 1) the base URI is the URI of the XML Schema namespace - 2) the fragment identifier is the name of the facet - - For example, to address the maxInclusive facet, the URI is: - - http://www.w3.org/2001/XMLSchema#maxInclusive - - Additionally, each facet usage in a built-in datatype definition - can be uniquely addressed via a URI constructed as follows: - 1) the base URI is the URI of the XML Schema namespace - 2) the fragment identifier is the name of the datatype, followed - by a period (".") followed by the name of the facet - - For example, to address the usage of the maxInclusive facet in - the definition of int, the URI is: - - http://www.w3.org/2001/XMLSchema#int.maxInclusive - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - + + + + source="../structures/structures.html#element-choice"/> - - - - - - - - - - - - - - - - - - - - - - + + + + source="../structures/structures.html#element-sequence"/> - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + simple type for the value of the 'namespace' attr of + 'any' and 'anyAttribute' + + + + Value is + ##any - - any non-conflicting WFXML/attribute at all - - - - - - - - - - - - - - - - - - - - - + ##other - - any non-conflicting WFXML/attribute from + namespace other than targetNS - - - - - - - - - - - - - - - - - - - - - + ##local - - any unqualified non-conflicting WFXML/attribute - - - - - - - - - - - - - - - - - - - - - + one or - - any non-conflicting WFXML/attribute from + more URI the listed namespaces + references + (space separated) - - - - - - - - - - - - - - - - + ##targetNamespace or ##local may appear in the above list, to + refer to the targetNamespace of the enclosing + schema or an absent targetNamespace respectively + + + + + A utility type, not for public use - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + A utility type, not for public use - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + A utility type, not for public use - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + A utility type, not for public use + - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + - NOTATION cannot be used directly in a schema; rather a type - must be derived from it by specifying at least one enumeration - facet whose value is the name of a NOTATION declared in the - schema. + A utility type, not for public use - - - + + + + + + + + + + + - - - - Now the derived primitive types - - - - + + + + + + + + + + + + + source="../structures/structures.html#element-attribute"/> - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + source="../structures/structures.html#element-attributeGroup"/> - - - - - - + + + source="../structures/structures.html#element-include"/> - - - - - pattern specifies the content of section 2.12 of XML 1.0e2 - and RFC 3066 (Revised version of RFC 1766). - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + source="../structures/structures.html#element-redefine"/> - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + source="../structures/structures.html#element-override"/> - - - - - - - - - + + + + + + + + + + + + + + + source="../structures/structures.html#element-import"/> - - - - - pattern matches production 7 from the XML spec - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + source="../structures/structures.html#element-selector"/> - - - - - - - - - + + + + + + + A subset of XPath expressions for use +in selectors + A utility type, not for public +use + + + + + + + + + + + + + + + + + + + + + A subset of XPath expressions for use +in fields + A utility type, not for public +use + + + + + + + + + + + + + + + + + + + + + + + - + The three kinds of identity constraints, all with + type of or derived from 'keybase'. + - - - - - pattern matches production 5 from the XML spec - - - - - - - + + + + + + + + source="../structures/structures.html#element-unique"/> - - - - - pattern matches production 4 from the Namespaces in XML spec - - - - - - - + + - + - - - - + + + source="../structures/structures.html#element-keyref"/> - - - - + + + + + + + + + + source="../structures/structures.html#element-notation"/> - - - - + + + + + + + + + + + - + + A utility type, not for public use + + A public identifier, per ISO 8879 - - - - + - - + + source="../structures/structures.html#element-appinfo"/> - - - - - - + + + + + + + + + + source="../structures/structures.html#element-documentation"/> - - - - - - + + + + + + + + + + - - - - + source="../structures/structures.html#element-annotation"/> - - - - - - - + + + + + + + + + + + + + + + notations for use within schema documents + + + + - + + Not the real urType, but as close an approximation as we can + get in the XML representation - - - - - + + + + + - - - - - - - - - + + + In keeping with the XML Schema WG's standard versioning policy, + the material in this schema document will persist at the URI + http://www.w3.org/2012/04/XMLSchema.xsd. - - - - - - - - - + At the date of issue it can also be found at the URI + http://www.w3.org/2009/XMLSchema/XMLSchema.xsd. - - - - - - - - + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XSD + and its namespace. In other words, if XSD or the XML Schema + namespace change, the version of this document at + http://www.w3.org/2009/XMLSchema/XMLSchema.xsd will change accordingly; + the version at http://www.w3.org/2012/04/XMLSchema.xsd will not change. - - - - - - - - - - - - + Previous dated (and unchanging) versions of this schema document + include: - - - - - - - - + http://www.w3.org/2012/01/XMLSchema.xsd + (XSD 1.1 Proposed Recommendation) - - - - - - - - + http://www.w3.org/2011/07/XMLSchema.xsd + (XSD 1.1 Candidate Recommendation) - - - - - - - - + http://www.w3.org/2009/04/XMLSchema.xsd + (XSD 1.1 Candidate Recommendation) - - - - - - - - + http://www.w3.org/2004/10/XMLSchema.xsd + (XSD 1.0 Recommendation, Second Edition) - - - - A utility type, not for public use + http://www.w3.org/2001/05/XMLSchema.xsd + (XSD 1.0 Recommendation, First Edition) + + + - - - - - - - - - - - - - - - - - - - #all or (possibly empty) subset of {restriction, union, list} - - + + + + + A utility type, not for public use - - - - - + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + #all or (possibly empty) subset of {restriction, extension, union, list} + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + @@ -2173,7 +1568,6 @@ use - @@ -2181,19 +1575,17 @@ use - + Required at the top level - + - @@ -2209,72 +1601,59 @@ use - + - + source="http://www.w3.org/TR/xmlschema11-2/#element-simpleType"/> + + + + + + An abstract element, representing facets in general. + The facets defined by this spec are substitutable for + this element, and implementation-defined facets should + also name this as a substitution-group head. + - - - - - We should use a substitution group for facets, but - that's ruled out because it would allow users to - add their own, which we're not ready for yet. - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - + + + base attribute and simpleType child are mutually exclusive, but one or other is required - - + + - - - - + + + itemType attribute and simpleType child are mutually exclusive, but one or other is required @@ -2283,19 +1662,18 @@ use + minOccurs="0"/> - - - - + + + memberTypes attribute must be non-empty or there must be at least one simpleType child @@ -2304,7 +1682,7 @@ use + minOccurs="0" maxOccurs="unbounded"/> @@ -2315,71 +1693,88 @@ use - - + - - - - - - - - - - - - - - + + + + + + + + + + + + + source="http://www.w3.org/TR/xmlschema11-2/#element-minExclusive"/> - + + source="http://www.w3.org/TR/xmlschema11-2/#element-minInclusive"/> - - + + source="http://www.w3.org/TR/xmlschema11-2/#element-maxExclusive"/> - + + source="http://www.w3.org/TR/xmlschema11-2/#element-maxInclusive"/> - - - - - - + + + + + + + + + + + + + + + + + - + + source="http://www.w3.org/TR/xmlschema11-2/#element-totalDigits"/> @@ -2388,48 +1783,56 @@ use - + - + + source="http://www.w3.org/TR/xmlschema11-2/#element-fractionDigits"/> - + + source="http://www.w3.org/TR/xmlschema11-2/#element-length"/> - + + source="http://www.w3.org/TR/xmlschema11-2/#element-minLength"/> - + + source="http://www.w3.org/TR/xmlschema11-2/#element-maxLength"/> - - + + source="http://www.w3.org/TR/xmlschema11-2/#element-enumeration"/> - - + + source="http://www.w3.org/TR/xmlschema11-2/#element-whiteSpace"/> @@ -2446,16 +1849,16 @@ use - + - - + + source="http://www.w3.org/TR/xmlschema11-2/#element-pattern"/> @@ -2463,11 +1866,85 @@ use - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + In keeping with the XML Schema WG's standard versioning policy, + this schema document will persist at the URI + http://www.w3.org/2012/04/datatypes.xsd. + + At the date of issue it can also be found at the URI + http://www.w3.org/2009/XMLSchema/datatypes.xsd. + + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XSD + and its namespace. In other words, if XSD or the XML Schema + namespace change, the version of this document at + http://www.w3.org/2009/XMLSchema/datatypes.xsd will change accordingly; + the version at http://www.w3.org/2012/04/datatypes.xsd will not change. + + Previous dated (and unchanging) versions of this schema document + include: + + http://www.w3.org/2012/01/datatypes.xsd + (XSD 1.1 Proposed Recommendation) + + http://www.w3.org/2011/07/datatypes.xsd + (XSD 1.1 Candidate Recommendation) + + http://www.w3.org/2009/04/datatypes.xsd + (XSD 1.1 Candidate Recommendation) + + http://www.w3.org/2004/10/datatypes.xsd + (XSD 1.0 Recommendation, Second Edition) + + http://www.w3.org/2001/05/datatypes.xsd + (XSD 1.0 Recommendation, First Edition) + + + + + + diff --git a/exist-core/src/test/resources/org/exist/validation/entities/datatypes.dtd b/exist-core/src/test/resources/org/exist/validation/entities/datatypes.dtd new file mode 100644 index 00000000000..f9352bae1c4 --- /dev/null +++ b/exist-core/src/test/resources/org/exist/validation/entities/datatypes.dtd @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/exist-core/src/test/resources/org/exist/validation/entities/xml.xsd b/exist-core/src/test/resources/org/exist/validation/entities/xml.xsd index de11f7e07b2..aea7d0db0a4 100644 --- a/exist-core/src/test/resources/org/exist/validation/entities/xml.xsd +++ b/exist-core/src/test/resources/org/exist/validation/entities/xml.xsd @@ -1,107 +1,107 @@ - - - - See http://www.w3.org/XML/1998/namespace.html and - http://www.w3.org/TR/REC-xml for information about this namespace. - - This schema document describes the XML namespace, in a form - suitable for import by other schema documents. - - Note that local names in this namespace are intended to be defined - only by the World Wide Web Consortium or its subgroups. The - following names are currently defined in this namespace and should - not be used with conflicting semantics by any Working Group, - specification, or document instance: - - base (as an attribute name): denotes an attribute whose value - provides a URI to be used as the base for interpreting any - relative URIs in the scope of the element on which it - appears; its value is inherited. This name is reserved - by virtue of its definition in the XML Base specification. - - id (as an attribute name): denotes an attribute whose value - should be interpreted as if declared to be of type ID. - The xml:id specification is not yet a W3C Recommendation, - but this attribute is included here to facilitate experimentation - with the mechanisms it proposes. Note that it is _not_ included - in the specialAttrs attribute group. - - lang (as an attribute name): denotes an attribute whose value - is a language code for the natural language of the content of - any element; its value is inherited. This name is reserved - by virtue of its definition in the XML specification. - - space (as an attribute name): denotes an attribute whose - value is a keyword indicating what whitespace processing - discipline is intended for the content of the element; its - value is inherited. This name is reserved by virtue of its - definition in the XML specification. - - Father (in any context at all): denotes Jon Bosak, the chair of - the original XML Working Group. This name is reserved by - the following decision of the W3C XML Plenary and - XML Coordination groups: - - In appreciation for his vision, leadership and dedication - the W3C XML Plenary on this 10th day of February, 2000 - reserves for Jon Bosak in perpetuity the XML name - xml:Father - - + + - This schema defines attributes and an attribute group - suitable for use by - schemas wishing to allow xml:base, xml:lang or xml:space attributes - on elements they define. - - To enable this, such a schema must import this schema - for the XML namespace, e.g. as follows: - <schema . . .> - . . . - <import namespace="http://www.w3.org/XML/1998/namespace" - schemaLocation="http://www.w3.org/2001/03/xml.xsd"/> - - Subsequently, qualified reference to any of the attributes - or the group defined below will have the desired effect, e.g. - - <type . . .> - . . . - <attributeGroup ref="xml:specialAttrs"/> - - will define a type which will schema-validate an instance - element with any of those attributes - + +
+

About the XML namespace

- - In keeping with the XML Schema WG's standard versioning - policy, this schema document will persist at - http://www.w3.org/2004/10/xml.xsd. - At the date of issue it can also be found at - http://www.w3.org/2001/xml.xsd. - The schema document at that URI may however change in the future, - in order to remain compatible with the latest version of XML Schema - itself, or with the XML namespace itself. In other words, if the XML - Schema or XML namespaces change, the version of this document at - http://www.w3.org/2001/xml.xsd will change - accordingly; the version at - http://www.w3.org/2004/10/xml.xsd will not change. +
+

+ This schema document describes the XML namespace, in a form + suitable for import by other schema documents. +

+

+ See + http://www.w3.org/XML/1998/namespace.html and + + http://www.w3.org/TR/REC-xml for information + about this namespace. +

+

+ Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. +

+

+ See further below in this document for more information about how to refer to this schema document from your own + XSD schema documents and about the + namespace-versioning policy governing this schema document. +

+
+
- + - Attempting to install the relevant ISO 2- and 3-letter - codes as the enumerated possible values is probably never - going to be a realistic possibility. See - RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry - at http://www.iana.org/assignments/lang-tag-apps.htm for - further information. + +
+ +

lang (as an attribute name)

+

+ denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

+ +
+
+

Notes

+

+ Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. +

+

+ See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + + http://www.iana.org/assignments/language-subtag-registry + for further information. +

+

+ The union allows for the 'un-declaration' of xml:lang with + the empty string. +

+
+
+ + + + + + + + +
+ + +
+ +

space (as an attribute name)

+

+ denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

+ +
+
+
@@ -109,18 +109,48 @@
- - - - See http://www.w3.org/TR/xmlbase/ for - information about this attribute. + + + +
+ +

base (as an attribute name)

+

+ denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

+ +

+ See http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

+
+
- See http://www.w3.org/TR/xml-id/ for - information about this attribute. + +
+ +

id (as an attribute name)

+

+ denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

+ +

+ See http://www.w3.org/TR/xml-id/ + for information about this attribute. +

+
+
@@ -128,6 +158,130 @@ + + + +
+ +

Father (in any context at all)

+ +
+

+ denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: +

+
+

+ In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". +

+
+
+
+
+
+ + + +
+

About this schema document

+ +
+

+ This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow xml:base, + xml:lang, xml:space or + xml:id attributes on elements they define. +

+

+ To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: +

+
+          <schema . . .>
+           . . .
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+     
+

+ or +

+
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+     
+

+ Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. +

+
+          <type . . .>
+           . . .
+           <attributeGroup ref="xml:specialAttrs"/>
+     
+

+ will define a type which will schema-validate an instance element + with any of those attributes. +

+
+
+
+
+ + + +
+

Versioning policy for this schema document

+
+

+ In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + + http://www.w3.org/2009/01/xml.xsd. +

+

+ At the date of issue it can also be found at + + http://www.w3.org/2001/xml.xsd. +

+

+ The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + + will change accordingly; the version at + + http://www.w3.org/2009/01/xml.xsd + + will not change. +

+

+ Previous dated (and unchanging) versions of this schema + document are at: +

+ +
+
+
+
+
+ diff --git a/exist-distribution/src/main/config/collection.xconf.init b/exist-distribution/src/main/config/collection.xconf.init index ccef02b7aa2..266c6c0da4c 100644 --- a/exist-distribution/src/main/config/collection.xconf.init +++ b/exist-distribution/src/main/config/collection.xconf.init @@ -1,5 +1,5 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +%xs-datatypes; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/XMLSchema.xsd b/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/XMLSchema.xsd index 575975b412e..21c707cd4a4 100644 --- a/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/XMLSchema.xsd +++ b/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/XMLSchema.xsd @@ -1,2163 +1,1558 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]> + + - Part 1 version: Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp - Part 2 version: Id: datatypes.xsd,v 1.3 2004/01/23 18:11:13 ht Exp + Part 1 version: structures.xsd (rec-20120405) + Part 2 version: datatypes.xsd (rec-20120405) - - + + The schema corresponding to this document is normative, with respect to the syntactic constraints it expresses in the - XML Schema language. The documentation (within <documentation> elements) + XML Schema Definition Language. The documentation (within 'documentation' elements) below, is not normative, but rather highlights important aspects of - the W3C Recommendation of which this is a part - + the W3C Recommendation of which this is a part. - - + See below (at the bottom of this document) for information about + the revision and namespace-versioning policy governing this + schema document. + + + + + The simpleType element and all of its members are defined - towards the end of this schema document + towards the end of this schema document. - - - - + + + Get access to the xml: attribute groups for xml:lang as declared on 'schema' and 'documentation' below - - - - - - + + + + + This type is extended by almost all schema types to allow attributes from other namespaces to be added to user schemas. - - - - - - - - - - - + + + + + + + + + + This type is extended by all types which allow annotation - other than <schema> itself + other than <schema> itself - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + This group is for the elements which occur freely at the top level of schemas. All of their types are based on the "annotated" type by extension. - - - - - - - - - - - - + + + + + + + + + + + This group is for the elements which can self-redefine (see <redefine> below). - - - - - - - - - - - - + + + + + + + + + + + A utility type, not for public use - - - - - - - - - - + + + + + + + + + A utility type, not for public use - - - - - - - - - - + + + + + + + + + A utility type, not for public use - + #all or (possibly empty) subset of {extension, restriction} - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + A utility type, not for public use - - - - - - - - - + + + + + + + + - - + + A utility type, not for public use - + #all or (possibly empty) subset of {extension, restriction, list, union} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - for maxOccurs - - - - - - - - - - - - for all particles - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + for maxOccurs + + + + + + + + + + + + + for all particles + + + + + + + for element, group and attributeGroup, - which both define and reference - - - - - - - - 'complexType' uses this - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + which both define and reference + + + + + + + + 'complexType' uses this + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - + + This branch is short for <complexContent> <restriction base="xs:anyType"> ... </restriction> </complexContent> - - - + + + + + - - - - - - - - - - - Will be restricted to required or forbidden - - - - - + + + + + + + + + + Will be restricted to required or prohibited + + + + + Not allowed if simpleContent child is chosen. - May be overriden by setting on complexContent child. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This choice is added simply to - make this a valid restriction per the REC - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Overrides any setting on complexType parent. - - - - + May be overridden by setting on complexContent child. + + + + + + + + -
- - - - - - - - - This choice is added simply to - make this a valid restriction per the REC - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This choice is added simply to + make this a valid restriction per the REC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overrides any setting on complexType parent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This choice is added simply to + make this a valid restriction per the REC + + + + + + + + + + + + + + + + No typeDefParticle group reference - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - + + A utility type, not for public use - + #all or (possibly empty) subset of {substitution, extension, restriction} - - - - - - - - - + + + + + + + - - - - - + + + + + + + + + - - - + - - - - + + + The element element can be used either at the top level to define an element-type binding globally, or within a content model to either reference a globally-defined element or type or declare an element-type binding locally. The ref form is not allowed at the top level. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This type is used for 'alternative' elements. + + + + + + + + + + + + + + + + + group type for explicit groups, named top-level groups and group references - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - group type for the three kinds of group - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This choice with min/max is here to - avoid a pblm with the Elt:All/Choice/Seq - Particle derivation constraint - - - - - - - - - - restricted max/min - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - -
- - - - - - - - - Only elements allowed inside - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + - - - - - simple type for the value of the 'namespace' attr of - 'any' and 'anyAttribute' - - - - Value is - ##any - - any non-conflicting WFXML/attribute at all - - ##other - - any non-conflicting WFXML/attribute from - namespace other than targetNS - - ##local - - any unqualified non-conflicting WFXML/attribute - - one or - - any non-conflicting WFXML/attribute from - more URI the listed namespaces - references - (space separated) - - ##targetNamespace or ##local may appear in the above list, to - refer to the targetNamespace of the enclosing - schema or an absent targetNamespace respectively - - - - - - A utility type, not for public use - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + group type for the three kinds of group + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - A subset of XPath expressions for use -in selectors - A utility type, not for public -use - - - - The following pattern is intended to allow XPath - expressions per the following EBNF: - Selector ::= Path ( '|' Path )* - Path ::= ('.//')? Step ( '/' Step )* - Step ::= '.' | NameTest - NameTest ::= QName | '*' | NCName ':' '*' - child:: is also allowed - - - - - - - - - - - - - - - - - - - - - - - A subset of XPath expressions for use -in fields - A utility type, not for public -use - - + + + + - The following pattern is intended to allow XPath - expressions per the same EBNF as for selector, - with the following change: - Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) - + This choice with min/max is here to + avoid a pblm with the Elt:All/Choice/Seq + Particle derivation constraint - - - - - - - - - - - - - - - - - - - - - - - - - The three kinds of identity constraints, all with - type of or derived from 'keybase'. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A utility type, not for public use - - A public identifier, per ISO 8879 - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + Only elements allowed inside + - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - notations for use within XML Schema schemas - - - - - - - - - Not the real urType, but as close an approximation as we can - get in the XML representation - - - - - - - - - - First the built-in primitive datatypes. These definitions are for - information only, the real built-in definitions are magic. - - - - For each built-in datatype in this schema (both primitive and - derived) can be uniquely addressed via a URI constructed - as follows: - 1) the base URI is the URI of the XML Schema namespace - 2) the fragment identifier is the name of the datatype - - For example, to address the int datatype, the URI is: - - http://www.w3.org/2001/XMLSchema#int - - Additionally, each facet definition element can be uniquely - addressed via a URI constructed as follows: - 1) the base URI is the URI of the XML Schema namespace - 2) the fragment identifier is the name of the facet - - For example, to address the maxInclusive facet, the URI is: - - http://www.w3.org/2001/XMLSchema#maxInclusive - - Additionally, each facet usage in a built-in datatype definition - can be uniquely addressed via a URI constructed as follows: - 1) the base URI is the URI of the XML Schema namespace - 2) the fragment identifier is the name of the datatype, followed - by a period (".") followed by the name of the facet - - For example, to address the usage of the maxInclusive facet in - the definition of int, the URI is: - - http://www.w3.org/2001/XMLSchema#int.maxInclusive - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - + + + + source="../structures/structures.html#element-choice"/> - - - - - - - - - - - - - - - - - - - - - - + + + + source="../structures/structures.html#element-sequence"/> - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + simple type for the value of the 'namespace' attr of + 'any' and 'anyAttribute' + + + + Value is + ##any - - any non-conflicting WFXML/attribute at all - - - - - - - - - - - - - - - - - - - - - + ##other - - any non-conflicting WFXML/attribute from + namespace other than targetNS - - - - - - - - - - - - - - - - - - - - - + ##local - - any unqualified non-conflicting WFXML/attribute - - - - - - - - - - - - - - - - - - - - - + one or - - any non-conflicting WFXML/attribute from + more URI the listed namespaces + references + (space separated) - - - - - - - - - - - - - - - - + ##targetNamespace or ##local may appear in the above list, to + refer to the targetNamespace of the enclosing + schema or an absent targetNamespace respectively + + + + + A utility type, not for public use - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + A utility type, not for public use - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + A utility type, not for public use - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + A utility type, not for public use + - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + - NOTATION cannot be used directly in a schema; rather a type - must be derived from it by specifying at least one enumeration - facet whose value is the name of a NOTATION declared in the - schema. + A utility type, not for public use - - - + + + + + + + + + + + - - - - Now the derived primitive types - - - - + + + + + + + + + + + + + source="../structures/structures.html#element-attribute"/> - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + source="../structures/structures.html#element-attributeGroup"/> - - - - - - + + + source="../structures/structures.html#element-include"/> - - - - - pattern specifies the content of section 2.12 of XML 1.0e2 - and RFC 3066 (Revised version of RFC 1766). - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + source="../structures/structures.html#element-redefine"/> - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + source="../structures/structures.html#element-override"/> - - - - - - - - - + + + + + + + + + + + + + + + source="../structures/structures.html#element-import"/> - - - - - pattern matches production 7 from the XML spec - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + source="../structures/structures.html#element-selector"/> - - - - - - - - - + + + + + + + A subset of XPath expressions for use +in selectors + A utility type, not for public +use + + + + + + + + + + + + + + + + + + + + + A subset of XPath expressions for use +in fields + A utility type, not for public +use + + + + + + + + + + + + + + + + + + + + + + + - + The three kinds of identity constraints, all with + type of or derived from 'keybase'. + - - - - - pattern matches production 5 from the XML spec - - - - - - - + + + + + + + + source="../structures/structures.html#element-unique"/> - - - - - pattern matches production 4 from the Namespaces in XML spec - - - - - - - + + - + - - - - + + + source="../structures/structures.html#element-keyref"/> - - - - + + + + + + + + + + source="../structures/structures.html#element-notation"/> - - - - + + + + + + + + + + + - + + A utility type, not for public use + + A public identifier, per ISO 8879 - - - - + - - + + source="../structures/structures.html#element-appinfo"/> - - - - - - + + + + + + + + + + source="../structures/structures.html#element-documentation"/> - - - - - - + + + + + + + + + + - - - - + source="../structures/structures.html#element-annotation"/> - - - - - - - + + + + + + + + + + + + + + + notations for use within schema documents + + + + - + + Not the real urType, but as close an approximation as we can + get in the XML representation - - - - - + + + + + - - - - - - - - - + + + In keeping with the XML Schema WG's standard versioning policy, + the material in this schema document will persist at the URI + http://www.w3.org/2012/04/XMLSchema.xsd. - - - - - - - - - + At the date of issue it can also be found at the URI + http://www.w3.org/2009/XMLSchema/XMLSchema.xsd. - - - - - - - - + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XSD + and its namespace. In other words, if XSD or the XML Schema + namespace change, the version of this document at + http://www.w3.org/2009/XMLSchema/XMLSchema.xsd will change accordingly; + the version at http://www.w3.org/2012/04/XMLSchema.xsd will not change. - - - - - - - - - - - - + Previous dated (and unchanging) versions of this schema document + include: - - - - - - - - + http://www.w3.org/2012/01/XMLSchema.xsd + (XSD 1.1 Proposed Recommendation) - - - - - - - - + http://www.w3.org/2011/07/XMLSchema.xsd + (XSD 1.1 Candidate Recommendation) - - - - - - - - + http://www.w3.org/2009/04/XMLSchema.xsd + (XSD 1.1 Candidate Recommendation) - - - - - - - - + http://www.w3.org/2004/10/XMLSchema.xsd + (XSD 1.0 Recommendation, Second Edition) - - - - A utility type, not for public use + http://www.w3.org/2001/05/XMLSchema.xsd + (XSD 1.0 Recommendation, First Edition) + + + - - - - - - - - - - - - - - - - - - - #all or (possibly empty) subset of {restriction, union, list} - - + + + + + A utility type, not for public use - - - - - + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + #all or (possibly empty) subset of {restriction, extension, union, list} + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + @@ -2173,7 +1568,6 @@ use - @@ -2181,19 +1575,17 @@ use - + Required at the top level - + - @@ -2209,72 +1601,59 @@ use
- + - + source="http://www.w3.org/TR/xmlschema11-2/#element-simpleType"/> + + + + + + An abstract element, representing facets in general. + The facets defined by this spec are substitutable for + this element, and implementation-defined facets should + also name this as a substitution-group head. + - - - - - We should use a substitution group for facets, but - that's ruled out because it would allow users to - add their own, which we're not ready for yet. - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - + + + base attribute and simpleType child are mutually exclusive, but one or other is required - - + + - - - - + + + itemType attribute and simpleType child are mutually exclusive, but one or other is required @@ -2283,19 +1662,18 @@ use + minOccurs="0"/> - - - - + + + memberTypes attribute must be non-empty or there must be at least one simpleType child @@ -2304,7 +1682,7 @@ use + minOccurs="0" maxOccurs="unbounded"/> @@ -2315,71 +1693,88 @@ use - - + - - - - - - - - - - - - - - + + + + + + + + + + + + + source="http://www.w3.org/TR/xmlschema11-2/#element-minExclusive"/> - + + source="http://www.w3.org/TR/xmlschema11-2/#element-minInclusive"/> - - + + source="http://www.w3.org/TR/xmlschema11-2/#element-maxExclusive"/> - + + source="http://www.w3.org/TR/xmlschema11-2/#element-maxInclusive"/> - - - - - - + + + + + + + + + + + + + + + + + - + + source="http://www.w3.org/TR/xmlschema11-2/#element-totalDigits"/> @@ -2388,48 +1783,56 @@ use - + - + + source="http://www.w3.org/TR/xmlschema11-2/#element-fractionDigits"/> - + + source="http://www.w3.org/TR/xmlschema11-2/#element-length"/> - + + source="http://www.w3.org/TR/xmlschema11-2/#element-minLength"/> - + + source="http://www.w3.org/TR/xmlschema11-2/#element-maxLength"/> - - + + source="http://www.w3.org/TR/xmlschema11-2/#element-enumeration"/> - - + + source="http://www.w3.org/TR/xmlschema11-2/#element-whiteSpace"/> @@ -2446,16 +1849,16 @@ use - + - - + + source="http://www.w3.org/TR/xmlschema11-2/#element-pattern"/> @@ -2463,11 +1866,85 @@ use - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + In keeping with the XML Schema WG's standard versioning policy, + this schema document will persist at the URI + http://www.w3.org/2012/04/datatypes.xsd. + + At the date of issue it can also be found at the URI + http://www.w3.org/2009/XMLSchema/datatypes.xsd. + + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XSD + and its namespace. In other words, if XSD or the XML Schema + namespace change, the version of this document at + http://www.w3.org/2009/XMLSchema/datatypes.xsd will change accordingly; + the version at http://www.w3.org/2012/04/datatypes.xsd will not change. + + Previous dated (and unchanging) versions of this schema document + include: + + http://www.w3.org/2012/01/datatypes.xsd + (XSD 1.1 Proposed Recommendation) + + http://www.w3.org/2011/07/datatypes.xsd + (XSD 1.1 Candidate Recommendation) + + http://www.w3.org/2009/04/datatypes.xsd + (XSD 1.1 Candidate Recommendation) + + http://www.w3.org/2004/10/datatypes.xsd + (XSD 1.0 Recommendation, Second Edition) + + http://www.w3.org/2001/05/datatypes.xsd + (XSD 1.0 Recommendation, First Edition) + + + + + + diff --git a/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/datatypes.dtd b/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/datatypes.dtd new file mode 100644 index 00000000000..f9352bae1c4 --- /dev/null +++ b/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/datatypes.dtd @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/xml.xsd b/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/xml.xsd index de11f7e07b2..aea7d0db0a4 100644 --- a/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/xml.xsd +++ b/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/xml.xsd @@ -1,107 +1,107 @@ - - - - See http://www.w3.org/XML/1998/namespace.html and - http://www.w3.org/TR/REC-xml for information about this namespace. - - This schema document describes the XML namespace, in a form - suitable for import by other schema documents. - - Note that local names in this namespace are intended to be defined - only by the World Wide Web Consortium or its subgroups. The - following names are currently defined in this namespace and should - not be used with conflicting semantics by any Working Group, - specification, or document instance: - - base (as an attribute name): denotes an attribute whose value - provides a URI to be used as the base for interpreting any - relative URIs in the scope of the element on which it - appears; its value is inherited. This name is reserved - by virtue of its definition in the XML Base specification. - - id (as an attribute name): denotes an attribute whose value - should be interpreted as if declared to be of type ID. - The xml:id specification is not yet a W3C Recommendation, - but this attribute is included here to facilitate experimentation - with the mechanisms it proposes. Note that it is _not_ included - in the specialAttrs attribute group. - - lang (as an attribute name): denotes an attribute whose value - is a language code for the natural language of the content of - any element; its value is inherited. This name is reserved - by virtue of its definition in the XML specification. - - space (as an attribute name): denotes an attribute whose - value is a keyword indicating what whitespace processing - discipline is intended for the content of the element; its - value is inherited. This name is reserved by virtue of its - definition in the XML specification. - - Father (in any context at all): denotes Jon Bosak, the chair of - the original XML Working Group. This name is reserved by - the following decision of the W3C XML Plenary and - XML Coordination groups: - - In appreciation for his vision, leadership and dedication - the W3C XML Plenary on this 10th day of February, 2000 - reserves for Jon Bosak in perpetuity the XML name - xml:Father - - + + - This schema defines attributes and an attribute group - suitable for use by - schemas wishing to allow xml:base, xml:lang or xml:space attributes - on elements they define. - - To enable this, such a schema must import this schema - for the XML namespace, e.g. as follows: - <schema . . .> - . . . - <import namespace="http://www.w3.org/XML/1998/namespace" - schemaLocation="http://www.w3.org/2001/03/xml.xsd"/> - - Subsequently, qualified reference to any of the attributes - or the group defined below will have the desired effect, e.g. - - <type . . .> - . . . - <attributeGroup ref="xml:specialAttrs"/> - - will define a type which will schema-validate an instance - element with any of those attributes - + +
+

About the XML namespace

- - In keeping with the XML Schema WG's standard versioning - policy, this schema document will persist at - http://www.w3.org/2004/10/xml.xsd. - At the date of issue it can also be found at - http://www.w3.org/2001/xml.xsd. - The schema document at that URI may however change in the future, - in order to remain compatible with the latest version of XML Schema - itself, or with the XML namespace itself. In other words, if the XML - Schema or XML namespaces change, the version of this document at - http://www.w3.org/2001/xml.xsd will change - accordingly; the version at - http://www.w3.org/2004/10/xml.xsd will not change. +
+

+ This schema document describes the XML namespace, in a form + suitable for import by other schema documents. +

+

+ See + http://www.w3.org/XML/1998/namespace.html and + + http://www.w3.org/TR/REC-xml for information + about this namespace. +

+

+ Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. +

+

+ See further below in this document for more information about how to refer to this schema document from your own + XSD schema documents and about the + namespace-versioning policy governing this schema document. +

+
+
- + - Attempting to install the relevant ISO 2- and 3-letter - codes as the enumerated possible values is probably never - going to be a realistic possibility. See - RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry - at http://www.iana.org/assignments/lang-tag-apps.htm for - further information. + +
+ +

lang (as an attribute name)

+

+ denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

+ +
+
+

Notes

+

+ Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. +

+

+ See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + + http://www.iana.org/assignments/language-subtag-registry + for further information. +

+

+ The union allows for the 'un-declaration' of xml:lang with + the empty string. +

+
+
+ + + + + + + + +
+ + +
+ +

space (as an attribute name)

+

+ denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

+ +
+
+
@@ -109,18 +109,48 @@
- - - - See http://www.w3.org/TR/xmlbase/ for - information about this attribute. + + + +
+ +

base (as an attribute name)

+

+ denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

+ +

+ See http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

+
+
- See http://www.w3.org/TR/xml-id/ for - information about this attribute. + +
+ +

id (as an attribute name)

+

+ denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

+ +

+ See http://www.w3.org/TR/xml-id/ + for information about this attribute. +

+
+
@@ -128,6 +158,130 @@ + + + +
+ +

Father (in any context at all)

+ +
+

+ denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: +

+
+

+ In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". +

+
+
+
+
+
+ + + +
+

About this schema document

+ +
+

+ This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow xml:base, + xml:lang, xml:space or + xml:id attributes on elements they define. +

+

+ To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: +

+
+          <schema . . .>
+           . . .
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+     
+

+ or +

+
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+     
+

+ Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. +

+
+          <type . . .>
+           . . .
+           <attributeGroup ref="xml:specialAttrs"/>
+     
+

+ will define a type which will schema-validate an instance element + with any of those attributes. +

+
+
+
+
+ + + +
+

Versioning policy for this schema document

+
+

+ In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + + http://www.w3.org/2009/01/xml.xsd. +

+

+ At the date of issue it can also be found at + + http://www.w3.org/2001/xml.xsd. +

+

+ The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + + will change accordingly; the version at + + http://www.w3.org/2009/01/xml.xsd + + will not change. +

+

+ Previous dated (and unchanging) versions of this schema + document are at: +

+ +
+
+
+
+
+ diff --git a/pom.xml b/pom.xml index ea267445539..1d0531bdc70 100644 --- a/pom.xml +++ b/pom.xml @@ -114,6 +114,13 @@ validate + + strict + + ${project.basedir}/exist-jetty-config/src/main/resources/webapp/WEB-INF/catalog.xml + ${project.basedir}/exist-distribution/src/main/config @@ -155,6 +162,18 @@ ${project.basedir}/schema/mime-types.xsd http://www.w3.org/XML/XMLSchema/v1.1 + + + ${project.basedir}/schema + + **/*.xsd + + ${project.basedir}/exist-jetty-config/src/main/resources/webapp/WEB-INF/entities/XMLSchema.xsd + http://www.w3.org/XML/XMLSchema/v1.1 + diff --git a/schema/README.md b/schema/README.md index 6fd76e13942..8946c03a329 100644 --- a/schema/README.md +++ b/schema/README.md @@ -34,6 +34,18 @@ All five schemas `xs:include` the `schemaVersionType` simple type from [`schema- [`ci-schema-checks.yml`](../.github/workflows/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`](../exist-jetty-config/src/main/resources/webapp/WEB-INF/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](https://github.com/eXist-db/exist/issues/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` | (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` | , `.../datatypes.dtd` — internal-subset companions `XMLSchema.xsd`'s `DOCTYPE`/parameter entities pull in | 2026-06-20 | +| `entities/xml.xsd` | — the `xml:` namespace schema `XMLSchema.xsd` itself imports | 2026-06-20 | + +Published under the [W3C Document License](https://www.w3.org/Consortium/Legal/2015/doc-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`](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()`](https://www.w3.org/TR/xpath-functions-30/#func-unparsed-text)/[`document()`](https://www.w3.org/TR/xslt-30/#document)/[`doc-available()`](https://www.w3.org/TR/xpath-functions-30/#func-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`](../.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`](../pom.xml), so it never runs on an ordinary `mvn install`/`mvn test`/`mvn validate` — only [`ci-schema-checks.yml`](../.github/workflows/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`). diff --git a/schema/collection.xconf.xsd b/schema/collection.xconf.xsd index 8e0cd261f31..f5522b8eb3b 100644 --- a/schema/collection.xconf.xsd +++ b/schema/collection.xconf.xsd @@ -6,7 +6,7 @@ xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" targetNamespace="http://exist-db.org/collection-config/1.0" - version="1.2.1"> + version="1.2.2"> @@ -14,7 +14,7 @@ Schema for eXist-db Collection Configuration files /db/system/config/db/**/collection.xconf Schema for eXist-db Collection Configuration Files - 2011-10-09T18:47:21.319+01:00 + 2011-10-09T18:47:21.319+01:00 Adam Retter diff --git a/schema/expath-pkg-extensions/cxan.xsd b/schema/expath-pkg-extensions/cxan.xsd index 613b09d961e..98440752004 100644 --- a/schema/expath-pkg-extensions/cxan.xsd +++ b/schema/expath-pkg-extensions/cxan.xsd @@ -6,13 +6,13 @@ xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" targetNamespace="http://cxan.org/ns/package" - version="1.0.0"> + version="1.0.1"> A schema for the EXPath Packaging CXAN concept. Schema for the EXPath Packaging CXAN concept. - 2013-11-03T11:36:19.343+01:00 + 2013-11-03T11:36:19.343+01:00 Adam Retter diff --git a/schema/expath-pkg-extensions/exist.xsd b/schema/expath-pkg-extensions/exist.xsd index eb53fa7f4d7..8825340f5dd 100644 --- a/schema/expath-pkg-extensions/exist.xsd +++ b/schema/expath-pkg-extensions/exist.xsd @@ -6,13 +6,13 @@ xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" targetNamespace="http://exist-db.org/ns/expath-pkg" - version="1.0.0"> + version="1.0.1"> A schema for eXist-db extensions to EXPath Packaging. eXist-db extensions to EXPath Packaging - 2013-11-03T11:36:19.343+01:00 + 2013-11-03T11:36:19.343+01:00 Adam Retter diff --git a/schema/expath-pkg-extensions/repo.xsd b/schema/expath-pkg-extensions/repo.xsd index c5000cd65cf..fe26db45a3a 100644 --- a/schema/expath-pkg-extensions/repo.xsd +++ b/schema/expath-pkg-extensions/repo.xsd @@ -6,13 +6,13 @@ xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" targetNamespace="http://exist-db.org/xquery/repo" - version="1.0.0"> + version="1.0.1"> A schema for eXist-db Package Repository extensions to EXPath Packaging. eXist-db Package Repository extensions to EXPath Packaging - 2013-11-03T11:36:19.343+01:00 + 2013-11-03T11:36:19.343+01:00 Adam Retter diff --git a/schema/expath-pkg.xsd b/schema/expath-pkg.xsd index a0248bd47ee..96c70473753 100644 --- a/schema/expath-pkg.xsd +++ b/schema/expath-pkg.xsd @@ -12,7 +12,7 @@ A schema for EXPath Packaging (i.e. expath-pkg.xml) file as per the EXPath Packaging System - Candidate Module 9 May 2012' specification. Schema for EXPath Packaging - 2013-11-03T11:36:19.343+01:00 + 2013-11-03T11:36:19.343+01:00 Adam Retter From ed6c307ddaf4d98ca8beb555b84f60713c6d8de5 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Tue, 23 Jun 2026 01:00:41 +0200 Subject: [PATCH 9/9] [feature] Generate SchemaVersion.java's constants from schema/*.xsd Removes manual sync between hand-copied version constants and the XSDs they describe. Also adds a test reporting which test/sample config fixtures still lack schemaVersion. --- exist-core/pom.xml | 58 ++++++++ .../java/org/exist/util/SchemaVersion.java | 16 ++- .../util/SchemaVersionFixtureAuditTest.java | 129 ++++++++++++++++++ schema/GeneratedSchemaVersions.xml | 8 ++ schema/generate-schema-version.xsl | 71 ++++++++++ 5 files changed, 276 insertions(+), 6 deletions(-) create mode 100644 exist-core/src/test/java/org/exist/util/SchemaVersionFixtureAuditTest.java create mode 100644 schema/GeneratedSchemaVersions.xml create mode 100644 schema/generate-schema-version.xsl diff --git a/exist-core/pom.xml b/exist-core/pom.xml index 2fcdb5ca616..bbe7a79ac3b 100644 --- a/exist-core/pom.xml +++ b/exist-core/pom.xml @@ -1082,6 +1082,64 @@ The BaseX Team. The original license statement is also included below.]]> + + + org.codehaus.mojo + xml-maven-plugin + + + schema-version-codegen + generate-sources + + transform + + + true + + + ${project.basedir}/../schema + + GeneratedSchemaVersions.xml + + ${project.basedir}/../schema/generate-schema-version.xsl + ${project.build.directory}/generated-sources/schema-version/org/exist/util + + + .java + + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + add-schema-version-source + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/schema-version + + + + + + org.apache.maven.plugins maven-compiler-plugin diff --git a/exist-core/src/main/java/org/exist/util/SchemaVersion.java b/exist-core/src/main/java/org/exist/util/SchemaVersion.java index 9491eec84c2..bd472dc384d 100644 --- a/exist-core/src/main/java/org/exist/util/SchemaVersion.java +++ b/exist-core/src/main/java/org/exist/util/SchemaVersion.java @@ -32,12 +32,16 @@ public final class SchemaVersion { public static final String ATTRIBUTE = "schemaVersion"; - /** Paired {@code xs:schema/@version} values for canonical templates (keep in sync with {@code schema/*.xsd}). */ - public static final String CONF = "2.1.1"; - public static final String COLLECTION_XCONF = "1.2.2"; - public static final String DESCRIPTOR = "1.2.1"; - public static final String MIME_TYPES = "1.2.1"; - public static final String CONTROLLER_CONFIG = "1.1.1"; + /** + * Paired {@code xs:schema/@version} values for canonical templates -- generated at build time + * from {@code schema/*.xsd} itself (see {@link GeneratedSchemaVersions}), so these can never + * drift from the schemas they describe. + */ + public static final String CONF = GeneratedSchemaVersions.CONF; + public static final String COLLECTION_XCONF = GeneratedSchemaVersions.COLLECTION_XCONF; + public static final String DESCRIPTOR = GeneratedSchemaVersions.DESCRIPTOR; + public static final String MIME_TYPES = GeneratedSchemaVersions.MIME_TYPES; + public static final String CONTROLLER_CONFIG = GeneratedSchemaVersions.CONTROLLER_CONFIG; private SchemaVersion() { } diff --git a/exist-core/src/test/java/org/exist/util/SchemaVersionFixtureAuditTest.java b/exist-core/src/test/java/org/exist/util/SchemaVersionFixtureAuditTest.java new file mode 100644 index 00000000000..1ef1dd60bd4 --- /dev/null +++ b/exist-core/src/test/java/org/exist/util/SchemaVersionFixtureAuditTest.java @@ -0,0 +1,129 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.util; + +import org.junit.Test; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static org.junit.Assert.assertTrue; + +/** + * Visibility check for test/sample fixture copies of the canonical config templates (the ones + * named e.g. {@code conf.xml} scattered across module test resources, each a hand-trimmed, + * per-module subset of the real {@code exist-distribution/.../conf.xml} -- never literal copies, + * so they can't be mechanically regenerated from canonical without destroying intentional + * per-module customization). + *

+ * None of these ~39 fixtures carry {@link SchemaVersion#ATTRIBUTE}, so none of them are checked + * for drift the way {@link SchemaVersionSyncTest} checks {@link SchemaVersion} itself. This is + * the cheaper "visibility before automation" interim step: list which fixtures are missing the + * attribute, so the gap is visible in CI rather than silent. Actually adding {@code schemaVersion} + * to all of them (via Maven resource filtering, so it can't drift once added) is a separate, + * larger follow-up -- this test does not edit any fixture. + */ +public class SchemaVersionFixtureAuditTest { + + private static final Set FIXTURE_FILE_NAMES = Set.of("conf.xml", "controller-config.xml", "collection.xconf.init"); + + /** The canonical instances themselves are not fixtures -- excluded from the scan. */ + private static final Set CANONICAL_PATHS = Set.of( + "exist-distribution/src/main/config/conf.xml", + "exist-distribution/src/main/config/collection.xconf.init", + "exist-jetty-config/src/main/resources/webapp/WEB-INF/controller-config.xml"); + + @Test + public void reportFixturesMissingSchemaVersion() throws Exception { + final Path repoRoot = resolveRepoRoot(); + + final List fixtures = findFixtures(repoRoot); + assertTrue("expected to find test/sample fixture copies of conf.xml/controller-config.xml/" + + "collection.xconf.init under " + repoRoot + " (found none -- is repo root resolution broken?)", + !fixtures.isEmpty()); + + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + + final List missing = new ArrayList<>(); + for (final Path fixture : fixtures) { + final Document doc = factory.newDocumentBuilder().parse(fixture.toFile()); + final String declared = doc.getDocumentElement().getAttribute(SchemaVersion.ATTRIBUTE); + if (declared == null || declared.isEmpty()) { + missing.add(repoRoot.relativize(fixture).toString()); + } + } + + // Not a hard failure (yet) -- every one of these is currently missing schemaVersion, by + // design (see class javadoc); this is the visibility step, not the enforcement step. The + // assertion just keeps the count itself from silently drifting (e.g. if a fixture + // unexpectedly starts carrying schemaVersion, or a new copy appears uninspected). + assertTrue("Found " + missing.size() + " fixture(s) without " + SchemaVersion.ATTRIBUTE + + " (expected, see class javadoc -- this is a visibility check, not enforcement): " + + missing, + missing.size() == fixtures.size()); + } + + private static List findFixtures(final Path repoRoot) throws IOException { + final List fixtures = new ArrayList<>(); + Files.walkFileTree(repoRoot, new SimpleFileVisitor<>() { + @Override + public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) { + final String name = dir.getFileName() != null ? dir.getFileName().toString() : ""; + if (name.equals("target") || name.equals(".git") || name.equals(".moderne") || name.equals("node_modules")) { + return FileVisitResult.SKIP_SUBTREE; + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) { + if (FIXTURE_FILE_NAMES.contains(file.getFileName().toString())) { + final String relative = repoRoot.relativize(file).toString().replace('\\', '/'); + if (!CANONICAL_PATHS.contains(relative)) { + fixtures.add(file); + } + } + return FileVisitResult.CONTINUE; + } + }); + return fixtures; + } + + private static Path resolveRepoRoot() { + final Path base = Path.of(System.getProperty("user.dir")); + Path p = base.resolve("schema"); + if (Files.isDirectory(p)) { + return base; + } + return base.getParent(); + } +} diff --git a/schema/GeneratedSchemaVersions.xml b/schema/GeneratedSchemaVersions.xml new file mode 100644 index 00000000000..4db47163365 --- /dev/null +++ b/schema/GeneratedSchemaVersions.xml @@ -0,0 +1,8 @@ + + diff --git a/schema/generate-schema-version.xsl b/schema/generate-schema-version.xsl new file mode 100644 index 00000000000..878628d51fb --- /dev/null +++ b/schema/generate-schema-version.xsl @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + /* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * GENERATED by schema/generate-schema-version.xsl at build time -- do not edit by hand. + * Source of truth: each canonical XSD's xs:schema/@version, under schema/. + */ +package org.exist.util; + +/** + * Build-time-generated {@code xs:schema/@version} values for the canonical native XSDs -- see + * {@link SchemaVersion}, which exposes these under its own stable, hand-written constant names. + */ +final class GeneratedSchemaVersions { + + private GeneratedSchemaVersions() { + } + + + + + + generate-schema-version.xsl: + has no xs:schema/@version (resolved as ) -- cannot generate . + + static final String + + = " + + "; + + + } + + + +