XmlDocument Save keeps file open - c#

I have a simple c# function that creates a basic XML file and saves:
private void CreateXMlFile(string Filename, string Name, string Company)
{
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(docNode);
XmlNode licenseNode = doc.CreateElement("license");
doc.AppendChild(licenseNode);
XmlNode node = doc.CreateElement("Name");
node.AppendChild(doc.CreateTextNode(Name));
licenseNode.AppendChild(node);
node = doc.CreateElement("Company");
node.AppendChild(doc.CreateTextNode(Company));
licenseNode.AppendChild(node);
doc.Save(Filename);
}
When I try to edit or delete the file I always get following error:
The process cannot access the file because it is being used by another
process.
XmlDocument doesnt have any inbuilt dispose or close routines and wondered how I can force the file to close before later editing or deleting it.
I have tried to save the file using StreamWriter:
StreamWriter outStream = System.IO.File.CreateText(outfile);
outStream.Write(data);
outStream.Close();
But this didnt make a difference with the same error.
Your advice is greatly accepted.
Thank you

Send Stream to XmlDocument's Save method instead of file name.
private static void Main(string[] args)
{
CreateXMlFile("c:\\test.xml", "testName", "testCompany");
}
private static void CreateXMlFile(string Filename, string Name, string Company)
{
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(docNode);
XmlNode licenseNode = doc.CreateElement("license");
doc.AppendChild(licenseNode);
XmlNode node = doc.CreateElement("Name");
node.AppendChild(doc.CreateTextNode(Name));
licenseNode.AppendChild(node);
node = doc.CreateElement("Company");
node.AppendChild(doc.CreateTextNode(Company));
licenseNode.AppendChild(node);
StreamWriter outStream = System.IO.File.CreateText(Filename);
doc.Save(outStream);
outStream.Close();
}
I tried executing above code and it is working fine at my end.

