LINQ-to-XML alfabetizzato:Best practice per deserializzare attributo/valore in coppie variabile/valore strutturate

StackOverflow https://stackoverflow.com/questions/1214326

  •  06-07-2019
  •  | 
  •  

Domanda

Sto lottando per deserializzare il seguente XML:

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

sperando di farlo nel modo più elegante e conciso utilizzando LINQ-to-XML, ma dato che non sono il ragazzo più intelligente della città quando si tratta di metodi nidificati, tipi dedotti, generici, eccetera, ho pensato che sarebbe stato sarebbe una buona idea chiedere se qualcuno di voi vorrebbe andare avanti e mostrarmi un po' di alfabetizzazione LINQ :)

In questo momento per ogni valore sto facendo qualcosa del tipo:

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

E io lo so Non ho assolutamente capito il punto, non solo perché mi sto ripetendo molto, ma anche perché le query funzionano solo quando c'è un solo elemento, quindi, ancora una volta, se hai qualche commento o suggerimento, sarebbe molto apprezzato.Grazie mille in anticipo!

AGGIORNAMENTO: nel caso in cui forse l'esempio precedente non fosse molto utile, ecco uno scenario più realistico:

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

Pertanto per ciascuno di questi elementi vorrei generare variabili in modo da poterle passare come parametri per qualche metodo di gestione FTP.

RISOLTO:

È stato facile come fare un per ciascuno:

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
        );
}
È stato utile?

Soluzione

Normalmente mi aspetterei di volere una singola rappresentazione di ciascun elemento, piuttosto che una sequenza di valori "uno" e un'altra sequenza di valori "due".In altre parole, mi aspetterei qualcosa del tipo:

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

Se hai molti attributi in un singolo elemento, trovo utile separare il codice "crea un oggetto da questo elemento" nel suo metodo (in questo caso Item.FromXElement) anziché inserire tutto nella query.Se Item non dovrebbe sapere della sua rappresentazione LINQ to XML, inserisci il metodo da qualche parte che dovrebbe :)

items è quindi un IEnumerable<Item> che puoi convertire in un elenco o qualsiasi altra cosa tu voglia fare.

Ovviamente dipende davvero da cosa stai cercando di fare e non sappiamo davvero cosa significhi rappresentare.Forse davvero Fare voglio che ogni "sequenza di attributi" separatamente...


Item.FromXElement assomiglierebbe a qualcosa del tipo:

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

(Dove ovviamente creeresti un costruttore con i parametri appropriati.)

Altri suggerimenti

Vorrei fare questo:

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top