LINQ для чтения XML
я получил этот 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>
может ли кто-нибудь дать мне код C# с помощью LINQ, самый простой способ распечатать этот результат:
(Обратите внимание на дополнительное пространство, если это узел level2)
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...???
}
5 ответов:
попробуйте это.
void Main() { StringBuilder result = new StringBuilder(); //Load xml XDocument xdoc = XDocument.Load("data.xml"); //Run query var lv1s = from lv1 in xdoc.Descendants("level1") select new { Header = lv1.Attribute("name").Value, Children = lv1.Descendants("level2") }; //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); }
или, если вы хотите более общий подход - т. е. для гнездования до "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(); }
пару простых старых
foreach
петли обеспечивает чистое решение:foreach (XElement level1Element in XElement.Load("data.xml").Elements("level1")) { result.AppendLine(level1Element.Attribute("name").Value); foreach (XElement level2Element in level1Element.Elements("level2")) { result.AppendLine(" " + level2Element.Attribute("name").Value); } }
вот несколько полных рабочих примеров, которые строятся на примерах @bendewey & @dommer. Мне нужно было немного настроить каждый из них, чтобы заставить его работать, но в случае, если другой LINQ noob ищет рабочие примеры, вот вам:
//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(); } }
Они оба компилируются и работают в VS2010 с помощью csc.exe версии 4.0.30319.1 и дают точно такой же результат. Надеюсь, это поможет кому-то еще, кто ищет рабочие примеры код.
EDIT: добавлен пример @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 } }
XDocument xdoc = XDocument.Load("data.xml"); 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); }
Ps. Вы должны использовать .Root на любой из этих версий.