Чтение вложенного XML с помощью XmlNode

я пытался читать вложенный XML с помощью xmlnode, но у меня возникла одна проблема

вот мой xml-файл

<role name="admin">
<menu name="Setting">
    <group name="settinggrup1"></group>
    <group name="settinggrup2"></group>
    <group name="settinggrup3"></group>
</menu>
<menu name="Service">
    <group name="servicegrup1"></group>
    <group name="servicegrup2"></group>
    <group name="servicegrup3"></group>
</menu>
<menu name="Search">
    <group name="serchgrup1"></group>
    <group name="serchgrup2"></group>
    <group name="serchgrup3"></group>
</menu>
</role>

и вот мой код

var xmlDoc = new XmlDocument();
xmlDoc.Load(file);
XmlNodeList nodeList = xmlDoc.SelectNodes("//role[@name='" + "admin" + "']/menu");
var menus = new List<Menu>();
var groupName = new List<Group>();
Menu menu = new Menu();  

foreach (XmlNode menuNode in nodeList)
            {                
                menu.name = menuNode.Attributes["name"].Value;

                foreach (XmlNode childNode in menuNode)
                {
                    groupName.Add(new Group() { name = childNode.Attributes["name"].Value });
                } 
                menus.Add(new Menu { name = menu.name, group = groupName });  
            }

вот мой класс

public class Menu
{
    public string name { get; set; }
    public List<Group> group { get; set; }
}
public class Group
{
    public string name { set; get; }
}

И тем самым я намеревался отобразить как

  • Настройка: группа настроек1, группа настроек2, группа настроек3.
  • Служба: сервисная группа1, сервисная группа2, сервисная группа3
  • Поиск : searchgrup1, searchgrup2, searchgrup3

Но то, что я получил, это

  • Параметр: settingsgrup1, settingsgrup2, settingsgrup3, servicegrup1, servicegrup2, servicegrup3, searchgrup1, searchgrup2, searchgrup3
  • Служба: группа настроек1, группа настроек2, группа настроек3, группа обслуживания1, группа обслуживания2, группа обслуживания3, группа поиска1, группа поиска2, группа поиска3
  • Поиск: группа настроек1, группа настроек2, группа настроек3, группа обслуживания1, группа обслуживания2, группа обслуживания3, группа поиска1, группа поиска2, группа поиска3

Что-то не так в моей части кода, я думаю, в части, когда я добавил список в свой вложенный foreach, но я пытался часами и до сих пор не могу это исправить. кто-нибудь может помочь мне, пожалуйста, а также, пожалуйста, объясните, что мой код сделал неправильно.


person Laxus    schedule 13.01.2014    source источник


Ответы (2)


Ваша проблема в том, что вы добавляете все группы в один экземпляр списка групп. И затем вы назначаете этот список со всеми группами внутри всем меню.

Вот правильный код:

var menus = new List<Menu>();

foreach (XmlNode menuNode in nodeList)
{
     var groupName = new List<Group>(); // create list here

     foreach (XmlNode childNode in menuNode)
        groupName.Add(new Group { name = childNode.Attributes["name"].Value });

     menus.Add(new Menu {
        name = menuNode.Attributes["name"].Value,
        group = groupName
     });  
}

Вы можете использовать Linq to Xml:

var xdoc = XDocument.Load(file);
var menus = xdoc.Descendants("role")
                .Where(r => (string)r.Attribute("name") == "admin")
                .Elements("menu")
                .Select(m => new Menu {
                    name = (string)m.Attribute("name"),
                    group = m.Elements("group")
                                .Select(g => new Group { 
                                     name = (string)g.Attribute("name") 
                                }).ToList()
                }).ToList();

Или с помощью xpath:

var menus = xdoc.XPathSelectElements("//role[@name='admin']/menu")
                .Select(m => new Menu { /* create menu as above */ })
                .ToList();

Кстати, рассмотрите возможность использования лучшего именования и регистра pascal для имен общедоступных членов:

public class Menu
{
    public string Name { get; set; }
    public List<Group> Groups { get; set; }
}
person Sergey Berezovskiy    schedule 13.01.2014
comment
Спасибо за ответ. Является ли использование LINQ единственным способом сделать это? потому что я не удовлетворен, я не знаю, что я сделал не так в своем коде - person Laxus; 13.01.2014
comment
ого, я вижу, я не получил новый список групп, я должен создать новый внутри своего цикла. Теперь все ясно, спасибо большое чувак - person Laxus; 13.01.2014

Как быстрое решение:

// after
menu.name = menuNode.Attributes["name"].Value; 
//please add
groupName = new List<Group>();
person Alex Zharnasek    schedule 13.01.2014