根据父节点对一系列XML节点进行分组
本文关键字:节点 XML 父节点 一系列 | 更新日期: 2023-09-27 18:04:58
我正在编写一个脚本,该脚本将根据要删除的解析项最终清理工作中用户访问供应系统使用的XML文件。XML文档有不同层次的子/父节点,如下所示:
<Enterprise>
<Channel name="a">
<busunit name="one">
<dept name="x">
<role name ="role1">
<role name="role2">
</dept>
<dept name="y">
<dept name="z">
</busunit >
<busunit name="two">
<busunit name="three">
</Channel>
<Channel name="b" >
<Channel name="c">
</Enterprise>
我想做的是读取文档并根据它们的父项分组,但是由于各种节点级别,我正在努力想出一种可靠的方法来做到这一点。
我已经开始为每个通道使用一系列列表,这些列表存储业务单元列表,存储部门列表,最终存储角色列表(本质上是多维列表),但我认为这可能很难很快遵循,并且是调试的噩梦。
其他注意事项:
- 通道中没有固定数量的总线单元,总线单元中也没有固定数量的部门,部门中也没有固定数量的角色
- 跨渠道/总线单位/部门存在重复的总线单位/部门/角色名称(这就是为什么需要清理)
希望这不是模糊的理解,但我想知道在一个简单的概括是:除了多维列表来分组和存储多个父/子节点之外,我还有什么其他选择?
提前感谢!
尝试将数据放入数据表中,这将使删除
更容易using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:'temp'test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
DataTable dt = new DataTable();
dt.Columns.Add("Channel", typeof(string));
dt.Columns.Add("busunit", typeof(string));
dt.Columns.Add("dept", typeof(string));
dt.Columns.Add("role", typeof(string));
foreach (XElement channel in doc.Descendants("Channel"))
{
string channelName = (string)channel.Attribute("name");
List<XElement> busunits = channel.Elements("busunit").ToList();
if (busunits.Count == 0)
{
dt.Rows.Add(new object[] { channelName });
}
else
{
foreach (XElement busunit in busunits)
{
string busunitName = (string)busunit.Attribute("name");
List<XElement> depts = busunit.Elements("dept").ToList();
if (depts.Count == 0)
{
dt.Rows.Add(new object[] { channelName, busunitName });
}
else
{
foreach (XElement dept in depts)
{
string deptName = (string)dept.Attribute("name");
List<XElement> roles = dept.Elements("role").ToList();
if (roles.Count == 0)
{
dt.Rows.Add(new object[] { channelName, busunitName, deptName });
}
else
{
foreach (XElement role in roles)
{
string roleName = (string)role.Attribute("name");
dt.Rows.Add(new object[] { channelName, busunitName, deptName, roleName });
}
}
}
}
}
}
}
dt = dt.AsEnumerable()
.OrderBy(m => m.Field<string>("Channel"))
.ThenBy(n => n.Field<string>("busunit"))
.ThenBy(o => o.Field<string>("dept"))
.ThenBy(p => p.Field<string>("role"))
.CopyToDataTable();
//remove duplicates
for (int row = dt.Rows.Count - 2; row >= 0; row--)
{
if ((dt.Rows[row].Field<object>("Channel") == dt.Rows[row + 1].Field<object>("Channel")) &&
(dt.Rows[row].Field<object>("busunit") == dt.Rows[row + 1].Field<object>("busunit")) &&
(dt.Rows[row].Field<object>("dept") == dt.Rows[row + 1].Field<object>("dept")) &&
(dt.Rows[row].Field<object>("role") == dt.Rows[row + 1].Field<object>("role")))
{
dt.Rows[row + 1].Delete();
}
}
dt.AcceptChanges();
}
}
}