首页 文章

LINQ读取XML

提问于
浏览
184

我有这个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>

有人可以使用LINQ给我一个C#代码,这是打印此结果的最简单方法:
(如果是level2节点,请注意额外的空间)

A
  A1
  A2
B
  B1
  B2
C

目前我得到了这段代码

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...???
}

5 回答

  • 21

    试试这个 .

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

    或者,如果您想要更通用的方法 - 即嵌套到“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();
    }
    
  • 53

    一些简单的旧 foreach 循环提供了一个干净的解决方案:

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

    以下是一些基于@bendewey和@dommer示例的完整工作示例 . 我需要稍微调整一下才能使它工作,但是如果另一个LINQ noob正在寻找工作示例,那么你去:

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

    接下来:

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

    这些都使用csc.exe版本4.0.30319.1在VS2010中编译和工作,并提供完全相同的输出 . 希望这些可以帮助那些正在寻找代码工作示例的人 .

    编辑:添加了@eglasius的例子,因为它对我有用:

    //@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
        }
    }
    
  • 18
    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 . 你必须在任何这些版本上使用.Root .

相关问题