C# : How to parse EDIFACT message using Xml Serializer

2.5k Views Asked by At

i have this kind EDIFACT message.

UNB+IATB:1+NGI+OOS+180918:2003+Export_Dump++TR2+X'
UNH+1+IFLIRR:15:2:1A'
FDR+OM+135+160918'
FDD++INT'
REF'
STX+ACT'
IFD+++C+USD++N'
APD+:::::::ULN:SVO'
DAT+708:160918:0915+707:160918:1055'
STX+FD'
EQP+J+76W::EIFGN+OM'
EQI+++++++:::FGN'
EQD++++++A01'
SSQ+AVIH:5:5::::0:SSR'
SSQ+BIKE:5:5::::0:SSR'
SSQ+BSCT:2:2::::0:SSR+J'
SSQ+BSCT:5:3::::2:SSR+Y'
SSQ+INFT:15:10::::5:SSR'
SSQ+PETC:1:1::::0:SSR+J'
SSQ+PETC:3:3::::0:SSR+Y'
SSQ+POXY:1:1::::0:SSR'
SSQ+SPEQ:5:5::::0:SSR'
SSQ+STCR:0:0::::0:SSR+J'
SSQ+STCR:1:1::::0:SSR+Y'
SSQ+SVAN:1:1::::0:SSR+J'
SSQ+SVAN:3:3::::0:SSR+Y'
SSQ+TVLG:5:5::::0:SSR'
SSQ+TVSM:10:10::::0:SSR'
SSQ+UMNR:5:5::::0:SSR'
SSQ+WCOB:0:0::::0:SSR'
LEG+A01+NXC'
EQI+J:24:S+J:21:A+J:24:O+J:21:E'

This message continues more than about 1 million line.

I have used C# Xml Serializer and successfully parsed this message into XML file. But not correct structure.

Here's my code:

    switch (keyword)
                        {
                            case "UNB":
                                
                                parts = specificLine.Split(new char[] { '+', ':' }, StringSplitOptions.RemoveEmptyEntries);
                                serialization = new XmlSerializer(typeof(UNB));
                                UNB HeaderText = new UNB(parts[1], parts[2], parts[3], parts[4], parts[5], parts[6]);
                                writer = XmlWriter.Create(TxtWriter, settings);
                                serialization.Serialize(writer, HeaderText, EmptyNS);
                                break;
                            case "UNH":
                                parts = specificLine.Split(new char[] { '+', ':' }, StringSplitOptions.RemoveEmptyEntries);
                                serialization = new XmlSerializer(typeof(UNH));
                                UNH BodyText = new UNH(parts[1],parts[2],parts[3],parts[4],parts[5]);
                                writer = XmlWriter.Create(TxtWriter, settings);
                                serialization.Serialize(writer, BodyText, EmptyNS);
                                break;
                            case "FDR":
                                flightDateInformation Gr0 = new flightDateInformation();
                                parts = specificLine.Split(new char[] { '+'}, StringSplitOptions.RemoveEmptyEntries);                        
                                serialization = new XmlSerializer(typeof(flightDateInformation));
                                flightDateDesignator fdrbody = new flightDateDesignator(parts[1], parts[2], parts[3]);
                                Gr0.flightDateDesignator = fdrbody;
                                writer = XmlWriter.Create(TxtWriter, settings);
                                serialization.Serialize(writer, Gr0, EmptyNS);
                                break;
} 

and this is my structure class code example:

    [XmlRoot(ElementName = "UNB", IsNullable = false), Serializable]
    public class UNB
    {
        [XmlAttribute]
        public string identifier;
        [XmlAttribute]
        public string version;
        [XmlAttribute]
        public string sender;
        [XmlAttribute]
        public string recipient;
        [XmlAttribute]
        public string dateofpreparation;
        [XmlAttribute]
        public string timeofpreparation;
        public UNB(string identifier, string version,string sender, string recipient, string dateofpreparation, string timeofpreparation)
        {
            this.identifier = identifier;
            this.version = version;
            this.sender = sender;
            this.recipient = recipient;
            this.dateofpreparation = dateofpreparation;
            this.timeofpreparation = timeofpreparation;
        }
        public UNB()
        {

        }
}

