5 Stimmen

LINQ-to-XML wörtlich nehmen: Bewährte Verfahren zur Deserialisierung von Attribut/Wert zu strukturierten Variablen/Wertpaaren

Ich ringe darum, die folgende XML-Datei zu deserialisieren:

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

in der Hoffnung, dies auf die eleganteste und prägnanteste Art und Weise zu tun, indem ich LINQ-to-XML verwende, aber da ich nicht der klügste Junge in der Stadt bin, wenn es um verschachtelte Methoden, abgeleitete Typen, Generika usw. geht, dachte ich, es wäre eine gute Idee zu fragen, ob jemand von euch mir ein paar LINQ-Kenntnisse beibringen möchte :)

Im Moment mache ich für jeden Wert so etwas wie:

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 Ich weiß Ich bin völlig fehlt der Punkt, nicht nur, weil ich mich wiederholen, eine Menge gibt, sondern auch, weil diese Abfragen nur funktionieren, wenn es nur ein Element so, wieder, wenn Sie einen Kommentar oder einen Vorschlag haben, es wäre wirklich geschätzt werden. Vielen Dank im Voraus!

UPDATE: Für den Fall, dass das erste Beispiel nicht wirklich hilfreich war, hier ein eher realistisches Szenario:

<?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 möchte ich für jedes dieser Elemente Variablen generieren, damit ich sie als Parameter für eine FTP-Verwaltungsmethode übergeben kann.

GELÖST:

Es war so einfach wie eine 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
        );
}

3voto

Jon Skeet Punkte 1325502

Normalerweise würde ich eine einzige Darstellung jedes Elements erwarten und nicht eine Folge von "Eins"-Werten und eine weitere Folge von "Zwei"-Werten. Mit anderen Worten, ich würde etwas erwarten wie:

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

Wenn Sie viele Attribute in einem einzelnen Element haben, finde ich es hilfreich, den Code für die Erstellung eines Objekts aus diesem Element in eine eigene Methode auszulagern (in diesem Fall Item.FromXElement ), anstatt alles in die Abfrage zu packen. Wenn Item sollte nicht über seine LINQ to XML-Darstellung wissen, setzen Sie die Methode irgendwo, die sollte :)

items ist dann ein IEnumerable<Item> die Sie in eine Liste umwandeln können oder was immer Sie sonst tun wollen.

Natürlich kommt es darauf an, was Sie damit bezwecken wollen - und wir wissen nicht wirklich, was das darstellen soll. Vielleicht wollen Sie wirklich tun jede "Attributfolge" einzeln haben wollen...


Item.FromXElement würde 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, ...);
}

(Wobei Sie natürlich einen Konstruktor mit den entsprechenden Parametern erstellen würden).

1voto

Pavel Minaev Punkte 97251

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X