使用 XmlNode 读取嵌套的 XML

Posted

技术标签:

【中文标题】使用 XmlNode 读取嵌套的 XML【英文标题】:Read nested XML with XmlNode 【发布时间】:2014-01-13 10:39:32 【问题描述】:

我尝试使用 xmlnode 读取嵌套的 XML,但遇到了一个问题

这是我的 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; 

我打算这样显示

设置 : settinggrup1, settinggrup2, settinggrup3 服务:servicegrup1、servicegrup2、servicegrup3 搜索:searchgrup1、searchgrup2、searchgrup3

但我得到的是这个

设置:settinggrup1、settinggrup2、settinggrup3、servicegrup1、 服务组 2、服务组 3、搜索组 1、搜索组 2、搜索组 3 服务 : settinggrup1, settinggrup2, settinggrup3, servicegrup1, 服务组 2、服务组 3、搜索组 1、搜索组 2、搜索组 3 搜索 : settinggrup1, settinggrup2, settinggrup3, servicegrup1, 服务组 2、服务组 3、搜索组 1、搜索组 2、搜索组 3

我的代码部分有问题,我猜是我在嵌套的 foreach 中添加列表时的部分,但我已经尝试了几个小时但仍然无法修复它。任何人都可以帮助我,也请解释我的代码做错了什么。

【问题讨论】:

【参考方案1】:

您的问题是您将所有组添加到组列表的同一实例中。然后您将包含所有组的列表分配给所有菜单。

这是正确的代码:

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

顺便说一句,考虑为公共成员名称使用更好的命名和帕斯卡大小写:

public class Menu

    public string Name  get; set; 
    public List<Group> Groups  get; set; 

【讨论】:

感谢您的回复。使用 LINQ 是完成这项工作的唯一方法吗?因为我不满意,我不知道我的代码做错了什么 呵呵,我明白了,我没有得到一个新的组列表,我应该在我的循环中创建一个新的组列表。现在已经清除了,非常感谢大佬【参考方案2】:

作为一种快速的解决方案:

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

【讨论】:

以上是关于使用 XmlNode 读取嵌套的 XML的主要内容,如果未能解决你的问题,请参考以下文章

读取 xmlnode 子标签值

将 XmlNode 转换为 XNode?

如何检查多个 XMLNode 属性的空值?

关于XML的读取,添加,修改,删除

如何使用 XmlNode() 作为 VB.NET 中 web 服务的结果?

将 XElement 转换为 XmlNode