XmlSerializer和嵌入式WhiteSpace

时间:2010-09-03 22:08:30

标签: .net xml-serialization

我有以下包含空格Field1Value的xml。当我反序列化该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 个答案:

答案 0 :(得分:3)

不,这不是一个错误,而是预期的行为。除非您选择保留空间,否则XML是处理器(即读取和写入XML的应用程序)应该规范化空白。请参阅XML 1.1规范here的第2.1节。

要保留空白,您必须包含xml:space="preserve"属性。因此,XML应如下所示:

<Request>
   <Field1>Field1Value</Field1>
   <!-- spaces inside Field2 will be preserved -->
   <Field2 xml:space="preserve">   </Field2> 
</Request>

答案 1 :(得分:3)

您可以使用XmlReader加载xml,并将IngoreWhitespace设置为false

new XmlSerializer(typeof(Request)).Deserialize(XmlReader.Create(_memoryStream, new XmlReaderSettings { IgnoreWhitespace = false })) as Request;

答案 2 :(得分:0)

也许xml:space属性可以通过将其设置为“保留”来提供帮助。请参阅this article作为起点。

答案 3 :(得分:0)

我只是在研究处理保留空白的问题,这个答案在这方面很有用:How do I preserve whitespace characters when parsing XML from C# LINQ

答案 4 :(得分:0)

我刚遇到这个问题。在我的例子中,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
        }
    }