Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ obj/
bin/
*.DotSettings.user
dist/
/.vs
2 changes: 1 addition & 1 deletion MRZCode.Samples/MRZCode.Samples.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>netstandard2.1;net9.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
41 changes: 41 additions & 0 deletions MRZCode.Samples/TD1_doc_longSample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using MRZCodeParser;

namespace MRZCode.Samples
{
public static class TD1_doc_long_Sample
{
public static void Run()
{
var text = @"IDBEL123456789<2383<<<<<<<<<<<
7408122F1204159BEL740812123457
ERIKSSON<<ANNA<MARIA<<<<<<<<<<";

Console.WriteLine("TD1 long document id code sample");
Console.WriteLine();
Console.WriteLine(text);
Console.WriteLine();

var mrzCode = MrzCode.Parse(text);

Console.WriteLine("Code type: {0}", mrzCode.Type);

Console.WriteLine("DocumentType: {0}", mrzCode[FieldType.DocumentType]);
Console.WriteLine("CountryCode: {0}", mrzCode[FieldType.CountryCode]);
Console.WriteLine("DocumentNumber: {0}", mrzCode[FieldType.DocumentNumber]);
Console.WriteLine("DocumentNumberCheckDigit: {0}", mrzCode[FieldType.DocumentNumberCheckDigit]);
Console.WriteLine("OptionalData1: {0}", mrzCode[FieldType.OptionalData1]);
Console.WriteLine("BirthDate: {0}", mrzCode[FieldType.BirthDate]);
Console.WriteLine("BirthDateCheckDigit: {0}", mrzCode[FieldType.BirthDateCheckDigit]);
Console.WriteLine("Sex: {0}", mrzCode[FieldType.Sex]);
Console.WriteLine("ExpiryDate: {0}", mrzCode[FieldType.ExpiryDate]);
Console.WriteLine("ExpiryDateCheckDigit: {0}", mrzCode[FieldType.ExpiryDateCheckDigit]);
Console.WriteLine("Nationality: {0}", mrzCode[FieldType.Nationality]);
Console.WriteLine("OptionalData2: {0}", mrzCode[FieldType.OptionalData2]);
Console.WriteLine("OverallCheckDigit: {0}", mrzCode[FieldType.OverallCheckDigit]);
Console.WriteLine("Names: {0}", mrzCode[FieldType.Names]);

Console.WriteLine();
}
}
}
2 changes: 1 addition & 1 deletion MRZCodeParser.Tests/MRZCodeParser.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>netstandard2.1;net9.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>
Expand Down
4 changes: 4 additions & 0 deletions MRZCodeParser.Tests/MrzSamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ public static class MrzSamples

public const string TD1_SINGLE_LETTER_COUNTRY_CODE = @"I<D<<D231458907<<<<<<<<<<<<<<<
7408122F1204159D<<<<<<<<<<<<<6
ERIKSSON<<ANNA<MARIA<<<<<<<<<<";

public const string TD1_LONGER_DOCUMENT_ID = @"IDBEL111111111<5227<<<<<<<<<<<
7408122F2912207BEL110801555552
ERIKSSON<<ANNA<MARIA<<<<<<<<<<";

public const string TD2 = @"I<UTOERIKSSON<<ANNA<MARIA<<<<<<<<<<<
Expand Down
60 changes: 60 additions & 0 deletions MRZCodeParser.Tests/TD1DocumentLongMrzCodeTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Collections.Generic;
using System.Linq;
using Xunit;

