Skip to main content

Search 436 pages — tools, formats, elements, namespaces, directory, comparisons, XPath, datatypes, glossary, parse errors, schema errors, use cases, guides, blog and product.

Comparison

XSD vs Schematron

A grammar says which elements may appear. Schematron says what they must add up to. Almost every regulated format needs both, layered.

This is the one comparison on this page where the answer is usually "both", and the reason is that the two answer different questions. XSD describes shape: which elements, in what order, how many, holding what kind of value. Schematron describes consequence: that a total equals the sum of its lines, that a delivery date does not precede its order date, that a code is only allowed when another field says so.

Neither can do the other's job. XSD has no way to compare two values in a document, because its model never looks at more than one element's content at a time. Schematron has no vocabulary of its own at all — it is a list of XPath assertions and the messages to show when they fail, and it will happily approve a document whose structure is nonsense as long as no rule fires.

That is why every serious profile ships both: UBL and Peppol for invoicing, ISO 20022 usage guidelines for payments, HL7 implementation guides for clinical documents. The XSD is the contract's shape and the Schematron is its conditions, and a document that passes only one of them will be rejected by the counterparty that checks the other.

The demonstrations below run the same invoice through each. It is schema-valid and arithmetically wrong, which is exactly the document that reaches production.

What actually differs

XSD compared with Schematron, one row per aspect
AspectXSDSchematron
StandardW3C RecommendationISO/IEC 19757-3
DescribesStructure and datatypesConditions between values
SeesOne element's content at a timeThe whole document, through XPath
Defines a vocabularyYes — this is the element listNo — it asserts about whatever is there
Cross-field rulesNot expressibleThe entire purpose
Error messagesGenerated by the validatorWritten by whoever wrote the rule
SeverityEverything is an errorRoles distinguish an error from a warning
Code generationA whole ecosystemNone, and none intended

Shown, not asserted

The differences above are claims, so here they are being made. Every one of these runs on each test run, against the same engines the tools use — the outputs are what came back, not what we expected.

  • The invoice against its XSD: valid. Every element is where the grammar says it should be.

    document.xml
    <?xml version="1.0"?>
    <invoice>
      <line><amount>30.00</amount></line>
      <line><amount>60.00</amount></line>
      <total>100.00</total>
    </invoice>
    schema.xsd
    <?xml version="1.0"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="invoice">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="line" maxOccurs="unbounded">
              <xs:complexType><xs:sequence>
                <xs:element name="amount" type="xs:decimal"/>
              </xs:sequence></xs:complexType>
            </xs:element>
            <xs:element name="total" type="xs:decimal"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>

    What came back

    Valid against the XSD grammar above.
  • The same invoice against one Schematron rule: the total is wrong, and it says so in the words whoever wrote the rule chose.

    document.xml
    <?xml version="1.0"?>
    <invoice>
      <line><amount>30.00</amount></line>
      <line><amount>60.00</amount></line>
      <total>100.00</total>
    </invoice>
    rules.sch
    <?xml version="1.0"?>
    <schema xmlns="http://purl.oclc.org/dsdl/schematron">
      <pattern>
        <rule context="invoice">
          <assert test="total = sum(line/amount)">The total must equal the sum of the line amounts.</assert>
        </rule>
      </pattern>
    </schema>

    What came back

    An assertion failed, in the words the rule's author wrote.The total must equal the sum of the line amounts.
  • Correct the total and the same rule passes. Nothing about the structure changed — only the arithmetic.

    document.xml
    <?xml version="1.0"?>
    <invoice>
      <line><amount>30.00</amount></line>
      <line><amount>60.00</amount></line>
      <total>90.00</total>
    </invoice>
    rules.sch
    <?xml version="1.0"?>
    <schema xmlns="http://purl.oclc.org/dsdl/schematron">
      <pattern>
        <rule context="invoice">
          <assert test="total = sum(line/amount)">The total must equal the sum of the line amounts.</assert>
        </rule>
      </pattern>
    </schema>

    What came back

    Every assertion holds.
  • And the reverse: a document XSD would reject outright passes every rule, because no rule asked about structure.

    document.xml
    <?xml version="1.0"?>
    <invoice><nonsense/></invoice>
    rules.sch
    <?xml version="1.0"?>
    <schema xmlns="http://purl.oclc.org/dsdl/schematron">
      <pattern>
        <rule context="line">
          <assert test="amount">A line must carry an amount.</assert>
        </rule>
      </pattern>
    </schema>

    What came back

    Every assertion holds.

Which to pick

XSD, when

  • You are defining the vocabulary itself — what the elements are and what may nest inside what.
  • Values need type checking: dates, decimals with a fixed scale, enumerations, patterns.
  • Something downstream generates code from the schema, which is XSD's world entirely.

Schematron, when

  • The rule involves more than one value — a total, a date ordering, a field that is required only when another is present.
  • The failure message has to be readable by whoever has to fix the document, rather than by whoever wrote the schema.
  • A counterparty publishes rules on top of a schema you do not control, which is how every e-invoicing and payments profile works.

Get started

Bring order to the XML your team can't afford to ignore.

Create a free account and get a private workspace to search, validate, diff, and monitor your XML feeds, sitemaps, schemas, and vendor integrations.