2009-03-22 20 views
176

ich diese XML-Datei bekamLINQ zu lesen 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> 

Könnte mir jemand einen C# -Code geben LINQ verwenden, der einfachste Weg, um dieses Ergebnis zu drucken:
(Beachten Sie den zusätzlichen Platz, wenn es ein Level2 Knoten

)
A 
    A1 
    A2 
B 
    B1 
    B2 
C 

Zur Zeit habe ich diesen Code

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

Hier ist schönes Beispiel, was u brauchen: [C# laden XML XLinq (LINQ to XML)] (http: //www.codearsenal.net/2012/07/c-sharp-load-xml-using-xlinq.html) –

Antwort

203

bereits.

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

Dies ist eine Art "hart codierter" Ansatz. – Mohanavel

+2

@bendewey Ich frage eine ähnliche Frage, würden Sie bitte überprüfen Sie es hier: http://StackOverflow.com/Questions/13247449/Customize-XML-Serialize-with-New-Tags-and-Attributes-and-root – Saeid

+1

Es ist wie ein Flugzeugträger zu nehmen, nur um zu angeln. – 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. Sie müssen .Root auf einer dieser Versionen verwenden.

+0

Drucken nicht alle Level2 nach all den Level1? – sblom

+0

@sblom oops, das stimmt, habe es mit dem aktualisiert, was ich veröffentlichen wollte (habe einen Test dagegen gemacht, also bin ich mir sicher, dass es jetzt funktioniert :)) – eglasius

21

Ein paar einfache alte foreach Schleifen eine saubere Lösung bietet:

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

Oder, wenn Sie einen allgemeineren Ansatz wollen - also für Verschachtelung bis zu „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 generischer Ansatz, elegante Rekursion – Askolein

17

Hier sind ein paar vollständige Arbeitsbeispiele, die auf den @bendewey & @dommer Beispielen aufbauen. Ich brauchte von denen jeder etwas zu zwicken, um es an die Arbeit, aber im Falle einer anderen LINQ Noob sucht Beispiele arbeiten, hier gehen Sie:

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

Und weiter:

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

Diese beiden kompilieren & arbeiten in VS2010 mit csc.exe Version 4.0.30319.1 und geben Sie die exakt gleiche Ausgabe. Hoffentlich helfen diese einem anderen, der nach Arbeitsbeispielen für Code sucht.

EDIT: hinzugefügt @eglasius' Beispiel auch, da sie nützlich für mich geworden:

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