Adam_G
Adam_G

Reputation: 7879

Querying xml into structure

I believe I am getting XDocument and XElement aspects confused. I am trying to:

  1. Load an xml file
  2. Query an attribute of an element's name
  3. Write aspects of the found element to a structure.

Simple Structure, called Rule:

public struct Rule
{
    public String keyDB;
    public String eventLog;
}

XML Structure:

<?xml version="1.0" encoding="utf-8" ?>
<Error_List>
  <Error code="0xC004C003">
      <KeyDB>
        default key
      </KeyDB>
      <EventLog>
        default event
      </EventLog>
  </Error>
  <Error code="000000000">
      <KeyDB>
        non-default key
      </KeyDB>
      <EventLog>
        non-default event
      </EventLog>
  </Error>
</Error_List>

Set Rule rule = new Rule();
If I pass into my method "000000000" I am looking to set rule.keyDB = "non-default key" and rule.eventLog = "non-default event". I'm pretty sure that this is possible, but that I just have my variables mixed up.

Edit:
My code, thus far, has been unsuccessful and incomplete. I have

IEnumerable<XElement> query =   (from elem in rulesXml.Root.Elements("Error")
                                where (String)elem.Attribute("code") == this.errorCode.ToString()
                                select elem);

but am unsure where to go from there.

Upvotes: 0

Views: 90

Answers (2)

C&#233;dric Bignon
C&#233;dric Bignon

Reputation: 13022

Linq-to-XML is extremely powerful and quite straightforward to understand once you master Linq. You can find a lot of tutorials about these two topics.

Here is what you can do:

string myCode = "000000000";  // Error Code to find
XDocument xDocument = XDocument.Load("C:/Path to the file.xml");  // Loads the Xml file to a XDocument

Rule rule = (from errorNode in xDocument.Descendants("Error")    // Go through Error elements
             where errorNode.Attribute("code").Value == myCode   // That has the specified code attribute
             select new Rule
             {
                 keyDB = errorNode.Element("KeyDB").Value,       // Gets the KeyDB element value of the Error node
                 eventLog = errorNode.Element("EventLog").Value  // Gets the EventLog element value of the Error node
             }).FirstOrDefault();

Update

If an Error element can have no code attribute or no KeyDB or EventLog attribute. Use the explicit type casting to retrieve their value. ie. Instead of writing Element.Attribute("...").Value write (string)Element.Attribute("...") (same for Element("..."))

Rule rule = (from errorNode in xDocument.Descendants("Error")      // Go through Error elements
             where (string)errorNode.Attribute("code") == myCode   // That has the specified code attribute
             select new Rule
             {
                 keyDB = (string)errorNode.Element("KeyDB"),       // Gets the KeyDB element value of the Error node
                 eventLog = (string)errorNode.Element("EventLog")  // Gets the EventLog element value of the Error node
             }).FirstOrDefault();

Upvotes: 3

Aditya Singh
Aditya Singh

Reputation: 9612

Try using the ILookup:

Error code is set as the key for the lookup.

public struct Rule
{
    public String keyDB;
    public String eventLog;
}

class Program
{
    static void Main(string[] args)
    {
        XDocument xdoc = XDocument.Load("src.xml");

        ILookup<string, Rule> lookup = xdoc.Descendants("Error").ToLookup(x => x.Attribute("code").Value, x => new Rule() { keyDB = x.Element("KeyDB").Value, eventLog = x.Element("EventLog").Value });

        //Perform operation based on the error code from the lookup

        Console.Read();
    }
}

Upvotes: 0

Related Questions