namespace MRZCodeParser.Tests
{
public class TD1DocumentLongMrzCodeTest
{
[Fact]
public void CodeFieldsTest()
{
var target = MrzCode.Parse(MrzSamples.TD1_LONGER_DOCUMENT_ID);

Assert.Equal(DocumentType.ID.ToString(), target[FieldType.DocumentType]);
Assert.Equal("BEL", target[FieldType.CountryCode]);
Assert.Equal("111111111522", target[FieldType.DocumentNumber]);
Assert.Equal("7", target[FieldType.DocumentNumberCheckDigit]);
Assert.Equal("", target[FieldType.OptionalData1]);
Assert.Equal("740812", target[FieldType.BirthDate]);
Assert.Equal("2", target[FieldType.BirthDateCheckDigit]);
Assert.Equal("F", target[FieldType.Sex]);
Assert.Equal("291220", target[FieldType.ExpiryDate]);
Assert.Equal("7", target[FieldType.ExpiryDateCheckDigit]);
Assert.Equal("BEL", target[FieldType.Nationality]);
Assert.Equal("11080155555", target[FieldType.OptionalData2]);
Assert.Equal("2", target[FieldType.OverallCheckDigit]);
Assert.Equal("ERIKSSON, ANNA MARIA", target[FieldType.Names]);
}


[Fact]
public void FieldTypeCollectionTest()
{
var target = MrzCode.Parse(MrzSamples.TD1);

var expected = new[]
{
FieldType.DocumentType,
FieldType.CountryCode,
FieldType.DocumentNumber,
FieldType.DocumentNumberCheckDigit,
FieldType.OptionalData1,
FieldType.BirthDate,
FieldType.BirthDateCheckDigit,
FieldType.Sex,
FieldType.ExpiryDate,
FieldType.ExpiryDateCheckDigit,
FieldType.Nationality,
FieldType.OptionalData2,
FieldType.OverallCheckDigit,
FieldType.Names
};

var actual = target.FieldTypes.ToList();

Assert.Equal(expected.Length, actual.Count());
Assert.Equal(expected, actual);
}
}
}
2 changes: 1 addition & 1 deletion MRZCodeParser.Tests/TD1MrzCodeLinesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public void FirstLineFieldsTest()
Assert.Equal("7", target.Fields[FieldType.DocumentNumberCheckDigit].Value);
Assert.Equal("", target.Fields[FieldType.OptionalData1].Value);
}

[Fact]
public void SecondLineFieldsTest()
{
Expand Down
3 changes: 2 additions & 1 deletion MRZCodeParser/CodeType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public enum CodeType
TD2,
TD3,
MRVA,
MRVB
MRVB,
TD1_LONG_DOC_NUMBER
}
}
8 changes: 7 additions & 1 deletion MRZCodeParser/CodeTypeDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ internal class CodeTypeDetector
{
private readonly IEnumerable<string> lines;

/// <summary>
/// Countries that use TD1 with long document number (30 characters).
/// </summary>
private readonly IEnumerable<string> Countries_LongDocNumber = new List<string> { "BEL" };

internal CodeTypeDetector(IEnumerable<string> lines)
{
this.lines = lines;
Expand All @@ -15,7 +20,8 @@ internal CodeTypeDetector(IEnumerable<string> lines)
internal CodeType DetectType()
{
CodeType type = lines.Count() == 3 && lines.First().Length == 30
? CodeType.TD1
? Countries_LongDocNumber.Contains(lines.First().Substring(2,3))
? CodeType.TD1_LONG_DOC_NUMBER : CodeType.TD1
: lines.First().Length == 44 && lines.Count() == 2
? lines.First()[0] == 'P'
? CodeType.TD3
Expand Down
4 changes: 2 additions & 2 deletions MRZCodeParser/CodeTypes/TD1FirstLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ namespace MRZCodeParser.CodeTypes
internal class TD1FirstLine : MrzLine
{
internal TD1FirstLine(string value) : base(value)
{
}
{ }

protected override string Pattern => "([A|C|I][A-Z0-9<]{1})([A-Z<]{3})([A-Z0-9<]{9})([0-9]{1})([A-Z0-9<]{15})";


internal override IEnumerable<FieldType> FieldTypes => new[]
{
FieldType.DocumentType,
Expand Down
22 changes: 22 additions & 0 deletions MRZCodeParser/CodeTypes/TD1FirstLineLongDocument.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Collections.Generic;

namespace MRZCodeParser.CodeTypes
{
internal class TD1FirstLineLongDocument : MrzLine
{
internal TD1FirstLineLongDocument(string value) : base(value)
{ }

protected override string Pattern => "([A|C|I][A-Z0-9<]{1})([A-Z<]{3})([A-Z0-9<]{13})([0-9]{1})([A-Z0-9<]{11})";


internal override IEnumerable<FieldType> FieldTypes => new[]
{
FieldType.DocumentType,
FieldType.CountryCode,
FieldType.DocumentNumber,
FieldType.DocumentNumberCheckDigit,
FieldType.OptionalData1
};
}
}
21 changes: 21 additions & 0 deletions MRZCodeParser/CodeTypes/TD1LongDocumentMrzCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Linq;

namespace MRZCodeParser.CodeTypes
{
internal class TD1LongDocumentMrzCode : MrzCode
{
internal TD1LongDocumentMrzCode(IEnumerable<string> lines) : base(lines)
{
}

public override CodeType Type => CodeType.TD1;

public override IEnumerable<MrzLine> Lines => new MrzLine[]
{
new TD1FirstLineLongDocument(RawLines.First()),
new TD1SecondLine(RawLines.ElementAt(1)),
new TD1ThirdLine(RawLines.Last())
};
}
}
3 changes: 2 additions & 1 deletion MRZCodeParser/DocumentType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum DocumentType
C,
I,
P,
V
V,
ID
}
}
1 change: 1 addition & 0 deletions MRZCodeParser/FieldType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum FieldType
{
DocumentType,
CountryCode,
[ReplaceHelper("")]
DocumentNumber,
DocumentNumberCheckDigit,
OptionalData1,
Expand Down
6 changes: 3 additions & 3 deletions MRZCodeParser/MRZCodeParser.csproj
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.1;netcoreapp3.1</TargetFrameworks>
<TargetFrameworks>netstandard2.1;net9.0</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageVersion>0.4.1</PackageVersion>
<PackageVersion>0.4.2</PackageVersion>
<Authors>snifter</Authors>
<AssemblyVersion>0.4.1</AssemblyVersion>
<AssemblyVersion>0.4.2</AssemblyVersion>
<Title>MRZCodeParser</Title>
<PackageProjectUrl>https://github.com/snifter/MRZCode.NET</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/snifter/MRZCode.NET/blob/master/LICENSE</PackageLicenseUrl>
Expand Down
1 change: 1 addition & 0 deletions MRZCodeParser/MrzCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public static MrzCode Parse(string code)
CodeType.TD3 => new TD3MrzCode(lines),
CodeType.MRVA => new MRVAMrzCode(lines),
CodeType.MRVB => new MRVBMrzCode(lines),
CodeType.TD1_LONG_DOC_NUMBER => new TD1LongDocumentMrzCode(lines),
_ => new UnknownMrzCode(lines)
};
}
Expand Down
4 changes: 2 additions & 2 deletions MRZCodeParser/MrzLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ public FieldsCollection Fields
{
fields.Add(new Field(
FieldTypes.ElementAt(i),
new ValueCleaner(match.Groups[i + 1].Value).Clean()));
new ValueCleaner(match.Groups[i + 1].Value).Clean(FieldTypes.ElementAt(i))));
}

