2009-03-22 35 views
176

Tôi có tập tin XML nàyLINQ để đọc XML

<root> 
    <level1 name="A"> 
     <level2 name="A1" /> 
     <level2 name="A2" /> 
    </level1> 
    <level1 name="B"> 
     <level2 name="B1" /> 
     <level2 name="B2" /> 
    </level1> 
    <level1 name="C" /> 
</root> 

Có thể ai đó cho tôi một mã C# sử dụng LINQ, cách đơn giản nhất để in kết quả này:
(Lưu ý không gian thêm nếu nó là một nút level2)

A 
    A1 
    A2 
B 
    B1 
    B2 
C 

Hiện nay tôi có mã này

XDocument xdoc = XDocument.Load("data.xml")); 
var lv1s = from lv1 in xdoc.Descendants("level1") 
      select lv1.Attribute("name").Value; 

foreach (var lv1 in lv1s) 
{ 
    result.AppendLine(lv1); 

    var lv2s = from lv2 in xdoc...??? 
} 
+14

Dưới đây là ví dụ tốt đẹp của những gì u cần: [C# Tải XML sử dụng XLINQ (LINQ to XML)] (http: //www.codearsenal.net/2012/07/c-sharp-load-xml-using-xlinq.html) –

Trả lời

203

Hãy thử điều này.

void Main() 
{ 
    StringBuilder result = new StringBuilder(); 

    //Load xml 
    XDocument xdoc = XDocument.Load("data.xml"); 

    //Run query 
    var lv1s = from lv1 in xdoc.Descendants("level1") 
       select new { 
        Header = lv1.Attribute("name").Value, 
        Children = lv1.Descendants("level2") 
       }; 

    //Loop through results 
    foreach (var lv1 in lv1s){ 
      result.AppendLine(lv1.Header); 
      foreach(var lv2 in lv1.Children) 
       result.AppendLine("  " + lv2.Attribute("name").Value); 
    } 

    Console.WriteLine(result); 
} 
+23

Đây là loại phương pháp "Được mã hóa cứng". – Mohanavel

+2

@bendewey Tôi hỏi một câu hỏi tương tự, bạn vui lòng kiểm tra xem nó, tại đây: http://stackoverflow.com/questions/13247449/customize-xml-serialize-with-new-tags-and-attributes-and-root – Saeid

+1

Nó giống như đi tàu sân bay chỉ để đi câu cá. – TomeeNS

8
XDocument xdoc = XDocument.Load("data.xml"); 
var lv1s = xdoc.Root.Descendants("level1"); 
var lvs = lv1s.SelectMany(l=> 
    new string[]{ l.Attribute("name").Value } 
    .Union(
     l.Descendants("level2") 
     .Select(l2=>" " + l2.Attribute("name").Value) 
    ) 
    ); 
foreach (var lv in lvs) 
{ 
    result.AppendLine(lv); 
} 

Ps. Bạn phải sử dụng. Chạy trên bất kỳ phiên bản nào trong số này.

+0

Không in tất cả các level2 sau tất cả các level1? – sblom

+0

@sblom oops, đúng vậy, cập nhật nó với những gì tôi muốn đăng (chạy thử nghiệm chống lại nó, vì vậy tôi chắc chắn nó hoạt động ngay bây giờ :)) – eglasius

21

Một vài đồng bằng cũ foreach vòng cung cấp một giải pháp làm sạch:

foreach (XElement level1Element in XElement.Load("data.xml").Elements("level1")) 
{ 
    result.AppendLine(level1Element.Attribute("name").Value); 

    foreach (XElement level2Element in level1Element.Elements("level2")) 
    { 
     result.AppendLine(" " + level2Element.Attribute("name").Value); 
    } 
} 
48

Hoặc, nếu bạn muốn có một cách tiếp cận tổng quát hơn - tức là cho làm tổ lên đến "levelN":

