Sam
Sam

Reputation: 25

XML not well formed after deleting node using LINQ

Original XML:

 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <Links>  
        <Category name="a" />  
        <Category name="b" />
 </Links>

I want to delete the category node whose attribute = "b" and I doing it with the following code

 using (IsolatedStorageFile myStore = IsolatedStorageFile.GetUserStoreForApplication())
 {
     using (IsolatedStorageFileStream myStream = new IsolatedStorageFileStream(App.FileName, FileMode.Open, FileAccess.ReadWrite, myStore))
     {
          XElement mainTree = XElement.Load(myStream);
          mainTree.Elements("Category").Where(s => s.Attribute("name").Value == "b").DescendantsAndSelf().Remove();
          myStream.Position = 0;
          mainTree.Save(myStream);
      }
 }

After the code runs, the resulting XML looks like this...

<?xml version="1.0" encoding="utf-8"?>
<Links>  
     <Category name="a" />
     </Links>="a" />  
     <Category name="b" />
 </Links>

As you can see the XML is toast and cannot be read by the IsolatedStorageFileStream reader and errors out.

Can you please tell me what I am doing wrong when deleting the node and also when writing it back to the isolatedfilestorage?

Upvotes: 0

Views: 87

Answers (3)

Dweeberly
Dweeberly

Reputation: 4777

You should try your code outside the scope of your stream operations. For example if you run this:

var mainTree = XDocument.Parse(@"<Links>  
                                     <Category name='a' />  
                                     <Category name='b' />
                                 </Links>");
mainTree.Elements("Category")
        .Where(s => s.Attribute("name").Value == "b")
        .DescendantsAndSelf()
        .Remove();

Console.WriteLine(mainTree.ToString(SaveOptions.None));

You will see it reproduces your input. Try this linq expression:

mainTree.Root
        .Elements("Category")
        .Where(s => s.Attribute("name").Value == "b")
        .Remove();

I think you were trying to find your "Category" elements at the same level as "Links". You don't need the DescendantsAndSelf() call, when you delete (remove) the xml node you will remove all it's contained children.

The next issue is that you are overwriting a file in place. You want to clear the file before rewriting it with a shorter content. After you create your XDocument, close the stream, run your linq then open the file again with a filemode of Create and write your xml.

Upvotes: 1

metaomniliquant
metaomniliquant

Reputation: 145

To expand upon the answer previously given -

I attempted a simple trial using LinqPad:

var xml = XElement.Parse(@"<?xml version='1.0' encoding='utf-8'?><Links><Category name='a' /><Category name='b' /></Links>");

xml.Elements("Category").Where(s => s.Attribute("name").Value == "b").DescendantsAndSelf().Remove();
Console.WriteLine(xml.ToString());

produced desired results:

<Links>
    <Category name="a" />
</Links>

You will want to verify that the xml is formatted correctly after removal. If that is the case, and the negative results are actually happening when attempting to save, then the issue would be saving over existing data as previously mentioned.

Upvotes: 0

mrtig
mrtig

Reputation: 2267

Looks like the trouble is you're saving over existing data in the same file without clearing it. You need to clear the file completely or save to a new file.

In {} is the valid xml segment, everything outside of that is the old file.

{<Links>  
     <Category name="a" />
     </Links>}="a" />  
     <Category name="b" />
 </Links>

Upvotes: 1

Related Questions