`XmlFluentValidator`: Code-First XML Validation That Stays Close to Your Rules

Published: (January 12, 2026 at 01:17 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

RzR

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.

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 close part of this gap.

What XmlFluentValidator Is

XmlFluentValidator is a .NET Standard 2.0 library that allows you to:

  • 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 on 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

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 (e.g., cross‑element logic, computed totals, 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

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 you to:

  • Share contracts with external systems.
  • Keep schemas aligned with runtime validation.
  • Avoid maintaining two parallel validation artefacts.

XmlFluentValidator bridges the gap between code‑first validation and contract‑first schema generation, giving you a single source of truth for XML validation.

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
  • schemas should be generated, not hand‑crafted

then XmlFluentValidator is worth your attention.

🔗 Repository:

Back to Blog

Related posts

Read more »

C#.NET - day 08

Day 08 : Unit Testing — The Real Reason Interfaces Exist Proving service behavior without repositories or databases Introduction Many tutorials introduce inter...