C# 扩展 where 方法 - 处理未找到元素的情况

发布于 2024-08-21 14:03:33 字数 988 浏览 4 评论 0原文

我正在尝试使用 xDocument 和 LINQ to XML 查询这个非常复杂的 XML 文档。我想要执行以下操作:

获取满足特定条件的所有元素,如果不满足,则从 xDocument 返回另一个属性。

示例:

<cars>
    <car>
        <patrol type="oil">
            <url> http://Toyotaoil.com </url>
        </patrol>
    </car>
    <car>
        <patrol type="oil">
            <url> http://BMWoil.com </url>
        </patrol>
        <patrol type="gas">
            <url> http://BMWgas.com </url>
        </patrol>
    </car>
    <car>
        <patrol type="gas">
            <url> http://Hondagas.com </url>
        </patrol>
    </car>

现在我想从这个查询中得到的是石油类型的巡逻列表,除非汽车不使用汽油,然后我对汽油感到满意。

如果我使用 where 子句,我就会错过汽车使用汽油的情况。是否有像 where 子句这样的东西,我可以在其中指定如果不满足条件该怎么办?

I am trying to query this very complicated XML document using xDocument and LINQ to XML. I want to perform the following action:

Get all elements that answer to a certain criteria, and if they don't, return another attribute from the xDocument.

Example:

<cars>
    <car>
        <patrol type="oil">
            <url> http://Toyotaoil.com </url>
        </patrol>
    </car>
    <car>
        <patrol type="oil">
            <url> http://BMWoil.com </url>
        </patrol>
        <patrol type="gas">
            <url> http://BMWgas.com </url>
        </patrol>
    </car>
    <car>
        <patrol type="gas">
            <url> http://Hondagas.com </url>
        </patrol>
    </car>

Now what I'd like to get from this query is a list of patrols of type oil, unless the car doesn't use petrol, and then I'd be satisfied with gas.

If I use the where clause I just miss the cases where the car uses gas. Is there any such thing like a where clause, where I can specify what to do if they condition wasn't met?

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

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

发布评论

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

评论(6

羅雙樹 2024-08-28 14:03:33

下面的解决方案应该让您可以灵活地查询您喜欢的任何内容:

var result = from car in xdoc.Element("cars").Elements("car") 
             let patrols = car.Elements("patrol")
             let oils = patrols.Where(patrol => patrol.Attribute("type") == "oil")
             select new {
                    Car = car,
                    Patrols = (oils.Any() ? oils : patrols)
             }

我这里没有 Visual Studio,所以我希望它可以编译:)
请提供有关您想要选择的内容的更多信息,我将为您提供更具体的 LINQ 语句。

The solution below should give you the flexibility to query whatever you like:

var result = from car in xdoc.Element("cars").Elements("car") 
             let patrols = car.Elements("patrol")
             let oils = patrols.Where(patrol => patrol.Attribute("type") == "oil")
             select new {
                    Car = car,
                    Patrols = (oils.Any() ? oils : patrols)
             }

I don't have Visual Studio here, so I hope it compiles :)
Give a bit more information on what you like to select, and I'll give you a more specific LINQ statement.

审判长 2024-08-28 14:03:33
xdoc.Element("cars")
    .Elements("car")
    .Select(car => car.Elements("patrol")
                      .SingleOrDefault(p => (string)p.Attribute("type") == "oil")
                   ??
                   car.Elements("patrol")
                      .Single(p => (string)p.Attribute("type") == "gas"));
xdoc.Element("cars")
    .Elements("car")
    .Select(car => car.Elements("patrol")
                      .SingleOrDefault(p => (string)p.Attribute("type") == "oil")
                   ??
                   car.Elements("patrol")
                      .Single(p => (string)p.Attribute("type") == "gas"));
不…忘初心 2024-08-28 14:03:33

你可以做这样的事情:

var query = from element in someElements
            select element.Attribute("type").Value == "oil"
                ? returnSomethingWhenItIsOil
                : returnSomethingWhenItIsSomethingElse;

或者

