I'm wrestling to deserialize the following 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>
hoping to do so in the most elegant and succinct way using LINQ-to-XML, but given that I'm not the smartest kid in town when it comes to nested methods, infered types, generics, et cétera, I thought it'd be a good idea to ask if any of you guys would like to go ahead and show me some LINQ literacy :)
Right now for every value I'm doing something like:
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");
And I do know I'm totally missing the point, not only because I'm repeating myself a lot there but also because that queries only work when there's only one item so, again if you have any comment or suggestion it would be really appreciated. Thanks much in advance!
UPDATE: in case that perhaps the former example wasn't really helpful, here's a more sort of realistic scenario:
<?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>
Therefore for each of those items I'd like to generate variables so I can pass them as parameters for some FTP management method.
SOLVED:
It was as easy as doing a 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
);
}
Normally I'd expect to want a single representation of each element, rather than one sequence of "one" values and another sequence of "two" values. In other words, I'd expect something like:
var items = config.Descendants("item")
.Select(element => Item.FromXElement(element));
If you have a lot of attributes in a single element, I find it helpful to separate out the "make an object from this element" code into its own method (in this case Item.FromXElement
) rather than stuff it all into the query. If Item
shouldn't know about its LINQ to XML representation, put the method somewhere that should :)
items
is then an IEnumerable<Item>
which you can convert into a list or whatever else you want to do.
Of course it really depends on what you're trying to do - and we don't really know what this is meant to represent. Maybe you really do want each "attribute sequence" separately...
Item.FromXElement
would look something like:
public static Item FromXElement(XElement element)
{
string name = (string) element.Attribute("name");
string host = (string) element.Attribute("host");
// etc
return new Item(name, host, ...);
}
(Where obviously you'd create a constructor with the appropriate parameters.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With