使用LINQ进行XML解析:获取附近节点值的最佳方法是什么

时间:2013-04-29 13:51:22

标签: c# sql xml linq

我正在尝试解析以下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");

它总是返回一个空对象。

1 个答案:

答案 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);