XML Schema Regex for Phone Numbers and Postal Codes
XML Schema Definition (XSD) enforces lexical constraints on data
elements using regular expressions defined within the
xs:pattern facet. By applying these patterns to simple
types derived from xs:string or xs:token, you
can restrict element values to match specific structural rules. This
article demonstrates how to construct and apply XML Schema patterns to
validate international phone numbers and varied postal code formats
accurately.
Mechanism for Enforcing Lexical Patterns
To constrain the lexical space of an element, create an
xs:simpleType with an xs:restriction base of
xs:string (or xs:token), and define the
matching rules using one or more <xs:pattern>
elements. In XSD, regular expressions are implicitly anchored, meaning
the entire value must match the pattern from start to end without
needing explicit ^ or $ anchors.
<xs:simpleType name="CustomPatternType">
<xs:restriction base="xs:token">
<xs:pattern value="[A-Z]{2}[0-9]{4}"/>
</xs:restriction>
</xs:simpleType>Enforcing International Phone Numbers
International phone numbers vary widely, but standard validation typically follows the ITU-T E.164 standard or allows common human-readable formatting with spaces, dashes, and parentheses.
Strict E.164 Format
The E.164 format requires a leading + followed by a
country code and subscriber number, totaling no more than 15 digits.
<xs:simpleType name="E164PhoneNumber">
<xs:restriction base="xs:token">
<!-- Requires a leading '+' followed by 1 to 15 digits (first digit 1-9) -->
<xs:pattern value="\+[1-9][0-9]{1,14}"/>
</xs:restriction>
</xs:simpleType>Flexible International Format
If your schema needs to accept human-formatted numbers containing hyphens, spaces, or parentheses:
<xs:simpleType name="FormattedPhoneNumber">
<xs:restriction base="xs:token">
<!-- Allows optional '+', digits, spaces, parentheses, and hyphens (7 to 20 chars) -->
<xs:pattern value="(\+)?[0-9\s\-\(\)]{7,20}"/>
</xs:restriction>
</xs:simpleType>Enforcing International Postal Codes
Because postal code formats differ significantly between countries,
you can enforce them using a flexible universal pattern or
country-specific patterns combined with an xs:union or
multi-branch regex.
Universal International Pattern
A general pattern accommodates alphanumeric codes, spaces, and hyphens used in most global postal systems (e.g., US ZIP codes, UK postcodes, Canadian alphanumeric codes).
<xs:simpleType name="InternationalPostalCode">
<xs:restriction base="xs:token">
<!-- 3 to 10 characters consisting of uppercase letters, numbers, hyphens, and spaces -->
<xs:pattern value="[A-Z0-9\s\-]{3,10}"/>
</xs:restriction>
</xs:simpleType>Multi-Pattern Country-Specific Validation
When strict validation is required for known formats, you can combine
specific patterns into a single regular expression using the alternation
operator (|):
<xs:simpleType name="StrictPostalCode">
<xs:restriction base="xs:token">
<!-- US: 12345 or 12345-6789 -->
<!-- UK: e.g., SW1A 1AA -->
<!-- Canada: e.g., K1A 0B1 -->
<xs:pattern value="[0-9]{5}(-[0-9]{4})?|[A-Z]{1,2}[0-9][A-Z0-9]?\s?[0-9][A-Z]{2}|[A-Z][0-9][A-Z]\s?[0-9][A-Z][0-9]"/>
</xs:restriction>
</xs:simpleType>Alternatively, you can define separate simple types for each country
and combine them using <xs:union>:
<xs:simpleType name="USPostalCode">
<xs:restriction base="xs:token">
<xs:pattern value="\d{5}(-\d{4})?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="CAPostalCode">
<xs:restriction base="xs:token">
<xs:pattern value="[A-CEGHJ-NPR-TVXY]\d[A-CEGHJ-NPR-TV-Z] \d[A-CEGHJ-NPR-TV-Z]\d"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PostalCodeUnion">
<xs:union memberTypes="USPostalCode CAPostalCode"/>
</xs:simpleType>Implementation Best Practices
- Use
xs:tokenInstead ofxs:string: Deriving your simple types fromxs:tokenautomatically strips leading and trailing whitespace and collapses internal contiguous whitespace, preventing validation failures caused by formatting artifacts. - Avoid Redundant Anchors: Do not include
^and$in thevalueattribute; XSD pattern matching inherently tests the full length of the string. - Account for Character Escaping: Ensure special
characters such as hyphens within character classes are properly escaped
(
\-) or placed at the beginning or end of the bracketed expression.