WP7 - XmlException - 根级别的数据无效

发布于 2024-10-06 23:37:53 字数 12470 浏览 2 评论 0原文

无法弄清楚为什么我的 xml 更新在isolatedStorage 上失败,并且想知道其他人是否也遇到过类似的问题。

我试图通过迭代所有某些节点并单独更新它们来更新文件。

由于某种原因,它中途失败,然后声明数据在根级别无效,并且无效数据位于文件末尾???

代码如下:

我为每个练习调用 Update 方法:

    foreach (var exercise in program.Exercises)
    {
        UpdateExercise(program, exercise, true);
    }

它使用静态属性并调用数据源的 Update 方法:

    public void UpdateExercise(WorkoutProgram program, Exercise entity, bool isConversionUpdate)
    {
        ProgramDataSource.Update(program, entity, isConversionUpdate);
    }

然后调用此方法,并在这一行进行几次循环后失败: 'root = XElement .Load(XmlReader.Create(fs));'

    public void Update(WorkoutProgram program, Exercise exercise, bool isConversionUpdate)
    {
        SetupProgramSource(program);
        XElement root;

        if (!isConversionUpdate)
            exercise.ChangeDate = DateTime.Now;

        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        {
            if (!store.FileExists(_exerciseFile))
            {
                throw new NotFoundException("The file does not exist!");
            }

            using (var fs = store.OpenFile(_exerciseFile, FileMode.Open, FileAccess.Read))
            {
                root = XElement.Load(XmlReader.Create(fs));
                var element = root.Element("Exercises").Elements("Exercise").Where(e => e.Element("ID").Value.ToLower().Equals(exercise.ID.ToString().ToLower())).Single();
                element.SetElementValue("Description", exercise.Description);
                element.SetElementValue("Name", exercise.Name);
                var exerciseChanges = element.Element("ExerciseChanges");

                if (exercise is AnaerobicExercise)
                {
                    var anaerobicExercise = exercise as AnaerobicExercise;
                    element.SetElementValue("Reps", anaerobicExercise.Repetitions);
                    element.SetElementValue("Sets", anaerobicExercise.Sets);
                    element.Element("Weight").SetElementValue("Amount", anaerobicExercise.Weight.Amount);
                    element.Element("Weight").SetElementValue("Measurement", anaerobicExercise.Weight.Measurement);
                    ...                    
                }

                if (exercise is AerobicExercise)
                {
                    var aerobicExercise = exercise as AerobicExercise;
                    element.SetElementValue("Distance", aerobicExercise.Distance);
                    element.Element("Duration").SetAttributeValue("hours", aerobicExercise.Duration.Hours);
                    element.Element("Duration").SetAttributeValue("minutes", aerobicExercise.Duration.Minutes);
                    element.Element("Duration").SetAttributeValue("seconds", aerobicExercise.Duration.Seconds);
                    element.SetElementValue("Measurement", aerobicExercise.Measurement);

                    if (!isConversionUpdate)
                    {
                        var exerciseChange = exercise.Changes.OfType<AerobicExerciseChange>().FirstOrDefault(ec => ec.ChangeDate.Date == exercise.ChangeDate.Date);

                        if (exerciseChange != null)
                        {
                            var changesElement = exerciseChanges.Elements("Changes").First(x => x.Attribute("id").Value.ToLower().Equals(exerciseChange.ID.ToString().ToLower()));
                            changesElement.SetAttributeValue("hours", aerobicExercise.Duration.Hours);
                            changesElement.SetAttributeValue("minutes", aerobicExercise.Duration.Minutes);
                            changesElement.SetAttributeValue("seconds", aerobicExercise.Duration.Seconds);
                            changesElement.SetAttributeValue("distance", aerobicExercise.Distance);
                            var change = exercise.Changes.OfType<AerobicExerciseChange>().First(ec => ec.ChangeDate.Date == exercise.ChangeDate.Date);
                            change.Duration = aerobicExercise.Duration;
                            change.Distance = aerobicExercise.Distance;
                        }
                        else
                        {
                            var changeDate = new XAttribute("changeDate", string.Format("{0:dd/MM/yyyy}", aerobicExercise.ChangeDate));
                            var typeAttribute = new XAttribute("type", "Aerobic");
                            var hoursAttribute = new XAttribute("hours", aerobicExercise.Duration.Hours);
                            var minutesAttribute = new XAttribute("minutes", aerobicExercise.Duration.Minutes);
                            var secondsAttribute = new XAttribute("seconds", aerobicExercise.Duration.Seconds);
                            var distanceAttribute = new XAttribute("distance", aerobicExercise.Distance);
                            var changesElement = new XElement("Changes");
                            exerciseChange = WorkoutManagerEntityFactory.GetEntityChange<AerobicExerciseChange>();
                            var idAttribute = new XAttribute("id", exerciseChange.ID.ToString());
                            changesElement.Add(idAttribute, typeAttribute, hoursAttribute, minutesAttribute, secondsAttribute, distanceAttribute, changeDate);
                            exerciseChanges.Add(changesElement);
                            exerciseChange.ChangeDate = aerobicExercise.ChangeDate;
                            exerciseChange.Distance = aerobicExercise.Distance;
                            exerciseChange.Duration = aerobicExercise.Duration;
                            aerobicExercise.Changes.Add(exerciseChange);
                        }
                    }
                    else
                    {
                        foreach (var aerobicExerciseChange in exercise.Changes.OfType<AerobicExerciseChange>())
                        {
                            var changesElement = exerciseChanges.Elements("Changes").First(x => x.Attribute("id").Value.ToLower().Equals(aerobicExerciseChange.ID.ToString().ToLower()));
                            changesElement.SetAttributeValue("hours", aerobicExercise.Duration.Hours);
                            changesElement.SetAttributeValue("minutes", aerobicExercise.Duration.Minutes);
                            changesElement.SetAttributeValue("seconds", aerobicExercise.Duration.Seconds);
                            changesElement.SetAttributeValue("distance", aerobicExercise.Distance);
                            var change = exercise.Changes.OfType<AerobicExerciseChange>().First(ec => ec.ID == aerobicExerciseChange.ID);
                            change.Duration = aerobicExercise.Duration;
                            change.Distance = aerobicExercise.Distance;
                        }
                    }
                }
            }

            using (var fs = store.OpenFile(_exerciseFile, FileMode.Open, FileAccess.Write))
            {
                root.Save(fs);
            }
        }
    }

