LINQ to read XML

前端 未结 5 1938
逝去的感伤
逝去的感伤 2020-11-22 00:47

I got this XML file:


    
        
        
             


        
相关标签:
5条回答
  • 2020-11-22 01:21

    Here are a couple of complete working examples that build on the @bendewey & @dommer examples. I needed to tweak each one a bit to get it to work, but in case another LINQ noob is looking for working examples, 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
        }
    }
    

    And next:

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

    These both compile & work in VS2010 using csc.exe version 4.0.30319.1 and give the exact same output. Hopefully these help someone else who's looking for working examples of code.

    EDIT: added @eglasius' example as well since it became useful to me:

    //@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
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:22

    A couple of plain old foreach loops provides a clean solution:

    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);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:33

    Try this.

    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);
    }
    
    0 讨论(0)
  • 2020-11-22 01:37

    Or, if you want a more general approach - i.e. for nesting up to "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();
    }
    
    0 讨论(0)
  • 2020-11-22 01:42
    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. You have to use .Root on any of these versions.

    0 讨论(0)
提交回复
热议问题