读取XML并根据属性执行操作

时间:2011-12-30 19:54:05

标签: c# .net xml

假设我有一个XML文件,例如:

<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>

如何根据元素读取此文件并执行代码段?例如,如果“name”元素显示“level7a”,则执行代码片段X.如果name元素表示level7B,则执行代码片段Y。

如果我能更轻松地回答这个问题,我可以提供这样的代码片段。谢谢你的帮助!

3 个答案:

答案 0 :(得分:5)

您可以创建一个Dictionary<string, Action>,将属性名称映射到操作。然后在解析xml时,您可以在字典中查找片段并执行它。

快速举例:

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

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

您需要检查密钥是否确实存在,但您可以使用扩展方法来封装该功能:

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

然后你可以这样称呼它:

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

而不是Action(这是一个返回void的无参数代码段),您可能需要使用Action<T>Func<T, R>,以防您需要传递参数和/或获得返回值。

答案 1 :(得分:4)

看来你需要两件事:

  1. 按特定顺序浏览文件(元素),我猜深度优先

  2. 根据字符串值执行操作。

  3. 这应该给你一个粗略的想法:

      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
            }
        }
    

答案 2 :(得分:3)

这个想法归功于@ChrisWue。这是一种不同的看法,它调用明确定义的方法而不是匿名方法:

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();
        }
    }
}

..显然,实际上会在method1,method2等的主体中添加一些内容。