return new FieldsCollection(fields);
}
}

protected abstract string Pattern { get; }
protected abstract string Pattern { get;}

internal abstract IEnumerable<FieldType> FieldTypes { get; }

Expand Down
28 changes: 28 additions & 0 deletions MRZCodeParser/ReplaceHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace MRZCodeParser
{
[AttributeUsage(AttributeTargets.Field)]
internal class ReplaceHelper :Attribute
{
public string Simple { get; set; } = " ";
public string Double { get; set; } = ", ";

public ReplaceHelper()
{ }

public ReplaceHelper(string simpleReplaceText)
{
Simple = simpleReplaceText;
Double = ", ";
}

public ReplaceHelper(string simpleReplaceText, string doubleReplaceText)
{
Simple = simpleReplaceText;
Double = doubleReplaceText;
}
}
}
20 changes: 18 additions & 2 deletions MRZCodeParser/ValueCleaner.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
using System;
using System.Linq;
using System.Reflection;

namespace MRZCodeParser
{
internal class ValueCleaner
Expand All @@ -12,8 +16,20 @@ internal ValueCleaner(string value)
internal string Clean()
{
return value.TrimEnd('<')
.Replace("<<", ", ")
.Replace("<", " ");
.Replace("<<", ", ")
.Replace("<", " ");
}

internal string Clean(FieldType f)
{
var member = typeof(FieldType).GetMember(f.ToString()).FirstOrDefault();
var s_replacer = member?.GetCustomAttribute<ReplaceHelper>() ?? new ReplaceHelper(" ", ", ");

var t_val = value.TrimEnd('<')
.Replace("<<", s_replacer.Double)
.Replace("<", s_replacer.Simple);

return t_val;
}
}
}