【问题标题】:WP7 - XmlException - Data at the root level is invalidWP7 - XmlException - 根级别的数据无效
【发布时间】:2011-05-22 05:19:56
【问题描述】:

无法弄清楚为什么我的 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>

编码是没有BOM的UTF-8。

有人见过这个吗?

感谢所有想法(即使有人说我的代码很垃圾,需要重构)。

编辑:

添加问题: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));

【问题讨论】:

  • 是否有生成的 xml 示例片段?
  • 我的错!我将添加 XML 文件。它应该只更新元素和属性值。

标签: c# xml windows-phone-7 linq-to-xml


【解决方案1】:

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

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

【讨论】:

  • 那就试试吧。您可以在第一次加载时查看fs 来检查这是否是问题所在。
  • 感谢您的回复。删除然后添加(由于文件不再存在而不更新)的问题是我需要将所有数据存储在内存中,包括 ID,然后覆盖 Add 方法。此外,当我尝试添加时,我得到一个 InvalidOperationException: The Parent is missing,在上面添加的行。
  • 是否可以只删除文档末尾的任何无效 xml?
  • 不幸的是,没有“一旦解析了有效的 xml 文档,最后忽略任何内容”设置。你可以尝试自己做这个。不过,您最好先确保数据不会损坏。
  • 干杯马特,无论如何我都要重构它。应该希望能突出这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
  • 2014-01-17
  • 2023-03-23
  • 1970-01-01
  • 2011-08-10
相关资源
最近更新 更多