Skip to content

Commit

Permalink
better parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanstapel committed Jul 22, 2023
1 parent b465d8d commit a082fdb
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 37 deletions.
5 changes: 3 additions & 2 deletions Demo/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
using IFTSTAParser;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -28,10 +29,10 @@ class Application
internal void run()
{
string path = @"..\..\..\sample.txt";
List<IFTSTAConsigment> consigments = IFTSTAParser.Load(path);
IFTSTADocument doc = IFTSTAParser.Load(path);

string data = System.IO.File.ReadAllText(path);
List<IFTSTAConsigment> consigments2 = IFTSTAParser.LoadFromString(data);
IFTSTADocument doc2 = IFTSTAParser.LoadFromString(data);
}
}
}
42 changes: 42 additions & 0 deletions IFTSTAParser/EDIDataElement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
using System;
using System.Collections.Generic;
using System.Text;

namespace IFTSTAParser
{
public class EDIDataElement
{
public List<string> Values { get; set; } = new List<string>();


public string GetValue(int index)
{
if (index >= this.Values.Count)
{
return null;
}
else
{
return this.Values[index];
}
} // !GetValue()
}
}
9 changes: 5 additions & 4 deletions IFTSTAParser/EDISegment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
using IFTSTAParser;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -26,20 +27,20 @@ namespace s2industries.IFTSTA
public class EDISegment
{
public string Qualififier { get; private set; }
public List<string> DataElements { get; set; }
public List<EDIDataElement> DataElements { get; set; }


public EDISegment(string qualifier, List<string> dataElements = null)
public EDISegment(string qualifier, List<EDIDataElement> dataElements = null)
{
this.Qualififier = qualifier;
this.DataElements = dataElements;
}

public string GetElement(int index, string defaultValue = "")
public EDIDataElement GetElement(int index)
{
if (index >= this.DataElements.Count)
{
return defaultValue;
return null;
}
else
{
Expand Down
31 changes: 31 additions & 0 deletions IFTSTAParser/IFTSTADocument.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
using s2industries.IFTSTA;
using System;
using System.Collections.Generic;
using System.Text;

namespace IFTSTAParser
{
public class IFTSTADocument
{
public DateTime? CreationDate { get; set; }
public List<IFTSTAConsigment> Consigments { get; set; } = new List<IFTSTAConsigment>();
}
}
139 changes: 110 additions & 29 deletions IFTSTAParser/IFTSTAParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
using System.Text;
using System.IO;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Net.Http.Headers;
using IFTSTAParser;

namespace s2industries.IFTSTA
{
Expand All @@ -31,7 +34,7 @@ public class IFTSTAParser
private const string STANDARD_DATEFORMAT = "yyyyMMddHHmm";
private const string SHORT_DATEFORMAT = "yyyyMMdd";

public static List<IFTSTAConsigment> Load(string path)
public static IFTSTADocument Load(string path)
{
if (!System.IO.File.Exists(path))
{
Expand All @@ -46,7 +49,7 @@ public static List<IFTSTAConsigment> Load(string path)
} // !Load()


public static List<IFTSTAConsigment> LoadFromString(string data)
public static IFTSTADocument LoadFromString(string data)
{
// clean data
data = data.Replace("\r", "").Replace("\n", "");
Expand All @@ -57,44 +60,85 @@ public static List<IFTSTAConsigment> LoadFromString(string data)
data = data.Substring(data.IndexOf(HEADER) + HEADER.Length).Trim();
}

List<IFTSTAConsigment> retval = new List<IFTSTAConsigment>();
List<IFTSTAConsigment> consigments = new List<IFTSTAConsigment>();

// iterate through segments, find CNI elements and evaluate consecutive segments
List<EDISegment> rawSegments = _SplitIntoSegments(data);
List<EDISegment> headerSegments = _GetHeaderSegments(rawSegments);
List<EDISegment> dataSegments = _GetDataSegments(rawSegments);
List<List<EDISegment>> transportStatusSegments = _SplitIntoTransportStatusSegments(rawSegments);

foreach(List<EDISegment> segments in transportStatusSegments)
EDISegment unbSegment = headerSegments.FirstOrDefault(s => s.Qualififier == "UNB");
DateTime? creationDate = null;
if (unbSegment != null)
{
IFTSTAConsigment consigment = new IFTSTAConsigment();
// data:
// element 0: SYNTAX IDENTIFIER
// element 1: INTERCHANGE SENDER
// element 2: INTERCHANGE RECIPIENT
// element 3: DATE AND TIME OF PREPARATION

string date = unbSegment.GetElement(3).GetValue(0);
string time = unbSegment.GetElement(3).GetValue(1);

if ((date.Length == 6) && (time.Length == 4))
{
creationDate = new DateTime(
2000 + Int32.Parse(date.Substring(0, 2)),
Int32.Parse(date.Substring(2, 2)),
Int32.Parse(date.Substring(4, 2)),
Int32.Parse(time.Substring(0, 2)),
Int32.Parse(time.Substring(2, 2)),
0
);
}
else if ((date.Length == 8) && (time.Length == 4))
{
creationDate = new DateTime(
Int32.Parse(date.Substring(0, 4)),
Int32.Parse(date.Substring(4, 2)),
Int32.Parse(date.Substring(6, 2)),
Int32.Parse(time.Substring(0, 2)),
Int32.Parse(time.Substring(2, 2)),
0
);
}
}

// analyze data
foreach (List<EDISegment> segments in transportStatusSegments)
{
IFTSTAConsigment consigment = new IFTSTAConsigment();

foreach(EDISegment segment in segments)
{
switch (segment.Qualififier.Trim().ToUpper())
{
case "CNI": // consigment
{
consigment.No = segment.GetElement(1);
segment.GetElement(0).GetValue(0); // Serial number differentiating each separate consignment included in the status report.
consigment.No = segment.GetElement(1).GetValue(0); // Consignor's shipment reference number
break;
}
case "GIN": // global identifier
{
consigment.GlobalIdentifier = segment.GetElement(1);
consigment.GlobalIdentifier = segment.GetElement(1).GetValue(0);
break;
}
case "DTM": // datetime
{
string _dateformat = STANDARD_DATEFORMAT; // qualifier 203 = default
if (segment.GetElement(2) == "102")
if (segment.GetElement(0).GetValue(2) == "102")
{
_dateformat = SHORT_DATEFORMAT;
}


if (segment.GetElement(0) == "334")
if (segment.GetElement(0).GetValue(0) == "334")
{
string s = segment.GetElement(1);
string s = segment.GetElement(0).GetValue(1);

consigment.StatusChangeDate = DateTime.ParseExact(segment.GetElement(1),
consigment.StatusChangeDate = DateTime.ParseExact(segment.GetElement(0).GetValue(1),
_dateformat,
CultureInfo.InvariantCulture,
DateTimeStyles.None);
Expand All @@ -105,25 +149,14 @@ public static List<IFTSTAConsigment> LoadFromString(string data)
{
if (segment.DataElements.Count == 2)
{
consigment.Status = segment.GetElement(1);
consigment.Status = segment.GetElement(1).GetValue(0);
}
break;
}
case "FTX": // free text
{
// join free text into one string
consigment.AdditionalInfo = "";
for (int k = 1; k < segment.DataElements.Count; k++)
{
if (!String.IsNullOrEmpty(segment.GetElement(k)))
{
if (consigment.AdditionalInfo.Length > 0)
{
consigment.AdditionalInfo += ", ";
}
consigment.AdditionalInfo += segment.GetElement(k);
}
} // !for(k)
consigment.AdditionalInfo = segment.GetElement(3)?.GetValue(0);
break;
}
default:
Expand All @@ -133,10 +166,14 @@ public static List<IFTSTAConsigment> LoadFromString(string data)
}
} // !for(i)

retval.Add(consigment);
consigments.Add(consigment);
} // !foreach(transportStatusSegments)

return retval;
return new IFTSTADocument()
{
CreationDate = creationDate,
Consigments = consigments
};
} // !LoadFromString()


Expand All @@ -154,15 +191,59 @@ private static List<EDISegment> _SplitIntoSegments(string rawData)

int pos = element.IndexOf("+");
string token = element.Substring(0, pos);
List<string> data = element.Substring(pos + 1).Split(new char[] { ':', '+' }).ToList();

retval.Add(new EDISegment(token, data));
List<EDIDataElement> dataElements = new List<EDIDataElement>();
foreach (string data in element.Substring(pos + 1).Split(new char[] { '+' }))
{
List<string> _values = data.Split(new char[] { ':' }).ToList();
dataElements.Add(new EDIDataElement()
{
Values = _values
});
}
retval.Add(new EDISegment(token, dataElements));
}

return retval;
} // !_SplitIntoSegments()


private static List<EDISegment> _GetHeaderSegments(List<EDISegment> rawSegments)
{
List<EDISegment> retval = new List<EDISegment>();
foreach(EDISegment segment in rawSegments)
{
if (segment.Qualififier == "BGM")
{
break;
}
retval.Add(segment);
}

return retval;
} // !_GetHeaderSegments()


private static List<EDISegment> _GetDataSegments(List<EDISegment> rawSegments)
{
List<EDISegment> retval = new List<EDISegment>();
bool bgmAlreadyFound = false;
foreach (EDISegment segment in rawSegments)
{
if (segment.Qualififier == "BGM")
{
bgmAlreadyFound = true;
}

if (bgmAlreadyFound)
{
retval.Add(segment);
}
}

return retval;
} // !_GetDataSegments()


private static List<List<EDISegment>> _SplitIntoTransportStatusSegments(List<EDISegment> rawSegments)
{
List<List<EDISegment>> retval = new List<List<EDISegment>>();
Expand Down
4 changes: 2 additions & 2 deletions IFTSTAParser/IFTSTAParser.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyVersion>1.2.0.0</AssemblyVersion>
<Version>1.2.0</Version>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<Version>2.0.0</Version>
<Description>Parse EDIFACT IFTSTA files easily with C#</Description>
<Title>IFTSTA parser for .net</Title>
<Copyright>Stephan Stapel</Copyright>
Expand Down

0 comments on commit a082fdb

Please sign in to comment.