我正在尝试解析以下XML:
<bs:School>
<bs:Class number="1">
<bs:Student>
<bs:Gender>Male</bs:Gender>
<bs:Name>Jason</bs:Name>
</bs:Student>
<bs:Student>
<bs:Gender>Male</bs:Gender>
<bs:Name>Danny</bs:Name>
</bs:Student>
<bs:Student>
<bs:Gender>Female</bs:Gender>
<bs:Name>Jessica</bs:Name>
</bs:Student>
<bs:Student>
<bs:Gender>Male</bs:Gender>
<bs:Name>Will</bs:Name>
</bs:Student>
<bs:Student>
<bs:Gender>Female</bs:Gender>
<bs:Name>Betty</bs:Name>
</bs:Student>
</bs:Class>
<bs:Class number="2">
<bs:Student>
<bs:Gender>Male</bs:Gender>
<bs:Name>Sean</bs:Name>
</bs:Student>
<bs:Student>
<bs:Gender>Female</bs:Gender>
<bs:Name>Jessica</bs:Name>
</bs:Student>
<bs:Student>
<bs:Gender>Male</bs:Gender>
<bs:Name>Dexter</bs:Name>
</bs:Student>
</bs:Class>
</bs:School>
如何选择所有男生姓名?
我尝试使用以下LINQ查询:
var resources = from c in doc.Descendants("Gender")
where (c.Value.ToString().Contains("Male"))
select c.Parent.Descendants("Name");
它总是返回一个空对象。
答案 0 :(得分:2)
注意:我在根节点xmlns:bs = ""MyNamespace""
中添加了名称空间声明。因此,在我的示例中,根节点看起来像<bs:School xmlns:bs = "MyNamespace">
而不是<bs:School>
var xml = //your xml
var doc = XDocument.Parse(xml);
XNamespace bs = "MyNamespace";
string[] malesNames =
doc.Descendants(bs + "Student")
.Where(stud => stud.Element(bs + "Gender").Value == "Male")
.Select(stud => stud.Element(bs + "Name").Value)
.ToArray();
Console.WriteLine(string.Join(Environment.NewLine, malesNames));
将打印:
Jason
Danny
Will
Sean
Dexter
搜索男学生姓名的命名空间不可知解决方案如下:
doc.Descendants()
.Where(node => node.Name.LocalName == "Student")
.Where(node => node.Elements().First(child => child.Name.LocalName == "Gender").Value == "Male")
.Select(node => node.Elements().First(child => child.Name.LocalName == "Name").Value);
随意将常见的查询片段提取到单独的扩展方法中,例如:
public static class XElementExtensions
{
public static XElement GetFirstChild(this XElement node, string nodeName)
{
return node.Elements().First(child => child.Name.LocalName == nodeName);
}
}
现在你可以:
doc.Descendants()
.Where(node => node.Name.LocalName == "Student")
.Where(node => node.GetFirstChild("Gender").Value == "Male")
.Select(node => node.GetFirstChild("Name").Value);