XML(删除了大部分练习节点的简化版本):

<?xml version="1.0" encoding="utf-8"?>
<Program name="Strength Training">
  <ID>2eec20d2-a278-11df-bc86-00138f82a706</ID>
  <Duration hours="0" minutes="39" seconds="0" />
  <Description>Main workout program for general all over fitness</Description>
  <Exercises>
    <Exercise exerciseType="Aerobic">
      <ID>6E391E75-E75C-49CA-95FC-FEDF03D3ED1A</ID>
      <Name>Treadmill Run</Name>
      <Description>With a bar-bell on your back, feet shoulder width apart, back straight, knees slightly bent and in line with the feet, slowly go down and then back up. Squats develop power and strength.</Description>
      <Distance>4</Distance>
      <Duration hours="0" minutes="10" seconds="0" />
      <Measurement>Kilometres</Measurement>
      <ExerciseChanges>
        <Changes id="291C3CCA-9997-4B4E-A1D5-75129DBB2638" type="Aerobic" hours="0" minutes="10" seconds="0" distance="4" changeDate="27/11/2010" />
      </ExerciseChanges>
    </Exercise>
    <Exercise exerciseType="Anaerobic">
      <ID>2eec20c5-a278-11df-bc86-00138f82a706</ID>
      <Name>Squats</Name>
      <Description>With a bar-bell on your back, feet shoulder width apart, back straight, knees slightly bent and in line with the feet, slowly go down and then back up. Squats develop power and strength.</Description>
      <Reps>10</Reps>
      <Weight>
        <Amount>130</Amount>
        <Measurement>Kilograms</Measurement>
      </Weight>
      <Sets>1</Sets>
      <ExerciseChanges>
        <Changes id="D20A177E-BC23-49B0-99CD-1F467590A996" type="Anaerobic" amount="130" sets="1" reps="10" changeDate="27/11/2010" />
      </ExerciseChanges>
    </Exercise>
    <Exercise exerciseType="Anaerobic">
      <ID>2eec20d1-a278-11df-bc86-00138f82a706</ID>
      <Name>Abs</Name>
      <Description>With a bar-bell on your back, feet shoulder width apart, back straight, knees slightly bent and in line with the feet, slowly go down and then back up. Squats develop power and strength.</Description>
      <Reps>15</Reps>
      <Weight>
        <Amount>0</Amount>
        <Measurement>Kilograms</Measurement>
      </Weight>
      <Sets>1</Sets>
      <ExerciseChanges>
        <Changes id="FFF2FF28-607F-465E-8BAC-B4F21E568253" type="Anaerobic" amount="0" sets="1" reps="15" changeDate="27/11/2010" />
      </ExerciseChanges>
    </Exercise>
  </Exercises>
  <ProgramChanges>
    <Duration id="0BA96209-CF3C-4E85-8EB5-3BEE6A2DB118" hours="0" minutes="45" seconds="0" changeDate="27/11/2010" />
    <Duration id="DAEEE9DF-A155-48AC-A5CE-09D738947C76" hours="0" minutes="39" seconds="0" changeDate="28/11/2010" />
  </ProgramChanges>
