C# IEnumerable<XElement> - 如何对 "root" 进行 Xpath 过滤?

C# IEnumerable<XElement> - How to Xpath Filter on "root"?

在 C# 中,我有一个 XElements 的 IEnumerable。所有 XElements 都具有相同的名称,但类型不同。我想对每个 XElement 的 "root" 元素执行 "xpath filter"。

样本XML:

<xml>
    <Location>
        <Type>Airport</Type>
        <Buildings></Buildings>
    </Location>
    <Location>
        <Type>Mine</Type>
        <Buildings></Buildings>
    </Location>
    <Location>
        <Type>Airport</Type>
        <Buildings></Buildings>
    </Location>
</xml>

示例 C#:

var elements = xml.Elements("Location");

我需要的是获取 Location/Type 为 "Airport" 的所有建筑物。我喜欢做的是:

elements.SelectMany(el => el.XPathSelectElements(".[Type = 'Airport']/Buildings/Building"));

但是,我无法弄清楚在 XElement(“.[Type”部分)的 "root" 处过滤的 xpath 语法。

可以做的是:

  1. 将元素添加到虚构的根元素,然后应用我的 xpath 过滤器(因为 Location 将不再位于 "root")。
  2. 使用 Linq 过滤位置,例如:elements.Where(loc => loc.Element("Type").Value == "Airport")

但是我想知道有没有xpath方式。 谁能指出 xpath 语法的正确方向?

谢谢!

编辑 上面的 XML 是一个极其简化的示例。 actualXML有几万行长,相对不可预测(源对象的一个​​变化可以改变XML的几千行),它的schema不完全为人所知(在我这边)。有些结构重复and/or嵌套。因此,使用“//”是不够的。对造成的混乱表示歉意。

试试这个:

var buildings = xml.XPathSelectElements("//xml/Location[Type=\"Airport\"]/Buildings");

示例:

string xmlString =
                @"<xml>
                    <Location>
                        <Type>Airport</Type>
                        <Buildings>First airport buildings</Buildings>
                    </Location>
                        <Type>Mine</Type>
                        <Buildings>Mine buildings</Buildings>
                    <Location>
                        <Type>Airport</Type>
                        <Buildings>Second airport buildings</Buildings>
                    </Location>
                </xml>";

XDocument xml = XDocument.Parse(xmlString);
var buildings = 
xml.XPathSelectElements("//xml/Location[Type=\"Airport\"]/Buildings");

foreach (var b in buildings)
    {
     Console.WriteLine(b.Value);
    }

结果:

 First airport buildings
 Second airport buildings

嗯,我想要的好像是不可能的。因此,我转而创建一个 "fake root" 元素,添加我的 XElement 集合,并使用 xpath:

var airportBlgs = new XElement("root", locations)
    .XPathSelectElements( "./Location[Type='Airport']/Building" );

假根意味着我不必使用“//”,这太宽泛了。太糟糕了,这不能仅使用 xpath 来完成。