/// <summary> /// Parses group header /// </summary> /// <param name="segment"> /// The edi segment /// </param> protected override void CreateGroupHeader(string segment) { Result.Groups.Add(new Group()); Result.Groups.Last().Messages = new List <Message>(); Result.Groups.Last().Ung = SegmentParser.ParseLine <S_UNG>(segment, InterchangeContext).Deserialize <S_UNG>(); }
/// <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> /// Parses group trailer /// </summary> /// <param name="segment"> /// The edi segment /// </param> protected override void CreateGroupTrailer(string segment) { Result.Groups.Last().Une = SegmentParser.ParseLine <S_UNE>(segment, InterchangeContext).Deserialize <S_UNE>(); }
/// <summary> /// Parses interchange trailer /// </summary> /// <param name="segment"> /// The edi segment /// </param> protected override void CreateInterchangeTrailer(string segment) { Result.Unz = SegmentParser.ParseLine <S_UNZ>(segment, InterchangeContext).Deserialize <S_UNZ>(); }
/// <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 interchange header /// </summary> /// <param name="segment"> /// The edi segment /// </param> protected override void CreateInterchangeHeader(string segment) { Result.Isa = SegmentParser.ParseLine <S_ISA>(segment, InterchangeContext).Deserialize <S_ISA>(); }
/// <summary> /// Reads the next message in the EDI stream. /// </summary> /// <returns>If reached the end of the stream.</returns> /// <example> /// This sample shows how to call the <see cref="GetNextMessage"/> method. /// <code lang="C#"> /// using(var es = new EdiStream(File.OpenRead(@"c:\verylarge.edi"))) /// { /// while (es.GetNextMessage()) /// { /// var message = es.Message; /// var header = es.InterchangeHeader; /// var group = es.InterchangeGroup; /// } /// } /// </code> /// </example> public bool GetNextMessage() { var message = new List <string>(); var result = false; while (_streamReader.Peek() >= 0 && !result) { var segment = _streamReader.ReadSegment(_interchangeContext.ReleaseIndicator, _interchangeContext.SegmentTerminator); switch (EdiHelper.GetSegmentName(segment, _interchangeContext)) { case EdiSegments.Una: break; case EdiSegments.Unb: InterchangeHeader = SegmentParser.ParseLine <S_UNB>(segment, _interchangeContext).Deserialize <S_UNB>(); break; case EdiSegments.Isa: InterchangeHeader = SegmentParser.ParseLine <S_ISA>(segment, _interchangeContext).Deserialize <S_ISA>(); break; case EdiSegments.Unz: case EdiSegments.Iea: break; case EdiSegments.Ung: InterchangeGroup = SegmentParser.ParseLine <S_UNG>(segment, _interchangeContext).Deserialize <S_UNG>(); break; case EdiSegments.Gs: InterchangeGroup = SegmentParser.ParseLine <S_GS>(segment, _interchangeContext).Deserialize <S_GS>(); _envelope.Add(segment); break; case EdiSegments.Une: case EdiSegments.Ge: _envelope.Clear(); break; case EdiSegments.Unh: case EdiSegments.St: message.Add(segment); _envelope.Add(segment); break; case EdiSegments.Unt: case EdiSegments.Se: message.Add(segment); Message = MessageLexer.Analyze(message, _envelope, _interchangeContext); result = true; // For X12 the ST segment is included in the headers // Once the message is parsed - it's removed _envelope.Remove(_envelope.Last()); message.Clear(); break; default: message.Add(segment); break; } } return(result); }