Skip to main content
Glama
SemanticDataCharter

sdcvalidator

Official
README.md
# sdcvalidator

<!-- mcp-name: io.github.SemanticDataCharter/sdcvalidator -->

**SDC4 structural validator** — a thin wrapper over [xmlschema](https://pypi.org/project/xmlschema/) with two-tier error classification.

[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Python](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)

## What it does

- Validates XML instances against SDC4 XSD schemas
- Classifies errors into **structural** (Tier 1: reject) vs **semantic** (Tier 2: report)
- Checks SDC4 schema compliance (no `xsd:extension` — only `xsd:restriction`)
- **Strict validation by default** — catches invalid restriction derivations (wrong element names, type mismatches) at schema load time
- Converts between XML and JSON using schema-aware conversion

## Install

```bash
pip install sdcvalidator
```

Or from source:

```bash
git clone https://github.com/SemanticDataCharter/sdcvalidator.git
cd sdcvalidator
pip install -e .
```

## Python API

```python
from sdcvalidator import SDC4Validator, ErrorTier

# Validate an XML instance (strict mode by default)
validator = SDC4Validator("my_schema.xsd")
result = validator.validate("my_instance.xml")

if result.is_valid:
    print("Valid!")
else:
    for err in result.structural_errors:
        print(f"STRUCTURAL: {err.reason}")
    for err in result.semantic_errors:
        print(f"SEMANTIC: {err.reason}")
```

### Validation modes

The `validation` parameter controls how strictly the XSD schema itself is checked when loaded:

- **`'strict'`** (default) — Raises `XMLSchemaParseError` if the schema contains invalid restriction derivations (e.g., element names that don't match the base type). This is the recommended mode.
- **`'lax'`** — Silently collects schema derivation errors without raising. Use only for pre-existing schemas known to have issues.
- **`'skip'`** — Skips schema-level validation entirely.

```python
# Explicit lax mode for legacy schemas
validator = SDC4Validator("legacy_schema.xsd", validation='lax')
```

### Schema compliance checking

```python
from sdcvalidator import validate_sdc4_schema_compliance, assert_sdc4_schema_compliance

# Check if a schema uses xsd:extension (not allowed in SDC4)
is_valid, errors = validate_sdc4_schema_compliance("schema.xsd")

# Or raise an exception
assert_sdc4_schema_compliance("schema.xsd")
```

### Error classification

```python
from sdcvalidator import ErrorClassifier, ErrorTier

classifier = ErrorClassifier()
tier = classifier.classify(some_xmlschema_error)
# ErrorTier.STRUCTURAL or ErrorTier.SEMANTIC
```

### Exceptional Value recovery

A semantic (Tier 2) error does not have to reject a record. Recovery keeps the value and inserts an ISO 21090
ExceptionalValue beside it (Invalid, for a value that fails its type, pattern, range or enumeration), so the record
says which value is unusable and why, and the rest of it stays usable.

```python
from sdcvalidator import SDC4Validator, SDC4UnrecoverableError

v = SDC4Validator("dm-xxxx.xsd", validation="lax")
result = v.recover("record.xml")         # RecoveryResult; the source is never mutated
for r in result.recoveries:              # Recovery: path, code ("INV"), name, reason, inserted
    print(r.code, r.reason, r.path)
if not result.ok:                        # an error no ExceptionalValue covers
    print(result.unrecoverable)

tree = v.validate_with_recovery("record.xml", save=False)   # raises SDC4UnrecoverableError instead
```

- An ExceptionalValue the record already carries (a refusal, a masked field, written where the record was made) is
  kept, and covers its value; recovery never inserts a second one. `remove_existing_ev=True` removes them first.
- An error recovery cannot cover is returned in `unrecoverable` by `recover()`, and raised as
  `SDC4UnrecoverableError` by `validate_with_recovery()`; it is never skipped.
- Structural (Tier 1) errors raise `SDC4StructuralValidationError`.
- Pass an `XMLResource` when the record carries prefixed QNames in content (`xsi:type="sdc4:..."`).

### XML/JSON conversion

```python
from sdcvalidator.converters import xml_to_json, json_to_xml

# XML -> JSON (schema-aware)
data = xml_to_json("instance.xml", schema_path="schema.xsd")

# JSON -> XML
json_to_xml(data, "schema.xsd", "output.xml")
```

## CLI

### `sdcvalidate` — Validate XML against schema

```bash
# Basic validation
sdcvalidate schema.xsd instance.xml

# JSON output
sdcvalidate schema.xsd instance.xml --json

# Skip SDC4 compliance check
sdcvalidate --no-compliance-check schema.xsd instance.xml
```

Exit codes: `0` valid, `1` semantic errors only, `2` structural errors.

### `sdcvalidator-xml2json` — Convert XML to JSON

```bash
sdcvalidator-xml2json instance.xml --schema schema.xsd
sdcvalidator-xml2json instance.xml -o output.json
```

### `sdcvalidator-json2xml` — Convert JSON to XML

```bash
sdcvalidator-json2xml data.json schema.xsd -o output.xml
```

## MCP Server

`sdcvalidator` ships a stdio MCP (Model Context Protocol) server so any MCP-capable agent can validate SDC4 data without importing the Python library. It implements JSON-RPC 2.0 directly over stdio — no external MCP SDK dependency.

```bash
sdcvalidator            # what an MCP registry client runs (uvx sdcvalidator)
sdcvalidator mcp        # the same, spelled like the other Semantic Data Charter servers
sdcvalidator-mcp serve --mcp   # still works for existing client configurations
```

A client configuration needs only `"command": "uvx", "args": ["sdcvalidator"]`.

### Tools

| Tool | Purpose |
|------|---------|
| `validate_instance` | Validate an XML instance against its SDC4 XSD schema. Returns pass/fail with error count and classified errors. |
| `validate_and_report` | Validate an instance and return a detailed report with two-tier (structural vs semantic) error classification. |
| `check_schema_compliance` | Check whether an XSD schema follows SDC4 principles (restriction only, no `xsd:extension`). Does not validate instances. |

`validate_instance` and `validate_and_report` take `schema_path` and `instance_path`, plus an optional `check_compliance` boolean (default `true`). `check_schema_compliance` takes `schema_path` only.

## Two-Tier Error Classification

| Tier | Type | Examples | Action |
|------|------|----------|--------|
| 1 | Structural | Unknown elements, cardinality violations, wrong nesting | **Reject** |
| 2 | Semantic | Type errors, pattern violations, enumeration mismatches | **Report**, or recover with an ExceptionalValue |

## SDC4 Schema Compliance

SDC4 data models must use `xsd:restriction` only — never `xsd:extension`. This enforces separation of structure (reference model) and semantics (data models), guaranteeing global interoperability.

The validator checks this by default and rejects schemas that violate this principle.

## Status

Production-ready. Available on [PyPI](https://pypi.org/project/sdcvalidator/) under Apache 2.0.

## License

Apache License 2.0 — see [LICENSE](LICENSE).

## Links

- [Semantic Data Charter](https://semanticdatacharter.com)
- [SDC4 Reference Model](https://semanticdatacharter.com/ns/sdc4/)
- [xmlschema](https://pypi.org/project/xmlschema/)

TDQS

A3.5/5.0

Scored across 3 tools

Disambiguation3/5

validate_instance and validate_and_report both validate XML instances and differ mainly in output detail, creating likely selection ambiguity. check_schema_compliance is clearly distinct, and the descriptions partially clarify the overlap, but the boundary between the two validators is not crisp.

Naming Consistency4/5

All names use snake_case and are reasonably predictable. The pattern is mostly action-oriented, though check_schema_compliance is a bit longer and less parallel with the validate_* tools.

Tool Count4/5

Three tools is appropriate for a focused SDC validator, but validate_instance and validate_and_report could likely be consolidated or differentiated more clearly. The count is not excessive, though the overlap suggests slight over-partitioning.

Completeness4/5

The surface covers instance validation, detailed reporting, and schema-principle checking, which are the core operations for this domain. Minor gaps may exist around explicit schema validity checking or reporting options, but no major workflow appears missing.

Maintenance

ActivityActive
ResponsivenessUnresponsive