C#中的XML - 没有hasAttribute、getAttribute,为什么?

5

我正在处理一个项目,需要将游戏的房间、物品和NPC建立在一个单独的数据库中。我选择了XML格式,但是我的C#代码无法正确解析XML文件。请问我做错了什么?

我的错误如下:

System.xml.xmlnode does not contain a definition for HasAttribute 

(这也适用于GetAttribute)没有扩展方法接受类型为System.Xml.XmlNode的第一个参数的'HasAttribute'?

对于GetParentNode也是如此,还有我的最后一行。

string isMoveableStr = xmlRoom.GetAttribute("isMoveable");

某种方式进行:

the name xmlRoom does not exist in the current context

这里是方法:

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;
            }

        }
    }

1
该死,抱歉。我忘记包含错误了。我收到这样的错误:System.xml.xmlnode不包含HasAttribute的定义(GetAttribute也是如此),也没有接受类型为system.xml.xmlnode的第一个参数的'HasAttribute'扩展方法。 - Ithaca
老实说,System.Xml 的对象古老且令人讨厌。我会使用 System.Xml.Linq 来处理这个问题。(或者干脆不使用 XML) - ChaosPandion
如果我们假设我的知识“不太出色”,那么System.Xml.Linq会要求我的代码具备什么条件? - Ithaca
2
Linq to XML:从XDocumentXElement实例开始:var xdoc = XDocument.Load("gamedata.xml"); var xRooms = xdoc.Descendants("room");。然后,例如,您可以使用以下内容替换整个循环以检查缺少的ID:if (xRooms.Any(xRoom => (string)xRoom.Attribute("ID") == null)) {Console.WriteLine("A room was in the xml file without an ID attribute...");} else {var rooms = xRooms.Select(xRoom => new Room(xRoom.Attribute("description"), (int)xRoom.Attribute("ID"))).ToList();} - Zev Spitz
@Zev - 很棒的例子,但对我们的朋友来说可能看起来像古希腊语。 - ChaosPandion
我其实懂古希腊语 ;)无论如何,我已经让它工作了 - 主要是遵循Bryan Roberts的建议。不过那看起来很有趣。我会在另一个项目中研究它的 :) 谢谢! - Ithaca
3个回答

6

System.Xml.XmlElement有您要查找的功能。您正在获取XMLNode。您需要将节点转换为XmlElement以获取该功能。

xmlElement = (System.Xml.XmlElement)xmlRoom;

啊,谢谢!我应该提一下我对C#还比较新。这个代码应该放在哪里?我本来想在代码中尝试不同的位置,但我更愿意学习正确的方法 :) - Ithaca
如果xmlRooms集合中的每个项目都是一个XmlElement,那么您可以这样做:foreach(XmlElement xmlRoom in xmlRooms) { // defaults for room:否则,创建一个新元素,如下所示:System.Xml.XmlElement xmlElement = (System.Xml.XmlElement)xmlRoom;并将所有对xmlRoom的调用替换为我们在for循环开始时创建的变量xmlElement,以处理与要使用的元素匹配的集合中的任何项目。 - Bryan Roberts
哇,好的。我的XML中确实有属性,所以我想我得尝试第二个建议。我会试一下的。 - Ithaca
GetElementsByName返回XMLNode集合,因为它是一个基类。就像该命名空间中的许多函数一样。因此,如果您需要检查返回的节点是否为注释或任何其他类型,请使用is比较。 if(xmlRoom is System.Xml.XmlElement) - Bryan Roberts
哦,该死。@bryan-roberts 现在我在 rooms.Add(myRoom); 上遇到了一个错误,说对象引用未设置为对象的实例。...不确定我是否能掌握这个。 - Ithaca
显示剩余3条评论

2

这并不是针对你的问题,而是回应了@ChaosPandion建议和你在评论中提出的问题,以下是使用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();
}

然后你可以在npcs集合上使用简单的foreach

foreach (var npc in npcs) {
    Console.WriteLine(inRoom.Attribute("ID"));
    Console.WriteLine(npc.IsMoveable);
}

然而,由于这段代码使用了Descendants方法,该方法返回一个XElement集合(对应XML元素的类型),而不是XNode集合(对应XML节点的类型),因此节点对象没有属性的问题得到了巧妙的解决。


1

XmlNode没有HasAttribute或GetAttribute方法。如果您查看XmlNode的MSDN条目,您可以看到它可用的方法。

http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.aspx

如果您使用XmlNode.Attributes ["ATTRIBUTE_NAME"]或在您的情况下xmlRoom.Attributes ["ID"],您应该能够找到您要查找的属性。也就是说,如果您想继续使用XmlNodes。
以下链接提供了一个从XmlNode按名称检索属性的示例: http://msdn.microsoft.com/en-us/library/1b823yx9.aspx

有趣。我会试着看一下这个。 - Ithaca

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接