Search code examples
c#.netxmlwhitespacexmlserializer

Preserve whitespace-only element content when deserializing XML using XmlSerializer


I have a class InputConfig which contains a List<IncludeExcludeRule>:

public class InputConfig
{
    // The rest of the class omitted 
    private List<IncludeExcludeRule> includeExcludeRules;
    public List<IncludeExcludeRule> IncludeExcludeRules
    {
        get { return includeExcludeRules; }
        set { includeExcludeRules = value; }
    }
}

public class IncludeExcludeRule
{
    // Other members omitted
    private int idx;
    private string function;

    public int Idx
    {
        get { return idx; }
        set { idx = value; }
    }

    public string Function
    {
        get { return function; }
        set { function = value; }
    }
}

Using ...

FileStream fs = new FileStream(path, FileMode.Create);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(InputConfig));
xmlSerializer.Serialize(fs, this);
fs.Close();

... and ...

StreamReader sr = new StreamReader(path);
XmlSerializer reader = new XmlSerializer(typeof(InputConfig));
InputConfig inputConfig = (InputConfig)reader.Deserialize(sr);

It works like a champ! Easy stuff, except that I need to preserve whitespace in the member function when deserializing. The generated XML file demonstrates that the whitespace was preserved when serializing, but it is lost on deserializing.

<IncludeExcludeRules>
  <IncludeExcludeRule>
    <Idx>17</Idx>
    <Name>LIEN</Name>
    <Operation>E =</Operation>
    <Function>  </Function>
  </IncludeExcludeRule>
</IncludeExcludeRules>

The MSDN documentation for XmlAttributeAttribute seems to address this very issue under the header Remarks, yet I don't understand how to put it to use. It provides this example:

// Set this to 'default' or 'preserve'.
[XmlAttribute("space", 
Namespace = "http://www.w3.org/XML/1998/namespace")]
public string Space 

Huh? Set what to 'default' or 'preserve'? I'm sure I'm close, but this just isn't making sense. I have to think there's just a single line XmlAttribute to insert in the class before the member to preserve whitespace on deserialize.

There are many instances of similar questions here and elsewhere, but they all seem to involve the use of XmlReader and XmlDocument, or mucking about with individual nodes and such. I'd like to avoid that depth.


Solution

  • To preserve all whitespace during XML deserialization, simply create and use an XmlReader:

    StreamReader sr = new StreamReader(path);
    XmlReader xr = XmlReader.Create(sr);
    XmlSerializer reader = new XmlSerializer(typeof(InputConfig));
    InputConfig inputConfig = (InputConfig)reader.Deserialize(xr);
    

    Unlike XmlSerializer.Deserialize(XmlReader), XmlSerializer.Deserialize(TextReader) preserves only significant whitespace marked by the xml:space="preserve" attribute.