C# 中的 XML - hasAttribute,getAttribute 不存在吗?为啥?
Posted
技术标签:
【中文标题】C# 中的 XML - hasAttribute,getAttribute 不存在吗?为啥?【英文标题】:XML in C# - hasAttribute, getAttribute is not there? Why?C# 中的 XML - hasAttribute,getAttribute 不存在吗?为什么? 【发布时间】:2012-11-29 10:20:49 【问题描述】:我正在开展一个项目,该项目需要我在单独的数据库中构建游戏的房间、物品和 NPC。我选择了 XML,但是有些东西阻止了我在 C# 代码中正确解析 XML。我做错了什么?
我的错误是:
System.xml.xmlnode does not contain a definition for HasAttribute
(这也适用于GetAttribute
)并且没有扩展方法接受'HasAttribute'
接受System.Xml.XmlNode
类型的第一个参数?
这也适用于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;
【问题讨论】:
该死,对不起。我忘了包括错误。我收到这样的错误: System.xml.xmlnode 不包含 HasAttribute 的定义(这也适用于 GetAttribute),并且没有接受“HasAttribute”的扩展方法接受 system.xml.xmlnode 类型的第一个参数? 老实说,System.Xml
对象既陈旧又烦人。我会为此使用System.Xml.Linq
。 (或者根本不使用 XML)
如果我们假设我的知识“不够出色”:System.Xml.Linq 对我的代码有什么要求?
Linq to XML:以 XDocument
或 XElement
实例开头: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 - 很棒的例子,但对我们这里的朋友来说,它一定看起来像古希腊。
【参考方案1】:
System.Xml.XmlElement 具有您正在寻找的功能。您正在获取 XMLNode。您需要将节点转换为 XmlElement 才能获得该功能。
xmlElement = (System.Xml.XmlElement)xmlRoom;
【讨论】:
啊,谢谢!我可能应该提到我对 C# 还很陌生。我在哪里放置这个?我只是想在代码中尝试不同的地方,但我宁愿学习正确:) 如果 xmlRooms 集合中的每个项目都将成为 XmlElement,您可以执行foreach(XmlElement xmlRoom in xmlRooms) // defaults for room:
否则创建一个新元素,如 System.Xml.XmlElement xmlElement = (System.Xml.XmlElement)xmlRoom;
并将所有对 xmlRoom 的调用替换为我们在开始时创建的变量为集合中与您要使用的元素匹配的任何项目调用 xmlElement 的 for 循环
哇。好吧,我的 XML 中确实有属性,所以我想我将不得不尝试第二个建议。我试试看。
这行得通,至少对于“房间”而言。我想。没有正确测试它,但它似乎可以解决问题。 @bryan-roberts:你能帮我解决“xmlRoom 在当前上下文中不存在”的错误吗?
GetElementsByName 返回 XMLNode 集合只是因为它是一个基类。就像该命名空间中的许多函数一样。因此,如果您需要检查它返回的节点是评论还是任何其他类型,只需使用 is 比较。 if(xmlRoom is System.Xml.XmlElement)
【参考方案2】:
这与您的问题无关,而是对@ChaosPandion 的建议和您在 cmets 中的问题的回应,这是您使用 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);
OTOH,因为此代码使用 Descendants
方法,该方法返回 XElement
(对应于 XML 元素的类型)而不是 XNode
(对应于 XML 节点的类型)的集合,所以节点对象没有属性的整个问题都被巧妙地回避了。
【讨论】:
【参考方案3】: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
【讨论】:
有趣。我会试着看看这个。以上是关于C# 中的 XML - hasAttribute,getAttribute 不存在吗?为啥?的主要内容,如果未能解决你的问题,请参考以下文章