2009-07-31 4 views
5

Ich ringe die folgenden XML deserialisieren:Literate LINQ-to-XML: Best Practice deserialisieren Attribut/Wert auf strukturierte Variable/Wert-Paare

<?xml version="1.0" encoding="utf-8" ?> 

<conf name="settings"> 

    <item name="lorem" 
     one="the" 
     two="quick" 
     three="brown" 
     four="fox" 
     five="jumps" 
     six="over" 
     seven="the" 
     eight="lazy" 
     nine="dog" 
      /> 

    <item name="ipsum" 
     one="how" 
     two="many" 
     three="roads" 
     four="must" 
     five="a" 
     six="man" 
     seven="walk" 
     eight="down" 
     nine="?" 
      /> 

</conf> 

so in der eleganteste und prägnant zu tun, die Hoffnung Mit LINQ-to-XML, aber da ich nicht das intelligenteste Kind in der Stadt bin, wenn es um verschachtelte Methoden, generierte Typen, Generika und andere geht, dachte ich, es wäre eine gute Idee, wenn jemand von Ihnen fragen würde Jungs möchten, gehen Sie vor und mir einige LINQ Alphabetisierungs zeigen :)

Gerade jetzt für jeden Wert, den ich wie etwas so mache:

XDocument config = XDocument.Load("whatever.conf"); 

var one = from q in config.Descendants("item") 
      select (string)q.Attribute("one"); 

var two = from q in config.Descendants("item") 
      select (string)q.Attribute("two"); 

Und weiß ich ich den Punkt völlig fehlt, nicht nur, weil ich wiederhole mich da viel, aber auch, weil die Abfragen nur funktionieren, wenn es gibt nur ein Element so, wieder, wenn Sie jeden Kommentar haben oder Vorschlag würde es wirklich geschätzt werden. Vielen Dank im Voraus!

UPDATE: in dem Fall, dass vielleicht das ehemalige Beispiel nicht wirklich hilfreich war, ist hier eine weitere Art realistischen Szenarios:

<?xml version="1.0" encoding="utf-8" ?> 

<conf name="ftp-settings" freq="daily" time="23:00"> 
    <item name="isis" 
      host="10.10.1.250" 
      user="jdoe" 
      pass="4/cB0kdFGprXR/3oTs8mtw==" 
      file="backup.tar.gz" 
      path="/var/log" 
     /> 
    <item name="seth" 
      host="10.10.2.250" 
      user="jdoe" 
      pass="4/cB0kdFGprXR/3oTs8mtw==" 
      file="backup.tar.gz" 
      path="/var/log" 
     /> 
</conf> 

Daher wird für jedes dieser Elemente Ich mag würde Variablen erzeugen, so Ich kann sie als Parameter für einige FTP-Management-Methode übergeben.

GELöST:

Es war so einfach wie dabei ein foreach:

var elements = from element in xml.Descendants("item") select element; 

foreach (XElement item in elements) { 
    ftp.DownloadFile(
     item.Attribute("host").Value, 
     item.Attribute("user").Value, 
     item.Attribute("pass").Value, 
     item.Attribute("file").Value, 
     item.Attribute("path").Value 
     ); 
} 

Antwort

3

Normalerweise würde ich erwarten, dass eine einzige Darstellung der einzelnen Elemente wollen, anstatt eine Folge von " ein "Werte und eine andere Folge von" zwei "Werten. Mit anderen Worten, würde ich erwarten, dass so etwas wie:

var items = config.Descendants("item") 
        .Select(element => Item.FromXElement(element)); 

Wenn Sie eine Menge von Attributen in einem einzigen Elemente haben, finde ich es hilfreich, die „ein Objekt macht von diesem Elemente“ zu trennen Code in die eigenen Methode (in diesem Fall Item.FromXElement), anstatt alles in die Abfrage stopfen. Wenn Item nicht um seine LINQ to XML-Darstellung wissen sollten, legen Sie die Methode irgendwo, dass

items ist dann ein IEnumerable<Item> :) sollte, die Sie in eine Liste umwandeln kann oder was auch immer Sie tun möchten.

Natürlich hängt es wirklich davon ab, was Sie versuchen zu tun - und wir wissen nicht wirklich, was das bedeuten soll. Vielleicht tun Sie wirklich jeder „-Attribut sequence“ separat wollen ...


Item.FromXElement würde in etwa so aussehen:

public static Item FromXElement(XElement element) 
{ 
    string name = (string) element.Attribute("name"); 
    string host = (string) element.Attribute("host"); 
    // etc 
    return new Item(name, host, ...); 
} 

(Wo offensichtlich Sie einen Konstruktor mit den entsprechenden Parametern erstellen würde.)

+0

zunächst alle vielen Dank für Ihren Kommentar Jon! Ich muss wirklich diese trennen; Stellen Sie sich vor, dass ich fortfahre, sagen wir, Verbindungsdetails oder Lesezeichen, usw., dann liegt es wirklich daran, die Elemente * lorem * und * ipsum * getrennt zu belassen und Schlüssel/Wert-Paare aus seinen Attributen zu erstellen. Ich hoffe, du hast meine Ausarbeitung verfolgt, zögere nicht, mich um weitere Erläuterungen zu bitten :) –

+1

Ich folge nicht wirklich der Ausarbeitung, nein. Können Sie Ihre Frage bearbeiten, um ein vollständigeres Beispiel dafür zu geben, was Sie tun möchten und wie Sie die Informationen anschließend verwenden möchten? –

+0

tat ich. Vielen Dank im Voraus Jon. –

1

Ich würde dies tun:

XDocument config = XDocument.Load("whatever.conf"); 

var pairs = from q in config.Descendants("item") 
      select new { 
       One = (string)q.Attribute("one"), 
       Two = (string)q.Attribute("two") }; 

var ones = pairs.Select(pair => pair.One); 
var twos = pairs.Select(pair => pair.Two); 
+0

Pavel bedankt sich sehr für den Kommentar, obwohl das, was ich wirklich brauche, zwei resultierende Sammlungen isis und seth hat, die beide mit all ihren Attributen zugänglich sind, vielleicht in der Form von isis.host, isis.user, so weiter. –