Literate LINQ-to-XML: práctica recomendada para deserializar atributos / valores en pares estructurados de variables / valores
-
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
);
}
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);