我编写了这个简单的linq-to-xml查询,似乎使用linq语法无法避免null异常。我用错了吗?什么应该是正确的(和简短的)Linq2Xml语法?
var userData =
queryUserResponseData.Elements("user")
.Single(u => u.Element("username").Value == userName);
<data>
<user>
<username>User1</username>
<userid>123</userid>
</user>
<user>
<username>User2</username>
<userid>456</userid>
</user>
<user>
<userid>999</userid>
</user>
</data>
答案 0 :(得分:5)
XElement和XAttribute有一些显式转换运算符,可将其值转换为特定类型。它们非常有用,因为当元素或属性丢失时返回null。
var userData = queryUserResponseData.Elements("user").Single(u => (string)u.Element("username") == userName);
答案 1 :(得分:2)
从你对Ahmad Mageed的回答的评论:
问题实际上是
u.Element("username").Value
,其中Resharper通知我可能的空异常
听起来你可能会担心潜在而不是真正的问题。您知道您的数据将意味着您将始终返回1个结果,但是ReSharper无法访问您的数据,因此它突出显示如果没有结果则会生成空引用异常。
你可以做以下三件事之一:
忽略警告并且什么都不做。
重新编码以解决此问题,以便不会出现异常(请参阅其他答案)。
将Linq包裹在try {} catch {}
中,这样如果“不可想象”发生,您的程序就不会崩溃。
只有你能真正决定你想做什么。
答案 2 :(得分:1)
使用Single
表示您预计会有1个结果。返回更多结果时,Single将抛出异常。您可以使用First
获取第一个项目,或使用Last
获取最后一个项目。对于多个项目,您需要遍历结果并单独访问每个项目。
如果不存在匹配结果,您可以使用SingleOrDefault
返回null
值或所用类型的默认值。
queryUserResponseData
是XElement还是XDocument?如果它是XDocument,则需要首先访问XML的根目录,例如:
var userData = queryUserResponseData.Root.Elements("user")
.Single(u => u.Element("username").Value == userName);
除此之外,在样本中搜索User1或User2也行。但是,如果您搜索不存在的 User3 ,则Single会抛出异常。在这种情况下,您应该使用SingleOrDefault:
var userData = queryUserResponseData.Elements("user")
.SingleOrDefault(u => u.Element("username").Value == "User3");
答案 3 :(得分:1)
根据您对Ahmad的回答的评论,我假设当元素没有节点时你会得到NullReferenceException。您可以像这样修复它 -
var userData =
doc.Elements("user")
.Single(u => u.Element("username") != null && u.Element("username").Value == userName);
但是如果DTD或XSD需要用户名节点,或者您确定所有元素都有用户名节点,则可以忽略ReSharper警告。
答案 4 :(得分:0)
var userData = queryUserResponseData.Elements("user")
.Select(u => u.Element("username"))
.Where(uNode => uNode != null)
.Single(uName => uName.Value == userName);