我正在使用这个XML文件:
<root>
<level1 name="A">
<level2 name="A1" />
<level2 name="A2" />
</level1>
<level1 name="B">
<level2 name="B1" />
<level2 name="B2" />
</level1>
<level1 name="C" />
</root>
谁能给我一个使用LINQ的c#代码,这是打印这个结果的最简单的方法:
(如果是2级节点,请注意额外的空间)
A
A1
A2
B
B1
B2
C
目前我已经写了这段代码:
XDocument xdoc = XDocument.Load("data.xml"));
var lv1s = from lv1 in xdoc.Descendants("level1")
select lv1.Attribute("name").Value;
foreach (var lv1 in lv1s)
{
result.AppendLine(lv1);
var lv2s = from lv2 in xdoc...???
}
或者,如果你想要一个更通用的方法-即嵌套到“levelN”:
void Main()
{
XElement rootElement = XElement.Load(@"c:\events\test.xml");
Console.WriteLine(GetOutline(0, rootElement));
}
private string GetOutline(int indentLevel, XElement element)
{
StringBuilder result = new StringBuilder();
if (element.Attribute("name") != null)
{
result = result.AppendLine(new string(' ', indentLevel * 2) + element.Attribute("name").Value);
}
foreach (XElement childElement in element.Elements())
{
result.Append(GetOutline(indentLevel + 1, childElement));
}
return result.ToString();
}
下面是基于@bendewey和@dommer示例构建的两个完整的工作示例。我需要稍微调整每一个让它工作,但以防另一个LINQ新手正在寻找工作示例,这里:
//bendewey's example using data.xml from OP
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
class loadXMLToLINQ1
{
static void Main( )
{
//Load xml
XDocument xdoc = XDocument.Load(@"c:\\data.xml"); //you'll have to edit your path
//Run query
var lv1s = from lv1 in xdoc.Descendants("level1")
select new
{
Header = lv1.Attribute("name").Value,
Children = lv1.Descendants("level2")
};
StringBuilder result = new StringBuilder(); //had to add this to make the result work
//Loop through results
foreach (var lv1 in lv1s)
{
result.AppendLine(" " + lv1.Header);
foreach(var lv2 in lv1.Children)
result.AppendLine(" " + lv2.Attribute("name").Value);
}
Console.WriteLine(result.ToString()); //added this so you could see the output on the console
}
}
和下一个:
//Dommer's example, using data.xml from OP
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
class loadXMLToLINQ
{
static void Main( )
{
XElement rootElement = XElement.Load(@"c:\\data.xml"); //you'll have to edit your path
Console.WriteLine(GetOutline(0, rootElement));
}
static private string GetOutline(int indentLevel, XElement element)
{
StringBuilder result = new StringBuilder();
if (element.Attribute("name") != null)
{
result = result.AppendLine(new string(' ', indentLevel * 2) + element.Attribute("name").Value);
}
foreach (XElement childElement in element.Elements())
{
result.Append(GetOutline(indentLevel + 1, childElement));
}
return result.ToString();
}
}
它们都使用csc.exe版本4.0.30319.1在VS2010中编译和工作,并给出完全相同的输出。希望这些内容能够帮助其他正在寻找代码示例的人。
编辑:添加了@eglasius的例子,因为它对我很有用:
//@eglasius example, still using data.xml from OP
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
class loadXMLToLINQ2
{
static void Main( )
{
StringBuilder result = new StringBuilder(); //needed for result below
XDocument xdoc = XDocument.Load(@"c:\\deg\\data.xml"); //you'll have to edit your path
var lv1s = xdoc.Root.Descendants("level1");
var lvs = lv1s.SelectMany(l=>
new string[]{ l.Attribute("name").Value }
.Union(
l.Descendants("level2")
.Select(l2=>" " + l2.Attribute("name").Value)
)
);
foreach (var lv in lvs)
{
result.AppendLine(lv);
}
Console.WriteLine(result);//added this so you could see the result
}
}
XML文件的异步加载可以提高性能,特别是在文件很大或加载时间较长的情况下。在本例中,我们使用XDocument。LoadAsync方法来异步加载和解析XML文件,这有助于防止在加载文件时应用程序失去响应。
演示:https://dotnetfiddle.net/PGFE7c(使用XML字符串解析)
实现:
XDocument doc;
// Open the XML file using File.OpenRead and pass the stream to
// XDocument.LoadAsync to load and parse the XML asynchronously
using (var stream = File.OpenRead("data.xml"))
{
doc = await XDocument.LoadAsync(stream, LoadOptions.None, CancellationToken.None);
}
// Select the level1 elements from the document and create an anonymous object for each element
// with a Name property containing the value of the "name" attribute and a Children property
// containing a collection of the names of the level2 elements
var results = doc.Descendants("level1")
.Select(level1 => new
{
Name = level1.Attribute("name").Value,
Children = level1.Descendants("level2")
.Select(level2 => level2.Attribute("name").Value)
});
foreach (var result in results)
{
Console.WriteLine(result.Name);
foreach (var child in result.Children)
Console.WriteLine(" " + child);
}
结果:
A
A1
A2
B
B1
B2
C