2010-12-08 3 views
0

IsolatedStorage에서 내 XML 업데이트가 실패하는 이유를 알아내는 데 어려움을 겪고 있으며 다른 누구와도 비슷한 문제가 있는지 궁금해하고 있습니다.WP7 - XmlException - 루트 수준의 데이터가 유효하지 않습니다.

모든 특정 노드를 반복 실행하고 파일을 개별적으로 업데이트하여 파일을 업데이트하려고합니다.

어떤 이유로 든 중간 단계에서 실패하고 루트 수준에서 데이터가 유효하지 않으며 유효하지 않은 데이터가 파일 끝에 있다는 것을 나타냅니다.

public void UpdateExercise(WorkoutProgram program, Exercise entity, bool isConversionUpdate) 
    { 
     ProgramDataSource.Update(program, entity, isConversionUpdate); 
    } 
: 데이터 소스의 업데이트 방법을 정적 속성을 사용하고 호출

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

:

나는 모든 운동에 대한 업데이트 방법에 대한 호출을 다음과 같이

코드는

이 메서드는이 줄에서 몇 루프 후 호출되고 실패합니다. '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)); 
+1

아마도 생성 된 XML의 샘플 조각이 있습니까? –

+0

나쁘다! 나는 XML 파일을 추가 할 것이다. 요소 및 속성 값을 업데이트해야합니다. –

답변

1

이 새를 저장하기 전에 기존 파일을 삭제하는 번역?

업데이트 된 XML이 원본보다 작은 경우 새 데이터를 쓸 때 원본 데이터의 끝이 남아있을 수 있습니다. 이렇게하면 파일 끝 부분에 XML을 무효로하는 추가 문자가 생깁니다.

+0

아니요, 기존 파일을 업데이트하기 만합니다. –

+0

시도해보십시오. 처음로드 할 때'fs '를보고 이것이 문제가되는지 확인할 수 있습니다. –

+0

답변 해 주셔서 감사합니다. 삭제 및 추가 (파일이 더 이상 존재하지 않아서 업데이트하지 않음) 문제는 ID를 포함하여 메모리에 모든 데이터를 저장하고 Add 메서드를 재정의해야한다는 것입니다. 또한 내가 추가하려고하면 InvalidOperationException가 발생합니다 : 위에 추가 된 행에 부모가 없습니다. –

관련 문제