获取XML的XElement

时间:2012-02-01 13:22:20

标签: c# xml linq xelement

这是我的XML文件:

<Applications>
   <Application Name="Abc">
     <Section Name="xyz">
        <Template Name="hello">
         ...
         ....
         </Template>
      </Section>
   </Application>
   <Application Name="Abc1">
     <Section Name="xyz1">
        <Template Name="hello">
         ...
         ....
         </Template>
      </Section>
   </Application>

我需要做的是根据Template标签的Name属性从给定结构中获取Template XElement。问题是可以有多个具有相同属性Name的模板标签。区别因素是Application Name属性值和section属性值。

目前我能够通过首先根据它的属性获取应用程序元素来获取XElement,然后根据它的属性获取Section,然后根据它的名称获得最终模板。

我想知道是否有办法一次性完成它。

4 个答案:

答案 0 :(得分:6)

我会使用你可以调用Elements或现有序列的事实,所以:

var template = doc.Descendants("Application")
                  .Where(x => (string) x.Attribute("Name") == applicationName)
                  .Elements("Section")
                  .Where(x => (string) x.Attribute("Name") == sectionName)
                  .Elements("Template")
                  .Where(x => (string) x.Attribute("Name") == templateName)
                  .FirstOrDefault();

您甚至可能想在某处添加扩展方法:

public static IEnumerable<XElement> WithName(this IEnumerable<XElement> elements,
                                             string name)
{
    this elements.Where(x => (string) x.Attribute("Name") == name);
}

然后您可以将查询重写为:

var template = doc.Descendants("Application").WithName(applicationName)
                  .Elements("Section").WithName(sectionName)
                  .Elements("Template").WithName(templateName)
                  .FirstOrDefault();

...我认为你会同意这一点很可读:)

请注意,使用XAttribute转换为string而非使用Value属性意味着任何没有Name属性的元素都会被有效忽略而不是导致NullReferenceException

答案 1 :(得分:1)

    XDocument doc = XDocument.Load("Path of xml");
    var selection =
        doc.Descendants("Section").Select(item => item).Where(
            item => item.Attribute("Name").Value.ToString().Equals("Section Name Value")).ToList();

    if(null != selection)
    {
        var template =
            selection.Descendants("Template").Select(item => item).Where(
            item => item.Attribute("Name").Value.ToString().Equals("Template name value"));
    }

答案 2 :(得分:1)

以下代码可以解决这个问题:

var template = doc.Descendants("Template")
                  .Where(x => x.Attribute("Name").Value == "hello"
                           && x.Parent.Attribute("Name").Value == "xyz1"
                           && x.Parent.Parent.Attribute("Name").Value == "Abc1");

请注意,如果XML不符合规范,此代码会抛出异常。具体来说,如果有问题的任何标签不包含名为“Name”的属性,则会有NullReferenceException。或者,如果模板标签没有两级父母。

答案 3 :(得分:1)

XPath应该可以帮到你。使用Extensions.XPathSelectElement Method (XNode, String)

XDocument xdoc = XDocument.Load("yourfile.xml");
string xPathQuery = string.Format(
    "/Applications/Application[@Name='{0}']/Section[@Name='{1}']/Template[@Name='{2}']",
    "MyApplication",
    "MySection",
    "MyTemplate"
);

XElement template = xdoc.Root.XPathSelectElement(xPathQuery);