views:

129

answers:

1

Hello,

I'm working on a program that needs to be able to load object-properties from an XML file. These properties are configurable by the user and XML makes sense to me to use.

Take the following XML document.

<?xml version="1.0" encoding="utf-8" ?>

<udpcommands>

  <command name="requser">
    <cvar name="reqchallege" value="false" />
  </command>

  <command name="reqprocs">
    <cvar name="reqchallenge" value="false" />
  </command>

</udpcommands>

I need to be able to load values from the cvars above to properties. I'm think Linq-To-XML would be good for it (I'm looking for applications of Linq so I can learn it). I've got a Linq-to-XML query done to select the right "command" based on the name.I was reading MSDN for help on this.

The following code snippet goes in a constructor that takes the parameter "string name" which identifies the correct XML <command> to pull.

I would like to have one linq statement to pull each <cvar> out of that XML given the section name, dumping everything to an IEnumerable. Or, I'm looking for a better option perhaps. I'm open for anything really. I would just like to use Linq so I can learn it better.

    XElement doc = XElement.Load("udpcommands.xml");

    IEnumerable<XElement> a = from el in doc.Elements()
                              where el.FirstAttribute.Value == name
                              select el;

    foreach (var c in a)
    {
        Console.WriteLine(c);
    }

The above code snippet outputs the following to the console:

<command name="requser">
  <cvar name="reqchallege" value="false" />
</command>
+2  A: 

Something like this should do:

var result = 
    doc.Elements("command")
    .Single( x => x.Attribute("name").Value == name)
    .Elements("cvar");

This will give you an IEnumerable<XElement> where each XElement represents a cvar in the specified command.

Note that if the specified command does not exist, the call to Single will cause an error. Likewise if the specified attribute is not found on the command.

EDIT As per your comments, you could do something along the lines of:

// Result will be an XElement, 
// or null if the command with the specified attribute is not found
var result = 
    doc.Elements("command")
    // Note the extra condition below
    .SingleOrDefault( x => x.Attribute("name")!=null && x.Attribute("name").Value == name)

if(result!=null)
{
    // results.Elements() gives IEnumerable<XElement>
    foreach(var cvar in results.Elements("cvar"))
    {
        var cvarName = cvar.Attribute("name").Value;
        var cvarValue = Convert.ToBoolean( cvar.Attribute("value").Value );
    }
}
Winston Smith
omg. Thanks! :D :) Makes sense to me too
Zack
Hmm. So, I should put this in a try-catch to see if it exists? Or is there a method I can call to check if a node and/or attribute exists on that node?
Zack
Question: How do I access the attributes now?
Zack
Which attributes?
Winston Smith
"name" and "value" for cvar's
Zack
In the same way as we got the values of the other attributes before. Answer updated.
Winston Smith
Thanks for the help! :D
Zack