XmlFluentValidator: Code-First XML Validation That Stays Close to Your Rules
XML is still alive and is almost everywhere used: configuration files, integration contracts, legacy systems, and enterprise messaging. Yet validating XML in a clean, maintainable, and expressive way remains a challenge for a part of developers.
A lot of teams end up choosing between:
- Hand-written XSDs that are verbose, fragile, and disconnected from business logic;
- Imperative validation code scattered across internal services, quite difficult to reuse or document.
XmlFluentValidator proposes another approach:
define XML validation rules fluently in C#, validate at runtime, and generate schemas and documentation from the same source of truth (source code).
The Problem/Difficulties with Traditional XML Validation
XSD has its own power, but it comes with real trade-offs:
- Low readability and poor discoverability;
- Limited expressiveness for cross-element or computed rules;
- Hard to evolve alongside application logic;
- No(or very poor) natural place for business-level validation semantics;
On the other hand, pure runtime validation often results in:
- Custom XPath logic duplicated across projects;
- No formal schema to share with consumers;
- Inconsistent validation behavior between runtime and contracts;
XmlFluentValidator can help you to close a part of this gap.
What XmlFluentValidator Is
XmlFluentValidator is a .NET Standard 2.0 library that allows:
- Define XML validation rules using a fluent, strongly-typed C# API;
- Validate XML documents at runtime with structured error output;
- Set documentation, severity, and messages to rules;
- Combine schema validation with custom runtime logic
- Generate XSD schemas from rules (supported and evolving)
It treats validation rules as first-class code artifacts, not static XML files.
Core Design Principles
1. The Code Is the Source of Truth
Validation rules live in C#, alongside your domain logic.
No duplication between schema files and runtime validation.
2. Fluent, Intent-Driven API
Rules read like requirements, not infrastructure:
- What element is required?
- What constraints apply?
- Why does this rule exist?
3. Runtime + Schema Compatibility
Rules are designed to map cleanly to XSD constructs where possible, while still allowing runtime-only logic when necessary.
Defining Validation Rules
At the core of the library is a fluent builder that targets paths, elements, and attributes.
Element Rules
var validator = new XmlFluentValidator()
.ForPath("/order/id")
.WithElementRequired("Order ID is required")
.WithElementMatchesRegex(@"^\d+$", "Order ID must be numeric")
.Done()
.ForPath("/order/total")
.WithElementInRange(0, 10000, true, "Total must be between 0 and 10000")
.Done();
This expresses clearly:
- The element must exist;
- The value must follow a specific format;
- The value must be within a valid numeric range;
No XSD syntax. No XPath boilerplate.
Attribute Validation
Attributes are validated explicitly and consistently:
validator
.ForPath("/order/items/item")
.WithAttributeRequired("sku", "SKU is mandatory")
.WithAttributeMatchesRegex("sku", @"^[A-Z0-9\-]+$")
.WithAttributeInRange("quantity", 1, 100, true)
.Done();
This avoids the common XSD problem where attribute rules are hard to read or scattered.
Cardinality, Length, and Uniqueness
The API supports common structural constraints:
- Element existence (required / optional);
- Maximum occurrences;
- Value length (min, max, exact);
- Uniqueness across sibling nodes;
- Data type enforcement;
- Nullable (
xs:nillable) control;
All of these can also be documented and messaged directly in code.
Custom and Global Rules
Some rules cannot be expressed in XSD at all.
For example: cross-element logic, computed totals, or document-wide constraints.
XmlFluentValidator supports global rules:
validator.GlobalRule(doc =>
{
var items = doc.XPathSelectElements("/order/items/item");
return items.Any();
}, "Order must contain at least one item");
These rules:
- Run at runtime;
- Participate in the same validation pipeline;
- Produce structured error messages;
- Can coexist with schema validation;
This is one of the strongest differentiators of the library.
Validation Execution and Results
Validation is executed explicitly:
var result = validator.Validate(xDocument);
if (!result.IsValid)
{
foreach (var error in result.Errors)
{
Console.WriteLine($"{error.Path}: {error.Message}");
}
}
Each validation error includes:
- The XML path;
- The violated rule;
- The configured message;
- Severity metadata;
This makes the output suitable for:
- APIs
- Logging
- Automated tests
XSD Schema Generation
A key goal of XmlFluentValidator is schema generation from fluent validation rules.
Rules such as:
- required elements;
- data types;
- ranges;
- enumerations;
- documentation annotations;
can be emitted into an XSD representation.
This allows:
- Share contracts with external systems;
- Keep schemas aligned with runtime validation;
- Avoid maintaining two parallel validation models;
The feature is actively evolving and designed into the API from the start.
How It Fits into Real Systems
XmlFluentValidator is especially useful when:
- XML validation rules evolve frequently;
- Business logic must be enforced beyond XSD capabilities;
- Validation must run dynamically at runtime;
- Schemas still need to be shared or documented;
- Validation logic belongs with application code, not static files;
Typical use cases include:
- Integration gateways;
- Configuration validation;
- ETL pipelines;
- Legacy XML modernization;
- Domain-specific XML formats;
Final Thoughts
XmlFluentValidator is not trying to replace XSD.
It aims to make XML validation more expressive, maintainable, and aligned with the way modern .NET developers think. **
If you also believe:
- validation rules should read like business rules;
- code should be the primary source of truth;
- and schemas should be generated, not hand-crafted;
Then, XmlFluentValidator is worth your attention.
🔗 Repository: https://github.com/I-RzR-I/XmlFluentValidator
Top comments (0)