WP7 - XmlException - Недопустимые данные на корневом уровне - PullRequest
0 голосов
/ 08 декабря 2010

Не могу понять, почему мои обновления 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 без спецификации.

Кто-нибудь видел это раньше?

Все мысли приветствуются (даже те, что говорят мой коддерьмо и нуждается в рефаctoring).

РЕДАКТИРОВАТЬ:

Проблема с добавлением: 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));

1 Ответ

1 голос
/ 08 декабря 2010

Вы удаляете существующий файл перед сохранением новой версии?

Если вы обновили XML меньше исходного, тогда конец исходных данных может остаться при записи новых данных. Это приведет к появлению лишних символов в конце вашего файла, что сделает XML недействительным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...