none
Best way to create an XML file without errors, which possibilities? RRS feed

  • Question

  • Hello,

    I have to create this XML file and send it via socket.
    Only a few variable contents change.
    What options do I have to create this file and fill the variables?

    Idea 1,
    I create a template file with placeholders and then replace them.

    <location lineNo="90" statNo="20" statIdx="1" fuNo="$FuNo$" workPos="1" toolPos="$ToolPos" application="Medicine"
    processName="WHITE Group" processNo="$ProcessNo$" />
    </header>

    I read it and replace the variable with Replace("$FuNo$", "1")

    I think it works, is probably not the correct solution.

    I am looking for a better and more correct solution.

    I found this, this can also bring out errors.
    https://www.c-sharpcorner.com/article/xml-manipulation-in-c-sharp/

    Would I have to create a schema file and how to do that?
    It may be, I need fewer attributes than the maximum possible.

    Request

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <root>
    <header eventId="2" eventName="ReceivedOrder" version="1.0" eventSwitch="A23" contentType="PlantEurope" >
    <location lineNo="90" statNo="20" statIdx="1" fuNo="1" workPos="1" toolPos="21" application="Medicine"
    processName="WHITE Group" processNo="277" />
    </header>
    <event>
    <ReceivedOrder identifier="BDR AC 0101 150330 1404" typeNo="ACTBMW" typeVar="0001" typeVersion="V01"
    />
    </event>
    <body>
    <structs/>
    </body>
    </root>
    
    
    Response
    
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <root>
    <header eventId="2" eventName="ReceivedOrder" version="1.0" eventSwitch="12" timeStamp="2020-06-
    23T15:40:41.9555440+02:00" contentType="3" >
    <location lineNo="90" statNo="20" statIdx="1" fuNo="1" workPos="1" toolPos="21" application="medicine"
    processName="WHITE Group" processNo="277" />
    </header>
    <event>
    <result returnCode="0" />
    <trace/>
    </event>
    <body>
    <items>
    <item name="ProcessState" value="0" dataType="bool" />
    <item name="LocationState" value="0" dataType="int" />
    </items>
    <values>
    <item pos="1" id="ACTBMW-GQ911.9-0001" partForStation="true" state="3" />
    <item pos="2" id="ACTBMW-GQ911.9-0002" partForStation="true" state="3" />
    <!-- NEW: -->
    <item pos="3" id="ACTBMW-GQ911.9-EMPTY3" partForStation="false" state="9" />
    <item pos="4" id="ACTBMW-GQ911.9-EMPTY4" partForStation="false" state="9" />
    <item pos="5" id="ACTBMW-GQ955.9-0003" partForStation="true" state="2" />
    <item pos="6" id="ACTBMW-GQ955.9-0004" partForStation="true" state="0" />
    </values>
    </body>
    </root>
    Best regards Markus

    Tuesday, June 30, 2020 6:50 PM

