2010-12-08 2 views
0

Не удается выяснить, почему мои обновления xml не работают на IsolStorage, и задавался вопросом, имела ли кто-либо еще аналогичная проблема.WP7 - XmlException - данные на корневом уровне недействительны

Я пытаюсь обновить файл, итерируя все определенные узлы и обновляя их отдельно.

По какой-то причине он выходит из строя наполовину, а затем указывает, что данные недопустимы на уровне корня и что недопустимые данные находятся в конце файла ???

Код выглядит следующим образом:

Я делаю вызов метода Update для каждого упражнения:

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

который использует статическое свойство и вызывает метод обновления источника данных:

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.

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

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

EDIT:

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

Возможно, существует фрагмент фрагмента генерируемого xml? – 2010-12-08 13:01:37

+0

Мой плохой! Я добавлю XML-файл. Он должен просто обновлять значения элементов и атрибутов. – 2010-12-08 13:31:17

ответ

1

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

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

Смежные вопросы