如何在不出现空异常的情况下使用 linq2Xml?

发布于 2024-08-11 05:04:54 字数 653 浏览 3 评论 0原文

我编写了这个简单的 linq-to-xml 查询,似乎使用 linq 语法无法避免 null 异常。难道是我用错了?正确(且简短)的 Linq2Xml 语法应该是什么?

linq2Xml 查询

var userData =
    queryUserResponseData.Elements("user")
        .Single(u => u.Element("username").Value == userName);

XML

<data>
    <user>
        <username>User1</username>
        <userid>123</userid>
    </user>
    <user>
        <username>User2</username>
        <userid>456</userid>
    </user>
    <user>
        <userid>999</userid>
    </user>
</data>

I wrote this simple linq-to-xml query and it seems that null exception could not be avoided using the the linq syntax. Am I using it wrong? What should be the right (and short) Linq2Xml syntax?

The linq2Xml query

var userData =
    queryUserResponseData.Elements("user")
        .Single(u => u.Element("username").Value == userName);

The XML

<data>
    <user>
        <username>User1</username>
        <userid>123</userid>
    </user>
    <user>
        <username>User2</username>
        <userid>456</userid>
    </user>
    <user>
        <userid>999</userid>
    </user>
</data>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

流云如水 2024-08-18 05:04:54

XElement 和 XAttribute 有一些显式转换运算符将它们的值转换为特定类型。它们非常有用,因为当元素或属性丢失时返回 null。

var userData = queryUserResponseData.Elements("user").Single(u => (string)u.Element("username") == userName);

XElement and XAttribute have some explicit conversion operators to convert their value to the specific types. They are so useful because, return null when the Element or Attribute is missing.

var userData = queryUserResponseData.Elements("user").Single(u => (string)u.Element("username") == userName);
草莓味的萝莉 2024-08-18 05:04:54

从您对艾哈迈德·马吉德的回答的评论:

问题实际上出在 u.Element("username").Value 处,Resharper 通知我可能存在 null 异常

听起来您可能担心的是潜在问题而不是真正的问题。您知道您的数据意味着您将始终返回 1 个结果,但是 ReSharper 无法访问您的数据,因此它强调了这样一个事实:如果没有结果,它将生成空引用异常。

您可以执行以下三件事之一:

  1. 忽略警告,不执行任何操作。

  2. 重新编码以解决此问题,以便不会出现异常(请参阅其他答案)。

  3. 将 Linq 封装在 try {} catch {} 中,这样,如果发生“不可想象的”情况,您的程序就不会崩溃。

只有你才能真正决定你想做什么。

From your comment to Ahmad Mageed's answer:

The problem is actually at u.Element("username").Value where the Resharper notifies me about a possible null exception

it sounds like you might be worrying about a potential rather than real problem. You know that your data will mean that you will always return 1 result, however ReSharper doesn't have access to your data so it's highlighting the fact that if there were no results it would generate a null reference exception.

You can do one of three things:

  1. Ignore the warning and do nothing.

  2. Recode to account for this so that there's no chance of an exception (see the other answers).

  3. Wrap the Linq in a try {} catch {} so that if the "unthinkable" happens your program won't crash.

Only you can really decide which you want to do.

佞臣 2024-08-18 05:04:54

使用 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");

Using Single means you expect there to be exactly 1 result. When more results are returned, Single will throw an exception. You could use First to get the first item, or Last for the last one. For multiple items you'll want to loop over the results and access each one individually.

If no matching result exists, you can use SingleOrDefault to return a null value or the default value of the type used.

Is queryUserResponseData an XElement or an XDocument? If it's an XDocument you need to access the XML's root first, such as:

var userData = queryUserResponseData.Root.Elements("user")
                 .Single(u => u.Element("username").Value == userName);

Apart from that, searching for User1 or User2 in your sample would work. However, if you searched for User3, which doesn't exist, Single will throw an exception. In that case you should use SingleOrDefault:

var userData = queryUserResponseData.Elements("user")
                 .SingleOrDefault(u => u.Element("username").Value == "User3");
╄→承喏 2024-08-18 05:04:54

根据您对艾哈迈德答案的评论,我认为当元素没有节点时您会得到 NullReferenceException。您可以这样修复它 -

var userData =
    doc.Elements("user")
    .Single(u => u.Element("username") != null && u.Element("username").Value == userName);

但如果 DTD 或 XSD 需要用户名节点,或者您确定所有元素都有用户名节点,您可以简单地忽略 ReSharper 警告。

According to your comment to Ahmad's answer, I presume you get NullReferenceException when element doesn't have node. You can fix it like this -

var userData =
    doc.Elements("user")
    .Single(u => u.Element("username") != null && u.Element("username").Value == userName);

But if username node is required there by DTD or XSD or you are sure all elements will have username node, you can simply ignore ReSharper warning.

够钟 2024-08-18 05:04:54
var userData = queryUserResponseData.Elements("user")
    .Select(u => u.Element("username"))
    .Where(uNode => uNode != null)
    .Single(uName => uName.Value == userName);
var userData = queryUserResponseData.Elements("user")
    .Select(u => u.Element("username"))
    .Where(uNode => uNode != null)
    .Single(uName => uName.Value == userName);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文