var query = from element in someElements
            where element.Attribute("type") == "oil"
                || element.Attribute("type") == "gas"
            select element;

但是更好地解释问题,谢谢:)

You can just make something like this:

var query = from element in someElements
            select element.Attribute("type").Value == "oil"
                ? returnSomethingWhenItIsOil
                : returnSomethingWhenItIsSomethingElse;

or

var query = from element in someElements
            where element.Attribute("type") == "oil"
                || element.Attribute("type") == "gas"
            select element;

But explain the problem better, thanks :)

爱的故事 2024-08-28 14:03:33

听起来您实际上根本不需要 where 子句 - 您只需要一个选择一个值或另一个值的 select 子句。

但是,您的示例并没有真正描述您如何根据值选择不同的项目 - 您会选择哪个“其他属性”? “汽车使用汽油的地方”是什么意思?如果您可以提供示例的更多详细信息,那么为您提供匹配的代码应该不会太难。

It sounds like you don't actually want a where clause at all - you just want a select clause that either picks one value or another.

However, your example doesn't really describe how you'd select a different item based on the values - which "other attribute" would you select? What do you mean by "where the car uses gas"? If you can give more details of the example, it shouldn't be too hard to give you matching code.

习惯成性 2024-08-28 14:03:33
                       var cars = from c in xdoc.Descendants("car")
                       where
                       (c.Element("patrol").Attribute("type").Value == "oil" ||
                       c.Element("patrol").Attribute("type").Value == "gas")
                       select new Car
                       {
                           FuelType = c.Element("patrol").Attribute("type").Value.ToString()
                       };

    foreach (Car c in cars)
        {
            Console.WriteLine(c.ToString());
        }

    class Car
    {
        public string FuelType { get; set; }
        public override string ToString()
        {
            return "Car FeulType = " + this.FuelType.ToString();
        }
    }

这些是结果,我得到

alt text http://img694.imageshack.us/ img694/5016/carse.jpg

                       var cars = from c in xdoc.Descendants("car")
                       where
                       (c.Element("patrol").Attribute("type").Value == "oil" ||
                       c.Element("patrol").Attribute("type").Value == "gas")
                       select new Car
                       {
                           FuelType = c.Element("patrol").Attribute("type").Value.ToString()
                       };

    foreach (Car c in cars)
        {
            Console.WriteLine(c.ToString());
        }

    class Car
    {
        public string FuelType { get; set; }
        public override string ToString()
        {
            return "Car FeulType = " + this.FuelType.ToString();
        }
    }

These are the results, I am getting

alt text http://img694.imageshack.us/img694/5016/carse.jpg

风情万种。 2024-08-28 14:03:33

根据您的规格按类型排序,采用FirstOrDefault()


编辑:我的意思是这样的:

var patrols = from car in doc.Root.Elements()
              let p = car.Elements().OrderBy(patrol=>patrol.Attribute("type").Value).First()
              select p;

这会返回每辆车一个结果。检查 OrderBy 子句并进行相应调整。这将导致:

<patrol type="oil">
  <url> http://Toyotaoil.com </url>
</patrol>

<patrol type="gas">
  <url> http://BMWgas.com </url>
</patrol>

<patrol type="gas">
  <url> http://Hondagas.com </url>
</patrol>

再次编辑:啊,现在它点击了。是的,这只会返回每辆车的一个项目 - Zyphrax 提供了一个很好的解决方案。

Order by type according to your specifications, take FirstOrDefault().


Edit: What I meant was something like this:

var patrols = from car in doc.Root.Elements()
              let p = car.Elements().OrderBy(patrol=>patrol.Attribute("type").Value).First()
              select p;

This returns one result per car. Check the OrderBy clause and adjust it accordingly. This would result in:

<patrol type="oil">
  <url> http://Toyotaoil.com </url>
</patrol>

<patrol type="gas">
  <url> http://BMWgas.com </url>
</patrol>

<patrol type="gas">
  <url> http://Hondagas.com </url>
</patrol>

Edit again: Ah, now it clicked. Yes, this only returns a single item per car - Zyphrax gave a nice solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文