LINQ để đọc XML


194

Tôi đã nhận được tệp XML này:

<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>

Ai đó có thể cho tôi mã C # bằng LINQ, cách đơn giản nhất để in kết quả này:
(Lưu ý không gian thừa nếu đó là level2nút)

A
  A1
  A2
B
  B1
  B2
C

Hiện tại tôi đã nhận đượ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ụ hay về những gì bạn cần: C # Tải XML bằng cách sử dụng XLINQ (LINQ to XML)

Câu trả lời:


224

Thử cái này.

using System.Xml.Linq;

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

3
@bendewey Tôi hỏi một câu hỏi tương tự, bạn vui lòng kiểm tra nó ở đây: stackoverflow.com/questions/13247449/ chủ
Saeid

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

53

Hoặc, nếu bạn muốn một cách tiếp cận tổng quát hơn - tức là để lồng lên tới "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();
}

23

Một vài foreachvòng lặp cũ đơn giản cung cấp một giải pháp 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);
    }
}

19

Dưới đây là một vài ví dụ hoạt động hoàn chỉnh dựa trên các ví dụ @bendewey & @dommer. Tôi cần phải tinh chỉnh từng cái một để làm cho nó hoạt động, nhưng trong trường hợp một LINQ noob khác đang tìm kiếm các ví dụ hoạt động, ở đây bạn đi:

//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();
    }
}

Cả hai đều biên dịch & hoạt động trong VS2010 bằng csc.exe phiên bản 4.0.30319.1 và cho cùng một đầu ra chính xác. Hy vọng những điều này sẽ giúp những người khác đang tìm kiếm các ví dụ làm việc về mã.

EDIT: cũng đã thêm ví dụ của @eglasius vì nó trở nên hữu ích với tôi:

//@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
    }
}

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

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


Điều này không in tất cả các level2 sau tất cả các level1 sao?
sblom

@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 với nó, vì vậy tôi chắc chắn rằng nó hoạt động ngay bây giờ :))
eglasius 22/03/2016
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.