Answers

  • You don't need ASP.NET for JSON. Not sure why you needed to do that.

    In general to convert XML to a C# type each element becomes a class. The attributes become properties. Child elements are properties of the associated class. In your case you are using camel casing so you'll customize the XML using the `XmlAttribute` and `XmlElement` attributes.

    Here's some starter code of what your model might look like but I haven't done all of it. 

    public class Data
    {
        [XmlElement("header")]
        public Header Header { get; set; }
    
        [XmlElement("event")]
        public EventData Event { get; set; }
    
        [XmlElement("body")]
        public BodyData Body { get; set; }
    }
    
    public class Header
    {
        [XmlAttribute("eventId")]
        public int EventId { get; set; }
    
        [XmlAttribute("eventName")]
        public string EventName { get; set; }
    
        [XmlAttribute("version")]
        public string Version { get; set; }
    
        [XmlAttribute("eventSwitch")]
        public int EventSwitch { get; set; }
    
        [XmlAttribute("timeStamp")]
        public DateTime Timestamp { get; set; }
    
        [XmlAttribute("contentType")]
        public int ContentType { get; set; }
    
        [XmlElement("location")]
        public HeaderLocation Location { get; set; }
    }
    
    public class HeaderLocation
    {
        [XmlAttribute("lineNo")]
        public int LineNumber { get; set; }
    
        [XmlAttribute("statNo")]
        public int StatNumber { get; set; }
    
        //TODO: Fill in the rest of the properties...
    }
    
    public class EventData
    {
        [XmlElement("result")]
        public EventResult Result { get; set; }
    
        //TODO: Fill in the rest of the elements...
    }
    
    public class EventResult
    {
        [XmlAttribute("returnCode")]
        public int ReturnCode { get; set; }
    }
    
    public class BodyData
    {
        [XmlArray(ElementName = "items")]
        [XmlArrayItem(typeof(BodyItem), ElementName = "item")]
        public BodyItem[] Items { get; set; }
    
        [XmlArray(ElementName = "values")]
        [XmlArrayItem(typeof(BodyValue), ElementName = "item")]
        public BodyValue[] Values { get; set; }
    }
    
    public class BodyItem
    {
        [XmlAttribute("name")]
        public string Name { get; set; }
    
        //TODO: Fill in the rest of the properties...
    }
    
    public class BodyValue
    {
        [XmlAttribute("pos")]
        public int Position { get; set; }
    
        //TODO: Fill in the rest of the properties...
    }

    To serialize just use XmlSerializer.

    var data = new Data()
    {
        Header = new Header()
        {
            EventId = 2,
            EventName = "ReceivedOrder",
            Version = "1.0",
            EventSwitch = 12,
            Timestamp = new DateTime(2020, 6, 23),
            Location = new HeaderLocation()
            {
                LineNumber = 90,
                StatNumber = 20
            }
        },
        Event = new EventData()
        {
            Result = new EventResult()
            {
                ReturnCode = 0
            }
        },
        Body = new BodyData()
        {
            Items = new []
            {
                new BodyItem() { Name = "ProcessState "},
                new BodyItem() { Name = "LocationState" }
            },
            Values = new []
            {
                new BodyValue() { Position = 1 },
                new BodyValue() { Position = 2 },
            }
        }
    };
    
    var serializer = new XmlSerializer(typeof(Data));
    
    var output = "";
    
    using (var stream = new MemoryStream())
    {
        serializer.Serialize(stream, data);
    
        var xml = stream.ToArray();
    
        //Look at the results...
        output = Encoding.UTF8.GetString(xml);
    };

    Note that the serialization types can be your business layer as well if needed but care should be taken that you don't make changes that break the XML. Therefore it is more common to have serialization-specific types for public APIs that are independent of the business object to disconnect the 2. This allows your business types to meet your business needs without having to be limited to the public-facing model you are exposing.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, July 1, 2020 3:57 PM
    Moderator

