具有复杂过滤 LINQ to XML c# 的查询
Posted
技术标签:
【中文标题】具有复杂过滤 LINQ to XML c# 的查询【英文标题】:Queries with complex filtering LINQ to XML c# 【发布时间】:2021-08-21 13:45:07 【问题描述】:我想了解使用 LINQ XML 进行的复杂过滤。 我创建了一个简单的 XML 示例(DataBaseCities.xml):
<?xml version="1.0" encoding="utf-8"?>
<DataBase>
<DocumentInfo version="1.0" schemaVersion="1.0"/>
<ListOfMegaCities>
<MegaCities city="Moscow" continent="Europe">
<VariantConstraint>
<LanguageRef LanguageId="russian">
<LanguageDialectsRef DialectsId="north"/>
</LanguageRef>
</VariantConstraint>
<Districts>
<CityDistrict District="Arbat"/>
<CityDistrict District="Basmanny"/>
</Districts>
</MegaCities>
<MegaCities city="New York" continent="North America">
<VariantConstraint>
<LanguageRef LanguageId="english">
<LanguageDialectsRef DialectsId="west"/>
</LanguageRef>
<LanguageRef LanguageId="spanish">
<LanguageDialectsRef DialectsId="cental"/>
</LanguageRef>
</VariantConstraint>
<Districts>
<CityDistrict District="Queens"/>
<CityDistrict District="Bronx"/>
</Districts>
</MegaCities>
<MegaCities city="London" continent="Europe">
<VariantConstraint>
<LanguageRef LanguageId="english">
<LanguageDialectsRef DialectsId="west"/>
</LanguageRef>
<LanguageRef LanguageId="spanish">
<LanguageDialectsRef DialectsId="central"/>
</LanguageRef>
<LanguageRef LanguageId="french">
<LanguageDialectsRef DialectsId="central"/>
</LanguageRef>
</VariantConstraint>
<Districts>
<CityDistrict District="Greenwich"/>
<CityDistrict District="Westminster"/>
</Districts>
</MegaCities>
</ListOfMegaCities>
</DataBase>
我尝试过滤如下:
XElement root = XElement.Load(@"DataBaseCities.xml");
IEnumerable<XElement> ListOfMegaCities =
from el in root.Descendants("MegaCities")
where
(from add in el.Descendants("LanguageRef")
where
(string)add.Attribute("LanguageId") == "english"
select add)
.Any()
select el;
foreach (XElement el in ListOfMegaCities)
Console.WriteLine((string)el.Attribute("city"));
所以输出是:
New York
London
但我想过滤多个属性。
如果我尝试使用这些行进行过滤:
(string)add.Attribute("LanguageId") == "english" && (string)add.Attribute("LanguageId") == "西班牙语"
为什么它不起作用?
-
如何过滤“方言 ID”?
示例:我想通过这个过滤得到“纽约”:
LanguageId="english"
DialectsId="west"
LanguageId="spanish"
DialectsId="cental"
也许有人有一个很好的复杂过滤来源?我找到了这个https://docs.microsoft.com/de-de/dotnet/standard/linq/write-queries-complex-filtering,但这只是部分帮助了我......
【问题讨论】:
IMO 创建代表 xml 结构的类,然后反序列化为新类,最后使用 linq 过滤等。 建立或条件。它的相同元素。 (string)add.Attribute("LanguageId") == "english" || (string)add.Attribute("LanguageId") == "西班牙语"。您请求的逻辑应该是: ((string)add.Attribute("LanguageId") == "english" || (string)add.Attribute("LanguageId") == "spanish") || ((string)add.Attribute("DialectsId") == "west" || (string)add.Attribute("DialectsId") == "cental") @Aleksej,要将 xml 反序列化为 CLR 对象,请参阅另一个问题:***.com/questions/364253/… 好的,谢谢。我会尝试。如果我找到解决方案,我会在这里发布。 西班牙语的 dialectsId 是纽约的“中部”和伦敦的“中部”。想要这种差异? 【参考方案1】:首先,请参阅@zaggler 评论。反序列化和操作对象会更容易。
其次,如果您想要只说英语和西班牙语的城市,请参阅@AkshayGaonkar 答案。如果您想要使用英语和西班牙语(可能还有其他语言)的城市,请参阅我的回答。
为了写复杂的Linq查询,我开始写模拟SQL:
-- I want all cities
select * from MegaCities as el
where
-- that speak english with west dialect
exists (
select * from el.LanguageRef as add
where add.LanguageId = 'english' and
add.LanguageDialectsRef.DialectsId = 'west'
)
-- and also speak spanish with central dialect
and exists (
select * from el.LanguageRef as add
where add.LanguageId == 'spanish' and
add.LanguageDialectsRef.DialectsId = 'cental'
)
然后我可以转置到 Linq :
IEnumerable<XElement> ListOfMegaCities =
from el in root.Descendants("MegaCities")
where
(from add in el.Descendants("LanguageRef")
where add.Attribute("LanguageId").Value == "english" &&
add.Element("LanguageDialectsRef").Attribute("DialectsId").Value == "west"
select add)
.Any()
&&
(from add in el.Descendants("LanguageRef")
where add.Attribute("LanguageId").Value == "spanish" &&
add.Element("LanguageDialectsRef").Attribute("DialectsId").Value == "cental"
select add)
.Any()
select el;
也许不是最好的技巧,但有时会有所帮助。
【讨论】:
@AkshayGaonkar,谢谢。central
或 cental
,这听起来像是问题中的错误。
嗯,这改变了整个场景。我曾使用All
专门将New York
作为输出。如果 London 也是有效输出,那么我必须更改为 Any
【参考方案2】:
我使用了All
而不是Any
,因此它只过滤那些满足所有条件的城市。我习惯于编写 LINQ 表达式而不是 LINQ 查询。
List<XElement> ListOfMegaCities = root.Descendants("MegaCities")
.Where(lr => lr.Descendants("LanguageRef")
.All(
li => (li.Attribute("LanguageId").Value == "english"
&& li.Element("LanguageDialectsRef").Attribute("DialectsId").Value == "west")
|| (li.Attribute("LanguageId").Value == "spanish"
&& li.Element("LanguageDialectsRef").Attribute("DialectsId").Value == "cental")
)
).ToList();
【讨论】:
我没有忘记请求。 :) 这看起来非常好。我将分析语法以了解更多信息。如果我有其他解决方案,我会告诉大家。以上是关于具有复杂过滤 LINQ to XML c# 的查询的主要内容,如果未能解决你的问题,请参考以下文章
具有 Lightswitch 计算属性的 Linq to SQL 查询过滤器