void Main() 
{ 
    XElement rootElement = XElement.Load(@"c:\events\test.xml"); 

    Console.WriteLine(GetOutline(0, rootElement)); 
} 

private string GetOutline(int indentLevel, XElement element) 
{ 
    StringBuilder result = new StringBuilder(); 

    if (element.Attribute("name") != null) 
    { 
     result = result.AppendLine(new string(' ', indentLevel * 2) + element.Attribute("name").Value); 
    } 

    foreach (XElement childElement in element.Elements()) 
    { 
     result.Append(GetOutline(indentLevel + 1, childElement)); 
    } 

    return result.ToString(); 
} 
+9

+1 cách tiếp cận chung, đệ quy thanh lịch – Askolein

17

đây là một vài ví dụ hoạt động hoàn chỉnh được xây dựng trên các ví dụ @bendewey & @dommer. Tôi cần thiết để tinh chỉnh mỗi người một chút để có được nó để làm việc, nhưng trong trường hợp khác Noob LINQ đang tìm kiếm ví dụ làm việc, here you go:

//bendewey's example using data.xml from OP 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml.Linq; 

class loadXMLToLINQ1 
{ 
    static void Main() 
    { 
     //Load xml 
     XDocument xdoc = XDocument.Load(@"c:\\data.xml"); //you'll have to edit your path 

     //Run query 
     var lv1s = from lv1 in xdoc.Descendants("level1") 
      select new 
      { 
       Header = lv1.Attribute("name").Value, 
       Children = lv1.Descendants("level2") 
      }; 

     StringBuilder result = new StringBuilder(); //had to add this to make the result work 
     //Loop through results 
     foreach (var lv1 in lv1s) 
     { 
      result.AppendLine(" " + lv1.Header); 
      foreach(var lv2 in lv1.Children) 
      result.AppendLine(" " + lv2.Attribute("name").Value); 
     } 
     Console.WriteLine(result.ToString()); //added this so you could see the output on the console 
    } 
} 

Và tiếp theo:

//Dommer's example, using data.xml from OP 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml.Linq; 

class loadXMLToLINQ 
{ 
static void Main() 
    { 
     XElement rootElement = XElement.Load(@"c:\\data.xml"); //you'll have to edit your path 
     Console.WriteLine(GetOutline(0, rootElement)); 
    } 

static private string GetOutline(int indentLevel, XElement element) 
    { 
     StringBuilder result = new StringBuilder(); 
     if (element.Attribute("name") != null) 
     { 
      result = result.AppendLine(new string(' ', indentLevel * 2) + element.Attribute("name").Value); 
     } 
     foreach (XElement childElement in element.Elements()) 
     { 
      result.Append(GetOutline(indentLevel + 1, childElement)); 
     } 
     return result.ToString(); 
    } 
} 

Những cả biên dịch & hoạt động trong VS2010 bằng cách sử dụng csc.exe phiên bản 4.0.30319.1 và cung cấp cho cùng một đầu ra chính xác. Hy vọng rằng điều này sẽ giúp người khác đang tìm kiếm các ví dụ làm việc về mã. Ví dụ thêm @eglasius' cũng vì nó đã trở thành hữu ích với tôi::

EDIT

//@eglasius example, still using data.xml from OP 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml.Linq; 

class loadXMLToLINQ2 
{ 
    static void Main() 
    { 
     StringBuilder result = new StringBuilder(); //needed for result below 
     XDocument xdoc = XDocument.Load(@"c:\\deg\\data.xml"); //you'll have to edit your path 
     var lv1s = xdoc.Root.Descendants("level1"); 
     var lvs = lv1s.SelectMany(l=> 
      new string[]{ l.Attribute("name").Value } 
      .Union(
       l.Descendants("level2") 
       .Select(l2=>" " + l2.Attribute("name").Value) 
      ) 
      ); 
     foreach (var lv in lvs) 
     { 
      result.AppendLine(lv); 
     } 
     Console.WriteLine(result);//added this so you could see the result 
    } 
}