public EdiStream(Stream ediStream) { _streamReader = new StreamReader(ediStream); _interchangeContext = new InterchangeContext(_streamReader); ediStream.Position = 0; _streamReader.DiscardBufferedData(); }
/// <summary> /// Initializes a new instance of the <see cref="SegmentContext"/> class. /// </summary> /// <param name="ediSegment">The edi segment.</param> /// <param name="interchangeContext">The interchange context.</param> /// <param name="format">The edi format.</param> public SegmentContext(string ediSegment, InterchangeContext interchangeContext, EdiFormats format) { if (string.IsNullOrEmpty(ediSegment)) throw new ArgumentNullException("ediSegment"); if (interchangeContext == null) throw new ArgumentNullException("interchangeContext"); // Blank segments shouldn't have gone that far var splitted = ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(), StringSplitOptions.None); if (splitted.Length < 2) throw new Exception("Segment is blank."); Name = splitted[0]; Value = null; ParentId = null; // UNA segments don't have values if (ediSegment.StartsWith(EdiSegments.Una)) { Name = EdiSegments.Una; } // Handle blank segments, e.g. BHT+' if (format == EdiFormats.Hipaa) { var splittedElement = splitted[1].Split(interchangeContext.ComponentDataElementSeparator.ToCharArray(), StringSplitOptions.None); Value = splittedElement[0]; if (ediSegment.StartsWith(EdiSegments.Hl) && !string.IsNullOrEmpty(splitted[2])) ParentId = splitted[2]; } }
public EdiStream(Stream ediStream, string definitionsAssemblyName = null) { _streamReader = new StreamReader(ediStream); _interchangeContext = new InterchangeContext(_streamReader, definitionsAssemblyName); ediStream.Position = 0; _streamReader.DiscardBufferedData(); }
/// <summary> /// Lexical analysis of the message /// </summary> /// <param name="segments">The edi segments.</param> /// <param name="envelopes">The edi envelopes.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns>The pased edi message.</returns> public static Message Analyze(List<string> segments, List<string> envelopes, InterchangeContext interchangeContext) { // Read the message context from the envelope headers var messageContext = new MessageContext(envelopes, interchangeContext); // This will read through the grammar and will build an xml // Get the grammar from the context var messageGrammar = ParseTree.LoadFrom(messageContext.SystemType, pt => pt.IsMessage || pt.IsGroup || pt.IsChoice || pt.IsAll || pt.IsLoopOfLoops); // Set the position in the grammar var lastSegment = messageGrammar.Children.First(); // Create the xml root of the parsed edi var ediXml = ToXml(messageGrammar, interchangeContext); // Set the position in the xml var lastXElement = ediXml; // Iterate trough the segment lines foreach (var segment in segments) { try { // Find the next segment grammar var currSeg = lastSegment.FindNextSegment(new SegmentFullName(segment, interchangeContext, messageContext.Format)); // Build the segment hierarchy // This will move to the required level up for the segment parents: groups, choices, all and loop of loops, // until another group is reached. var segmentTree = GetSegmentTree(currSeg, lastSegment); // Intersect the grammar with the parsed xml. // The new chunk will be attched to this intersection point. lastXElement = lastXElement.AncestorsAndSelf().Last(xe => xe.Name.LocalName == segmentTree.First().Parent.Name); // Attach each bit foreach (var parseTree in segmentTree) { // Parse if a segment, otherwise convert to xml var element = parseTree.IsSegment ? SegmentParser.ParseLine(parseTree, segment, interchangeContext) : ToXml(parseTree, interchangeContext); // Attach to the xml lastXElement.Add(element); // Set the last attached as the attachment point as we iterate from the top parent to the bottom segment lastXElement = element; } // Reset the position in the grammar lastSegment = currSeg; } catch (Exception ex) { throw new ParserException("Failed at line: " + segment, ex); } } return new Message(ediXml, messageContext); }
/// <summary> /// Initializes a new instance of the <see cref="MessageContext"/> class. /// </summary> /// <param name="envelopes"> /// From interchange headers /// </param> /// <param name="interchangeContext"> /// The interchange context /// </param> public MessageContext(IEnumerable<string> envelopes, InterchangeContext interchangeContext) { var context = ToContext(envelopes, interchangeContext); Format = context.Item4; Version = context.Item2; Tag = context.Item1; Origin = context.Item3; _systemType = ToSystemType(Format, Version, Tag, Origin); }
/// <summary> /// Initializes a new instance of the <see cref="XmlLexer"/> class. /// </summary> /// <param name="xmlEdi"> /// Edi as Xml /// </param> /// <param name="context"> /// The interchange context /// </param> public ToEdiLexer(XElement xmlEdi, InterchangeContext context) : base(xmlEdi) { InterchangeContext = new InterchangeContext(EdiFormats.Edifact); // Merge the custom context to the default InterchangeContext.Merge(context); // Make sure no same separator is used more than once if (!InterchangeContext.IsValid(EdiFormats.Edifact)) throw new ParserException("Invalid interchange context."); }
//----------------------------------------------------------------------------------------------------- public void SaveEdi(string filename, string segmentTerminator = null) { var interchangeContext = new InterchangeContext { SegmentTerminator = segmentTerminator, }; var parsedXml = _interchange.ToEdi(interchangeContext); using (TextWriter tw = File.CreateText(filename)) { tw.Write(string.Concat(parsedXml)); } }
/// <summary> /// Splits a segment line into composite data elements /// </summary> /// <param name="ediSegment">The segment line</param> /// <param name="interchangeContext">The interchange context containing the separators</param> /// <returns>The collection of composite data elements</returns> public static string[] GetEdiCompositeDataElements(string ediSegment, InterchangeContext interchangeContext) { if (string.IsNullOrEmpty(ediSegment)) throw new ArgumentNullException("ediSegment"); if (interchangeContext == null) throw new ArgumentNullException("interchangeContext"); // Handle escapes // Retains blank lines var result = !string.IsNullOrEmpty(interchangeContext.ReleaseIndicator) ? ediSegment.EscapeSplit(interchangeContext.ReleaseIndicator[0], interchangeContext.DataElementSeparator[0], StringSplitOptions.None) : ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(), StringSplitOptions.None); // Skip the segment name return result.Skip(1).ToArray(); }
/// <summary> /// Gets the segment name from a segment line. /// </summary> /// <param name="ediSegment">The segment line.</param> /// <param name="interchangeContext">The interchange context containing the separators.</param> /// <returns>The segment name.</returns> public static string GetSegmentName(string ediSegment, InterchangeContext interchangeContext) { if (string.IsNullOrEmpty(ediSegment)) { throw new ArgumentNullException("ediSegment"); } if (interchangeContext == null) { throw new ArgumentNullException("interchangeContext"); } if (ediSegment.StartsWith(EdiSegments.Una)) { return(EdiSegments.Una); } return(ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(), StringSplitOptions.None)[0]); }
/// <summary> /// Parses segment xml /// </summary> /// <param name="segment">The segment xml.</param> /// <param name="parseTree">The segment grammar.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns>The parsed line.</returns> private static string Parse(XElement segment, ParseTree parseTree, InterchangeContext interchangeContext) { // Start with the segment name // BHT+, etc. var result = parseTree.EdiName + interchangeContext.DataElementSeparator; // For all elements in the parse tree - append to the segment name to build the edi string // BHT+88, etc. // Parse according to the parse tree foreach (var element in parseTree.Children) { var currentElement = element; // Find the matching elemtns by name // If > 1 found, then there are repetitions var matchingElements = segment.Elements().Where(e => e.Name.LocalName == currentElement.Name); string line = string.Empty; foreach (var matchingElement in matchingElements) { // Parse the element and split the repetitions line = line + ParseElement(matchingElement, element, interchangeContext) + interchangeContext.RepetitionSeparator; } // Make sure the trailing repetitions separator is removed // To avoid stripping the default repetitions separator in case there is something like 88:55:: // The result should be 88:55:, therefore we can't just strip the trailing separators line = line.EndsWith(interchangeContext.RepetitionSeparator + interchangeContext.RepetitionSeparator) ? line.Substring(0, line.Length - 1) : line.TrimEnd(interchangeContext.RepetitionSeparator.ToCharArray()); // Add to the segment string // BHT+88:55:+ result = result + line + interchangeContext.DataElementSeparator; } // Remove the trailing data element separator // BHT+88:55: result = CleanupTrailingSeparators(result, interchangeContext.DataElementSeparator, interchangeContext); //result.TrimEnd(interchangeContext.DataElementSeparator.ToCharArray()); // Append the segment terminator // BHT+88:55:' result = result + interchangeContext.SegmentTerminator; return(result); }
/// <summary> /// Converts EDI interchange headers into message context. /// </summary> /// <param name="envelopes">The interchange headers.</param> /// <param name="interchangeContext">The interchange context.</param> private void ToContextX12(IEnumerable <string> envelopes, InterchangeContext interchangeContext) { var enumerable = envelopes as List <string> ?? envelopes.ToList(); string version; string origin; string format; string tag; try { var gs = enumerable.Single(es => es.StartsWith(EdiSegments.Gs)); var ediCompositeDataElementsGs = EdiHelper.GetEdiCompositeDataElements(gs, interchangeContext); version = ediCompositeDataElementsGs[7].Substring(0, 6); origin = ediCompositeDataElementsGs[7].Count() >= 10 ? ediCompositeDataElementsGs[7].Substring(6, 4) : null; format = HipaaHelper.IsHipaa(version + origin) ? EdiFormats.Hipaa.ToString() : EdiFormats.X12.ToString(); if (!HipaaHelper.IsHipaa(version + origin)) { origin = null; } } catch (Exception ex) { throw new ParserException("Can't parse GS segment.", ex); } try { var st = enumerable.Single(es => es.StartsWith(EdiSegments.St)); var ediCompositeDataElementsSt = EdiHelper.GetEdiCompositeDataElements(st, interchangeContext); tag = ediCompositeDataElementsSt[0]; } catch (Exception ex) { throw new ParserException("Can't parse ST segment.", ex); } Tag = tag; Version = version; Origin = origin; Format = ToFormat(format); }
/// <summary> /// Converts EDI interchange headers into message context. /// </summary> /// <param name="envelopes">The interchange headers.</param> /// <param name="interchangeContext">The interchange context.</param> private void ToContextEdifact(IEnumerable <string> envelopes, InterchangeContext interchangeContext) { try { var unh = envelopes.Single(es => es.StartsWith(EdiSegments.Unh)); var ediCompositeDataElements = EdiHelper.GetEdiCompositeDataElements(unh, interchangeContext); var ediDataElements = EdiHelper.GetEdiComponentDataElements(ediCompositeDataElements[1], interchangeContext); Tag = ediDataElements[0]; Version = ediDataElements[1] + ediDataElements[2]; Origin = null; Format = EdiFormats.Edifact; } catch (Exception ex) { throw new ParserException("Can't parse UNH segment.", ex); } }
/// <summary> /// Escapes a string value to be valid in xml /// </summary> /// <param name="dataElement">The xml element.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns>The valid xml value.</returns> private static string GetValidDataElementValue(XElement dataElement, InterchangeContext interchangeContext) { var dataElementValue = dataElement == null ? string.Empty : dataElement.Value; // Secure non valid XML symbols // Currently only & if (dataElementValue.Contains("&")) { var securityElement = SecurityElement.FromString("<parse>" + dataElementValue + "</parse>"); if (securityElement == null) { throw new ParserException("Can't parse value " + dataElementValue); } dataElementValue = securityElement.Text; } // Escape all terminator symbols return(interchangeContext.EscapeLine(dataElementValue)); }
/// <summary> /// Converts EDI interchange headers into message context. /// </summary> /// <param name="envelopes">The interchange headers.</param> /// <param name="interchangeContext">The interchange context.</param> private void ToContext(IEnumerable <string> envelopes, InterchangeContext interchangeContext) { if (envelopes == null) { throw new ArgumentNullException("envelopes"); } switch (interchangeContext.Format) { case EdiFormats.Edifact: ToContextEdifact(envelopes, interchangeContext); break; case EdiFormats.X12: ToContextX12(envelopes, interchangeContext); break; default: throw new Exception(string.Format("Unsupported message format = {0}", interchangeContext.Format)); } }
/// <summary> /// Initializes a new instance of the <see cref="SegmentContext"/> class. /// </summary> /// <param name="ediSegment">The edi segment.</param> /// <param name="interchangeContext">The interchange context.</param> /// <param name="format">The edi format.</param> public SegmentContext(string ediSegment, InterchangeContext interchangeContext, EdiFormats format) { if (string.IsNullOrEmpty(ediSegment)) { throw new ArgumentNullException("ediSegment"); } if (interchangeContext == null) { throw new ArgumentNullException("interchangeContext"); } // Blank segments shouldn't have gone that far var splitted = ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(), StringSplitOptions.None); if (splitted.Length < 2) { throw new Exception("Segment is blank."); } Name = splitted[0]; Value = null; ParentId = null; // UNA segments don't have values if (ediSegment.StartsWith(EdiSegments.Una)) { Name = EdiSegments.Una; } // Handle blank segments, e.g. BHT+' if (format == EdiFormats.Hipaa && !splitted[1].Contains(interchangeContext.ComponentDataElementSeparator)) { Value = splitted[1]; if (ediSegment.StartsWith(EdiSegments.Hl) && !string.IsNullOrEmpty(splitted[2])) { ParentId = splitted[2]; } } }
/// <summary> /// Splits a segment line into composite data elements /// </summary> /// <param name="ediSegment">The segment line</param> /// <param name="interchangeContext">The interchange context containing the separators</param> /// <returns>The collection of composite data elements</returns> public static string[] GetEdiCompositeDataElements(string ediSegment, InterchangeContext interchangeContext) { if (string.IsNullOrEmpty(ediSegment)) { throw new ArgumentNullException("ediSegment"); } if (interchangeContext == null) { throw new ArgumentNullException("interchangeContext"); } // Handle escapes // Retains blank lines var result = !string.IsNullOrEmpty(interchangeContext.ReleaseIndicator) ? ediSegment.EscapeSplit(interchangeContext.ReleaseIndicator[0], interchangeContext.DataElementSeparator[0], StringSplitOptions.None) : ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(), StringSplitOptions.None); // Skip the segment name return(result.Skip(1).ToArray()); }
/// <summary> /// Splits an Edi messages into a collection of segments /// </summary> /// <param name="contents">The edi message</param> /// <param name="interchangeContext">The interchange context containing the separators</param> /// <returns>The collection of segments</returns> public static string[] GetEdiSegments(string contents, InterchangeContext interchangeContext) { if (contents == null) throw new ArgumentNullException("contents"); if (interchangeContext == null) throw new ArgumentNullException("interchangeContext"); // Handle carriage return\new line separator if (interchangeContext.SegmentTerminator != Environment.NewLine) contents = contents.Replace(Environment.NewLine, string.Empty); // Handle escape segment separator // Removes blank lines var result = !string.IsNullOrEmpty(interchangeContext.ReleaseIndicator) ? contents.EscapeSplit(interchangeContext.ReleaseIndicator[0], interchangeContext.SegmentTerminator[0], StringSplitOptions.RemoveEmptyEntries) : contents.Split(interchangeContext.SegmentTerminator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); result = (from r in result select r.Trim()).ToArray(); return result; }
public void TestToEdiWithInvalidContext() { // ARRANGE const string sample = "EdiFabric.Tests.Xml.X12_810_00204.xml"; var interchangeContext = new InterchangeContext { DataElementSeparator = "*", ComponentDataElementSeparator = "*" }; // ACT try { Interchange.LoadFrom( XElement.Load(Assembly.GetExecutingAssembly().GetManifestResourceStream(sample))).ToEdi(interchangeContext); } catch (Exception ex) { // ASSERT Assert.IsInstanceOfType(ex, typeof(ParserException)); Assert.IsTrue(ex.Message.StartsWith("Invalid interchange context")); } }
/// <summary> /// Converts edi interchange headers into message context. /// </summary> /// <param name="envelopes">The interchange headers.</param> /// <param name="interchangeContext">The interchange context.</param> private void ToContext(IEnumerable<string> envelopes, InterchangeContext interchangeContext) { if (envelopes == null) throw new ArgumentNullException("envelopes"); switch (interchangeContext.Format) { case EdiFormats.Edifact: ToContextEdifact(envelopes, interchangeContext); break; case EdiFormats.X12: ToContextX12(envelopes, interchangeContext); break; default: throw new Exception(string.Format("Unsupported message format = {0}", interchangeContext.Format)); } }
/// <summary> /// Parses data element xml /// </summary> /// <param name="dataElement">The dataelement xml.</param> /// <param name="parseTree">The dataelement grammar.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns>The parsed line.</returns> private static string ParseElement(XElement dataElement, ParseTree parseTree, InterchangeContext interchangeContext) { if (parseTree.IsComplex) { var line = string.Empty; // If complex data element, build a line from all the children in the parse tree foreach (var element in parseTree.Children) { // Can be only one match // If the XML contains data element that is not defined in the class, it will be skipped // This way only know data elements will be parsed var matchingElement = dataElement.Elements().SingleOrDefault(e => e.Name.LocalName == element.Name); // Build the line line = line + GetValidDataElementValue(matchingElement, interchangeContext) + interchangeContext.ComponentDataElementSeparator; } // Remove the trailing composite terminator return(CleanupTrailingSeparators(line, interchangeContext.ComponentDataElementSeparator, interchangeContext)); //return line.TrimEnd(interchangeContext.ComponentDataElementSeparator.ToCharArray()); } // If simple just escape the value return(GetValidDataElementValue(dataElement, interchangeContext)); }
/// <summary> /// Gets the segment name from a segment line /// </summary> /// <param name="ediSegment">The segment line</param> /// <param name="interchangeContext">The interchange context containing the separators</param> /// <returns>The segment name</returns> public static string GetSegmentName(string ediSegment, InterchangeContext interchangeContext) { if (string.IsNullOrEmpty(ediSegment)) throw new ArgumentNullException("ediSegment"); if (interchangeContext == null) throw new ArgumentNullException("interchangeContext"); return ediSegment.StartsWith(EdiSegments.Una) ? EdiSegments.Una : ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(), StringSplitOptions.None)[0]; }
/// <summary> /// Converts the interchange to edi message. /// </summary> /// <param name="context"> /// The interchange context. /// This sets the non format default separators. /// </param> /// <returns> /// The edi message. /// </returns> public abstract List<string> ToEdi(InterchangeContext context = null);
public static string[] GetRepetitions(string value, InterchangeContext interchangeContext) { if (!string.IsNullOrEmpty(interchangeContext.ReleaseIndicator)) return value.EscapeSplit(interchangeContext.ReleaseIndicator[0], interchangeContext.RepetitionSeparator[0], StringSplitOptions.None); return value.Split(interchangeContext.RepetitionSeparator.ToCharArray()); }
/// <summary> /// Convert a parse tree to a root XML node. /// Without the hierarchy, only the name. /// </summary> /// <param name="parseTree">The parse tree.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns>A XML node.</returns> private static XElement ToXml(ParseTree parseTree, InterchangeContext interchangeContext) { XNamespace ns = interchangeContext.TargetNamespace; return(new XElement(ns + parseTree.Name)); }
/// <summary> /// Initializes a new instance of the <see cref="InterchangeLexer"/> class. /// </summary> /// <param name="ediString"> /// The edi message. /// </param> /// <param name="definitionsAssemblyName">The assembly name of the project containing the classes and xsd.</param> protected InterchangeLexer(string ediString, string definitionsAssemblyName) { _ediString = ediString; InterchangeContext = new InterchangeContext(ediString, definitionsAssemblyName); }
public void TestToEdiWithInvalidContext() { // ARRANGE const string sample = "EdiFabric.Tests.Xml.Edifact_INVOIC_D00A_EscapedSegmentTerminator.xml"; var interchangeContext = new InterchangeContext { DataElementSeparator = "|", ComponentDataElementSeparator = "|" }; // ACT try { Interchange.LoadFrom( XElement.Load(Assembly.GetExecutingAssembly().GetManifestResourceStream(sample))).ToEdi(interchangeContext); } catch (Exception ex) { // ASSERT Assert.IsInstanceOfType(ex, typeof(ParserException)); Assert.IsTrue(ex.Message.StartsWith("Invalid interchange context")); } }
/// <summary> /// Initializes a new instance of the <see cref="MessageContext"/> class. /// </summary> /// <param name="message"> /// From xml /// </param> /// <param name="interchangeContext"> /// The interchange context /// </param> public MessageContext(XElement message, InterchangeContext interchangeContext) { ToContext(message); _systemType = ToSystemType(Format, Version, Tag, Origin, interchangeContext.DefinitionsAssemblyName); }
/// <summary> /// Converts edi interchange headers into message context. /// </summary> /// <param name="envelopes">The interchange headers.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns> /// The message context. /// </returns> private Tuple<string, string, string, EdiFormats> ToContextX12(IEnumerable<string> envelopes, InterchangeContext interchangeContext) { var enumerable = envelopes as List<string> ?? envelopes.ToList(); string version; string origin; string format; string tag; try { var gs = enumerable.Single(es => es.StartsWith(EdiSegments.Gs)); var ediCompositeDataElementsGs = EdiHelper.GetEdiCompositeDataElements(gs, interchangeContext); version = ediCompositeDataElementsGs[7].Substring(0, 6); origin = ediCompositeDataElementsGs[7].Count() >= 10 ? ediCompositeDataElementsGs[7].Substring(6, 4) : null; format = HipaaHelper.IsHipaa(version + origin) ? EdiFormats.Hipaa.ToString() : EdiFormats.X12.ToString(); if (!HipaaHelper.IsHipaa(version + origin)) { origin = null; } } catch(Exception ex) { throw new ParserException("Can't parse GS segment.", ex); } try { var st = enumerable.Single(es => es.StartsWith(EdiSegments.St)); var ediCompositeDataElementsSt = EdiHelper.GetEdiCompositeDataElements(st, interchangeContext); tag = ediCompositeDataElementsSt[0]; } catch (Exception ex) { throw new ParserException("Can't parse ST segment.", ex); } return new Tuple<string, string, string, EdiFormats>(tag, version, origin, ToFormat(format)); }
/// <summary> /// Converts edi interchange headers into message context. /// </summary> /// <param name="envelopes">The interchange headers.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns> /// The message context. /// </returns> private Tuple<string, string, string, EdiFormats> ToContextEdifact(IEnumerable<string> envelopes, InterchangeContext interchangeContext) { try { var unh = envelopes.Single(es => es.StartsWith(EdiSegments.Unh)); var ediCompositeDataElements = EdiHelper.GetEdiCompositeDataElements(unh, interchangeContext); var ediDataElements = EdiHelper.GetEdiComponentDataElements(ediCompositeDataElements[1], interchangeContext); return new Tuple<string, string, string, EdiFormats>(ediDataElements[0], ediDataElements[1] + ediDataElements[2], null, EdiFormats.Edifact); } catch (Exception ex) { throw new ParserException("Can't parse UNH segment.", ex); } }
/// <summary> /// Converts edi interchange headers into message context. /// </summary> /// <param name="envelopes">The interchange headers.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns> /// The message context. /// </returns> private Tuple<string, string, string, EdiFormats> ToContext(IEnumerable<string> envelopes, InterchangeContext interchangeContext) { if (envelopes == null) throw new ArgumentNullException("envelopes"); switch (interchangeContext.Format) { case EdiFormats.Edifact: return ToContextEdifact(envelopes, interchangeContext); case EdiFormats.X12: return ToContextX12(envelopes, interchangeContext); } throw new Exception(string.Format("Unsupported message format = {0}", interchangeContext.Format)); }
private static string CleanupTrailingSeparators(string result, string separator, InterchangeContext interchangeContext) { while (result.EndsWith(separator)) { if (!string.IsNullOrEmpty(interchangeContext.ReleaseIndicator) && result.EndsWith(interchangeContext.ReleaseIndicator + separator)) { break; } result = result.Substring(0, result.Length - separator.Length); } return(result); }
/// <summary> /// Converts edi interchange headers into message context. /// </summary> /// <param name="envelopes">The interchange headers.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns> /// The message context. /// </returns> private Tuple <string, string, string, EdiFormats> ToContext(IEnumerable <string> envelopes, InterchangeContext interchangeContext) { if (envelopes == null) { throw new ArgumentNullException("envelopes"); } switch (interchangeContext.Format) { case EdiFormats.Edifact: return(ToContextEdifact(envelopes, interchangeContext)); case EdiFormats.X12: return(ToContextX12(envelopes, interchangeContext)); } throw new Exception(string.Format("Unsupported message format = {0}", interchangeContext.Format)); }
/// <summary> /// Lexical analysis of the message /// </summary> /// <param name="segments">The edi segments.</param> /// <param name="envelopes">The edi envelopes.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns>The pased edi message.</returns> public static Message Analyze(List <string> segments, List <string> envelopes, InterchangeContext interchangeContext) { // Read the message context from the envelope headers var messageContext = new MessageContext(envelopes, interchangeContext); // This will read through the grammar and will build an xml // Get the grammar from the context var messageGrammar = ParseTree.LoadFrom(messageContext.SystemType, pt => pt.IsMessage || pt.IsGroup || pt.IsChoice || pt.IsAll || pt.IsLoopOfLoops); // Set the position in the grammar var lastSegment = messageGrammar.Children.First(); // Create the xml root of the parsed edi var ediXml = ToXml(messageGrammar, interchangeContext); // Set the position in the xml var lastXElement = ediXml; // Iterate trough the segment lines foreach (var segment in segments) { try { // Find the next segment grammar var currSeg = lastSegment.FindNextSegment(new SegmentFullName(segment, interchangeContext, messageContext.Format)); // Build the segment hierarchy // This will move to the required level up for the segment parents: groups, choices, all and loop of loops, // until another group is reached. var segmentTree = GetSegmentTree(currSeg, lastSegment); // Intersect the grammar with the parsed xml. // The new chunk will be attched to this intersection point. lastXElement = lastXElement.AncestorsAndSelf().Last(xe => xe.Name.LocalName == segmentTree.First().Parent.Name); // Attach each bit foreach (var parseTree in segmentTree) { // Parse if a segment, otherwise convert to xml var element = parseTree.IsSegment ? SegmentParser.ParseLine(parseTree, segment, interchangeContext) : ToXml(parseTree, interchangeContext); // Attach to the xml lastXElement.Add(element); // Set the last attached as the attachment point as we iterate from the top parent to the bottom segment lastXElement = element; } // Reset the position in the grammar lastSegment = currSeg; } catch (Exception ex) { throw new ParserException("Failed at line: " + segment, ex); } } return(new Message(ediXml, messageContext)); }
public void TestToEdiWithSegmentList() { // ARRANGE const string sample = "EdiFabric.Tests.Xml.X12_810_00204_SegmentList.xml"; const string expectedResult = "EdiFabric.Tests.Edi.X12_810_00204.txt"; var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(expectedResult); Debug.Assert(stream != null, "stream != null"); var reader = new StreamReader(stream); var expectedEdi = new List<string>(); while (reader.Peek() >= 0) { expectedEdi.Add(reader.ReadLine()); } var interchangeContext = new InterchangeContext { RepetitionSeparator = "|" }; // ACT var parsedEdi = Interchange.LoadFrom(XElement.Load(Assembly.GetExecutingAssembly().GetManifestResourceStream(sample))).ToEdi(interchangeContext); // ASSERT Assert.AreEqual(expectedEdi.Count, parsedEdi.Count); for (int i = 0; i < parsedEdi.Count; i++) { Assert.IsTrue(parsedEdi[i] == expectedEdi[i]); } }
public void TestToEdiWithSegmentsComparisonAndNonDefaultSeparators() { // ARRANGE const string sample = "EdiFabric.Tests.Xml.Edifact_INVOIC_D00A.xml"; const string expectedResult = "EdiFabric.Tests.Edi.Edifact_INVOIC_D00A_NonDefaultSeparators.txt"; var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(expectedResult); Debug.Assert(stream != null, "stream != null"); var reader = new StreamReader(stream); var expectedEdi = new List<string>(); while (reader.Peek() >= 0) { expectedEdi.Add(reader.ReadLine()); } // ACT var interchangeContext = new InterchangeContext { DataElementSeparator = "|", SegmentTerminator = "'"}; var parsedEdi = Interchange.LoadFrom(XElement.Load(Assembly.GetExecutingAssembly().GetManifestResourceStream(sample))).ToEdi(interchangeContext); // ASSERT Assert.AreEqual(expectedEdi.Count, parsedEdi.Count); for (int i = 0; i < parsedEdi.Count; i++) { Assert.IsTrue(parsedEdi[i] == expectedEdi[i]); } }
//----------------------------------------------------------------------------------------------------- public FileAnalysis Func_File_Validate( string filename, string errorOut, string validOut, string type, char dataSep, char lineSep) { this.FileStatus = new FileAnalysis(); if (File.Exists(filename)) { try { this.FileStatus.HasError = Func_File_Validate(filename); this.FileStatus.HasCWError = Func_File_Validate_StatusAndFilename(filename); if (this.FileStatus.HasError && (this.FileStatus.HasCWError == false)) { if (!filename.Contains(type)) { var ediObject = Interchange.LoadFrom(File.OpenRead(filename)); if (ediObject.Groups != null) { foreach (var g in ediObject.Groups) { foreach (var m in g.Messages) { var brokenRules = (List<string>) m.Validate(); if (brokenRules.Count > 0) { this.FileStatus.HasError = true; this.FileStatus.Errors = Func_X12_AssignErrors(brokenRules); this.FileStatus.Fixable = Func_X12_Eval_ErrorCodes( this.FileStatus.Errors, type); this.FileStatus.HasCWError = Func_File_Validate_StatusAndFilename(filename); if (this.FileStatus.Fixable && (!filename.Contains(type)) && (this.FileStatus.HasCWError == false)) { var errContext = new InterchangeContext { DataElementSeparator = dataSep.ToString(), SegmentTerminator = lineSep.ToString() }; var errContent = Func_X12_Eval_Segments( filename, ediObject.ToEdi(errContext), type, dataSep, lineSep); if ( File.Exists( string.Concat( Path.GetDirectoryName(filename), "\\", Path.GetFileNameWithoutExtension(filename), "_", type, ".txt"))) { File.Delete( string.Concat( Path.GetDirectoryName(filename), "\\", Path.GetFileNameWithoutExtension(filename), "_", type, ".txt")); } TextWriter errWriter = File.CreateText( string.Concat( Path.GetDirectoryName(filename), "\\", Path.GetFileNameWithoutExtension(filename), "_", type, ".txt")); try { errWriter.Write(string.Concat(errContent)); } finally { ((IDisposable) errWriter).Dispose(); } this.FileStatus.HasError = Func_File_Validate( string.Concat( Path.GetDirectoryName(filename), "\\", Path.GetFileNameWithoutExtension(filename), "_", type, ".txt")); if (this.FileStatus.HasError) { Func_File_Move( filename, string.Concat(errorOut, "\\", Path.GetFileName(filename))); this.FileStatus.FileErrName = string.Concat( errorOut, "\\", Path.GetFileName(filename)); this.FileStatus.ExcpMessage = "Cannot Recover From EDI Errors: " + filename; this.FileStatus.Status = false; if ( File.Exists( string.Concat( Path.GetDirectoryName(filename), "\\", Path.GetFileNameWithoutExtension(filename), "_", type, ".txt"))) { File.Delete( string.Concat( Path.GetDirectoryName(filename), "\\", Path.GetFileNameWithoutExtension(filename), "_", type, ".txt")); } return this.FileStatus; } this.FileStatus.FileOutName = string.Concat( Path.GetDirectoryName(filename), "\\", Path.GetFileNameWithoutExtension(filename), "_", type, ".txt"); this.FileStatus.Status = true; this.FileStatus.Created = true; if (File.Exists(filename)) { File.Delete(filename); } return this.FileStatus; } Func_File_Move( filename, string.Concat(errorOut, "\\", Path.GetFileName(filename))); this.FileStatus.FileErrName = string.Concat( errorOut, "\\", Path.GetFileName(filename)); this.FileStatus.ExcpMessage = "Cannot Recover From EDI Errors: " + filename; this.FileStatus.Status = false; return this.FileStatus; } var valContext = new InterchangeContext { DataElementSeparator = dataSep.ToString(), SegmentTerminator = lineSep.ToString() }; var valContent = Func_X12_Eval_Segments( filename, ediObject.ToEdi(valContext), type, dataSep, lineSep); if (Func_Data_ListIsEqual(valContent, ediObject.ToEdi(valContext))) { Func_File_Move( filename, string.Concat(validOut, "\\", Path.GetFileName(filename))); this.FileStatus.FileErrName = string.Concat( validOut, "\\", Path.GetFileName(filename)); this.FileStatus.Created = true; this.FileStatus.Status = true; return this.FileStatus; } if ( File.Exists( string.Concat( Path.GetDirectoryName(filename), "\\", Path.GetFileNameWithoutExtension(filename), "_", type, ".txt"))) { File.Delete( string.Concat( Path.GetDirectoryName(filename), "\\", Path.GetFileNameWithoutExtension(filename), "_", type, ".txt")); } TextWriter valWriter = File.CreateText( string.Concat( Path.GetDirectoryName(filename), "\\", Path.GetFileNameWithoutExtension(filename), "_", type, ".txt")); try { valWriter.Write(string.Concat(valContent)); } finally { ((IDisposable) valWriter).Dispose(); } Func_File_Move( filename, string.Concat(validOut, "\\", Path.GetFileName(filename))); this.FileStatus.FileErrName = string.Concat( validOut, "\\", Path.GetFileName(filename)); this.FileStatus.Created = true; this.FileStatus.Status = true; return this.FileStatus; } } } } else { Func_File_Move(filename, string.Concat(errorOut, "\\", Path.GetFileName(filename))); this.FileStatus.FileErrName = string.Concat(errorOut, "\\", Path.GetFileName(filename)); this.FileStatus.ExcpMessage = "Cannot Recover From EDI Errors"; this.FileStatus.Status = false; this.FileStatus.Created = false; return this.FileStatus; } } else { if (this.FileStatus.HasCWError) { Func_File_Move(filename, string.Concat(errorOut, "\\", Path.GetFileName(filename))); this.FileStatus.FileErrName = string.Concat(errorOut, "\\", Path.GetFileName(filename)); this.FileStatus.Status = false; this.FileStatus.Created = false; return this.FileStatus; } Func_File_Move(filename, string.Concat(validOut, "\\", Path.GetFileName(filename))); this.FileStatus.FileErrName = string.Concat(validOut, "\\", Path.GetFileName(filename)); this.FileStatus.Created = true; this.FileStatus.Status = true; return this.FileStatus; } } catch (ParserException parEx) { Func_File_Move(filename, string.Concat(errorOut, "\\", Path.GetFileName(filename))); this.FileStatus.FileErrName = string.Concat(errorOut, "\\", Path.GetFileName(filename)); this.FileStatus.ExcpMessage = parEx.Message; this.FileStatus.Status = false; this.FileStatus.Created = false; return this.FileStatus; } catch (NullReferenceException nulEx) { Func_File_Move(filename, string.Concat(errorOut, "\\", Path.GetFileName(filename))); this.FileStatus.FileErrName = string.Concat(errorOut, "\\", Path.GetFileName(filename)); this.FileStatus.ExcpMessage = nulEx.Message; this.FileStatus.Status = false; this.FileStatus.Created = false; return this.FileStatus; } } else { this.FileStatus.ExcpMessage = "Could Not Find: " + filename; this.FileStatus.Status = false; this.FileStatus.Created = false; return this.FileStatus; } return this.FileStatus; }
/// <summary> /// Converts edi interchange headers into message context. /// </summary> /// <param name="envelopes">The interchange headers.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns> /// The message context. /// </returns> private Tuple <string, string, string, EdiFormats> ToContextEdifact(IEnumerable <string> envelopes, InterchangeContext interchangeContext) { try { var unh = envelopes.Single(es => es.StartsWith(EdiSegments.Unh)); var ediCompositeDataElements = EdiHelper.GetEdiCompositeDataElements(unh, interchangeContext); var ediDataElements = EdiHelper.GetEdiComponentDataElements(ediCompositeDataElements[1], interchangeContext); return(new Tuple <string, string, string, EdiFormats>(ediDataElements[0], ediDataElements[1] + ediDataElements[2], null, EdiFormats.Edifact)); } catch (Exception ex) { throw new ParserException("Can't parse UNH segment.", ex); } }
/// <summary> /// Lexical analysis of the message /// </summary> /// <param name="segments">The edi segments.</param> /// <param name="envelopes">The edi envelopes.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns>The passed Edi message.</returns> public static Message Analyze(List<string> segments, List<string> envelopes, InterchangeContext interchangeContext) { // Read the message context from the envelope headers var messageContext = new MessageContext(envelopes, interchangeContext); // This will read through the grammar and will build an xml // Get the grammar from the context var messageGrammar = ParseTree.LoadFrom(messageContext.SystemType, pt => pt.IsMessage || pt.IsGroup || pt.IsChoice || pt.IsAll || pt.IsLoopOfLoops); // Set the position in the grammar var lastSegment = messageGrammar.Children.First(); // Create the xml root of the parsed edi var ediXml = ToXml(messageGrammar, interchangeContext); // Set the position in the xml var lastXElement = ediXml; // Iterate trough the segment lines foreach (var segment in segments) { try { var segmentContext = new SegmentContext(segment, interchangeContext, messageContext.Format); Logger.Log(string.Format("Segment to find: {0}", segmentContext.ToPropertiesString())); // Jump back to HL segment if needed if (segmentContext.IsJump()) { XElement hlParent; if (segmentContext.ParentId != null) { // Parent HL, start right after it hlParent = ediXml.Descendants().Single(d => d.Name.LocalName.StartsWith("S_HL") && d.Elements().First().Value == segmentContext.ParentId); var hl = messageGrammar.Descendants().Single(pt => pt.Name == hlParent.Name.LocalName); lastSegment = hl.Parent.Children[1]; } else { // Root HL, start from it hlParent = ediXml.Descendants().First(d => d.Name.LocalName.StartsWith("S_HL")); var hl = messageGrammar.Descendants().Single(pt => pt.Name == hlParent.Name.LocalName); lastSegment = hl; } } // Find the next segment grammar var currSeg = lastSegment.FindNextSegment(segmentContext); Logger.Log(string.Format("Segment found: {0}", currSeg.Name)); // Build the segment hierarchy // This will move to the required level up for the segment parents: groups, choices, all and loop of loops, // until another group is reached. var segmentTree = GetSegmentTree(currSeg, lastSegment); // Intersect the grammar with the parsed XML. // The new chunk will be attached to this intersection point. lastXElement = lastXElement.AncestorsAndSelf().Last(xe => xe.Name.LocalName == segmentTree.First().Parent.Name); // Attach each bit foreach (var parseTree in segmentTree) { // Parse if a segment, otherwise convert to XML var element = parseTree.IsSegment ? SegmentParser.ParseLine(parseTree, segment, interchangeContext) : ToXml(parseTree, interchangeContext); // Attach to the XML lastXElement.Add(element); // Set the last attached as the attachment point as we iterate from the top parent to the bottom segment lastXElement = element; } // Reset the position in the grammar lastSegment = currSeg; //var lastfound = AttachTree(segmentTree, segment, interchangeContext); } catch (Exception ex) { throw new ParserException("Failed at line: " + segment, ex); } } return new Message(ediXml, messageContext); }
/// <summary> /// Lexically analyses a message. /// </summary> /// <param name="segments">The EDI segments.</param> /// <param name="envelopes">The EDI envelopes.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns>The passed Edi message.</returns> public static Message Analyze(List <string> segments, List <string> envelopes, InterchangeContext interchangeContext) { // Read the message context from the envelope headers var messageContext = new MessageContext(envelopes, interchangeContext); // This will read through the grammar and will build an XML // Get the grammar from the context var messageGrammar = ParseTree.LoadFrom(messageContext.SystemType, pt => pt.IsMessage || pt.IsGroup || pt.IsChoice || pt.IsAll || pt.IsLoopOfLoops); // Set the position in the grammar var lastSegment = messageGrammar.Children.First(); // Create the XML root of the parsed EDI var ediXml = ToXml(messageGrammar, interchangeContext); // Set the position in the XML var lastXElement = ediXml; // Iterate trough the segment lines foreach (var segment in segments) { try { var segmentContext = new SegmentContext(segment, interchangeContext, messageContext.Format); Logger.Log(string.Format("Segment to find: {0}", segmentContext.ToPropertiesString())); // Jump back to HL segment if needed if (segmentContext.IsJump()) { XElement hlParent; if (segmentContext.ParentId != null) { // Parent HL, start right after it hlParent = ediXml.Descendants().Single(d => d.Name.LocalName.StartsWith("S_HL") && d.Elements().First().Value == segmentContext.ParentId); var hl = messageGrammar.Descendants().Single(pt => pt.Name == hlParent.Name.LocalName); lastSegment = hl.Parent.Children[1]; } else { // Root HL, start from it hlParent = ediXml.Descendants().First(d => d.Name.LocalName.StartsWith("S_HL")); var hl = messageGrammar.Descendants().Single(pt => pt.Name == hlParent.Name.LocalName); lastSegment = hl; } } // Find the next segment grammar var currSeg = lastSegment.FindNextSegment(segmentContext); Logger.Log(string.Format("Segment found: {0}", currSeg.Name)); // Build the segment hierarchy // This will move to the required level up for the segment parents: groups, choices, all and loop of loops, // until another group is reached. var segmentTree = GetSegmentTree(currSeg, lastSegment); // Intersect the grammar with the parsed XML. // The new chunk will be attached to this intersection point. lastXElement = lastXElement.AncestorsAndSelf().Last(xe => xe.Name.LocalName == segmentTree.First().Parent.Name); // Attach each bit foreach (var parseTree in segmentTree) { // Parse if a segment, otherwise convert to XML var element = parseTree.IsSegment ? SegmentParser.ParseLine(parseTree, segment, interchangeContext) : ToXml(parseTree, interchangeContext); // Attach to the XML lastXElement.Add(element); // Set the last attached as the attachment point as we iterate from the top parent to the bottom segment lastXElement = element; } // Reset the position in the grammar lastSegment = currSeg; } catch (Exception ex) { throw new ParserException("Failed at line: " + segment, ex); } } return(new Message(ediXml, messageContext)); }
/// <summary> /// Parses a data element /// </summary> /// <param name="parseTree">The dataelement grammar.</param> /// <param name="value">The dataelement line.</param> /// <param name="interchangeContext"></param> /// <returns>The parsed xml.</returns> private static XElement ParseElement(ParseTree parseTree, string value, InterchangeContext interchangeContext) { if (value == null) { throw new ArgumentNullException("value"); } if (!parseTree.IsComplex && !parseTree.IsSimple) { throw new Exception("Not a data element."); } XNamespace ns = interchangeContext.TargetNamespace; var result = new XElement(ns + parseTree.Name); if (parseTree.IsComplex) { if (value == string.Empty) { // Only deal with blank values for envelope headers if (parseTree.IsEnvelope) { foreach (var dataElement in parseTree.Children) { var element = new XElement(ns + dataElement.Name); element.SetValue(string.Empty); result.Add(element); } } } else { // Get the simple data elements var componentDataElements = EdiHelper.GetEdiComponentDataElements(value, interchangeContext).ToList(); // Index the composite data elements from the class definition var indexedGrammar = parseTree.Children.Select((g, p) => new { Grammar = g, Position = p }).ToList(); // Index the composite data elements from the edi string var indexedValues = componentDataElements.Select((v, p) => new { Value = v, Position = p }).ToList(); // This will try to parse the edi string into the class definition // Load a parse tree against each value // If there are more values in the edi string than in the class definition - they will be ignored // If there are less values in the edi string than in the class definition - it will throw an exception var indexedList = from ig in indexedGrammar from iv in indexedValues where ig.Position == iv.Position select new { ig.Position, iv.Value }; // Index the list so we can position each element //var indexed = componentDataElements.Select((a, i) => new {Item = a, Position = i}).ToList(); foreach (var dataElement in indexedList) { // Skip blank data elements otherwise this will produce blank XML nodes if (string.IsNullOrEmpty(dataElement.Value)) { if (!parseTree.IsEnvelope) { continue; } } // Handle the repetitions // If the children the the edi straing are more than the class definition, // Then the diff are considered repetitions of the last child in the class definition var objectToParse = dataElement.Position >= parseTree.Children.Count ? parseTree.Children.Last() : parseTree.Children[dataElement.Position]; var element = new XElement(ns + objectToParse.Name); // Set the value and escape to prevent faulty XML element.SetValue(SecurityElement.Escape(dataElement.Value) ?? string.Empty); result.Add(element); } } } else { // Prevent faulty XML result.SetValue(SecurityElement.Escape(value) ?? string.Empty); } return(result); }
/// <summary> /// Initializes a new instance of the <see cref="MessageContext"/> class. /// </summary> /// <param name="envelopes"> /// From interchange headers. /// </param> /// <param name="interchangeContext"> /// The interchange context. /// </param> public MessageContext(IEnumerable <string> envelopes, InterchangeContext interchangeContext) { ToContext(envelopes, interchangeContext); _systemType = ToSystemType(Format, Version, Tag, Origin, interchangeContext.DefinitionsAssemblyName); }
/// <summary> /// Converts edi interchange headers into message context. /// </summary> /// <param name="envelopes">The interchange headers.</param> /// <param name="interchangeContext">The interchange context.</param> private void ToContextEdifact(IEnumerable<string> envelopes, InterchangeContext interchangeContext) { try { var unh = envelopes.Single(es => es.StartsWith(EdiSegments.Unh)); var ediCompositeDataElements = EdiHelper.GetEdiCompositeDataElements(unh, interchangeContext); var ediDataElements = EdiHelper.GetEdiComponentDataElements(ediCompositeDataElements[1], interchangeContext); Tag = ediDataElements[0]; Version = ediDataElements[1] + ediDataElements[2]; Origin = null; Format = EdiFormats.Edifact; } catch (Exception ex) { throw new ParserException("Can't parse UNH segment.", ex); } }
/// <summary> /// Convert a parse tree to a root xml node /// Without the hierarchy, only the name. /// </summary> /// <param name="parseTree">The parse tree.</param> /// <param name="interchangeContext">The interchange context.</param> /// <returns>A xml node.</returns> private static XElement ToXml(ParseTree parseTree, InterchangeContext interchangeContext) { XNamespace ns = interchangeContext.TargetNamespace; return new XElement(ns + parseTree.Name); }
/// <summary> /// Initializes a new instance of the <see cref="MessageContext"/> class. /// </summary> /// <param name="envelopes"> /// From interchange headers /// </param> /// <param name="interchangeContext"> /// The interchange context /// </param> public MessageContext(IEnumerable<string> envelopes, InterchangeContext interchangeContext) { ToContext(envelopes, interchangeContext); _systemType = ToSystemType(Format, Version, Tag, Origin, interchangeContext.DefinitionsAssemblyName); }
/// <summary> /// Initializes a new instance of the <see cref="MessageContext"/> class. /// </summary> /// <param name="message"> /// From XML. /// </param> /// <param name="interchangeContext"> /// The interchange context. /// </param> public MessageContext(XElement message, InterchangeContext interchangeContext) { ToContext(message); _systemType = ToSystemType(Format, Version, Tag, Origin, interchangeContext.DefinitionsAssemblyName); }
/// <summary> /// Converts the interchange to edi message. /// </summary> /// <param name="context"> /// The interchange context. /// This sets the non format default separators. /// </param> /// <returns> /// The edi message. /// </returns> public List<string> ToEdi(InterchangeContext context = null) { var x12Lexer = new ToEdiLexer(EdiHelper.Serialize(this), context); x12Lexer.Analyze(); return x12Lexer.Result; }
/// <summary> /// Converts the interchange to edi message. /// </summary> /// <param name="context"> /// The interchange context. /// This sets the non format default separators. /// </param> /// <returns> /// The edi message. /// </returns> public override List<string> ToEdi(InterchangeContext context = null) { var edifactLexer = new ToEdiLexer(EdiHelper.Serialize(this), context); edifactLexer.Analyze(); return edifactLexer.Result; }
//----------------------------------------------------------------------------------------------------- public List<string> Func_EDI_GetOriginalMessage(string filename, char dataSep, char lineSep) { var ediObject = Interchange.LoadFrom(File.OpenRead(filename)); var ediContext = new InterchangeContext { DataElementSeparator = dataSep.ToString(), SegmentTerminator = lineSep.ToString() }; var lstMsg = ediObject.ToEdi(ediContext); return lstMsg; }