Your code is fine. I tested it on my machine and there is no lock left after Save().
Try to use Unlocker (http://www.softpedia.com/get/System/System-Miscellaneous/Unlocker.shtml) to check whether you are really the one who holds the lock.
Which .NET framework do you use? Theres also a report (http://bytes.com/topic/net/answers/467028-xmldocument-save-does-not-close-file-properly) which was not reproducable too.

Related

Null return on XmlDocument.SelectSingleNode through valid xpath (did try the old answer)

I've read the other question and apply the answer to my code, but it still doesn't work.
I use xml to read the csproj file to read/write something into it body.
This is my csproject file if anyone care!
My code:
static void Main(string[] args)
{
string file = #"D:\Project\svn_longnx\LearnSvnRevision\ConsoleApp1\WindowsFormsApp1\WindowsFormsApp1.csproj";
XmlDocument xdoc = new XmlDocument();
xdoc.Load(file);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("default", "http://schemas.microsoft.com/developer/msbuild/2003");
XmlElement root = xdoc.DocumentElement;
XmlNode node = root.SelectSingleNode("Project/PropertyGroup/ApplicationVersion",nsmgr);
Console.WriteLine(node.Value);
}
This dummy code failed either:
static void Main(string[] args)
{
string file = #"D:\Project\svn_longnx\LearnSvnRevision\ConsoleApp1\WindowsFormsApp1\WindowsFormsApp1.csproj";
XmlDocument xdoc = new XmlDocument();
xdoc.Load(file);
XmlElement root = xdoc.DocumentElement;
XmlNode node = root.SelectSingleNode("Project/PropertyGroup/ApplicationVersion");
Console.WriteLine(node.Value);
}
It's much easier to use XDocument and associated objects instead of the older XmlDocument bits. Also, you're probably falling down because of namespaces. Instead, try this code:
var doc = XDocument.Load(#"D:\Project\svn_longnx\Lear...\WindowsFormsApp1.csproj");
var ns = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");
var applicationVersionElements = doc.Element(ns + "Project")
.Descendants(ns + "PropertyGroup")
.Descendants(ns + "ApplicationVersion");
foreach (var element in applicationVersionElements)
{
Console.WriteLine(element.Name);
}
This is just one way as an example of how to get that specific element to demonstrate how easy it is to use.
Note, you may need to add using System.Xml.Linq;

ExceptionLogger with using xml

I am writing to ask you about such question. So i have method which writes exception's info into xml file, but if some exception processed, this method replace all that it is in that file. I want that method write to end file a new info about exception
Code of my method is given below:
public void WriteIntoFile()
{
XDocument xdoc = new XDocument(
new XElement("Exceptions",
new XElement("Exception",
new XElement("Message",this.ErrorMessage.ToString())
)));
xdoc.Save("1.xml");
}
Please, help me with it
This should do the Job, assuming the file exists and you create a new node call "Exceptions".
public void WriteIntoFile(string Message)
{
const string Path = "C:\\Temp\\Log.xml";
XmlDocument MyDocument = new XmlDocument();
MyDocument.Load(Path);
XmlNode ExceptionsNode = MyDocument.CreateElement("Exceptions");
XmlNode ExceptionNode = MyDocument.CreateElement("Exception");
XmlNode MessageNode = MyDocument.CreateElement("Message");
MessageNode.InnerText = Message;
ExceptionNode.AppendChild(MessageNode);
ExceptionsNode.AppendChild(ExceptionNode);
MyDocument.AppendChild(ExceptionsNode);
}
if you want the "Exception"- Node append to a existing "Exceptions" node, use this:
XmlNode ExceptionsNode = MyDocument.SelectSingleNode("/Exceptions");
Greetings from Austria.

Trying to Load an XML File Upon Form Load, Getting Error

In C# am trying to check to see if an XML file is created, if not create the file and then create the xml declaration, a comment and a parent node.
When I try to load it, it gives me this error:
"The process cannot access the file 'C:\FileMoveResults\Applications.xml' because it is being used by another process."
I checked the task manager to ensure it wasn't open and sure enough there were no open applications of it. Any ideas of what's going on?
Here is the code I am using:
//check for the xml file
if (!File.Exists(GlobalVars.strXMLPath))
{
//create the xml file
File.Create(GlobalVars.strXMLPath);
//create the structure
XmlDocument doc = new XmlDocument();
doc.Load(GlobalVars.strXMLPath);
//create the xml declaration
XmlDeclaration xdec = doc.CreateXmlDeclaration("1.0", null, null);
//create the comment
XmlComment xcom = doc.CreateComment("This file contains all the apps, versions, source and destination paths.");
//create the application parent node
XmlNode newApp = doc.CreateElement("applications");
//save
doc.Save(GlobalVars.strXMLPath);
Here is the code I ended up using to fix this issue:
//check for the xml file
if (!File.Exists(GlobalVars.strXMLPath))
{
using (XmlWriter xWriter = XmlWriter.Create(GlobalVars.strXMLPath))
{
xWriter.WriteStartDocument();
xWriter.WriteComment("This file contains all the apps, versions, source and destination paths.");
xWriter.WriteStartElement("application");
xWriter.WriteFullEndElement();
xWriter.WriteEndDocument();
}
File.Create() returns a FileStream that locks the file until it's closed.
You don't need to call File.Create() at all; doc.Save() will create or overwrite the file.
I would suggest something like this:
string filePath = "C:/myFilePath";
XmlDocument doc = new XmlDocument();
if (System.IO.File.Exists(filePath))
{
doc.Load(filePath);
}
else
{
using (XmlWriter xWriter = XmlWriter.Create(filePath))
{
xWriter.WriteStartDocument();
xWriter.WriteStartElement("Element Name");
xWriter.WriteEndElement();
xWriter.WriteEndDocument();
}
//OR
XmlDeclaration xdec = doc.CreateXmlDeclaration("1.0", null, null);
XmlComment xcom = doc.CreateComment("This file contains all the apps, versions, source and destination paths.");
XmlNode newApp = doc.CreateElement("applications");
XmlNode newApp = doc.CreateElement("applications1");
XmlNode newApp = doc.CreateElement("applications2");
doc.Save(filePath); //save a copy
}
The reason your code is currently having problems is because of: File.Create creates the file and opens the stream to the file, and then you never make use of it (never close it) on this line:
//create the xml file
File.Create(GlobalVars.strXMLPath);
if you did something like
//create the xml file
using(Stream fStream = File.Create(GlobalVars.strXMLPath)) { }
Then you would not get that in use exception.
As a side note XmlDocument.Load will not create a file, only work with an already create one
You could create a stream, setting the FileMode to FileMode.Create and then use the stream to save the Xml to the path specified.
using (System.IO.Stream stream = new System.IO.FileStream(GlobalVars.strXMLPath, FileMode.Create))
{
XmlDocument doc = new XmlDocument();
...
doc.Save(stream);
}

C# XMLdocument writing same thing over again

In my application, lots of data is generated and then written in a XML file using XmlDocument.
The mechanics works fine, but when I call the function that serializes again and again to write data in a new XML, it copies what it wrote previously to the new XML plus the new data!
I don't understand, I'm calling XmlDocument doc = new XmlDocument() at the beggining of the function that serializes...
private static Boolean SaveParsedDataAsXML(ParsedData DataParsed, String Name)
{
try
{
XmlDocument doc = new XmlDocument();
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
doc.AppendChild(xmlnode);
XmlElement generalVariables = doc.CreateElement("Variables");
generalVariables.AppendChild(SerializeElement(doc, "Path", DataParsed.Path));
.
.
.
XmlElement chatMessages = doc.CreateElement("ChatMessages");
foreach (Message mess in DataParsed.ChatMessages)
{
XmlElement singleMess = doc.CreateElement("SingleMessage");
singleMess.AppendChild(SerializeElement(doc, "MessageID", mess.MessageID.ToString()));
singleMess.AppendChild(SerializeElement(doc, "MessageName", mess.MessageName));
singleMess.AppendChild(SerializeElement(doc, "MessageTime", mess.MessageTime.ToString()));
singleMess.AppendChild(SerializeElement(doc, "MessageContent", mess.MessageContent));
singleMess.AppendChild(SerializeElement(doc, "MessageTarget", mess.MessageTarget.ToString()));
chatMessages.AppendChild(singleMess);
}
generalVariables.AppendChild(chatMessages);
.
.
.
doc.AppendChild(generalVariables);
//Saving and returning true, serialization successful.
doc.Save(OutputPath + "\\" + ReplayName + ".xml");
return true;
}
catch
{
return false;
}
}
My assumption would be that you're not clearing the DataParsed.ChatMessages object before you pass it in to the function you posted.
Are you sure you're using a new DataParsed object each time? Or are you re-using the same instance and appending more messages to it?

creating new xml file by C#

how we can create new xml file by C# in the following situation:
its winform.
our xml code is in a string str = "<><><><>...etc"
now i want to create an xml file myxml.xml which contains everything in str,
please answer in the context and thanks...
need simple source code
XmlDocument.LoadXml
using System;
using System.Xml;
public class Sample {
public static void Main() {
// Create the XmlDocument.
XmlDocument doc = new XmlDocument();
doc.LoadXml("<item><name>wrench</name></item>"); //Your string here
// Save the document to a file and auto-indent the output.
XmlTextWriter writer = new XmlTextWriter("data.xml",null);
writer.Formatting = Formatting.Indented;
doc.Save(writer);
}
}
Hi how about creating a method just for this:
private static void CreateXMLFile(string xml, string filePath)
{
// Create the XmlDocument.
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml); //Your string here
// Save the document to a file and auto-indent the output.
XmlTextWriter writer = new XmlTextWriter(filePath, null);
writer.Formatting = Formatting.Indented;
doc.Save(writer);
}
If the only thing you want to do is to save the string as a file (and you don't want to do do XML-specific stuff like checking well-formedness or automatic indenting), you can simply use File.WriteAllText().

Categories