I'm working on a project that requires me to build a game's rooms, items and NPC in a separate database. I've chosen XML, but something prevents me from properly parsing the XML in my C# code. What am I doing wrong?
My errors are these:
System.xml.xmlnode does not contain a definition for HasAttribute
(this goes for GetAttribute
as well) and no extension method accepting 'HasAttribute'
accepting a first argument of type System.Xml.XmlNode
?
This also goes for GetParentNode
, and my very last line
string isMoveableStr = xmlRoom.GetAttribute("isMoveable");
somehow goes:
the name xmlRoom does not exist in the current context
Here's the method:
public void loadFromFile()
{
XmlDocument xmlDoc = new XmlDocument(); // create an xml document object in memory.
xmlDoc.Load("gamedata.xml"); // load the XML document from the specified file into the object in memory.
// Get rooms, NPCs, and items.
XmlNodeList xmlRooms = xmlDoc.GetElementsByTagName("room");
XmlNodeList xmlNPCs = xmlDoc.GetElementsByTagName("npc");
XmlNodeList xmlItems = xmlDoc.GetElementsByTagName("item");
foreach(XmlNode xmlRoom in xmlRooms) { // defaults for room:
string roomID = "";
string roomDescription = "this a standard room, nothing special about it.";
if( !xmlRoom.HasAttribute("ID") ) //http://msdn.microsoft.com/en-us/library/acwfyhc7.aspx
{
Console.WriteLine("A room was in the xml file without an ID attribute. Correct this to use the room");
continue; //skips remaining code in loop
} else {
roomID = xmlRoom.GetAttribute("id"); //http://msdn.microsoft.com/en-us/library/acwfyhc7.aspx
}
if( xmlRoom.hasAttribute("description") )
{
roomDescription = xmlRoom.GetAttribute("description");
}
Room myRoom = new Room(roomDescription, roomID); //creates a room
rooms.Add(myRoom); //adds to list with all rooms in game ;)
} foreach(XmlNode xmlNPC in xmlNPCs)
{ bool isMoveable = false;
if( !xmlNPC.hasAttribute("id") )
{
Console.WriteLine("A NPC was in the xml file, without an id attribute, correct this to spawn the npc");
continue; //skips remaining code in loop
}
XmlNode inRoom = xmlNPC.getParentNode();
string roomID = inRoom.GetAttribute("id");
if( xmlNPC.hasAttribute("isMoveable") )
{
string isMoveableStr = xmlRoom.GetAttribute("isMoveable");
if( isMoveableStr == "true" )
isMoveable = true;
}
}
}
System.Xml.XmlElement has the function you are looking for. You are getting XMLNode's. You will need to cast the nodes to XmlElement to get that function.
xmlElement = (System.Xml.XmlElement)xmlRoom;
This is not specifically germane to your question, but a response to @ChaosPandion's suggestion and your question in the comments, here is your code example using Linq to XML:
var xdoc = XDocument.Load("gamedata.xml");
var xRooms = xdoc.Descendants("room");
List<Room> rooms;
//If an element doesn't have a given attribute, the Attribute method will return null for that attribute
//Here we first check if any rooms are missing the ID attribute
if (xRooms.Any( xRoom => (string)xRoom.Attribute("ID") == null )) {
Console.WriteLine("A room was in the xml file without an ID attribute...");
} else {
rooms = (
from xRoom in xRooms
select new Room(
xRoom.Attribute("description") ?? "this a standard room, nothing special about it.",
(int)xRoom.Attribute("ID")
)
).ToList();
}
var xNPCs = xdoc.Descendants("npc");
if (xNPCs.Any( xNPC => (string)xNPC.Attribute("id") == null )) {
Console.WriteLine("A NPC was in the xml file, without an id attribute, correct this to spawn the npc");
} else {
var npcs = (
from xNPC in xNPCs
let inRoom = xNPC.Parent
select new {
xNPC,
inRoom,
isMoveable = (string)xNPC.Attribute("isMoveable") != null &&
(string)inRoom.Attribute("isMoveable") == true
}
).ToList();
}
Then you can use a simple foreach
on the npcs
collection:
foreach (var npc in npcs) {
Console.WriteLine(inRoom.Attribute("ID"));
Console.WriteLine(npc.IsMoveable);
}
OTOH since this code makes use of the Descendants
method, which returns an collection of XElement
(the type corresponding to an XML element) and not of XNode
(the type corresponding to an XML node), the whole issue of a node object not having attributes is neatly sidestepped.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With