Extract useful data from X12Parser object

Jun 28, 2013 at 12:06 AM
I've successfully read in an 811 EDI file into the X12Parser:
        using (StreamReader sr = new StreamReader(ediFilePath))
        {
            String EdiLine = sr.ReadToEnd();

            X12Parser parser = new X12Parser();
            Interchange interchange = parser.ParseMultiple(new MemoryStream(Encoding.ASCII.GetBytes(EdiLine))).First();

And I can get header info:
            Assert.AreEqual("          ", interchange.AuthorInfo);
            Assert.AreEqual("00", interchange.AuthorInfoQualifier);
            Assert.AreEqual(1, interchange.FunctionGroups.Count());
            Assert.AreEqual("000000006", interchange.InterchangeControlNumber);
            Assert.AreEqual(new DateTime(2013, 6, 18, 15, 8, 0), interchange.InterchangeDate);
            Assert.AreEqual("123456789MT    ", interchange.InterchangeReceiverId);
            Assert.AreEqual("ZZ", interchange.InterchangeReceiverIdQualifier);
            Assert.AreEqual("STFM   SF00001 ", interchange.InterchangeSenderId);
            Assert.AreEqual("ZZ", interchange.InterchangeSenderIdQualifier);
            Assert.AreEqual("          ", interchange.SecurityInfo);
            Assert.AreEqual("00", interchange.SecurityInfoQualifier);
But that's as far as I can get. I need to get information like the bank name, customer names and dollar values, etc...

I don't know and can't find information about the internal structure of this object to retrieve this information. Any help would be vastly appreciated!
Jul 9, 2013 at 6:22 PM
Here is a quick stripped down example:
foreach (var functionGroup in interchange.FunctionGroups)
            {
                foreach (var transaction in functionGroup.Transactions)
                {
                   switch (transaction.IdentifierCode)
                    {
                        case "856": //ASN
                            var d856 = ParsedDocuments.CTDI.Edi856.CreateFromTransaction(transaction);

                            break;
                    }

                }
            }

a few lines from CreateFromTransaction Method that show different ways to pull data:
 var document = new Edi856 {Transaction = transaction};
 var header = GetLoop<HierarchicalLoopContainer>(transaction.HLoops,"HL").First();
 document.AsnNumber =GetElement(transaction.Segments, "BSN", 2);

var n1Loops = GetLoop(header.Segments, "N1");
            foreach (var container in n1Loops)
            {
                switch (container.GetElement(1))
                {
                    case "MF":
                        document.Oem = container.GetElement(2);
                        break;
                    case "ST":
                        document.ShipToName = container.GetElement(2);
                        document.ShipToLocation = container.GetElement(4);
                        break;
                }
            }

var orderLoop = GetLoop<HierarchicalLoopContainer>(header.HLoops, "HL");
            foreach (var order in orderLoop)
            {
                var detail = new Edi856Detail();
                detail.PurchaseOrderNumber = GetElement(order.Segments, "PRF", 1);
              

                var packLoop = GetLoop<HierarchicalLoopContainer>(order.HLoops, "HL");
                foreach (var pack in packLoop)
                {
                    var packDetail = new Edi856DetailPack();

                    packDetail.PalletId = GetElement(pack.Segments, "REF", 2);

                    var itemLoop = GetLoop<HierarchicalLoopContainer>(pack.HLoops, "HL");
                    foreach (var item in itemLoop)
                    {
                        var itemDetail = new Edi856DetailPackItem();

                        itemDetail.LineNumber = GetElement(item.Segments, "LIN", 1);
                        itemDetail.ItemNumber = GetElement(item.Segments, "LIN", 3);
                        itemDetail.UnitCount = Convert.ToDecimal(GetElement(item.Segments, "SN1", 2));
                        itemDetail.PurchaseOrderNumber = GetElement(item.Segments, "PRF", 1);
                        itemDetail.PurchaseOrderLineNumber = GetElement(item.Segments, "PRF", 2);

                        packDetail.Items.Add(itemDetail);
                    }

                    detail.Packs.Add(packDetail);
                }


                document.Orders.Add(detail);
            }

A few helper methods i use in my base class for parsed EDI documents such as the Edi856 object:
        public static string GetElement(IEnumerable<Segment> segments, string segmentId, int index, int skip = 0)
        {
            try
            {
                var segment = segments.Where(o => o.SegmentId == segmentId).Skip(skip).FirstOrDefault();
                if (segment != null)
                {
                    return segment.GetElement(index).Trim();
                }

                return "";
            }
            catch (Exception)
            {
                return "ERR";
            }
        }
        public static IEnumerable<Segment> GetSegments(IEnumerable<Segment> segments, string segmentId)
        {
            try
            {
                return segments.Where(o => o.SegmentId == segmentId);
            }
            catch (Exception)
            {
                return null;
            }
        }
        public static IEnumerable<LoopContainer> GetLoop(IEnumerable<Segment> segments, string segmentId)
        {
            return GetLoop<LoopContainer>(segments, segmentId);
        }
        public static IEnumerable<T> GetLoop<T>(IEnumerable<Segment> segments, string segmentId) where T : LoopContainer
        {
            try
            {

                var containers = new List<T>();

                var detailLoop = GetSegments(segments.ToList(), segmentId);

                foreach (var segment in detailLoop)
                {
                    var container = segment as T;
                    containers.Add(container);
                }

                return containers;
            }
            catch (Exception)
            {
                return null;
            }
        }
Aug 5, 2013 at 8:31 AM
Edited Aug 5, 2013 at 8:35 AM
"ParsedDocuments" does not seem to be something that's available to me (compiler doesn't recognize and I can't find it in the source).
Also, just about everything in the 2nd to last code snippet is not compilable.

I've downloaded the May source and have references to OopFactory.X12, OopFactory.X12.Hipaa, & OopFactory.X12.Validation.

The labels, in particular, that are causing problems:
Edi856
Transaction
GetLoop<...>
GetElement()

What am I missing?
Aug 16, 2013 at 3:00 PM
It was merely meant as sample information not copy & paste friendly but i hope the following can help a bit more.
ParsedDocuments.CTDI.Edi856.CreateFromTransaction(transaction);
This is my own Edi856 class which i parse specific fields into a class that I can easily read and use.

Inside of the Edi856 object i have a static method called CreateFromTransaction this converts the transaction object from the X12 parser and returns the Edi856 object created. This is the main meat and potatoes i was trying to show you how I pulled information.

The only reason I included the 3rd block with the helper methods was because I used them in the CreateFromTransaction and didn't want to leave you hanging.

All my parsed objects such as the Edi856 have a base class with those methods such as GetLoop.


Here is the base class i use although you may want to throw a some of it out.
    public class EdiDocumentBase
    {

        public ProcessResultDetail ResultDetail;
        public Transaction Transaction;
        public static string GetElement(IEnumerable<Segment> segments, string segmentId, int index, int skip = 0)
        {
            try
            {
                var segment = segments.Where(o => o.SegmentId == segmentId).Skip(skip).FirstOrDefault();
                if (segment != null)
                {
                    return segment.GetElement(index).Trim();
                }

                return "";
            }
            catch (Exception)
            {
                return "ERR";
            }
        }
        public static IEnumerable<Segment> GetSegments(IEnumerable<Segment> segments, string segmentId)
        {
            try
            {
                return segments.Where(o => o.SegmentId == segmentId);
            }
            catch (Exception)
            {
                return null;
            }
        }
        public static IEnumerable<LoopContainer> GetLoop(IEnumerable<Segment> segments, string segmentId)
        {
            return GetLoop<LoopContainer>(segments, segmentId);
        }
        public static IEnumerable<T> GetLoop<T>(IEnumerable<Segment> segments, string segmentId) where T : LoopContainer
        {
            try
            {

                var containers = new List<T>();

                var detailLoop = GetSegments(segments.ToList(), segmentId);

                foreach (var segment in detailLoop)
                {
                    var container = segment as T;
                    containers.Add(container);

                    Console.WriteLine(segment.SegmentString);

                }

                return containers;
            }
            catch (Exception)
            {
                return null;
            }
        }
        public static DateTime ConvertG62ToDateTime(Segment segment)
        {
            DateTime date;
            if (DateTime.TryParseExact(segment.GetElement(2) + segment.GetElement(4), "yyyyMMddHHmmss", null, System.Globalization.DateTimeStyles.None, out date))
                return date;

            if (DateTime.TryParseExact(segment.GetElement(2) + segment.GetElement(4), "yyyyMMddHHmm", null, System.Globalization.DateTimeStyles.None, out date))
                return date;

            if (DateTime.TryParseExact(segment.GetElement(2) + segment.GetElement(4), "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out date))
                return date;

            throw new Exception("Unable to convert G62 segment to DateTime object.");

        }
        

    }