Get the XElement for the XML

本文关键字:the XML for XElement Get | 更新日期: 2023-09-27 18:22:02

这是我的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属性从给定的结构中获取TemplateXElement。问题是可能存在多个具有相同属性Name的模板标记。区别因素是"应用程序名称"属性值和截面属性值。

目前,我可以通过首先根据其属性获取ApplicationElement,然后根据其属性获得Section,最后根据其名称获取模板来获取XElement。

我想知道是否有办法一次搞定。

Get the XElement for the XML

我会使用这样一个事实,即您可以调用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

下面的代码应该可以做到这一点:

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。或者如果Template标记没有两个级别的父级。

    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"));
    }

XPath应该会对您有所帮助。使用Extensions.XPathSelectElement方法(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);