我目前将一些数据存储在XML文件中,现在需要为另一个应用程序生成一个文件。这个应用程序要求每一行都包含它的路径。我目前正在用C#进行开发。
示例XML为:
<?xml version="1.0" encoding="utf-8"?>
<root name="Master">
<Menu name="Menu One">
<Entry name="Data One">
<Value>Data goes here</Value>
</Entry>
<Menu name="Sub Menu One">
<Entry name="Sub Data One">
<Value>Data goes here</Value>
</Entry>
</Menu>
</Menu>
<Menu name="Menu Two">
<Entry name="Data Two">
<Value>Data goes here</Value>
</Entry>
<Menu name="Sub Menu Two">
<Entry name="Sub Data Two">
<Value>Data goes here</Value>
</Entry>
<Menu name="Sub Sub Menu Two">
<Entry name="Sub Sub Data Two">
<Value>Data goes here</Value>
</Entry>
</Menu>
</Menu>
</Menu>
</root>
我想构建一个输出(在"Sub Data Two“的例子中)如下所示:
Menu Two --- Sub Menu Two --- Sub Sub Menu Two --- Sub Sub Data Two
XML是以图形方式生成的,所以有可能有非常深的信息树,所以我希望LINQ或一些递归函数能在这里帮助我。
目前的方法类似于:
XmlSerializer serializer = new XmlSerializer(typeof(root));
root resultingMessage = (root)serializer.Deserialize(new XmlTextReader(xFileLocation));
try
{
foreach (var menu in resultingMessage.MenuItem)
{
try
{
foreach (var val in menu.val)
{
WriteToFile((menu.name + "..." + ahk.shortcut + " " + val.name + "..."));
}
foreach (var menu1 in menu.MenuItem1)
{
try
{
foreach (var val in menu1.val)
{
WriteToFile((menu.name + "..." + menu1.name + "..." + ahk.shortcut + " " + val.name + "..."));
}
foreach (var menu2 in menu1.MenuItem1)
{
try
{
foreach (var val in menu2.val)
{
WriteToFile((menu.name + "..." + menu1.name + "..." + menu2.name + "..." + val.shortcut + " " + ahk.name + "..."));
}
}
catch (Exception)
{
//ignore
}
}
}
catch (Exception)
{
//ignore
}
}
}
catch (Exception)
{
//ignore
}
}
}
catch (Exception)
{
//ignore
}
}
发布于 2019-05-23 09:31:31
使用LINQ to XML解决了这个任务,只需要依靠DescendantsAndSelf-method进行递归搜索):
var x = XElement.Parse(xml);
var result = x.Elements("Menu")
.Select(v =>
{
var menuElements = v.DescendantsAndSelf("Menu").ToArray();
var lastEntryElement = menuElements.Last().Element("Entry");
var menuNames = string.Join(" --- ", menuElements.Select(m => m.Attribute("name")?.Value ?? "?"));
return lastEntryElement == null
? menuNames
: $"{menuNames} --- {lastEntryElement.Attribute("name")?.Value ?? "?"}";
})
.ToArray();
/*
Result of execution:
[0]: "Menu One --- Sub Menu One --- Sub Data One"
[1]: "Menu Two --- Sub Menu Two --- Sub Sub Menu Two --- Sub Sub Data Two"
[2]: "Menu Three (no Menu-children) --- Data One"
[3]: "Menu Four (empty)"
*/
源数据:
var xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<root name=""Master"">
<Menu name=""Menu One"">
<Entry name=""Data One"">
<Value>Data goes here</Value>
</Entry>
<Menu name=""Sub Menu One"">
<Entry name=""Sub Data One"">
<Value>Data goes here</Value>
</Entry>
</Menu>
</Menu>
<Menu name=""Menu Two"">
<Entry name=""Data Two"">
<Value>Data goes here</Value>
</Entry>
<Menu name=""Sub Menu Two"">
<Entry name=""Sub Data Two"">
<Value>Data goes here</Value>
</Entry>
<Menu name=""Sub Sub Menu Two"">
<Entry name=""Sub Sub Data Two"">
<Value>Data goes here</Value>
</Entry>
</Menu>
</Menu>
</Menu>
<Menu name=""Menu Three (no Menu-children)"">
<Entry name=""Data One"">
<Value>Data goes here</Value>
</Entry>
</Menu>
<Menu name=""Menu Four (empty)"">
</Menu>
</root>";
发布于 2019-05-24 03:06:50
我最终使用了递归,因为我不能让LINQ成功地遍历整个结构(缺乏知识,而不是缺少LINQ!)
代码如下:
private string AHKoutput;
foreach (var menu in resultingMessage.MenuItem)
{
Recurse(menu, menu.name);
}
private void Recurse(MenuItem menuit, string title)
{
if (menuit.AHKEntry != null && menuit.AHKEntry.Any())
{
foreach (var ahk in menuit.AHKEntry)
{
AHKoutput = AHKoutput + (title);
}
}
if (menuit.MenuItem1 != null && menuit.MenuItem1.Any())
{
foreach (var menuItem in menuit.MenuItem1)
{
Recurse(menuItem, title + "..." + menuItem.name);
}
}
}
https://stackoverflow.com/questions/56262576
复制相似问题