简体   繁体   中英

Updating data in XML (Linq To XML) generate wrongclosing tags

I have this XmlFile (tasks.xml):

<?xml version="1.0" encoding="utf-8"?>
<Tasks>
  <Task>
    <Id>dc77b03f-468c-4709-b8dc-4d9741c984dd</Id>
    <Name>buy paper</Name>
    <Category>inbox</Category>
    <DueDate></DueDate>
    <Project></Project>
    <Context></Context>
    <Note></Note>
    <Created>03/16/2013 15:33:29</Created>
    <Finished></Finished>
  </Task>
</Tasks>

And when I update element like this everything works ok:

try
{
    var item = (CheckBox)sender;
    dynamic itemDC = item.DataContext;

    var folder = ApplicationData.Current.LocalFolder;
    var file = await folder.GetFileAsync("tasks.xml");
    var readStream = await FileIO.ReadTextAsync(file);
    using (var writeStream = await file.OpenStreamForWriteAsync())
    {
        XElement xElem = XElement.Parse(readStream);

        IEnumerable<XElement> singleTask = from task in xElem.Elements("Task")
                                           where (string)task.Element("Id") == itemDC.Id
                                           select task;

        foreach (XElement task in singleTask)
        {
            task.SetElementValue("Finished", DateTime.Now.ToString("MM") + "/" + DateTime.Now.ToString("dd") + "/" + DateTime.Now.ToString("yyyy HH:mm:ss"));
        }

        xElem.Save(writeStream);
    }
}
catch (Exception ex)
{
    new MessageDialog(ex.Message).ShowAsync();
}

but if I want to edit <Finnished> element again and set value to "" it will generate two wrong closing tags in my XML file.

Edit again code:

try
{
    var item = (CheckBox)sender;
    dynamic itemDC = item.DataContext;

    var folder = ApplicationData.Current.LocalFolder;
    var file = await folder.GetFileAsync("tasks.xml");
    var readStream = await FileIO.ReadTextAsync(file);
    using (var writeStream = await file.OpenStreamForWriteAsync())
    {
        XElement xElem = XElement.Parse(readStream);

        IEnumerable<XElement> singleTask = from task in xElem.Elements("Task")
                                           where (string)task.Element("Id") == itemDC.Id
                                           select task;

        foreach (XElement task in singleTask)
        {
            task.SetElementValue("Finished", "");
        }

        xElem.Save(writeStream);
    }
}
catch (Exception ex)
{
    new MessageDialog(ex.Message).ShowAsync();
}

Wrong generated XML after editing <Finished> to "":

<?xml version="1.0" encoding="utf-8"?>
<Tasks>
  <Task>
    <Id>dc77b03f-468c-4709-b8dc-4d9741c984dd</Id>
    <Name>dnešní úkol</Name>
    <Category>inbox</Category>
    <DueDate></DueDate>
    <Project></Project>
    <Context></Context>
    <Note></Note>
    <Created>03/16/2013 15:33:29</Created>
    <Finished></Finished>
  </Task>
</Tasks>  </Task>
</Tasks>

If I edit Again with string same size as date string, everything work OK, but clear "" value do that error.

I spend a lot of time to figure it out but now I don't have any idea how to solve this problem.

What I'm doing wrong?

Your problem is not related to Linq to XML in any way. It's just how streams work. In first case you're getting a longer file therefore all of the previous contents are overwritten. In second case the new file is shorter therefore the rest of the contents remain unchanged.

You should overwrite the existing file when you're saving the modified XML:

var folder = ApplicationData.Current.LocalFolder;
var file = await folder.GetFileAsync("tasks.xml");
var readStream = await FileIO.ReadTextAsync(file);
XElement xElem = XElement.Parse(readStream);

IEnumerable<XElement> singleTask = from task in xElem.Elements("Task")
                                    where (string)task.Element("Id") == itemDC.Id
                                    select task;
foreach (XElement task in singleTask)
{
    task.SetElementValue("Finished", "");
}

file = await folder.CreateFileAsync("tasks.xml", CreationCollisionOption.ReplaceExisting);
using (var writeStream = await file.OpenStreamForWriteAsync())
{
    xElem.Save(writeStream);
}

Also, when saving DateTime to XML you really should be serializing it with XmlConvert :

task.SetElementValue("Finished", XmlConvert.ToString(DateTime.Now));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM