c# 将路径列表转换为 xml 的有效方法
c# efficient way to convert a list of paths to xml
我有一个来自数据库的文件夹路径列表,我需要将其导出到 xml。原始数据如下:
我需要做的是创建一个树状结构,类似于 xml:
- networkAdd
- users
- test1
- delete unicode character test
- character test 1
- linked to folder
- character test 2
- character test 3
- sp2013
- newTestsite
- newTestLib
- sampleFolder
- Renamed at source again
- SecurityTest2013Folder
- Shared Documents
- sample.folder
我目前有一个有效的 xml 写入方法可供我使用,但它需要一个树视图。我获取了上面的列表(来自数据库)并将其转换为可以与此方法一起使用的树视图(效果很好)但它需要我先转换为效率低下的树视图。我使用此代码:
public static TreeView PopulateTreeView(IEnumerable<FolderInfo> paths)
{
var treeView = new TreeView();
treeView.PathSeparator = "\";
TreeNode lastNode = null;
string subPathAgg;
string lastRootFolder = null;
foreach (var item in paths)
{
var path = item.FolderName; // folder path.
if (lastRootFolder != item.FolderRoot)
{
lastRootFolder = item.FolderRoot;
lastNode = null;
}
subPathAgg = string.Empty;
foreach (string subPath in path.Split('\'))
{
if (subPath.Length > 0)
{
subPathAgg += subPath + "\";
TreeNode[] nodes = treeView.Nodes.Find(subPathAgg, true);
var newNode = new TreeNode
{
Name = subPathAgg,
Text = subPath,
ImageIndex = 2,
ToolTipText = item.FullFolderPath
};
if (nodes.Length == 0)
{
if (lastNode == null)
treeView.Nodes.Add(newNode);
else
lastNode.Nodes.Add(newNode);
lastNode = newNode;
}
else
lastNode = nodes[0];
}
}
}
return treeView;
}
当我有超过 1000 万条记录要处理时,这行代码执行起来非常慢:
TreeNode[] nodes = treeView.Nodes.Find(subPathAgg, true);
直接从 DB 转换为 XML(没有 treeview 中间人)对我来说会更有效率。
有没有人对将文件夹路径解析为 xml 并考虑嵌套的替代方法有任何建议?提前感谢您的指点!
事实证明,如果您可以确保您的字符串正确排序(如果它们来自数据库,这应该很容易),如果您直接使用 XmlWriter
,这将非常容易。类似于:
var strings = new[]
{
@"\networkAdd",
@"\networkAdd\users",
@"\networkAdd\users\test1\",
@"\networkAdd\users\test1\delete unicode character test",
@"\networkAdd\users\test1\delete unicode character test\character test 1",
@"\networkAdd\users\test1\delete unicode character test\character test 1\linked to folder",
@"\networkAdd\users\test1\delete unicode character test\character test 2",
@"\networkAdd\users\test1\delete unicode character test\character test 3",
@"http:\sp2013",
@"http:\sp2013\newTestsite",
@"http:\sp2013\newTestlib",
@"http:\sp2013\newTestlib\sampleFolder",
};
// Obviously, stream it out to a file rather than an in-memory string
using (var stringWriter = new StringWriter())
using (var writer = new XmlTextWriter(stringWriter))
{
writer.WriteStartDocument();
writer.WriteStartElement("Items");
var previous = Array.Empty<string>();
foreach (var str in strings)
{
var current = str.Split('\', StringSplitOptions.RemoveEmptyEntries);
int i;
// Find where the first difference from the previous element is
for (i = 0; i < Math.Min(current.Length, previous.Length); i++)
{
if (current[i] != previous[i])
{
break;
}
}
// i now contains the index of the first difference
// First, close off anything in previous which isn't in the current
for (int j = i; j < previous.Length; j++)
{
writer.WriteEndElement();
}
// Then, any new elements
for (int j = i; j < current.Length; j++)
{
writer.WriteStartElement("Item");
writer.WriteAttributeString("value", current[j]);
}
previous = current;
}
writer.WriteEndDocument();
}
给出:
<?xml version="1.0" encoding="utf-16"?>
<Items>
<Item value="networkAdd">
<Item value="users">
<Item value="test1">
<Item value="delete unicode character test">
<Item value="character test 1">
<Item value="linked to folder" />
</Item>
<Item value="character test 2" />
<Item value="character test 3" />
</Item>
</Item>
</Item>
</Item>
<Item value="http:">
<Item value="sp2013">
<Item value="newTestsite" />
<Item value="newTestlib">
<Item value="sampleFolder" />
</Item>
</Item>
</Item>
</Items>
在处理 ://
等方面需要做一些工作,但基本原则应该是合理的。
我有一个来自数据库的文件夹路径列表,我需要将其导出到 xml。原始数据如下:
我需要做的是创建一个树状结构,类似于 xml:
- networkAdd
- users
- test1
- delete unicode character test
- character test 1
- linked to folder
- character test 2
- character test 3
- sp2013
- newTestsite
- newTestLib
- sampleFolder
- Renamed at source again
- SecurityTest2013Folder
- Shared Documents
- sample.folder
我目前有一个有效的 xml 写入方法可供我使用,但它需要一个树视图。我获取了上面的列表(来自数据库)并将其转换为可以与此方法一起使用的树视图(效果很好)但它需要我先转换为效率低下的树视图。我使用此代码:
public static TreeView PopulateTreeView(IEnumerable<FolderInfo> paths)
{
var treeView = new TreeView();
treeView.PathSeparator = "\";
TreeNode lastNode = null;
string subPathAgg;
string lastRootFolder = null;
foreach (var item in paths)
{
var path = item.FolderName; // folder path.
if (lastRootFolder != item.FolderRoot)
{
lastRootFolder = item.FolderRoot;
lastNode = null;
}
subPathAgg = string.Empty;
foreach (string subPath in path.Split('\'))
{
if (subPath.Length > 0)
{
subPathAgg += subPath + "\";
TreeNode[] nodes = treeView.Nodes.Find(subPathAgg, true);
var newNode = new TreeNode
{
Name = subPathAgg,
Text = subPath,
ImageIndex = 2,
ToolTipText = item.FullFolderPath
};
if (nodes.Length == 0)
{
if (lastNode == null)
treeView.Nodes.Add(newNode);
else
lastNode.Nodes.Add(newNode);
lastNode = newNode;
}
else
lastNode = nodes[0];
}
}
}
return treeView;
}
当我有超过 1000 万条记录要处理时,这行代码执行起来非常慢:
TreeNode[] nodes = treeView.Nodes.Find(subPathAgg, true);
直接从 DB 转换为 XML(没有 treeview 中间人)对我来说会更有效率。
有没有人对将文件夹路径解析为 xml 并考虑嵌套的替代方法有任何建议?提前感谢您的指点!
事实证明,如果您可以确保您的字符串正确排序(如果它们来自数据库,这应该很容易),如果您直接使用 XmlWriter
,这将非常容易。类似于:
var strings = new[]
{
@"\networkAdd",
@"\networkAdd\users",
@"\networkAdd\users\test1\",
@"\networkAdd\users\test1\delete unicode character test",
@"\networkAdd\users\test1\delete unicode character test\character test 1",
@"\networkAdd\users\test1\delete unicode character test\character test 1\linked to folder",
@"\networkAdd\users\test1\delete unicode character test\character test 2",
@"\networkAdd\users\test1\delete unicode character test\character test 3",
@"http:\sp2013",
@"http:\sp2013\newTestsite",
@"http:\sp2013\newTestlib",
@"http:\sp2013\newTestlib\sampleFolder",
};
// Obviously, stream it out to a file rather than an in-memory string
using (var stringWriter = new StringWriter())
using (var writer = new XmlTextWriter(stringWriter))
{
writer.WriteStartDocument();
writer.WriteStartElement("Items");
var previous = Array.Empty<string>();
foreach (var str in strings)
{
var current = str.Split('\', StringSplitOptions.RemoveEmptyEntries);
int i;
// Find where the first difference from the previous element is
for (i = 0; i < Math.Min(current.Length, previous.Length); i++)
{
if (current[i] != previous[i])
{
break;
}
}
// i now contains the index of the first difference
// First, close off anything in previous which isn't in the current
for (int j = i; j < previous.Length; j++)
{
writer.WriteEndElement();
}
// Then, any new elements
for (int j = i; j < current.Length; j++)
{
writer.WriteStartElement("Item");
writer.WriteAttributeString("value", current[j]);
}
previous = current;
}
writer.WriteEndDocument();
}
给出:
<?xml version="1.0" encoding="utf-16"?>
<Items>
<Item value="networkAdd">
<Item value="users">
<Item value="test1">
<Item value="delete unicode character test">
<Item value="character test 1">
<Item value="linked to folder" />
</Item>
<Item value="character test 2" />
<Item value="character test 3" />
</Item>
</Item>
</Item>
</Item>
<Item value="http:">
<Item value="sp2013">
<Item value="newTestsite" />
<Item value="newTestlib">
<Item value="sampleFolder" />
</Item>
</Item>
</Item>
</Items>
在处理 ://
等方面需要做一些工作,但基本原则应该是合理的。