All replies

  • Quite a few options. Probably the easiest is to define a .NET structure that matches the structure of the XML you need. Then use XmlSerializer to serializer it. However the serializer tends to put its own additional requirements on the XML so it might not format the way you want. Refer to the docs for an example.

    Then again for a couple lines of XML you can also just build it by hand. Nothing wrong with that either.


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, June 30, 2020 7:29 PM
    Moderator
  • Thanks for the quick response.

    What you think about my

    idea1, file, replace?

    If I use XDocument, how I can add serialize?

    Can you make for one Element in my XML a sample?

    Thanks in advance.

    Greetings Markus

    Tuesday, June 30, 2020 9:04 PM
  • File replace is good if you have a large XML and the replacement is simple. Simple would be something like "change this URL", "set this value". However if you need to add one or more elements to an XML file then templating by itself is not good enough. You couldn't easily create a default template smart enough to allow you to insert arbitrary sets of elements unless you used a more advanced templating engine. There are some available. Razor comes to mind but there is also StringTemplates and others. But at that point I'd ask the question of why. If you need to generate XML then use an XML serializer.

    XDocument is the correct approach if you need to load XML into memory. However if you're using XML serialization or even templating then you won't load the XML as there is no reason to. It is just text.

    So, if you need to enumerate business data and inject XML elements then use XDocument but templating wouldn't be used here. You'd instead find the XML element that is the parent of where you want your data to go and then add the elements. But the more complex the element is the harder it is to do. Hence using XML serialization is better. 

    You'll have to decide which approach works best for your specific problem. It is a case by case basis.


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, June 30, 2020 9:28 PM
    Moderator
  • The advantage of using XmlSerializer is that you can extend the structure later on without having to redesign everything.  Using string replace on a template can be made to work, but it's a hack, and it will always be delicate.

    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Wednesday, July 1, 2020 3:01 AM
  • Hello,

     

    I Installed ASP.NET , is now available.

     Added insert as xml


     

    For JSON works well, if i copy this inside Clipboard.

    { "Comment": "All OK",
    
       "OutputSerialNumber": ["00001","00002","00003"]
    
    }
    
    
    I get this
    
    public class Rootobject
    
        {
    
            public string Comment { get; set; }
    
            public string[] OutputSerialNumber { get; set; }
    
       }

    http://xmltocsharp.azurewebsites.net/

    How is the best way for serialize?

    Is this tool good, what is your opinion?

     

    What is the procedure, you know the XML and have to write a serialization.

    How would you approach the topic so that it works 100%? Can you make a good sample with my data?

    Thanks in advance.

     

    Regards Markus


    Wednesday, July 1, 2020 3:26 PM
  • You don't need ASP.NET for JSON. Not sure why you needed to do that.

    In general to convert XML to a C# type each element becomes a class. The attributes become properties. Child elements are properties of the associated class. In your case you are using camel casing so you'll customize the XML using the `XmlAttribute` and `XmlElement` attributes.

    Here's some starter code of what your model might look like but I haven't done all of it. 

    public class Data
    {
        [XmlElement("header")]
        public Header Header { get; set; }
    
        [XmlElement("event")]
        public EventData Event { get; set; }
    
        [XmlElement("body")]
        public BodyData Body { get; set; }
    }
    
    public class Header
    {
        [XmlAttribute("eventId")]
        public int EventId { get; set; }
    
        [XmlAttribute("eventName")]
        public string EventName { get; set; }
    
        [XmlAttribute("version")]
        public string Version { get; set; }
    
        [XmlAttribute("eventSwitch")]
        public int EventSwitch { get; set; }
    
        [XmlAttribute("timeStamp")]
        public DateTime Timestamp { get; set; }
    
        [XmlAttribute("contentType")]
        public int ContentType { get; set; }
    
        [XmlElement("location")]
        public HeaderLocation Location { get; set; }
    }
    
    public class HeaderLocation
    {
        [XmlAttribute("lineNo")]
        public int LineNumber { get; set; }
    
        [XmlAttribute("statNo")]
        public int StatNumber { get; set; }
    
        //TODO: Fill in the rest of the properties...
    }
    
    public class EventData
    {
        [XmlElement("result")]
        public EventResult Result { get; set; }
    
        //TODO: Fill in the rest of the elements...
    }
    
    public class EventResult
    {
        [XmlAttribute("returnCode")]
        public int ReturnCode { get; set; }
    }
    
    public class BodyData
    {
        [XmlArray(ElementName = "items")]
        [XmlArrayItem(typeof(BodyItem), ElementName = "item")]
        public BodyItem[] Items { get; set; }
    
        [XmlArray(ElementName = "values")]
        [XmlArrayItem(typeof(BodyValue), ElementName = "item")]
        public BodyValue[] Values { get; set; }
    }
    
    public class BodyItem
    {
        [XmlAttribute("name")]
        public string Name { get; set; }
    
        //TODO: Fill in the rest of the properties...
    }
    
    public class BodyValue
    {
        [XmlAttribute("pos")]
        public int Position { get; set; }
    
        //TODO: Fill in the rest of the properties...
    }

    To serialize just use XmlSerializer.

    var data = new Data()
    {
        Header = new Header()
        {
            EventId = 2,
            EventName = "ReceivedOrder",
            Version = "1.0",
            EventSwitch = 12,
            Timestamp = new DateTime(2020, 6, 23),
            Location = new HeaderLocation()
            {
                LineNumber = 90,
                StatNumber = 20
            }
        },
        Event = new EventData()
        {
            Result = new EventResult()
            {
                ReturnCode = 0
            }
        },
        Body = new BodyData()
        {
            Items = new []
            {
                new BodyItem() { Name = "ProcessState "},
                new BodyItem() { Name = "LocationState" }
            },
            Values = new []
            {
                new BodyValue() { Position = 1 },
                new BodyValue() { Position = 2 },
            }
        }
    };
    
    var serializer = new XmlSerializer(typeof(Data));
    
    var output = "";
    
    using (var stream = new MemoryStream())
    {
        serializer.Serialize(stream, data);
    
        var xml = stream.ToArray();
    
        //Look at the results...
        output = Encoding.UTF8.GetString(xml);
    };

    Note that the serialization types can be your business layer as well if needed but care should be taken that you don't make changes that break the XML. Therefore it is more common to have serialization-specific types for public APIs that are independent of the business object to disconnect the 2. This allows your business types to meet your business needs without having to be limited to the public-facing model you are exposing.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, July 1, 2020 3:57 PM
    Moderator
  • Hello Michael,

    Thanks a lot. That looks good.
    Answered the question. I leave the question open for a day or two if someone
    has other ideas. Yours is now understandable. That makes me happy.
    Many thanks and greetings Markus
    Wednesday, July 1, 2020 8:15 PM