Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading XML and performing an action depending on the attribute

Tags:

c#

.net

xml

Let's say I have an XML file such as this:

<root>
  <level1 name="level1A">
    <level2 name="level2A">
      <level3 name="level3A">
        <level4 name="level4A">
          <level5 name="level5A">
            <level6 name="level6A">
              <level7 name="level7A">
                <level8 name="level8A"></level8>
              </level7>
            </level6>
          </level5>
        </level4>
      </level3>
    </level2>
  </level1>
   <level1 name="level1B">
     <level2 name="level2B">
       <level3 name="level3B">
        <level4 name="level4B">
          <level5 name="level5B">
            <level6 name="level6B">
              <level7 name="level7B">
                <level8 name="level8B"></level8>
              </level7>
            </level6>
          </level5>
        </level4>
      </level3>
    </level2>
  </level1>
</root>

How can I read this file and execute a code snippet depending on the element? for example, if the "name" element says "level7a", execute code snippet X. If the name element says level7B, execute code snippet Y.

I can provide such code snippets if t makes answering the question easier. Thanks for the help!

like image 518
MVZ Avatar asked Dec 30 '11 19:12

MVZ


3 Answers

You could create a Dictionary<string, Action> which maps attribute names to actions. Then while parsing the xml you can look up the snippet in the dictionary and execute it.

Quick example:

var attributeActions = new Dictionary<string, Action>();
attributeActions["level1A"] = () => { /* do something */ };
attributeActions["level2A"] = () => { /* do something else */ };

...
// call it
attributActions[node.Attributes["name"]]();

You would need to check that the key actually exists but you could make extension method for that to encapsulate that functionality:

public static void Execute<TKey>(this IDictionary<TKey, Action> actionMap, TKey key)
{
    Action action;
    if (actionMap.TryGet(key, out action))
    {
         action();
    }
}

Then you can call it like this:

attributActions.Execute(node.Attributes["name"]);

Instead of an Action (which is a parameterless snippet returning void) you might want to use Action<T> or Func<T, R> in case you need to pass paramters and/or get return values.

like image 95
ChrisWue Avatar answered Oct 14 '22 09:10

ChrisWue


It seems you need 2 things:

  1. going through the file (the Elements) in a specific order, I guess depth-first

  2. execute an action based on a string value.

This should give you a rough idea:

  var doc =  System.Xml.Linq.XDocument.Load(fileName);       
  Visit(doc.Root);


    private static void Visit(XElement element)
    {
        string name = element.Attribute("name").Value;
        Execute(name);

        // you seem to have just 1 child, this will handle multiple
        // adjust to select only elements with a specific name 
        foreach (var child in element.Elements())
            Visit(child);
    }


    private static void Execute(string name)
    {
        switch (name)
        {
            case "level1A" :
                // snippet a
                break;

            // more cases
        }
    }
like image 36
Henk Holterman Avatar answered Oct 14 '22 11:10

Henk Holterman


Credit for this idea goes to @ChrisWue. This is a different take that calls explicitly defined methods rather than anonymous ones:

private Dictionary<String, Action> actionList = new Dictionary<string, Action>();

private void method1() { }
private void method2() { }

private void buildActionList() {
    actionList.Add("level7a", new Action(method1));
    actionList.Add("level7B", new Action(method2));
    // .. etc
}

public void processDoc() {
    buildActionList();
    foreach (XElement e in (XDocument.Parse(File.ReadAllText(@"C:\somefile.xml")).Elements())) {
        string name = e.Attribute("name").Value;
        if (name != null && actionList.ContainsKey(name)) {
            actionList[name].Invoke();
        }
    }
}

.. obviously one would actually put something in the body of method1, method2, etc..

like image 26
Joshua Honig Avatar answered Oct 14 '22 11:10

Joshua Honig