XmlSerializer и встроенный WhiteSpace - PullRequest
       10

XmlSerializer и встроенный WhiteSpace

5 голосов
/ 04 сентября 2010

У меня есть следующий xml, который содержит пробел Field1Value. Когда я десериализую этот xml, я теряю один пробел. Значение Request.Field2 равно "". Это ошибка в сериализаторе xml? Кто-нибудь может порекомендовать решение / обходной путь, чтобы сохранить это место?

  ...
            var encoding = new System.Text.UTF8Encoding();
            var _xmlData = "<Request><Field1>Field1Value</Field1><Field2>   </Field2></Request>";
            var _xmlDataAsByteArray = new byte[_xmlData.Length];
            _xmlDataAsByteArray = encoding.GetBytes(_xmlData);

            var _memoryStream = new MemoryStream(_xmlDataAsByteArray);

           var _XmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(Request));

            Request _request = _XmlSerializer.Deserialize(_memoryStream) as Request;

  ...
         public class Request
           {
               public string Field1;
               public string Field2;
           }

Ответы [ 5 ]

3 голосов
/ 16 января 2015

Вы можете использовать XmlReader для загрузки xml с установленным на IngoreWhitespace значением false

new XmlSerializer(typeof(Request)).Deserialize(XmlReader.Create(_memoryStream, new XmlReaderSettings { IgnoreWhitespace = false })) as Request;
3 голосов
/ 04 сентября 2010

Нет, это не ошибка, а ожидаемое поведение.Если вы не выбрали сохранение пространства, XML - это процессоры (т.е. приложения, читающие и пишущие XML), должны нормализовать пробелы .См. Раздел 2.1 спецификации XML 1.1 здесь .

Чтобы сохранить пробелы, вы должны включить атрибут xml:space="preserve".Следовательно, XML должен выглядеть так:

<Request>
   <Field1>Field1Value</Field1>
   <!-- spaces inside Field2 will be preserved -->
   <Field2 xml:space="preserve">   </Field2> 
</Request>
0 голосов
/ 28 сентября 2011

Я только что столкнулся с этой проблемой. В моем случае XML генерируется кодом, который я контролирую, поэтому я смог добавить атрибут xml: space = preserve. Я использовал IXmlSerializable (по уважительной причине, что я не буду вдаваться здесь). Вот как я это сделал, на случай, если это кому-нибудь пригодится (трудно найти примеры значительной части этой сериализации / десериализации Xml). Этот метод WriteSettings () вызывается моим методом WriteXml (), реализующим IXmlSerializable.

    public static void WriteSettings(XmlWriter writer, Dictionary<string, string> settings)
    {
        foreach (string key in settings.Keys)
        {
            string value = settings[key];
            writer.WriteStartElement("Setting");
            writer.WriteElementString("SettingType", key);

            //writer.WriteElementString("SettingValue", value);
            // I replaced the above line, which I had previously, 
            // with the below 5 lines. 
            writer.WriteStartElement("SettingValue");
            if (value != value.Trim())
                writer.WriteAttributeString("xml", "space", null, "preserve");
            writer.WriteString(value);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }
    }

Это дает мне XML, который выглядит следующим образом (включающий элемент, записанный включающим объектом, а не методом WriteSettings, описанным выше):

<ResourceSettings>
  <Setting>
    <SettingType>SomeSettingName</SettingType>
    <SettingValue>1</SettingValue>
  </Setting>
  <Setting>
    <SettingType>AnotherSettingName</SettingType>
    <SettingValue xml:space="preserve"> </SettingValue>
  </Setting>
  <Setting>
    <SettingType>ADifferentSettingName</SettingType>
    <SettingValue>some other value</SettingValue>
  </Setting>
</ResourceSettings>

Я прочитал это, используя тот же код, что и раньше, и XmlReader учитывает атрибут xml: space = preserve, например:

    public void ReadXml(XmlReader reader)
    {
        _cache = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
        if (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "ResourceSettings")
        {
            // Deal with the case where there are no settings
            if (reader.ReadToDescendant("Setting"))
            {
                while (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "Setting")
                {
                    reader.ReadStartElement("Setting");
                    string key = reader.ReadElementString("SettingType");
                    string value = reader.ReadElementString("SettingValue");
                    reader.ReadEndElement();
                    _cache.Add(key, value);
                }
            }
            reader.Read(); // move past container
        }
    }
0 голосов
/ 16 августа 2011

Я просто хотел разобраться с сохранением пробелов, и этот ответ полезен в этом отношении: Как сохранить пробельные символы при разборе XML из C # LINQ

0 голосов
/ 04 сентября 2010

Может быть, атрибут xml: space может помочь, установив для него значение «сохранить». См. эту статью в качестве отправной точки.

...