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 语法。
我可以做的是:
- 将元素添加到虚构的根元素,然后应用我的 xpath 过滤器(因为 Location 将不再位于 "root")。
- 使用 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 来完成。
在 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 语法。
我可以做的是:
- 将元素添加到虚构的根元素,然后应用我的 xpath 过滤器(因为 Location 将不再位于 "root")。
- 使用 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 来完成。