</Program>

编码为 UTF-8,无 BOM。

有人以前见过这个吗?

所有的想法都值得赞赏(即使是那些说我的代码很糟糕并且需要重构的想法)。

编辑:

添加问题:InvalidOperationException - 缺少父级:

    private static XElement GetExerciseElement(Exercise entity)
    {
        var exerciseElement = new XElement("Exercise");

        if (entity is AnaerobicExercise)
        {
            var anaerobicExercise = entity as AnaerobicExercise;
            var exerciseTypeAttribute = new XAttribute("exerciseType", "Anaerobic");
            var amountElement = new XElement("Amount", anaerobicExercise.Weight.Amount);
            var measurementElement = new XElement("Measurement", anaerobicExercise.Weight.Measurement);
            var weightElement = new XElement("Weight");
            var nameElement = new XElement("Name", anaerobicExercise.Name);
            var descriptionElement = new XElement("Description", anaerobicExercise.Description);
            var repsElement = new XElement("Reps", anaerobicExercise.Repetitions);
            var setsElement = new XElement("Sets", anaerobicExercise.Sets);
            var idElement = new XElement("ID", anaerobicExercise.ID);
            var exerciseChangesElement = new XElement("ExerciseChanges");
            weightElement.Add(amountElement, measurementElement);
            var exerciseChange = new AnaerobicExerciseChange
                                     {
                                         ChangeDate = entity.ChangeDate,
                                         Amount = anaerobicExercise.Weight.Amount,
                                         Sets = anaerobicExercise.Sets,
                                         Repetitions = anaerobicExercise.Repetitions
                                     };
            entity.Changes.Add(exerciseChange);
            exerciseElement.Add(exerciseTypeAttribute, idElement, nameElement, descriptionElement, repsElement, weightElement, setsElement);
            exerciseChangesElement.ReplaceWith(GetExerciseChanges(entity, exerciseElement, exerciseChange));
            exerciseElement.Add(exerciseChangesElement);
        }

特别是这一行:

exerciseChangesElement.ReplaceWith(GetExerciseChanges(entity, exerciseElement, exerciseChange));

Having trouble working out why my xml updates are failing on IsolatedStorage and was wondering if anyone else has had a similar problem.

I'm trying to update a file by iterating through all certain nodes and updating them individually.

For some reason, it fails half way through and then states the data is invalid at root level and that the invalid data is at the end of the file???

The code is as follows:

I make a call to the Update method for every exercise:

    foreach (var exercise in program.Exercises)
    {
        UpdateExercise(program, exercise, true);
    }

Which uses a static property and calls the data source's Update method:

    public void UpdateExercise(WorkoutProgram program, Exercise entity, bool isConversionUpdate)
    {
        ProgramDataSource.Update(program, entity, isConversionUpdate);
    }

This method is then called and fails after a few loops at this line: 'root = XElement.Load(XmlReader.Create(fs));'

    public void Update(WorkoutProgram program, Exercise exercise, bool isConversionUpdate)
    {
        SetupProgramSource(program);
        XElement root;

        if (!isConversionUpdate)
            exercise.ChangeDate = DateTime.Now;

        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        {
            if (!store.FileExists(_exerciseFile))
            {
                throw new NotFoundException("The file does not exist!");
            }

            using (var fs = store.OpenFile(_exerciseFile, FileMode.Open, FileAccess.Read))
            {
                root = XElement.Load(XmlReader.Create(fs));
                var element = root.Element("Exercises").Elements("Exercise").Where(e => e.Element("ID").Value.ToLower().Equals(exercise.ID.ToString().ToLower())).Single();
                element.SetElementValue("Description", exercise.Description);
                element.SetElementValue("Name", exercise.Name);
                var exerciseChanges = element.Element("ExerciseChanges");

                if (exercise is AnaerobicExercise)
                {
                    var anaerobicExercise = exercise as AnaerobicExercise;
                    element.SetElementValue("Reps", anaerobicExercise.Repetitions);
                    element.SetElementValue("Sets", anaerobicExercise.Sets);
                    element.Element("Weight").SetElementValue("Amount", anaerobicExercise.Weight.Amount);
                    element.Element("Weight").SetElementValue("Measurement", anaerobicExercise.Weight.Measurement);
                    ...                    
                }

                if (exercise is AerobicExercise)
                {
                    var aerobicExercise = exercise as AerobicExercise;
                    element.SetElementValue("Distance", aerobicExercise.Distance);
                    element.Element("Duration").SetAttributeValue("hours", aerobicExercise.Duration.Hours);
                    element.Element("Duration").SetAttributeValue("minutes", aerobicExercise.Duration.Minutes);
                    element.Element("Duration").SetAttributeValue("seconds", aerobicExercise.Duration.Seconds);
                    element.SetElementValue("Measurement", aerobicExercise.Measurement);

                    if (!isConversionUpdate)
                    {
                        var exerciseChange = exercise.Changes.OfType<AerobicExerciseChange>().FirstOrDefault(ec => ec.ChangeDate.Date == exercise.ChangeDate.Date);

                        if (exerciseChange != null)
                        {
                            var changesElement = exerciseChanges.Elements("Changes").First(x => x.Attribute("id").Value.ToLower().Equals(exerciseChange.ID.ToString().ToLower()));
                            changesElement.SetAttributeValue("hours", aerobicExercise.Duration.Hours);
                            changesElement.SetAttributeValue("minutes", aerobicExercise.Duration.Minutes);
                            changesElement.SetAttributeValue("seconds", aerobicExercise.Duration.Seconds);
                            changesElement.SetAttributeValue("distance", aerobicExercise.Distance);
                            var change = exercise.Changes.OfType<AerobicExerciseChange>().First(ec => ec.ChangeDate.Date == exercise.ChangeDate.Date);
                            change.Duration = aerobicExercise.Duration;
                            change.Distance = aerobicExercise.Distance;
                        }
                        else
                        {
                            var changeDate = new XAttribute("changeDate", string.Format("{0:dd/MM/yyyy}", aerobicExercise.ChangeDate));
                            var typeAttribute = new XAttribute("type", "Aerobic");
                            var hoursAttribute = new XAttribute("hours", aerobicExercise.Duration.Hours);
                            var minutesAttribute = new XAttribute("minutes", aerobicExercise.Duration.Minutes);
                            var secondsAttribute = new XAttribute("seconds", aerobicExercise.Duration.Seconds);
                            var distanceAttribute = new XAttribute("distance", aerobicExercise.Distance);
                            var changesElement = new XElement("Changes");
                            exerciseChange = WorkoutManagerEntityFactory.GetEntityChange<AerobicExerciseChange>();
                            var idAttribute = new XAttribute("id", exerciseChange.ID.ToString());
                            changesElement.Add(idAttribute, typeAttribute, hoursAttribute, minutesAttribute, secondsAttribute, distanceAttribute, changeDate);
                            exerciseChanges.Add(changesElement);
                            exerciseChange.ChangeDate = aerobicExercise.ChangeDate;
                            exerciseChange.Distance = aerobicExercise.Distance;
                            exerciseChange.Duration = aerobicExercise.Duration;
                            aerobicExercise.Changes.Add(exerciseChange);
                        }
                    }
                    else
                    {
                        foreach (var aerobicExerciseChange in exercise.Changes.OfType<AerobicExerciseChange>())
                        {
                            var changesElement = exerciseChanges.Elements("Changes").First(x => x.Attribute("id").Value.ToLower().Equals(aerobicExerciseChange.ID.ToString().ToLower()));
                            changesElement.SetAttributeValue("hours", aerobicExercise.Duration.Hours);
                            changesElement.SetAttributeValue("minutes", aerobicExercise.Duration.Minutes);
                            changesElement.SetAttributeValue("seconds", aerobicExercise.Duration.Seconds);
                            changesElement.SetAttributeValue("distance", aerobicExercise.Distance);
                            var change = exercise.Changes.OfType<AerobicExerciseChange>().First(ec => ec.ID == aerobicExerciseChange.ID);
                            change.Duration = aerobicExercise.Duration;
                            change.Distance = aerobicExercise.Distance;
                        }
                    }
                }
            }

            using (var fs = store.OpenFile(_exerciseFile, FileMode.Open, FileAccess.Write))
            {
                root.Save(fs);
            }
        }
    }

The XML (reduced version with most exercise nodes removed):

<?xml version="1.0" encoding="utf-8"?>
<Program name="Strength Training">
  <ID>2eec20d2-a278-11df-bc86-00138f82a706</ID>
  <Duration hours="0" minutes="39" seconds="0" />
  <Description>Main workout program for general all over fitness</Description>
  <Exercises>
    <Exercise exerciseType="Aerobic">
      <ID>6E391E75-E75C-49CA-95FC-FEDF03D3ED1A</ID>
      <Name>Treadmill Run</Name>
      <Description>With a bar-bell on your back, feet shoulder width apart, back straight, knees slightly bent and in line with the feet, slowly go down and then back up. Squats develop power and strength.</Description>
      <Distance>4</Distance>
      <Duration hours="0" minutes="10" seconds="0" />
      <Measurement>Kilometres</Measurement>
      <ExerciseChanges>
        <Changes id="291C3CCA-9997-4B4E-A1D5-75129DBB2638" type="Aerobic" hours="0" minutes="10" seconds="0" distance="4" changeDate="27/11/2010" />
      </ExerciseChanges>
    </Exercise>
    <Exercise exerciseType="Anaerobic">
      <ID>2eec20c5-a278-11df-bc86-00138f82a706</ID>
      <Name>Squats</Name>
      <Description>With a bar-bell on your back, feet shoulder width apart, back straight, knees slightly bent and in line with the feet, slowly go down and then back up. Squats develop power and strength.</Description>
      <Reps>10</Reps>
      <Weight>
        <Amount>130</Amount>
        <Measurement>Kilograms</Measurement>
      </Weight>
      <Sets>1</Sets>
      <ExerciseChanges>
        <Changes id="D20A177E-BC23-49B0-99CD-1F467590A996" type="Anaerobic" amount="130" sets="1" reps="10" changeDate="27/11/2010" />
      </ExerciseChanges>
    </Exercise>
    <Exercise exerciseType="Anaerobic">
      <ID>2eec20d1-a278-11df-bc86-00138f82a706</ID>
      <Name>Abs</Name>
      <Description>With a bar-bell on your back, feet shoulder width apart, back straight, knees slightly bent and in line with the feet, slowly go down and then back up. Squats develop power and strength.</Description>
      <Reps>15</Reps>
      <Weight>
        <Amount>0</Amount>
        <Measurement>Kilograms</Measurement>
      </Weight>
      <Sets>1</Sets>
      <ExerciseChanges>
        <Changes id="FFF2FF28-607F-465E-8BAC-B4F21E568253" type="Anaerobic" amount="0" sets="1" reps="15" changeDate="27/11/2010" />
      </ExerciseChanges>
    </Exercise>
  </Exercises>
  <ProgramChanges>
    <Duration id="0BA96209-CF3C-4E85-8EB5-3BEE6A2DB118" hours="0" minutes="45" seconds="0" changeDate="27/11/2010" />
    <Duration id="DAEEE9DF-A155-48AC-A5CE-09D738947C76" hours="0" minutes="39" seconds="0" changeDate="28/11/2010" />
  </ProgramChanges>
</Program>

The encoding is UTF-8 without BOM.

Anyone seen this before?

All thoughts are appreciated (even ones saying my code's crap and needs refactoring).

EDIT:

Problem with adding: InvalidOperationException - The Parent is missing:

    private static XElement GetExerciseElement(Exercise entity)
    {
        var exerciseElement = new XElement("Exercise");

        if (entity is AnaerobicExercise)
        {
            var anaerobicExercise = entity as AnaerobicExercise;
            var exerciseTypeAttribute = new XAttribute("exerciseType", "Anaerobic");
            var amountElement = new XElement("Amount", anaerobicExercise.Weight.Amount);
            var measurementElement = new XElement("Measurement", anaerobicExercise.Weight.Measurement);
            var weightElement = new XElement("Weight");
            var nameElement = new XElement("Name", anaerobicExercise.Name);
            var descriptionElement = new XElement("Description", anaerobicExercise.Description);
            var repsElement = new XElement("Reps", anaerobicExercise.Repetitions);
            var setsElement = new XElement("Sets", anaerobicExercise.Sets);
            var idElement = new XElement("ID", anaerobicExercise.ID);
            var exerciseChangesElement = new XElement("ExerciseChanges");
            weightElement.Add(amountElement, measurementElement);
            var exerciseChange = new AnaerobicExerciseChange
                                     {
                                         ChangeDate = entity.ChangeDate,
                                         Amount = anaerobicExercise.Weight.Amount,
                                         Sets = anaerobicExercise.Sets,
                                         Repetitions = anaerobicExercise.Repetitions
                                     };
            entity.Changes.Add(exerciseChange);
            exerciseElement.Add(exerciseTypeAttribute, idElement, nameElement, descriptionElement, repsElement, weightElement, setsElement);
            exerciseChangesElement.ReplaceWith(GetExerciseChanges(entity, exerciseElement, exerciseChange));
            exerciseElement.Add(exerciseChangesElement);
        }

This line in particular:

exerciseChangesElement.ReplaceWith(GetExerciseChanges(entity, exerciseElement, exerciseChange));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

原谅过去的我 2024-10-13 23:37:53

您是否在保存新版本之前删除现有文件?

如果更新后的 XML 小于原始数据,则在写入新数据时可能会留下原始数据的末尾。这将导致文件末尾出现额外的字符,从而使 XML 无效。

Are you deleting the existing file before saving the new version?

If you're updated XML is smaller than the original then the end of the original data may be left when you write the new data. This will lead to extra characters at the end of your file which will invalidate the XML.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文