-1

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.

mJrA
  • 11
  • 3
  • 1
    Have you tried a XML to C# converter? https://json2csharp.com/xml-to-csharp – McNets May 18 '22 at 18:25
  • 1
    The `i0`, `i1`, etc. elements will trip up a generator, as presumably that's an open-ended sequence of unique tag names. That's not a very good design, really. Do you have control over the document structure? – madreflection May 18 '22 at 18:27
  • unfortunatly not. Its a savegame of a game. i need to keep it as is (i can add elements like a `i4` for example but thats about it :( I mean the game somehow manages to read this file, so it must be possible somehow, i just need a way to do so. I dont mind if it becomes messy or much writing. Just need to somehow do this – mJrA May 18 '22 at 18:31
  • linq to xml can be your friend here – Daniel A. White May 18 '22 at 18:41
  • Add a sample c# object structure to which you want this xml mapped to. – Mat J May 18 '22 at 18:42
  • basicly to a list, this was the code i used for another portion of the XML. EDIT: put the code in the question, couldnt really make it a s a code – mJrA May 18 '22 at 18:45
  • Please review my edits for future reference on how to format and what should / should not be included in the post. – madreflection May 18 '22 at 18:59
  • i am sorry, i am not native english, but i will try my best nexttime – mJrA May 18 '22 at 19:05
  • Those `` element names are very unfortunate since the XML Schema mechanism presupposes fixed element names with variable data like a key name presented as an attribute. You might think of serializing the `` sequence via a dictionary, but [XmlSerializer does not even support them](https://stackoverflow.com/q/2911514). For one workaround see [How do you deserialize XML with dynamic element names?](https://stackoverflow.com/q/37255149). – dbc May 18 '22 at 19:43

1 Answers1

0

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();
    }
}
mJrA
  • 11
  • 3