C
C#11mo ago
Wicked Cat

❔ struggling with reading data from xml files

Hello there. I'm struggling with referencing only the subpart nodes inside the relevant bodypart node, instead of either all or none of them.
56 Replies
JakenVeina
JakenVeina11mo ago
struggling how?
Wicked Cat
Wicked Cat11mo ago
sorry i'm having a hard time figuring out how to explain it. So second image, ive got a body object with it's constructor using the attributes in the xml file. the body object has a Parts list which i am able to add to successfully. so the human body in the xml file has the head, chest, gut, arms in it's Parts list. but each of those head, chest etc objects also has a list of sub parts, which is where the eyes, ears etc are supposed to go. the problem i'm having is I can't figure out how to reference the subparts in the xml file. The code in the second image sees the bodypart, but not any subpart
JakenVeina
JakenVeina11mo ago
define "sees the bodypart, but not any subpart"
Wicked Cat
Wicked Cat11mo ago
the body object'Parts list is being filled properly (ex the body has a head, chest, etc), but the head's subpart list is not being added to (the head bodypart object is supposed to have eyes, ears etc in it's subparts list)
JakenVeina
JakenVeina11mo ago
but the head's subpart list is not being added to
why not?
Wicked Cat
Wicked Cat11mo ago
i'm assuming it's because in the second image i posted, i'm not referring to the subparts in the xml file correctly.
JakenVeina
JakenVeina11mo ago
depends how you think about it how you refer to the subparts in the XML depends on 2 things where you're referring from and what path you refer to
node.SelectNodes("SubParts/SubPart")
node.SelectNodes("SubParts/SubPart")
what is node?
Wicked Cat
Wicked Cat11mo ago
also here's my github because at this point it's probably eaiser https://github.com/Wicked-Cat/StoryRPG
GitHub
GitHub - Wicked-Cat/StoryRPG
Contribute to Wicked-Cat/StoryRPG development by creating an account on GitHub.
Wicked Cat
Wicked Cat11mo ago
in engine/factories/bodyfactory
JakenVeina
JakenVeina11mo ago
so node is a <Body>
Wicked Cat
Wicked Cat11mo ago
yes
JakenVeina
JakenVeina11mo ago
let's say the first one, for the moment how many <SubParts> children does it have?
Wicked Cat
Wicked Cat11mo ago
the whole body? technically none
JakenVeina
JakenVeina11mo ago
that would by why node.SelectNodes("SubParts/SubPart") returns nothing, then
Wicked Cat
Wicked Cat11mo ago
right. I don't know what the correct code would look like
JakenVeina
JakenVeina11mo ago
depends what you want to do
Wicked Cat
Wicked Cat11mo ago
i already told you what i want to do
JakenVeina
JakenVeina11mo ago
not really you said that the subparts lists aren't getting populated what do you want to populate them with?
Wicked Cat
Wicked Cat11mo ago
with the subparts in the xml file. so the head subparts list gets populated with onlythe subparts within the head bodypart tags
JakenVeina
JakenVeina11mo ago
so, for starters, you want to be searching for subparts only within the head bodypart or whatever your current bodypart is not the whole body
Wicked Cat
Wicked Cat11mo ago
yes. I don't know how to do that
JakenVeina
JakenVeina11mo ago
sure you do how do you search for nodes within a node
Wicked Cat
Wicked Cat11mo ago
I think it would make more sense to me if I saw an example of this being done correctly
JakenVeina
JakenVeina11mo ago
it wouldn't look any different than what you have now you literally have one line to change
Wicked Cat
Wicked Cat11mo ago
so it would look different than what I have now
JakenVeina
JakenVeina11mo ago
no, as I said there's no new syntax no new method calls nothing new that you're not doing already you're just searching on the wrong node you're searching for head subparts within the entire body instead of within the head bodypart
Wicked Cat
Wicked Cat11mo ago
i've tried childnode.selectnodes, or node.selectnodes("parts/bodyparts/subparts/subpart"). both of thoses things result in all head subparts from all bodies being applied to each head
JakenVeina
JakenVeina11mo ago
gonna have to disagree
childNode.SelectNodes("SubParts/SubPart")
childNode.SelectNodes("SubParts/SubPart")
is correct
Wicked Cat
Wicked Cat11mo ago
disagree with... my results? because those are my results
Wicked Cat
Wicked Cat11mo ago
Wicked Cat
Wicked Cat11mo ago
the code you have results in this
JakenVeina
JakenVeina11mo ago
then you're not running the code you showed me plus the line I just gave
Wicked Cat
Wicked Cat11mo ago
this is what i'm running
Wicked Cat
Wicked Cat11mo ago
and the first image i posted is the xml file plus you have my git
JakenVeina
JakenVeina11mo ago
that code is correct start challenging your assumptions is that the code you're actually running? are you quite sure you have the correct XML file? is your output routine correct? is your output routine actually operating on the right body objects?
Wicked Cat
Wicked Cat11mo ago
define output routine please
JakenVeina
JakenVeina11mo ago
whatever is generating that screenshot you posted
Wicked Cat
Wicked Cat11mo ago
it's just a foreach for the output
JakenVeina
JakenVeina11mo ago
looks reasonable
Wicked Cat
Wicked Cat11mo ago
looks like the subparts lists aren't getting subparts from other bodies but it's being duplicated a differing amount of times like, the rat body only has twice the subparts, but the human body has four times
JakenVeina
JakenVeina11mo ago
sounds like you're leaking list instances
Wicked Cat
Wicked Cat11mo ago
what does that mean?
JakenVeina
JakenVeina11mo ago
you're inadvertently reusing lists you've already populated, instead of creating a new one each time I kinda suspected that earlier, but I didn't see it
Wicked Cat
Wicked Cat11mo ago
huh. what's the best practice for something like this? should i clear the lists in the foreach? or delete them somehow
JakenVeina
JakenVeina11mo ago
no, your goal is to use unique lists each time
Wicked Cat
Wicked Cat11mo ago
i'm struggling hard to understand the minutiae of how ToList copies things, but am I on the right track?
JakenVeina
JakenVeina11mo ago
possibly there isn't really any minutiae, .ToList() creates a full duplicate list in memory at any rate, the XML logic is good
JakenVeina
JakenVeina11mo ago
BlazeBin - airdjrksbykn
A tool for sharing your source code with the world!
JakenVeina
JakenVeina11mo ago
var document = new XmlDocument();
document.LoadXml(File.ReadAllText(@"D:\Projects\Test\Test\Bodies.xml"));

if (document.SelectNodes("/Bodies/Body") is not XmlNodeList bodies)
return;

foreach(XmlNode body in bodies)
{
Console.WriteLine($"Body: {body.Attributes?.GetNamedItem("ID")?.Value}, {body.Attributes?.GetNamedItem("Name")?.Value}");

if (body.SelectNodes("Parts/BodyPart") is not XmlNodeList bodyParts)
continue;

foreach(XmlNode bodyPart in bodyParts)
{
Console.WriteLine($"\tBodyPart: {bodyPart.Attributes?.GetNamedItem("Name")?.Value}");

if (bodyPart.SelectNodes("SubParts/SubPart") is not XmlNodeList subParts)
continue;

foreach(XmlNode subPart in subParts)
Console.WriteLine($"\t\tSubPart: {subPart.Attributes?.GetNamedItem("Name")?.Value}");
}
}
var document = new XmlDocument();
document.LoadXml(File.ReadAllText(@"D:\Projects\Test\Test\Bodies.xml"));

if (document.SelectNodes("/Bodies/Body") is not XmlNodeList bodies)
return;

foreach(XmlNode body in bodies)
{
Console.WriteLine($"Body: {body.Attributes?.GetNamedItem("ID")?.Value}, {body.Attributes?.GetNamedItem("Name")?.Value}");

if (body.SelectNodes("Parts/BodyPart") is not XmlNodeList bodyParts)
continue;

foreach(XmlNode bodyPart in bodyParts)
{
Console.WriteLine($"\tBodyPart: {bodyPart.Attributes?.GetNamedItem("Name")?.Value}");

if (bodyPart.SelectNodes("SubParts/SubPart") is not XmlNodeList subParts)
continue;

foreach(XmlNode subPart in subParts)
Console.WriteLine($"\t\tSubPart: {subPart.Attributes?.GetNamedItem("Name")?.Value}");
}
}
Wicked Cat
Wicked Cat11mo ago
I don't understand what this is for
JakenVeina
JakenVeina11mo ago
this is to verify that the logic you now have for reading the XML is correct
Wicked Cat
Wicked Cat11mo ago
ah alright do you have any advice for what I should do about the lists? I don't even know where to start to fix this
JakenVeina
JakenVeina11mo ago
not a lot I really don't see the issue
public List<BodyPart> SubParts { get; set; }
public List<BodyPart> SubParts { get; set; }
I will suggest you handle this differently question: what's your intention here, regarding mutating these models? can parts be added/removed at runtime? or should that just be part of initialization? if you need to be able to add/remove parts at any time, what you should do is....
public List<BodyPart> SubParts { get; }
public List<BodyPart> SubParts { get; }
this prevents you from accidentally screwing up your instance management the List<T> is still editable by consumers, but they can't replace the whole instance nor should they if parts should only be created during initialization, then you should do....
public IReadOnlyList<BodyPart> SubParts { get; }
public IReadOnlyList<BodyPart> SubParts { get; }
this clarifies your intent, as the list can now not be edited at all you can still mutate the individual parts within it, but the list itself is frozen your initializer would then change to look something like....
var subParts = new List<BodyPart>();

foreach(XmlNode subPartNode in subPartNodes)
{
subParts.Add(new BodyPart(...));
}

parts.Add(new BodyPart(..., subParts));
var subParts = new List<BodyPart>();

foreach(XmlNode subPartNode in subPartNodes)
{
subParts.Add(new BodyPart(...));
}

parts.Add(new BodyPart(..., subParts));
so, you create the list, populate it, and then hand it to the new owner the new owner doesn't even KNOW that it's a List<T> cause it doesn't care it only knows that it's an IReadOnlyList<T> because that's the minimum functionality that it requires and again getting rid of set prevents you from screwing up the instance management there's a decent chance that removing the set will immediately reveal the problem, as it'll cause a compiler error to throw at some line that's swapping out the instance where it shouldn't
Wicked Cat
Wicked Cat11mo ago
well, i got rid of the set, no error: ') I do want to be able to add and remove parts during runtime
JakenVeina
JakenVeina11mo ago
then just leave it as a List<T> that you set in the constructor beyond that, you're gonna need to start digging with the debugger
Accord
Accord11mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.