C# 我已经搜索过了,但似乎无法根据c中同级xml元素的属性获取xml元素的属性

C# 我已经搜索过了,但似乎无法根据c中同级xml元素的属性获取xml元素的属性,c#,xml,xpath,xelement,C#,Xml,Xpath,Xelement,以下是我的示例xml: <customers group="A"> <customer ID="1234" phone="555-555-0123" name="Golf Clubs International"> <services> <service type="Golf" premise="89645" priority="0" /> </services> <customFields

以下是我的示例xml:

<customers group="A">
  <customer ID="1234" phone="555-555-0123" name="Golf Clubs International">
    <services>
      <service type="Golf" premise="89645" priority="0" />
    </services>
    <customFields>
      <customField key="address" value="5431 E Golf Way, Altanta, GA, 31111" />
      <customField key="connection" value="CONNECTED" />
    </customFields>
  </customer>
我需要返回customField地址值,其中服务等于89645。我使用XElement尝试了几种不同的方法,但没有一种方法可以过滤我需要的内容,即使在我将其过滤时,我也不知道如何重新导航以获得同级元素的属性。下面是一些我试图为premise属性过滤的内容。我已经使用这个网站好几年了,这是我第一次被难倒而发帖

        IEnumerable<XElement> tests =
            from el in cust.Elements("services")
            where (string)el.Elements("service").Attributes("premise").ToString() == ID
            select el;

        var y = cust.Element("customers")
                    .Elements("services")
                    .Where(b => b.Element("service").Value == ID)
                    .SingleOrDefault();

        var x = from a in cust.Elements("service")
                where a.Attribute("premise").Value == ID
                select cust.Elements("customfields").Elements("customfield").Attributes("key");

在这种情况下我喜欢用字典。见下面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication58
{
    class Program
    {
        const string FILENAME = @"C:\TEMP\TEST.XML";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            var query = doc.Descendants("customer").Select(x => new{
                premise = (string)x.Descendants("service").FirstOrDefault().Attribute("premise"),
                customFields = x.Descendants("customField").GroupBy(y => (string)y.Attribute("key"), z => (string)z.Attribute("value"))
                .ToDictionary(y => y.Key, z => z.FirstOrDefault())
            }).ToList();

            var results = query.Where(x => x.premise == "89645").FirstOrDefault();


        }
    }
}
这里有一个单语句解决方案

XDocument doc=XDocument.LoadFILENAME

var query = doc.Descendants("customer").Select(x => new {
    premise = (string)x.Descendants("service").FirstOrDefault().Attribute("premise"),
    customFields = x.Descendants("customField").GroupBy(y => (string)y.Attribute("key"), z => (string)z.Attribute("value"))
    .ToDictionary(y => y.Key, z => z.FirstOrDefault())
}).Where(x => x.premise == "89645")
.FirstOrDefault();

对于可能会发现这一点的VB用户

首先是一些样本数据

    Dim xe As XElement

    xe = <customers group="A">
             <customer ID="1234" phone="555-555-0123" name="Golf Clubs International">
                 <services>
                     <service type="Golf" premise="89645" priority="0"/>
                 </services>
                 <customFields>
                     <customField key="address" value="5431 E Golf Way, Altanta, GA, 31111"/>
                     <customField key="connection" value="CONNECTED"/>
                 </customFields>
             </customer>
             <customer ID="567" phone="555-555-0123" name="Golf Clubs International">
                 <services>
                     <service type="Golf" premise="54698" priority="0"/>
                 </services>
                 <customFields>
                     <customField key="address" value="5431 E Golf Way, Altanta, GA, 31111"/>
                     <customField key="connection" value="CONNECTED"/>
                 </customFields>
             </customer>
             <customer ID="890" phone="555-555-0123" name="Golf Clubs International">
                 <services>
                     <service type="Golf" premise="89645" priority="0"/>
                 </services>
                 <customFields>
                     <customField key="address" value="718 W. High, Jefferson City, MO 65101"/>
                     <customField key="connection" value="CONNECTED"/>
                 </customFields>
             </customer>
         </customers>
然后是获取地址的步骤

    Dim rslts As IEnumerable(Of XElement)

    'first get service equals 89645, using above there are two
    rslts = From el In xe...<service>
            Where el.@premise = "89645"
            Select el

    'for each of those find the address
    For Each rel As XElement In rslts
        Dim ie As IEnumerable(Of XElement)
        ie = rel.Parent.Parent.<customFields>.<customField>.Where(Function(cfel)
                                                                      Return cfel.@key = "address"
                                                                  End Function)

        For Each a As XElement In ie
            Debug.WriteLine(a.@value)
        Next
    Next

查询可以缩短,但这段代码是为了说明发生了什么。

这非常有效,非常感谢。不过很好奇,如果查询全部在一个语句中,您将如何调试它呢?我添加了一个单语句解决方案。我想如果我把解决方案分为两部分,会更容易理解。这两部分帮助很大,我也很感谢你把这一句话也发出来。