Home > Software engineering >  best approach to read a difficult XML into a list with C#
best approach to read a difficult XML into a list with C#

Time:05-23

I need to read the values out of following XML in C#. The XML here is just a small portion of the whole XML. It's a savegame. Deserialization probably won't work because of the complex nature.

<Profession>
  <StrengthSkills>
    <strengthSkills size="3">
      <i0>
        <skillKey>25</skillKey>
        <skillLevel>1</skillLevel>
        <accuracyLevel>0</accuracyLevel>
        <damageLevel>0</damageLevel>
        <staminaLevel>0</staminaLevel>
        <chanceLevel>0</chanceLevel>
      </i0>
      <i1>
        <skillKey>41</skillKey>
        <skillLevel>1</skillLevel>
        <accuracyLevel>0</accuracyLevel>
        <damageLevel>0</damageLevel>
        <staminaLevel>0</staminaLevel>
        <chanceLevel>0</chanceLevel>
      </i1>
      <i2>
        <skillKey>12</skillKey>
        <skillLevel>1</skillLevel>
        <accuracyLevel>0</accuracyLevel>
        <damageLevel>0</damageLevel>
        <staminaLevel>0</staminaLevel>
        <chanceLevel>0</chanceLevel>
      </i2>
    </strengthSkills>
  </StrengthSkills>
  <DexteritySkills>
    <dexteritySkills size="2">
      <i0>
        <skillKey>105</skillKey>
        <skillLevel>1</skillLevel>
        <accuracyLevel>0</accuracyLevel>
        <damageLevel>0</damageLevel>
        <staminaLevel>0</staminaLevel>
        <chanceLevel>0</chanceLevel>
      </i0>
      <i1>
        <skillKey>131</skillKey>
        <skillLevel>1</skillLevel>
        <accuracyLevel>0</accuracyLevel>
        <damageLevel>0</damageLevel>
        <staminaLevel>0</staminaLevel>
        <chanceLevel>0</chanceLevel>
      </i1>
    </dexteritySkills>
  </DexteritySkills>
  <IntelligenceSkills>
    <intelligenceSkills size="1">
      <i0>
        <skillKey>208</skillKey>
        <skillLevel>1</skillLevel>
        <accuracyLevel>0</accuracyLevel>
        <damageLevel>0</damageLevel>
        <staminaLevel>0</staminaLevel>
        <chanceLevel>0</chanceLevel>
      </i0>
    </intelligenceSkills>
  </IntelligenceSkills>
  <CharismaSkills>
    <charismaSkills size="2">
      <i0>
        <skillKey>304</skillKey>
        <skillLevel>2</skillLevel>
        <accuracyLevel>0</accuracyLevel>
        <damageLevel>0</damageLevel>
        <staminaLevel>0</staminaLevel>
        <chanceLevel>0</chanceLevel>
      </i0>
      <i1>
        <skillKey>309</skillKey>
        <skillLevel>1</skillLevel>
        <accuracyLevel>0</accuracyLevel>
        <damageLevel>0</damageLevel>
        <staminaLevel>0</staminaLevel>
        <chanceLevel>0</chanceLevel>
      </i1>
    </charismaSkills>
  </CharismaSkills>
  <PerceptionSkills>
    <perceptionSkills size="1">
      <i0>
        <skillKey>405</skillKey>
        <skillLevel>1</skillLevel>
        <accuracyLevel>0</accuracyLevel>
        <damageLevel>0</damageLevel>
        <staminaLevel>0</staminaLevel>
        <chanceLevel>0</chanceLevel>
      </i0>
    </perceptionSkills>
  </PerceptionSkills>
  <FortitudeSkills>
    <fortitudeSkills size="1">
      <i0>
        <skillKey>500</skillKey>
        <skillLevel>2</skillLevel>
        <accuracyLevel>0</accuracyLevel>
        <damageLevel>0</damageLevel>
        <staminaLevel>0</staminaLevel>
        <chanceLevel>0</chanceLevel>
      </i0>
    </fortitudeSkills>
  </FortitudeSkills>
</Profession>

I am really struggling with this one. I hope someone here can help me. The problem is that the values have nodes ("i0", "i1", etc.) can't seem to find a good way to address them.

This was what i used for another portion of the XML, which did the job just fine:

public static List<GetSkills> SkillsList()
{
    return XDocument.Load(ProcessFile.tempFilePath)
      .Element("root")
      .Element("FamilyMembers")
      .Elements().Where(e => e.Name.LocalName.StartsWith("Member_"))
      .Select(p => GetSkillsForMember(p))
      .ToList();
}

But if I try the same for this part of the XML, I struggle with the <i0> part.

The goal for me is to put the values in a list, beeing able to change them, add new (ix) Nodes with new values, and put them back into that XML. It is very important that the Output XML follows the same build up.

CodePudding user response:

I solved it by doing following:

var skillsAmount = xDoc.Descendants("Profession").Descendants(skillType   "Skills").FirstOrDefault().Attribute("size").Value;
                    
var skillNum = new[]
{
    new {Nr = 14, Skill = "Str", Type = "strengthSkills"},
    new {Nr = 12, Skill = "Dex", Type = "dexteritySkills"},
    new {Nr = 17, Skill = "Int", Type = "intelligenceSkills"},
    new {Nr = 13, Skill = "Cha", Type = "charismaSkills"},
    new {Nr = 17, Skill = "Per", Type = "perceptionSkills"},
    new {Nr = 20, Skill = "For", Type = "fortitudeSkills"}

}.ToList();

foreach (var num in skillNum)
{

    for (int i = 0; i < Convert.ToInt32(skillsAmount); i  )
    {
        List<Skills> Skills = xDoc
            .Descendants("Profession")
            .Descendants(skillNum.Type)
            .Descendants("i"   i)
            .Select(q => new Skills()
                {
                    SkillKey = q.Element("skillKey").Value,
                    SkillLevel = q.Element("skillLevel").Value
                })
                .ToList();
    }
}
  • Related