We have a product which uses ‘XmlTextWriter’ in C# – .NET 2.0 to create a large number of small XML Files. These files are then repeatedly read using ‘XmlTextReader’.
We have found that in very rare cases on a few customer machines the contents of the XML File is replaced by a large number of white spaces. Once this happens the ‘XmlTextReader’ will obviously fail to read the XML File with the error “Root Element is missing”.
Here are the logic details:
-
When writing a new Xml File – the file is first written to a temporary folder using :
XmlTextWriter xDoc = new XmlTextWriter(Path, Encoding.UTF8); -
Once the file is written to the temporary folder – ‘XmlTextReader’ is used to verify the file.
-
If and only if the file is verified then it is copied to the final location.
-
Over a few days the file is read multiple times using:
XmlTextReader xDoc = new XmlTextReader(Path); -
In some rare cases the reader fails with the error ‘Root Element is Missing’ and we see that the XML File now contains a number of whitespaces and no XML data.
Here are some code extracts:
This code is used for the serialization.
(Keep in mind that the serialization is done to a temporary folder and only copied to the final location once the temporary XmlFile is verified.)
public void SerializeWithXmlTextWriter(XMLMetaData instance, string Path)
{
instance.CommitLists();
#region XmlTextWriter
XmlTextWriter xDoc = null;
try
{
xDoc = new XmlTextWriter(Path, Encoding.UTF8);
xDoc.Formatting = Formatting.Indented;
xDoc.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
xDoc.WriteStartElement("MD");
xDoc.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
xDoc.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
// A number of other elements are written here
xDoc.WriteEndElement();
}
finally
{
if (xDoc != null)
{
xDoc.Close();
xDoc = null;
}
}
#endregion
}
This code is used for the deserialization.
(it is also used to verify the file after serialization.)
public XMLMetaData DeserializeWithXmlTextReader(string Path)
{
XMLMetaData instance = new XMLMetaData();
#region XmlTextReader
XmlTextReader xDoc = null;
try
{
xDoc = new XmlTextReader(Path);
while (xDoc.Read())
{
switch (xDoc.Name)
{
//Each element is processed using a case statement
//Omitted from this code sample
}
}
}
finally
{
if (xDoc != null)
{
xDoc.Close();
xDoc = null;
}
}
#endregion
return instance;
}
We’ve been trying to solve this issue for a number of months and cannot get anywhere since it only happens on a few client machines out of thousands. We have never been able to replicate it on our development and test machines.
We have had reports of the issue vanishing when backup applications are stopped. We also have a customer who only seems to have issues when running Visual Studio.
Also for customers with this problem – it only seems to happen every few weeks!
Thanks in advance for your help 🙂
Simon
You state that the file is verified, then copied, and that the verified file later breaks. I can see at least four possibilities:
The solution to 1 is to use cross-process synchronisation – e.g. semaphores.
To investigate 2, you can check the file after copying.
To be paranoid about 3 and 4 you can ensure that the copy is created read-only, and for 4 you can pass XmlTextReader a FileStream opened read-only rather than a path.
If none of these help, at least you’ll have ruled out a few possibilities.