Search code examples
windowssilverlightwindows-phone-7xelement

Adding XElement to XML file using Linq to XML


Using Linq to XML, I am trying to add an XElement to an existing XML file. It has to be done in the Windows Phone .NET framework. Currently my XML file looks like this:

    <?xml version="1.0" encoding="utf-8"?>
    <Kids>
      <Child>
        <Name>Kid1</Name>
        <FirstName>hisname</FirstName>
      </Child>
    </Kids>

and my code looks like this:



    using (IsolatedStorageFileStream stream = 
               new IsolatedStorageFileStream("YourKids.xml", fileMode, store))
    { 
        XDocument x = XDocument.Load(stream);
        XElement t =  new XElement("Child",
                                           new XElement("Name", pName),
                                           new XElement("FirstName", pFirstname));

       t.Add(from el in x.Elements()
             where el == el.Descendants("Child").Last()
             select el);

       x.Save(stream);
    }

this doesn't do what I want to achieve. I want to add a new "Child" element to the the exisiting XML file like this :

     <?xml version="1.0" encoding="utf-8"?>
    <Kids>
      <Child>
        <Name>Kid1</Name>
        <FirstName>hisname</FirstName>
      </Child>
    <Child>
        <Name>kid2</Name>
        <FirstName>SomeName</FirstName>
      </Child>
    </Kids>

Could use some help because I am stuck ;-)

After the tips from GSerjo, my code looks like this now:

 try
            {

                if (store.FileExists("YourKids.xml"))
                {



                    using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("YourKids.xml",FileMode.Open, store))
                    {


                        var x = XElement.Load(stream);
                        var t =  new XElement("Child",
                                                        new XElement("Name", pName),
                                                        new XElement("FirstName", pFirstname)
                                                                  );

                        x.Add(t);

                        x.Save(stream);




                        stream.Close();
                        return;
                    }

                }
                else
                {



                    using (IsolatedStorageFileStream CreateIsf = new IsolatedStorageFileStream("YourKids.xml",FileMode.Create,store))
                    {

                        var xDoc = new XElement("Kids",
                                                     new XElement("Child",
                                                       new XElement("Name", pName),
                                                       new XElement("FirstName", pFirstname)
                                                                 )

                                                  );

                        xDoc.Save(CreateIsf);
                        CreateIsf.Close();

                        return;
                    }
                }
            }
            catch (Exception ex)
            {
              message = ex.Message;
            }

Which gives me an xml file like this:

<?xml version="1.0" encoding="utf-8"?>
<Kids>
  <Child>
    <Name>test</Name>
    <FirstName>test</FirstName>
  </Child>
</Kids><?xml version="1.0" encoding="utf-8"?>
<Kids>
  <Child>
    <Name>test</Name>
    <FirstName>test</FirstName>
  </Child>
  <Child>
    <Name>testing</Name>
    <FirstName>testing</FirstName>
  </Child>
</Kids>

Which is still not correct, any ideas anyone ?


Solution

  • Initial xml file

    <?xml version="1.0" encoding="utf-8"?>
    <Kids>
      <Child>
        <Name>Kid1</Name>
        <FirstName>hisname</FirstName>
      </Child>
    </Kids>
    

    Following code add one new child to existing xml

        [Test]
        public void Test()
        {
            string filPath = @"YourKids.xml";
            var root = XElement.Load(filPath);
             var newChild =  new XElement("Child",
                                       new XElement("Name", "NewName"),
                                       new XElement("FirstName", "NewFirstName"));
             root.Add(newChild);
            root.Save(filPath);
        }
    

    Result xml file

    <?xml version="1.0" encoding="utf-8"?>
    <Kids>
      <Child>
        <Name>Kid1</Name>
        <FirstName>hisname</FirstName>
      </Child>
      <Child>
        <Name>NewName</Name>
        <FirstName>NewFirstName</FirstName>
      </Child>
    </Kids>
    

    Update

    Bug on save, you should set stream length to 0

    Explanation

    After reader existing file, stream does not remove any data

    using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("YourKids.xml",FileMode.Open, store))
                        {
                            var x = XElement.Load(stream);
    

    So when you call, data has been appended

       x.Save(stream);
       stream.Close();
    

    Add stream.SetLength(0); before x.Save(stream); and all data will be overwritten.

    Here is full version

                if (store.FileExists("YourKids.xml"))
                {
                    using (var stream = new IsolatedStorageFileStream("YourKids.xml", FileMode.Open,
                                                                                         store))
                    {
                        var x = XElement.Load(stream);
                        var t = new XElement("Child",
                                             new XElement("Name", pName),
                                             new XElement("FirstName", pFirstname)
                            );
                        x.Add(t);
                        stream.SetLength(0);
                        x.Save(stream);
                        stream.Close();
                    }
                }
                else
                {
                    using (var CreateIsf = new IsolatedStorageFileStream("YourKids.xml", FileMode.Create, store))
                    {
                        var xDoc = new XElement("Kids",
                                                new XElement("Child",
                                                             new XElement("Name", pName),
                                                             new XElement("FirstName", pFirstname)
                                                    )
                            );
                        xDoc.Save(CreateIsf);
                        CreateIsf.Close();
                    }
                }
    

    Please note: I've removed return statements as useless.

    P.S. Take a look on resharper, it can improve code.