Matching

When you have multiple possible formats for the same data, TokenMatcher tries each template and selects the best match based on scoring.

TokenMatcher

Register multiple templates, then match input against all of them:

C#
using Tokens;

var matcher = new TokenMatcher();

matcher.RegisterTemplate("Price: £{Amount}", "gbp");
matcher.RegisterTemplate("Price: ${Amount}", "usd");
matcher.RegisterTemplate("Price: €{Amount}", "eur");

var result = matcher.Match("Price: £99.99");

Console.WriteLine(result.BestMatch.Template.Name); // "gbp"
Console.WriteLine(result.BestMatch.First("Amount")); // "99.99"

You can also match onto a typed object:

C#
public class PriceResult
{
    public string Amount { get; set; }
}

var result = matcher.Match<PriceResult>("Price: €149.00");
Console.WriteLine(result.Value.Amount); // "149.00"

Scoring

The matcher scores each template based on how many tokens were successfully matched. The template with the most matches wins. In case of a tie, the first registered template takes priority.

Access all results to see how each template performed:

C#
var result = matcher.Match(input);

foreach (var match in result.Results)
{
    Console.WriteLine($"{match.Template.Name}: {match.Tokens.Matches.Count} matches");
}

Tags

Tags let you filter which templates are tried. Define tags in the template's front matter:

Plain text
---
Tags: dns, whois
---
Domain: {Domain}
Registrar: {Registrar}

Then filter by tag when matching:

C#
var result = matcher.Match(input, tags: new[] { "whois" });
// Only templates tagged "whois" are tried

Hints

Hints are strings you expect to find in the input. They help the matcher score templates more accurately:

Plain text
---
Hint: 'registered on'
Hint: 'expiration date' [Optional]
---
Domain: {Domain}
Registered: {RegisteredDate}
Expiration: {ExpirationDate}

Required hints (default) must be found in the input for the template to match. Optional hints contribute to scoring but don't prevent matching.

Real-World Example

A common use case is parsing WHOIS data, where different registrars use different formats:

C#
var matcher = new TokenMatcher();

// Format 1: GoDaddy-style
matcher.RegisterTemplate(@"---
Hint: 'Domain Name:'
---
Domain Name: {DomainName}
Registrar: {Registrar}
Creation Date: {Created}", "godaddy");

// Format 2: Namecheap-style
matcher.RegisterTemplate(@"---
Hint: 'domain name....'
---
   domain name....: {DomainName}
   registrar......: {Registrar}
   created........: {Created}", "namecheap");

var result = matcher.Match(whoisOutput);
Console.WriteLine($"Matched: {result.BestMatch.Template.Name}");
Console.WriteLine($"Domain: {result.BestMatch.First("DomainName")}");