/// <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> /// 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> /// Initializes a new instance of the <see cref="Message"/> class. /// </summary> /// <param name="context">Edi xml</param> /// <param name="item">Context</param> public Message(XElement item, MessageContext context) { Context = context; Item = item; }
/// <summary> /// Parses an edi message /// </summary> /// <param name="typedMessage"> /// The Xml edi. /// </param> protected void CreateSegments(XElement typedMessage) { // Clear all empty nodes typedMessage.Descendants().Where(d => string.IsNullOrEmpty(d.Value)).Remove(); typedMessage.Descendants().Where(d => string.IsNullOrWhiteSpace(d.Value)).Remove(); var messageContext = new MessageContext(typedMessage); // Get all segments, which are not parents of other segments foreach (var segment in typedMessage.Descendants().Where(d => d.Name.LocalName.StartsWith("S_") && !d.Elements().Any(e => e.Name.LocalName.StartsWith("S_")))) { Result.Add(SegmentParser.ParseXml(messageContext.SystemType, segment, InterchangeContext)); } }
/// <summary> /// Initializes a new instance of the <see cref="Message"/> class. /// </summary> /// <param name="instance"> /// Edi object /// </param> public Message(object instance) { Context = new MessageContext(instance.GetType()); Item = EdiHelper.Serialize(instance); }