views:

813

answers:

2

I have a class with a property marked with [XmlText], that accepts multiline input. In my XML file, I've verified that the line endings inside the text content are infact "\r\n", the same as the rest of the file.

The code I'm using to deserialize is:

XmlSerializer configSerializer = new XmlSerializer(typeof(WorldList));
string file = "test.xml";

if (File.Exists(file))
{
    using (TextReader r = new StreamReader(file))
    {
        foo = configSerializer.Deserialize(r);
    }
}

But, inside the setter for the [XmlText] property, value already has "\n" as a line ending. The main reason this is annoying is because "\n" line endings don't display properly in a TextBox... I'm not exactly sure which part is causing the problems, but I thought someone here might be able to shed some light on the situation.

+2  A: 

If you were serializing, then XmlWriterSettings.NewLineHandling (Replace) would be worth trying - but this won't help reading. A bit grungy, but perhaps do this directly in the setter:

private string text;
[XmlText]
public string Text {
    get { return text; }
    set 
    {
        Regex r = new Regex("(?<!\r)\n");
        text = r.Replace(value, "\r\n"); 
    }
}
Marc Gravell
Yea, I was thinking a regex replace might be the only solution, but I was hoping there was some "better way"[tm]
Matthew Scharley
There is another way, I wouldn't say it was better- I will post an answer shortly.
RichardOD
The Regex is a nice example of finding out when only \n is used instead of \r\n.
RichardOD
+2  A: 

I've change the sample code to make it easier to quickly put the code into a C# development environment. I've also deliberately not included using statements- it is only sample code.

For the example we have the follow class we wish to serialize:

   public class DataToSerialize
   {
       public string Name { get; set; }
   }

If we try to serialize and deserialize this in the way you describe the line where "Same" gets printed out will not get executed (I'm assuming the code will run on Windows with Environment.NewLine, replace with "\r\n" if you are not):

    DataToSerialize test = new DataToSerialize();
    test.Name = "TestData" + Environment.NewLine;
    XmlSerializer configSerializer = new XmlSerializer(typeof(DataToSerialize));
    MemoryStream ms = new MemoryStream();
    StreamWriter sw = new StreamWriter(ms);
    configSerializer.Serialize(sw, test);
    ms.Position = 0;
    DataToSerialize deserialized = (DataToSerialize)configSerializer.Deserialize(ms);
    if (deserialized.Name.Equals("TestData" + Environment.NewLine))
    {
        Console.WriteLine("Same");
    }

However this can be fixed, by manually assigning an XmlTextReader to the serializer, with it's Normalization property set to false (the one used by default in the serializer is set to true):

    DataToSerialize test = new DataToSerialize();
    test.Name = "TestData" + Environment.NewLine;
    XmlSerializer configSerializer = new XmlSerializer(typeof(DataToSerialize));
    MemoryStream ms = new MemoryStream();
    StreamWriter sw = new StreamWriter(ms);

    configSerializer.Serialize(sw, test);
    ms.Position = 0;
    XmlTextReader reader = new XmlTextReader(ms);
    reader.Normalization = false;
    DataToSerialize deserialized = (DataToSerialize)configSerializer.Deserialize(reader);
    if (deserialized.Name.Equals("TestData" + Environment.NewLine))
    {
        Console.WriteLine("Same");
    }

Same will now be printing out, which unless I am wrong is the behaviour you require?

RichardOD
I like that ;-p
Marc Gravell
For the record though, lack of using statements in sample code makes it harder to read in my opinion... nothing wrong with using.
Matthew Scharley
@Matthew- I guess it is one of those subjective things- to prove one is better than the other you'd really need to perform a controlled experiment. With my answer it is a little odd as the MemoryStream needs to be scoped across both the serialization and the deserialization, which in the real world wouldn't happen. In the case of your question having using statements is useful (in my opinion). When I was writing the code I actually included the using statements, but ripped them out when posting the answer (my brain is wired up to prevent FXCop complaining).
RichardOD
"my brain is wired up to prevent FXCop complaining" - That can only be a good thing, in my experience.
Matthew Scharley