Literate LINQ-to-XML: práctica recomendada para deserializar atributos / valores en pares estructurados de variables / valores

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

  •  06-07-2019
  •  | 
  •  

Pregunta

Estoy luchando para deserializar el siguiente 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>

con la esperanza de hacerlo de la manera más elegante y sucinta usando LINQ-to-XML, pero dado que no soy el chico más inteligente de la ciudad cuando se trata de métodos anidados, tipos de infusión, genéricos, etc. & # 233; tera, pensé que sería una buena idea preguntar si alguno de ustedes querría seguir adelante y mostrarme algo de alfabetización LINQ :)

En este momento por cada valor estoy haciendo algo como:

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

Y Lo sé me estoy perdiendo totalmente el punto, no solo porque me estoy repitiendo mucho allí, sino también porque esas consultas solo funcionan cuando solo hay un elemento, así que de nuevo si Tiene algún comentario o sugerencia, sería muy apreciado. ¡Muchas gracias de antemano!

ACTUALIZACIÓN: en caso de que tal vez el ejemplo anterior no fuera realmente útil, aquí hay un escenario más realista:

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

Por lo tanto, para cada uno de esos elementos me gustaría generar variables para poder pasarlos como parámetros para algún método de administración de FTP.

RESUELTO :

Fue tan fácil como hacer un 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
        );
}
¿Fue útil?

Solución

Normalmente esperaría querer una representación única de cada elemento, en lugar de una secuencia de " one " valores y otra secuencia de & "; dos &"; valores. En otras palabras, esperaría algo como:

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

Si tiene muchos atributos en un solo elemento, me resulta útil separar el & "; haga un objeto de este elemento &"; codifique en su propio método (en este caso Item.FromXElement) en lugar de introducirlo todo en la consulta. Si Item no debe conocer su representación de LINQ to XML, coloque el método en algún lugar que debería :)

items es entonces un IEnumerable<Item> que puede convertir en una lista o cualquier otra cosa que desee hacer.

Por supuesto, realmente depende de lo que intente hacer, y realmente no sabemos qué significa representar. Tal vez realmente do desee que cada & Quot; secuencia de atributos & Quot; por separado ...


<=> se vería algo así como:

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

(Donde obviamente crearías un constructor con los parámetros apropiados.)

Otros consejos

Haría esto:

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);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top