C#IEnumerable <xelement> - 如何在“root”上过滤Xpath?

时间:2018-04-16 21:03:36

标签: c# xpath linq-to-xml

在C#中,我有一个IEnumerable的XElements。所有XElements都具有相同的名称,但类型不同。我想在每个XElement的“root”元素上执行“xpath过滤器”。

示例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");

我需要的是获得位置/类型为“机场”的所有建筑物。我喜欢做的事情就像:

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

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

可以做的是:

  1. 将元素添加到一个虚构的根元素,然后应用我的xpath过滤器(因为Location不再位于“root”)。
  2. 使用Linq过滤地点,例如:elements.Where(loc => loc.Element("Type").Value == "Airport")
  3. 但我想知道是否有xpath方式。 有人能指出我正确的xpath语法方向吗?

    谢谢!

    修改 上面的XML是一个非常愚蠢的样本。 实际 XML长达数万行,相对不可预测(源对象的更改可能会改变数千行XML),并且其架构尚不完全清楚(在我的最后)。一些结构重复和/或嵌套。因此,使用“//”不太可能。为混乱道歉。

2 个答案:

答案 0 :(得分:1)

试试这个:

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

答案 1 :(得分:-1)

嗯,似乎我想要的不可能。所以相反,我创建了一个“假根”元素,添加了我的XElement集合,并使用了一个xpath:

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

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