3

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.

Abbas
  • 14,186
  • 6
  • 41
  • 72
Booyaches
  • 1,669
  • 4
  • 27
  • 40

1 Answers1

2

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);
    } 
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Unfortunately my code doesn`t go past "XDocument loadedDoc = XDocument.Load(stream);" I`m getting "Root element is missing" so I can`t even try it out. – Booyaches Sep 21 '11 at 17:39
  • I tried doing it with **using** statement as you suggested but again, I'am getting "Root element missing" on XDocument loadedDoc = XDocument.Load(stream);. Generally it seems like there is a problem loading my XML file into stream. – Booyaches Sep 21 '11 at 17:48
  • @Booyaches: That means your file is empty. – SLaks Sep 21 '11 at 17:48
  • @SLaks: I created this document "manually" so I know Its not empty, If I got it right. I`ll post a little screenshot underneath. EDIT: Ok I am sorry I can`t post pictures yet, I am new user. – Booyaches Sep 21 '11 at 17:55
  • Here is [link](http://zdziechowski.com/MyDocuments/Capture.JPG) to the screenshot I said I`ll put up. – Booyaches Sep 21 '11 at 18:02
  • Path seems correct as well... is there a difference between **"Items.xml"** and **"/Items.xml"** ? – Booyaches Sep 21 '11 at 18:09
  • @Booyaches: That shows it in Visual Studio - but that doesn't mean it's present in Isolated Storage... – Jon Skeet Sep 21 '11 at 21:08
  • @Jon Skeet: And it probably doesn`t... what could be the reason for that ? – Booyaches Sep 22 '11 at 08:10
  • @Booyaches: I haven't come across any suggestion that putting a file in your app project automatically puts it into IsolatedStorage - that's meant to be for user files... – Jon Skeet Sep 22 '11 at 08:19
  • Don't you also need to clear the file contents e.g. with `stream.SetLength(0)`? In this case OP is adding content to the XML but if they were removing content then the old XML would still appear at the end of the file. See e.g. [FileMode.Open and FileMode.OpenOrCreate difference when file exists? c# bug?](https://stackoverflow.com/q/29799265/3744182). But I'm also not sure if this works with isolated storage. – dbc Mar 16 '18 at 18:05
  • @dbc: My example is broken anyway, as I don't do what I say! Will fix that and add a note about setting the length. – Jon Skeet Mar 16 '18 at 18:30