0

I need small help for XML file Parsing. I am getting the error while Null value in XML file while iterating by for each loop. How to parse with different data Type with Null value.

Source XML file :

<XMLList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <measList>
    <Measurement>
      <MeasurementGuid>87ae41e0-e9ec-4570-83c1-75fbfc96db17</MeasurementGuid>   
      <SequenceNumber>953</SequenceNumber>
      <Time>2020-10-07T15:39:06</Time>
      <SensorBlobVersion xsi:nil="true" />     
    </Measurement>

    <Measurement>
      <MeasurementGuid>1243234-e9ec-2324-83c1-43fbfc96db17</MeasurementGuid>   
      <SequenceNumber>111</SequenceNumber>
      <Time>2022-11-07T15:39:06</Time>
      <SensorBlobVersion xsi:nil="true" />     
    </Measurement>

 </measList>
</XMLList>

I am getting the error for SensorBlobVersion. It's Null. Error : "Input string was not in a correct format."

When I put the debug point at SensorBlobVersion then I can see the Null as below :

"<SensorBlobVersion xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />"

Sample Source Code :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XMLFileUploader
{
    using System.Linq;
    using System.Xml;
    using System.Xml.Linq;

    namespace XMLFileUploader
    {
        public static class ExtractLogFile
        {
            public static void ExtractData(string filePath)
            {
                XElement root = XElement.Load(filePath);
                IEnumerable<XElement> tests =
                                     from el in root.Elements("measList") 
                                     select el;

                IEnumerable<XElement> measList =
                  from el2 in tests.Elements("Measurement")
                  select el2;

                foreach (XElement el2 in measList)
                {
                    Measurement mes = new Measurement();

                    if (el2.NodeType == XmlNodeType.Element && el2.Name == "Measurement")
                    {
                        mes.MeasurementInfoGuid = (String)el2.Element("MeasurementGuid");
                        mes.SequenceNumber = (int)el2.Element("SequenceNumber");
                        mes.Time = (DateTime)el2.Element("Time");

                        if (el2.Element("SensorBlobVersion") == null)
                        {
                            mes.SensorBlobVersion = 0;
                        }
                        else
                        {
                            mes.SensorBlobVersion = (int?)(el2.Element("SensorBlobVersion"));   // **ERROR AT THIS LINE**
                        }
                    }
                }
            }

            public class Measurement
            {
                public String MeasurementInfoGuid { get; set; }
                public int SequenceNumber { get; set; }
                public DateTime Time { get; set; }
                public int? SensorBlobVersion { get; set; }
            }

        }
    }
}
1
  • Following works : int version = 0; Boolean isInt = int.TryParse((string)el2.Element("SensorBlobVersion"),out version ); mes.SensorBlobVersion = isInt ? version : null; Commented Aug 18, 2022 at 18:51

2 Answers 2

0

I made code a little simpler :

public static class ExtractLogFile
    {
        public static void ExtractData(string filePath)
        {
            XDocument doc = XDocument.Load(filePath);
           
            IEnumerable<XElement> measList = doc.Descendants("Measurement");

            foreach (XElement el2 in measList)
            {
                Measurement mes = new Measurement();

                mes.MeasurementInfoGuid = (String)el2.Element("MeasurementGuid");
                mes.SequenceNumber = (int)el2.Element("SequenceNumber");
                mes.Time = (DateTime)el2.Element("Time");

                if (el2.Element("SensorBlobVersion") == null)
                {
                    mes.SensorBlobVersion = 0;
                }
                else
                {
                    int version = 0; 
                    Boolean isInt = int.TryParse((string)el2.Element("SensorBlobVersion"),out version );
                    mes.SensorBlobVersion = isInt ? version : null;
                }
            }
        }

        public class Measurement
        {
            public String MeasurementInfoGuid { get; set; }
            public int SequenceNumber { get; set; }
            public DateTime Time { get; set; }
            public int? SensorBlobVersion { get; set; }
        }

    }
Sign up to request clarification or add additional context in comments.

Comments

0

The attribute xsi:nil is a w3c standard attribute that indicates that an element has no content. Microsoft's XmlSerializer will sometimes serialize a null value as an empty XML element with xsi:nil="true" as specified in the docs:

When serializing objects into an XML document: If the XmlSerializer class encounters a null reference for an object corresponding to an XML element, it either generates an element that specifies xsi:nil="true" or leaves the element out entirely, depending on whether a nillable="true" setting applies.

If your XML was generated with elements that have xsi:nil="true" attributes for null values and you are parsing manually using LINQ to XML, you will need to check for them manually.

First, introduce the following extension method:

public static class XNodeExtensions
{
    static readonly XNamespace xsi = @"http://www.w3.org/2001/XMLSchema-instance";
    static readonly XName xsiNil = xsi + "nil";
    
    public static bool IsNull(this XElement? element) => element == null || element.Attribute(xsiNil)?.Value == "true";
}

And now modify your code as follows:

var sensorBlobVersionElement = el2.Element("SensorBlobVersion");

if (sensorBlobVersionElement == null)
    mes.SensorBlobVersion = 0; // Element was missing, assign to 0
else if (sensorBlobVersionElement.IsNull()) 
    mes.SensorBlobVersion = null; // Element was present but explicitly null
else
    mes.SensorBlobVersion = (int?)(sensorBlobVersionElement);

Here I am assuming you need to distinguish between the case of a missing <SensorBlobVersion> element and a null <SensorBlobVersion xsi:nil="true" /> element. If you don't need to distinguish you could assign both cases to the same value, e.g.:

if (sensorBlobVersionElement.IsNull()) 
    mes.SensorBlobVersion = null; // Element was missing or null
else
    mes.SensorBlobVersion = (int?)(sensorBlobVersionElement);

Demo fiddle here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.