如何在XDocument上使用LINQ进行自联接?

时间:2014-07-22 11:20:15

标签: c# asp.net linq linq-to-xml xelement

我的XDocument随机包含这种格式的几条记录:

<Course>
  <CourseId>21</CourseId>
  <CourseName>leaf</CourseName>
  <CourseDesc>This course</CourseDesc>
  <Event>
    <EventName>Dallas, US - August 19, 2013</EventName>
    <EventStart>2013-08-19T00:00:00-04:00</EventStart>
    <EventEnd>2013-08-23T00:00:00-04:00</EventEnd>
  </Event>
  <Event>
    <EventName>Texas, US - August 19, 2013</EventName>
    <EventStart>2013-08-19T00:00:00-04:00</EventStart>
    <EventEnd>2013-08-23T00:00:00-04:00</EventEnd>
  </Event>
  <Event>
    <EventName>NY, US - August 19, 2013</EventName>
    <EventStart>2013-08-19T00:00:00-04:00</EventStart>
    <EventEnd>2013-08-23T00:00:00-04:00</EventEnd>
  </Event>
</Course>

(通常<Event>个节点只出现一次)

我需要提取/选择/过滤它们:

<Course>
      <CourseId>21</CourseId>
      <CourseName>leaf</CourseName>
      <CourseDesc>This course</CourseDesc>
      <Event>
        <EventName>Dallas, US - August 19, 2013</EventName>
        <EventStart>2013-08-19T00:00:00-04:00</EventStart>
        <EventEnd>2013-08-23T00:00:00-04:00</EventEnd>
      </Event>
</Course>
 <Course>
      <CourseId>21</CourseId>
      <CourseName>leaf</CourseName>
      <CourseDesc>This course</CourseDesc>
      <Event>
        <EventName>Texas, US - August 19, 2013</EventName>
        <EventStart>2013-08-19T00:00:00-04:00</EventStart>
        <EventEnd>2013-08-23T00:00:00-04:00</EventEnd>
      </Event>
</Course>
 <Course>
      <CourseId>21</CourseId>
      <CourseName>leaf</CourseName>
      <CourseDesc>This course</CourseDesc>
      <Event>
        <EventName>NY, US - August 19, 2013</EventName>
        <EventStart>2013-08-19T00:00:00-04:00</EventStart>
        <EventEnd>2013-08-23T00:00:00-04:00</EventEnd>
      </Event>
</Course>

4 个答案:

答案 0 :(得分:2)

你可以这样做,对我来说很好:

var doc = XDocument.Load("path_to_xml_file.xml");
var result = from e in doc.Root.Elements("Event")
             let id = doc.Root.Element("CourseId")
             let name = doc.Root.Element("CourseName")
             let desc = doc.Root.Element("CourseDesc")
             select new XElement("Course",
                                 id,
                                 name,
                                 desc,
                                 e);
foreach (XElement r in result)
{
    Console.WriteLine(r.ToString());
}

更新(使用@Enigmativiy指出的更一般的方法修改):

var result = from e in doc.Descendants("Event")
             let id = e.Parent.Element("CourseId")
             let name = e.Parent.Element("CourseName")
             let desc = e.Parent.Element("CourseDesc")
             select new XElement("Course",
                                 id,
                                 name,
                                 desc,
                                 e);

答案 1 :(得分:1)

试试这个:

var query =
    doc
        .Root
        .Descendants("Event")
        .Select(e =>
            new XElement(
                "Course",
                e.Parent.Element("CourseId"),
                e.Parent.Element("CourseName"),
                e.Parent.Element("CourseDesc"),
                e));

这很简单,对我有用。

答案 2 :(得分:0)

我会这样做:

var xdoc = XDocumnet.Load(path);

var courses = xdoc.Descendants("Course").SelectMany(course => {
  var id = Getnode("CourseId");
  var name = Getnode("CourseName");
  var desc = Getnode("CourseDesc");
  var events = course.Descendants("Event");

return events.Select(e => new Course{
  Name = name,
  Id = id,
  Desc = desc,
  Event = e
});

});

我没有检查这段代码,但逻辑上应该可行。你需要实现Getnode,然后将其写入文件。祝你好运。

答案 3 :(得分:0)

尝试这种方法:

命名空间XMLChildNodesSelection {

public class Course
{
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public string CourseDesc { get; set; }
    public List<Event> Events { get; set; }

    public Course(int _courseId, string _courseName, string _courseDesc, List<Event> _events)
    {
        CourseId = _courseId;
        CourseName = _courseName;
        CourseDesc = _courseDesc;
        Events = _events;
    }
}

public class Event
{
    public string EventName { get; set; }
    public string EventStart { get; set; }
    public string EventEnd { get; set; }

    public Event(string _eventName, string _eventStart, string _eventEnd)
    {
        EventName = _eventName;
        EventStart = _eventStart;
        EventEnd = _eventEnd;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var xdoc = XDocument.Load(@"F:\Test\XMLChildNodesSelection\XMLFile1.xml");

        var course = xdoc.Descendants("Course")
           .Select(x => new Course((int)x.Element("CourseId"),
                                 (string)x.Element("CourseName"),
                                 (string)x.Element("CourseDesc"),
                                 (List<Event>)x.Descendants("Event")
                                     .Select(y => new Event(
                                         (string)y.Element("EventName"),
                                         (string)y.Element("EventStart"),
                                         (string)y.Element("EventEnd")
                                         )).ToList()
                                   )
                   );


        var table = from c in course
                    from e in c.Events
                    select new
                    {
                        CourseId = c.CourseId,
                        CourseName = c.CourseName,
                        CourseDesc = c.CourseDesc,
                        EventName = e.EventName,
                        EventStart = e.EventStart,
                        EventEnd = e.EventEnd
                    };
    }
}

}