1

我正在尝试使用 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条款这样的东西,我可以在其中指定如果不满足条件该怎么办?

4

6 回答 6

2
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"));
于 2010-02-13T12:56:21.600 回答
2

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

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 语句。

于 2010-02-13T13:17:04.750 回答
1

你可以做这样的事情:

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;

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

于 2010-02-13T13:00:08.487 回答
0

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

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

于 2010-02-13T12:52:04.693 回答
0
                       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();
        }
    }

这些是结果,我得到

替代文字 http://img694.imageshack.us/img694/5016/carse.jpg

于 2010-02-13T13:15:01.167 回答
-1

Order根据您的规格按类型,取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 提供了一个很好的解决方案。

于 2010-02-13T12:51:44.210 回答