So I'm currently working on an ASP.NET project. It requires me to write a List<> onto a XML file. I created a "data.xml" file within the project folder and here are my few lines of code:
XmlSerializer serializer = new XmlSerializer(typeof(List<BookItem>));
TextWriter filestream = new StreamWriter("data.xml");
serializer.Serialize(filestream, book);
filestream.Close();
it works well
like this
until I want to add a new record, then the file is overwritten every single time. I believe i only need few tricky lines of code to solve this problem but since my research didn't bring up any answer, i really need your help.
Related
I am working on a WPF application and I have a simple XML file that I am parsing using 'XmlDocument' and is working fine for the readinh part.
I want the use to be able to add, edit or delete any node and save these changes to the file.
I tried using 'XElement' but it seems to change the instance itself and not the file.
My XML file looks something like this:
<Configuration>
<A_0.04_5>
<ML407Configuration>
<AM_Amp>10</AM_Amp>
<AMRJ_Amp>10</AMRJ_Amp>
<FM_Freq>20</FM_Freq>
<FM_Phase_Shift>20</FM_Phase_Shift>
</ML407Configuration>
<BertConfiguration>
<BERT_LR>25.78125</BERT_LR>
<BERT_PRBS>7</BERT_PRBS>
<BERT_Scaling>1000</BERT_Scaling>
</BertConfiguration>
</A_0.04_5>
<B_1.333_0.15>
<ML407Configuration>
<AM_Amp>10</AM_Amp>
<AMRJ_Amp>10</AMRJ_Amp>
<FM_Freq>20</FM_Freq>
<FM_Phase_Shift>20</FM_Phase_Shift>
</ML407Configuration>
<BertConfiguration>
<BERT_LR>25.78125</BERT_LR>
<BERT_PRBS>7</BERT_PRBS>
</BertConfiguration>
</B_1.333_0.15>
<C_4_0.05>
<ML407Configuration>
<BUJ_LR>25</BUJ_LR>
<BUJ_Pattern>7</BUJ_Pattern>
<PM_BUJ_Amp>7</PM_BUJ_Amp>
<BUJ_Amp>80</BUJ_Amp>
</ML407Configuration>
<BertConfiguration>
<BERT_LR>25.78125</BERT_LR>
<BERT_PRBS>7</BERT_PRBS>
</BertConfiguration>
</C_4_0.05>
</Configuration>
What I tried is the following:
string filePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"/Configuration.xml";
XElement xml = XElement.Load(filePath);
// This seems to remove the node from xml instance and not from the file
// Should I save the file again or is there another way to do it
// Same applies for add and edit
xml.Elements("C_4_0.05").Remove();
I have seen a lot of similar questions but I don't know if any of them change directly to the file or not
XElement.Load loads an XML structure from a file into memory. Any changes you make to that structure are also done in memory. If you want to write those changes back to a file (technically called serialization) you need to call XElement.Save.
I have a program written in .NET 3.5 which saves data to an XML file, and most of the time will leave it alone after that. However, sometimes it needs to read that XML file back in. When I try to do this, the XML file read fails with the error that the file is "in use by another process".
Here's the code that performs the XML file write:
DataSet ds = new DataSet();
ds.Tables.Add(populatedDataTable);
XmlTextWriter xmlWrite = new XmlTextWriter("C:\test\output.xml", Encoding.UTF8);
ds.WriteXml(xmlWrite);
xmlWrite.Close();
And here's the code that tries to read the XML file back in:
TextReader tr = new StreamReader("C:\test\output.xml");
DataSet dsXmlData = new DataSet();
dsXmlData.ReadXml(tr);
Since the XmlTextWriter.Close() method is run in the first block, why would the file still be in use? I tried calling the Dispose() method on the DataSet in the first block as well, but that didn't help. What could be missing here?
I also tested running the program in debug mode, and then waiting a bit after the first code block has run, before continuing. It still gave the same error, this isn't an issue of the code running so close together that the file write isn't fully released before the read is attempted.
Thanks!
I was able to resolve the problem by changing the logic to have using statements instead of creating the XmlTextWriter and then closing it manually.
Here's the old code:
XmlTextWriter xmlWrite = new XmlTextWriter("C:\test\output.xml", Encoding.UTF8);
ds.WriteXml(xmlWrite);
xmlWrite.Close();
Here's the new code that does not have the issue anymore:
using(XmlTextWriter xmlWrite = new XmlTextWriter("C:\test\output.xml", Encoding.UTF8))
ds.WriteXml(xmlWrite);
For anyone curious, I don't have an answer as to why the using statement resolves the problem, but I'm happy to have worked it out.
I am opening existing .docx files from a SharePoint Document Library over the SharePoint web services, and am attempting to attach a new Template to them. The current code for this piece seems to not be doing anything at all.
XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
OpenXmlPart documentSettingsPart = document.MainDocumentPart.DocumentSettingsPart;
XDocument documentSettingsXDoc = documentSettingsPart.GetXDocument();
documentSettingsPart.AddExternalRelationship("http://schemas.openxmlformats/org/officeDocument/2006/relationships/attachedTemplate", new Uri(_outLibraryTemplate, UriKind.Absolute));
using (XmlWriter xw = XmlWriter.Create(documentSettingsPart.GetStream(FileMode.Create, FileAccess.Write)))
documentSettingsXDoc.Save(xw);
Does anyone have any thoughts as to why this isn't working - and what I need to do to get this going?
This may help. It creates a new docx file from a dotx file.
I modified it a little for my own use - I added the external relationship (a dotm) to an existing file. Unfortunately I can't work out yet if I can easily programatically update the styles without having to actually open the file.
https://web.archive.org/web/20150716111136/http://blogs.msdn.com/b/vsod/archive/2012/02/18/how-to-create-a-document-from-a-template-dotx-dotm-and-attach-to-it-using-open-xml-sdk.aspx
I found this great tutorial for loading XML using XLINQ (LINQ to XML).
http://www.codearsenal.net/2012/07/c-sharp-load-xml-using-xlinq.html
It helped me a lot and I got the job done with it.
The only change I made was where he had this line:
from e in XDocument.Load(#"..\..\Employees.xml").Root.Elements("employee")
I write it like this:
from el in XDocument.Load("XML_Files/Employees.xml").Root.Elements("employee")
I had to change the path like this to access a local xml file found right inside my Visual Studio project.
But now I need to save the data back to the file in my project solution. Again, my xml file is located inside my C# project. It's not on the desktop or anything, it is a file added to the project solution.
I can't seem to find any good resources for how to do this task. Does anyone know a good tutorial, or code, a reference to start?
I am inserting a list of objects into the xml files. The objects have basic data type properties, except for one of the object properties, which is a List of doubles.
Can anyone advise a good tutorial or link? Or even a generic code sample?
I'd like to keep this function as basic as possible.
Please help.
------------------ UPDATE ------------------
I actually got this kind of working now. The below code does what I need EXCEPT that it won't write the data to my local file in the Visual Studio project. It will gladly write the data to a test file I created on my desktop, however.
Does anyone know why this is??
//create the serialiser to create the xml
XmlSerializer serialiser = new XmlSerializer(typeof(List<Student>));
// Create the TextWriter for the serialiser to use
TextWriter Filestream = new StreamWriter(#"C:\\Users\\MyName\\Desktop\\output.xml");
//write to the file
serialiser.Serialize(Filestream, employees);
// Close the file
Filestream.Close();
-------- UPDATE ---------
Okay, figured it out.
This code works:
public void WriteXML()
{
//create the serialiser to create the xml
XmlSerializer serialiser = new XmlSerializer(typeof(List<Student>));
// Create the TextWriter for the serialiser to use
TextWriter Filestream = new StreamWriter(#"XML_Files\Employees.xml");
//write to the file
serialiser.Serialize(Filestream, employees);
// Close the file
Filestream.Close();
}
The data is inserted to the xml file, but it does not show in Visual Studio. But when I checked here:
C:\Users\Me\Desktop\MyProject\MyProject\bin\Debug\XML_Files
The file is overwritten.
Also, when I reload the data from the application again, the new entries come up.
The problem is in line:
TextWriter Filestream = new StreamWriter(#"C:\\Users\\MyName\\Desktop\\output.xml");
Change it to one of following:
TextWriter Filestream = new StreamWriter("C:\\Users\\MyName\\Desktop\\output.xml");
TextWriter Filestream = new StreamWriter(#"C:\Users\MyName\Desktop\output.xml");
Simply remove the "#", OR use single slashes:
I am serializing an object with the following code, which uses GZip and Xml:
FileStream fs = new FileStream(destinationfolder + "/myFileName.gz",
FileMode.Create, FileAccess.Write);
using (var gz = new GZipStream(fs, CompressionMode.Compress)) {
var serializer = new XmlSerializer(typeof(MyObjectType));
serializer.Serialize(gz, myObject);
}
That works fine, with one single problem: The user can open the .gz file with 7Zip (after setting the file association), but then he can't just doubleclick the shown xml inside the .gz file, since it doesn't have the .xml extension (although the content is actually there, xml formatted and all).
Question is: "How can I serialize XML to a GZipStream so that the .xml extension is saved with the file, inside the .gz archive?" I'm using .NET 4.0.
Thanks for reading.
I have figure out a simple way to solve that. If this way should be considered a hack or a pragmatic and fine solution, is up to each one, I think.
Simply set the GZip filename to myFileName.xml.gz. This actually makes the inner file appear as myFileName.xml (trimming out the .gz extension as before).
I hope this won't break in the future...