How do we update an existing XML file in C# - c#

I have an existing xml file which I want to update.
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
{
// Load the xml document for reading
using (IsolatedStorageFileStream ISFS = ISF.OpenFile(FILE_NAME, FileMode.Open, FileAccess.ReadWrite))
{
XDocument file= XDocument.Load(ISFS);
//Edit the file
file.Save(ISFS);
}
}
The problem is whenever I use file.Save(ISFS), and then try to load it again, using same method, an error is reported
System.Xml.XmlException was unhandled by user code
HResult=-2146232000
Message=Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it. Line 25, position 14.
UPDATE :
Here's the file after saving
<?xml version="1.0" encoding="utf-8"?>
<A>
<AB ID="0">
<NickName>Dummy</NickName>
</AB>
</A><?xml version="1.0" encoding="utf-8"?>
<A>
<AB ID="0">
<NickName>Dummy</NickName>
</AB>
<AB ID="1">
<NickName>My1</NickName>
</AB>
</A>

Related

XML Tag / Prolog Missing

i am reading and serializing a xml file. I then make some changes to the serialized xml data and save again back to a new file. The serializing and deserializing, saving to file is all working, however I have a value at the top of the xml file that is missing.
How do I set this value before saving the xml file?
Original XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?>
New File XML (missing )
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
It is very simple to implement via LINQ to XML API.
c#
void Main()
{
XDocument xdoc = XDocument.Parse("<root><el>123</el></root>"); // or .Load()
xdoc.Declaration = new XDeclaration("1.0", "UTF-8", "false");
xdoc.Save(#"e:\temp\Output.xml");
}

Saving an xml file using stream results in a duplicate root elements

So I'm attempting to open an xml file, add an XElement to the root element, and save it. Except my C# Code:
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("UserPinouts.tpack", CreationCollisionOption.OpenIfExists);
using (var stream = await file.OpenStreamForWriteAsync())
{
XDocument doc = XDocument.Load(stream);
doc.Root.Add(new XElement(XElement.Parse(CurrentPinOut)));
doc.Save(stream);
Debug.WriteLine(doc.ToString());
stream.Flush();
}
Gives me the following xml file:
<?xml version="1.0" encoding="utf-8" ?>
<RootElement>
<XElement1/>
</RootElement>
<?xml version="1.0" encoding="utf-8" ?>
<RootElement>
<XElement1/>
<XElement2/>
</RootElement>
Instead of just that second part. I've tried changing the way I add the XElement, but I get this everytime, so I'm guessing it must be a problem with the way I open/close the stream. How could I fix this?
Try to reset stream position to the beginning, just before calling Save() method :
stream.Position = 0;
doc.Save(stream);
I have seen this solved similar problem in old Windows Phone questions. These are some of them : 1. Appending new XElement adds an entire XML to existing xml in stream, 2. updating an existing xml file in Windows Phone

export list of object to xml file in c#

I try to export a list of object(type of "Doctor") to an xml file in c#.
It compiles and runs, but the file I get isn't correct. Can someone please can tell me what I did incorrect?
the code is:
public static void exportAsXml(string fileName, List<Entity> ListOfEntity)
{
FileInfo file = new FileInfo(fileName + ".xml");
StreamWriter sw = file.AppendText();
System.Xml.Serialization.XmlSerializer writer = new System.Xml.Serialization.XmlSerializer(typeof(Doctor));
foreach (Entity e in ListOfEntity)
{
writer.Serialize(sw,e as Doctor);
}
sw.Close();
}
the xml file is:
<?xml version="1.0" encoding="utf-8"?>
<Doctor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>87587579</ID>
<FirstName>Dan</FirstName>
<LastName>Adi</LastName>
<Gender>male</Gender>
<Salary>15000</Salary>
</Doctor><?xml version="1.0" encoding="utf-8"?>
<Doctor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>302342246</ID>
<FirstName>Lital</FirstName>
<LastName>Gal</LastName>
<Gender>female</Gender>
<Salary>25600</Salary>
</Doctor><?xml version="1.0" encoding="utf-8"?>
<Doctor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>205992457</ID>
<FirstName>Yaron</FirstName>
<LastName>Mor</LastName>
<Gender>male</Gender>
<Salary>10000</Salary>
</Doctor>
Thanks!
First of all, the resulting xml violates 2 core rules.
Xml file should have only one <?xml version="1.0" encoding="utf-8"> declaration
All your xml should be enclosed inside one root file.
In other words, in loop you generate a separate, fully-fledged xml file for each item.
Try this
var writer = new System.Xml.Serialization.XmlSerializer(typeof(List<Doctor>));
writer.Serialize(sw, ListOfEntity);
You are corrupting the xml file by serializing the doctor objects and saving it to the same file using file.AppendText();, generating corrupted xml with multiple <?xml version="1.0" encoding="utf-8"?> declarations as consequence.
You should serialize the List<Doctor> instead of serializing each doctor alone and modifying the xml file by appending text.
If you want to modify a serialized object saved inside a file, you need to deserialize the file into an object, modify it and then replace the file with the new serialized object. you cannot simply append it.

Incorrect structured XML document after deleting element

When I try to load a XML file after deleting an Element from the file, it shows the following error: Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it. Line 9, position 10. What is wrong with my code?
This is my XML file:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze3</booze>
<booze>booze4</booze>
</data>
And my code:
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("favorites.xml", FileMode.Open, file))
{
XDocument xDoc = XDocument.Load(stream, LoadOptions.None);
// delete node
xDoc.Descendants("data").Elements("booze").Where(x => x.Value == favorite).DescendantsAndSelf().Remove();
xDoc.Save(stream);
}
}
My guess is that when you run the code for the first time, the delete succeeds and your XDoc contains :
<?xml version="1.0" encoding="utf-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze4</booze>
</data>
, but when calling XDoc.Save you simply append this to the favorites.xml file. After that, the favorites.xml file contains something like this:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze3</booze>
<booze>booze4</booze>
</data><?xml version="1.0" encoding="utf-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze4</booze>
</data>
That is why all the subsequent file loads throw the error. What you should do is overwrite the file, and not append to it. The first way of doing that that comes to mind is to close the stream, open it with Mode.Truncate and then save the XDoc. Or you can delete and recreate the file. I am not that familiar with IsolatedStorageFiles so this is a wild guess.