And my output XML file like this :

<UNB identifier="IATB" version="1" sender="NGI" recipient="OOS" dateofpreparation="180918" timeofpreparation="2003" /><UNH identifier="1" type="IFLIRR" version="15" release="2" agency="1A" /><flightDateInformation>
  <flightDateDesignator airlineCode="OM" flightNumber="135" departureDate="160918" />
</flightDateInformation><flightLevelInfo flightCharacteristics="INT" /><referenceInfomation /><flightFlags statusIndicator="ACT" /><inventoryParametersFD controlType="C" currencyCode="USD" isUnderActiveRevControl="N" /><additionalproductdetails>
  <departureLocation>ULN</departureLocation>
  <arrivalLocation>SVO</arrivalLocation>
</additionalproductdetails><scheduledTiming>
  <qualifier>708</qualifier>
  <date>160918</date>
  <time>0915</time>
</scheduledTiming><scheduledTiming>
  <qualifier>707</qualifier>
  <date>160918</date>
  <time>1055</time>
</scheduledTiming><dcsInformation statusIndicator="FD" /><aircraftInformation serviceType="J" aircraftType="76W">
  <eqtRegistrationNumber>EIFGN</eqtRegistrationNumber>
  <aircraftOwner>OM</aircraftOwner>
</aircraftInformation><acvInformation acvCode="FGN" /><saleableConfiguration configurationCode="A01" />
<newSSR quotaCounterName="AVIH">
  <maxQuantity>5</maxQuantity>
  <availability>5</availability>
  <counter>0</counter>
  <quotaType>SSR</quotaType>
</newSSR><newSSR quotaCounterName="BIKE">
  <maxQuantity>5</maxQuantity>
  <availability>5</availability>
  <counter>0</counter>
  <quotaType>SSR</quotaType>
</newSSR>
<newSSR quotaCounterName="BSCT" cabinCode="J">
  <maxQuantity>2</maxQuantity>
  <availability>2</availability>
  <counter>0</counter>
  <quotaType>SSR</quotaType>
</newSSR>

Now my problem is : Yes my code has worked and parsed successfully into XML file. But not as i want. Each node with only 1 line.

It's my wanted structure.

Branching Diagram

Each node has included to other parent node. Some nodes expand into other nodes. my output XML don't have any parent.

Can i solve this by improving my code or should try different way?

If you have any need more details, please kindly ask me? i will give you more details

UPDATE: I'm resolved this problem.

2

There are 2 best solutions below

0
On

This question is very broad. Basically you have to understand the format, then write a software to extract and convert it to your desired format. Luckily you are not the first one with this problem and there are openSource solutions available:

Is there any good open source EDIFACT parser in Java?

0
On

I would want to see a specification of the input format, not just an example, before tackling this task, especially as the quantity of data to be converted is too large to check the correctness of the result by visual inspection.

I think you are on the right lines, however: first do a crude parse of the input that produces some kind of XML representation. Then use XML tools (specifically, XSLT) to transform this crude XML into the target XML that you actually want.

I can't tell from your "actual output" and the diagram of your "desired output" what the detailed transformation rules are, but it's likely to be some kind of grouping transformation to create a hierarchic structure from a flat structure. That's a common task in XSLT and is best tacked by getting hold of an XSLT 2.0 (or 3.0) processor and using the <xsl:for-each-group> instruction. For example, if your task is to put wrapper elements around adjacent elements having the same name, you could do:

<xsl:for-each-group select="*" group-adjacent="name()">
  <xsl:choose>
    <xsl:when test="name()="SSR">
      <SSR-LIST><xsl:copy-of select="current-group()"/></SSR-LIST>
    </xsl:when>
    ....
    <xsl:otherwise>
      <xsl:copy-of select="current-group()"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:for-each-group>

If you want more specific advice on this transformation, I suggest posting a new question with a concrete (and short!) example of the input and output, expressed as XML documents, with a clear relationship between the two.