C# XML Сериализатор не может десериализовать знак градуса Цельсия - PullRequest
0 голосов
/ 07 августа 2020

У меня есть несколько xml файлов, которые мне нужно десериализовать и сохранить в базе данных. Я нашел общую реализацию c десерилизатора XML, которая отлично справляется со своей задачей. Единственное неудобство состоит в том, что я не могу десериализовать знак градуса Цельсия.

Следующие XML образцы содержат знак градуса Цельсия, который я не могу десериализовать:

<pt>
          <ch>1</ch>
          <type>Analog</type>
          <chtype>Temperature</chtype>
          <chunits>°C</chunits>
          <time>2020-05-03 22:10:00</time>
          <value>0</value>
        </pt>

или

 <pt>
          <ch>5</ch>
          <type>Analog</type>
          <chtype>Wind Direction</chtype>
          <chunits>°</chunits>
          <time>2020-05-03 22:10:00</time>
          <value>0</value>
        </pt>

Моя реализация десериализатора следующая:

public class XmlConvert
    {
        public static string SerializeObject<T>(T dataObject)
        {
            if (dataObject == null)
            {
                return string.Empty;
            }
            try
            {
                using (StringWriter stringWriter = new System.IO.StringWriter())
                {
                    var serializer = new XmlSerializer(typeof(T));
                    serializer.Serialize(stringWriter, dataObject);
                    return stringWriter.ToString();
                }
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
        }

        public static T DeserializeObject<T>(string xml)
            where T : new()
        {
            if (string.IsNullOrEmpty(xml))
            {
                return new T();
            }
            try
            {
                using (var stringReader = new StringReader(xml))
                {
                    var serializer = new XmlSerializer(typeof(T));
                    return (T)serializer.Deserialize(stringReader);
                }
            }
            catch (Exception ex)
            {
                return new T();
            }
        }
    }

Класс, который я использую для преобразования, следующий:

  /// <summary>
    /// Container for a single data point.
    /// </summary>
    public class MessageDataPoint
    {
        /// <summary>
        /// Channel number for data point.
        /// </summary>
        [System.Xml.Serialization.XmlElement("ch")]
        public string Ch { get; set; }

        /// <summary>
        /// Point type (Analog, Flow)
        /// </summary>
        [System.Xml.Serialization.XmlElement("type")]
        public string Type { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [System.Xml.Serialization.XmlElement("chtype")]
        public string ChType { get; set; }

        /// <summary>
        /// Channel units
        /// </summary>
        [System.Xml.Serialization.XmlElement("chunits")]
        public string ChUnits { get; set; }

        /// <summary>
        /// Point timestamp. 
        /// </summary>
        [System.Xml.Serialization.XmlElement("time")]
        public string Time { get; set; }

        [System.Xml.Serialization.XmlIgnore]
        public DateTime? TimeParsed
        {
            get
            {
                DateTime.TryParse(Time, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt);
                return dt;
            }
            private set { }
        }

        /// <summary>
        /// Channel Value
        /// </summary>
        [System.Xml.Serialization.XmlElement("value")]
        public string Value { get; set; }

    }

Реализация десериализатора следующая:

 public async Task<string> GetFileAsStream(string key)
 {
            
 var content = string.Empty;
            
try
{
   GetObjectRequest request = new GetObjectRequest
                {
                    BucketName = bucketName,
                    Key = key
                };

   using (GetObjectResponse response = await client.GetObjectAsync(request))
   {
    using (StreamReader reader = new StreamReader(response.ResponseStream))
    {
        content = await reader.ReadToEndAsync();
                        
        var logger = XmlConvert.DeserializeObject<Logger>(content);

        // code removed for brevity
     }
  }
 }
}

Результат следующий:

<pt>
          <ch>1</ch>
          <type>Analog</type>
          <chtype>Temperature</chtype>
          <chunits>�C</chunits>
          <time>2020-05-03 22:10:00</time>
          <value>0</value>
        </pt>
        <pt>
          <ch>2</ch>
          <type>Analog</type>
          <chtype>Wind Chill</chtype>
          <chunits>�C</chunits>
          <time>2020-05-03 22:10:00</time>
          <value>0</value>
        </pt>

Есть идеи?

Это образец файла:

<?xml version="1.0" encoding="ISO-8859-15"?>
<logger>
   <id>111111</id>
   <mobileNumber>12345676</mobileNumber>
   <serialNumber>01404</serialNumber>
   <siteName>abcdef</siteName>
   <siteId>abcdef</siteId>
   <maintenanceflag>False</maintenanceflag>
   <messages>
     <message>
       <id>123456789</id>
       <number>123456</number>
       <dateReceived>2020-05-04 00:02:25.0</dateReceived>
       <dateCredited>2020-05-04 00:02:25.0</dateCredited>
       <message>        <siteId>abcdef</siteId>
        <type>data</type>
        <RST>2020-01-18 08:50:00</RST>
        <RTC>2020-05-03 23:02:24</RTC>
        <DST>2020-05-03 22:00:00</DST>
        <mode>0</mode>
        <SR>600</SR>
        <pt>
          <ch>1</ch>
          <type>Analog</type>
          <chtype>Temperature</chtype>
          <chunits>°C</chunits>
          <time>2020-05-03 23:00:00</time>
          <value>0</value>
        </pt>
      
        <pt>
          <ch>5</ch>
          <type>Analog</type>
          <chtype>Wind Direction</chtype>
          <chunits>°</chunits>
          <time>2020-05-03 23:00:00</time>
          <value>0</value>
        </pt>
     
     
      </message>
       <format>BINARY</format>
       <source>FTP</source>
       <batteryCondition>123</batteryCondition>
       <signalStrength>12</signalStrength>
    </message>
  </messages>
</logger>

Ответы [ 2 ]

0 голосов
/ 07 августа 2020

Передать поток сериализатору. Это значительно упростит код. Более того, вы можете полностью удалить свой класс XmlConvert.

using (GetObjectResponse response = await client.GetObjectAsync(request))
using (var stream = response.ResponseStream)
{
    var serializer = new XmlSerializer(typeof(Logger));
    var logger = (Logger)serializer.DeserializeObject(stream);
}

Но если вы считаете, что класс XmlConvert необходим, например, он выполняет некоторую дополнительную работу, то по крайней мере используйте в нем Stream вместо string.

public static T DeserializeObject<T>(Stream stream)
    where T : new()
{
    try
    {
        var serializer = new XmlSerializer(typeof(T));
        return (T)serializer.Deserialize(stream);
    }
    catch (Exception ex)
    {
        return new T();
    }
}
0 голосов
/ 07 августа 2020

Я нашел решение, просмотрев следующий пост в Stackoverflow

Использование. NET как преобразовать текстовые файлы в кодировке ISO 8859-1, содержащие символы с диакритическими знаками Latin-1, в UTF-8

Спасибо Нергудсу и Александру Хаасу за то, что указали мне в правильном направлении

Решение для меня было

public async Task<string> GetFileAsStream(string key)
 {
            
 var content = string.Empty;
            
try
{
   GetObjectRequest request = new GetObjectRequest
                {
                    BucketName = bucketName,
                    Key = key
                };

   using (GetObjectResponse response = await client.GetObjectAsync(request))
   {
    using (StreamReader reader = new StreamReader(response.ResponseStream, Encoding.GetEncoding("iso-8859-1")))
    {
        content = await reader.ReadToEndAsync();
                        
        var logger = XmlConvert.DeserializeObject<Logger>(content);

        // code removed for brevity
     }
  }
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...