How do I add a new element to the existing XML file on Windows Phone 7 using LINQ to XML?

For the last couple of hours I was struggling with LINQ to XML on Windows Phone 7. I simply just want to add new element to an existing XML file.
XElement newItem = new XElement("item",new XAttribute("id",3),
new XElement("content","Buy groceries"),
new XElement("status","false"));
IsolatedStorageFile isFile = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream stream = new IsolatedStorageFileStream("/Items.xml", System.IO.FileMode.Open, isFile);
XDocument loadedDoc = XDocument.Load(stream);
loadedDoc.Add(newItem);
loadedDoc.Save(stream);
Generally I'm experiencing very weird behavior. Sometimes I am getting an error "Operation not permitted on IsolatedStorageFileStream.". Sometimes it is "Root element is missing" and sometimes it is "Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it." If, for example, I would change System.IO.FileMode.Open to Create I would get "Root element is missing" but apart from that there doesn't seem to be any pattern according to which error occurs.
It all seems like its my XML file which causes the problem:
<?xml version="1.0" encoding="utf-8" ?>
<items>
<item id="1">
<content>Get groceries</content>
<status>false</status>
</item>
<item id="2">
<content>Wash your car</content>
<status>true</status>
</item>
</items>
It doesn't get any simpler than that and I am absolutely sure I don't have any white spaces before the declaration in the actual XML file.
And to make it all even more weird I have downloaded little sample application that uses the same technique of writing to XML file. When I try to run it I am getting a very familiar error:
Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it.
Here is link to that thread: http://mobileworld.appamundi.com/blogs/petevickers/archive/2010/12/06/windows-phone-7-linq-to-xml-corruption.aspx/
Yesterday I installed Windows Phone SDK 7.1 BETA. Could that be causing the problem?
It seems like the problem is with locating xml file in isolated storage. I have created completely new project and new xml file inside.
Thats the only code I have:
// Constructor
public MainPage()
{
InitializeComponent();
var isFile = IsolatedStorageFile.GetUserStoreForApplication();
var stream = isFile.OpenFile("file.xml", System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite);
}
I'am still getting: Operation not permitted on IsolatedStorageFileStream. I have tried going into properties of file.xml changing Built action and copy to output directory but that didn't work. I tried adding:
isFile.Dispose();
I also tried adding conditional statement:
if (isFile.FileExists("file.xml"))...
But he couldn't find the file.
I have never been so stuck in my life. Please advice me what else can i try.
You're trying to save to the same stream you loaded from - but without "rewinding" it to the start. I don't know whether isolated storage streams are seekable, but you can try just changing the code to:
XDocument loadedDoc = XDocument.Load(stream);
loadedDoc.Add(newItem);
stream.Position = 0;
loadedDoc.Save(stream);
Note that while we don't need to reset the size of stream in this case as we're adding content, in other cases you might need to do so in order to avoid "leftover" bits at the end of the file.
Alternatively, load the document and close the stream, then open up a new stream to the same file. Note that you should use using statements to close the streams after each use, e.g.
using (var isFile = IsolatedStorageFile.GetUserStoreForApplication())
{
XDocument loadedDoc;
using (var stream = isFile.OpenFile("/Items.xml", FileMode.Open))
{
loadedDoc = XDocument.Load(stream);
}
loadedDoc.Add(newItem);
using (var stream = isFile.OpenFile("/Items.xml", FileMode.Create))
{
loadedDoc.Save(stream);
}
}

Categories