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

时间:2010-12-08 12:57:57

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

无法解决为什么我的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 - 缺少Parent:

    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));

1 个答案:

答案 0 :(得分:1)

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

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