简体   繁体   中英

Cannot get list of elements using LINQ to XML

Sample XML:

<CONFIGURATION>
    <Files>
        <File>D:\Test\TestFolder\TestFolder1\TestFile.txt</File>
        <File>D:\Test\TestFolder\TestFolder1\TestFile01.txt</File>
        <File>D:\Test\TestFolder\TestFolder1\TestFile02.txt</File>
        <File>D:\Test\TestFolder\TestFolder1\TestFile03.txt</File>
        <File>D:\Test\TestFolder\TestFolder1\TestFile04.txt</File>
    </Files>
    <SizeMB>3</SizeMB>
    <BackupLocation>D:\Log backups\File backups</BackupLocation>
</CONFIGURATION>

I've been doing some tutorials, but I am unable to get all the list of files inside the files element. It only shows the first <File> element and doesn't display the rest. This is my code:

var fileFolders = from file in XDocument.Load(@"D:\Hello\backupconfig1.xml").Descendants("Files")
                         select new
                         {
                             File = file.Element("File").Value
                         };

foreach (var fileFolder in fileFolders)
{
     Console.WriteLine("File = " + fileFolder.File);
}

How do I display all the File in the Files element, the SizeMB and BackupLocation?

[Edited]

Use SelectMany() :

IEnumerable<string> files = 
    XDocumentLoad(@"D:\Hello\backupconfig1.xml").Descendants("Files")
        .SelectMany(files => files.Descendants("File"))
        .Select(file => file.Value)

SelectMany() concatenates multiple enumerations into one.

string xml = @"<CONFIGURATION> 
<Files> 
    <File>D:\Test\TestFolder\TestFolder1\TestFile.txt</File> 
    <File>D:\Test\TestFolder\TestFolder1\TestFile01.txt</File> 
    <File>D:\Test\TestFolder\TestFolder1\TestFile02.txt</File> 
    <File>D:\Test\TestFolder\TestFolder1\TestFile03.txt</File> 
    <File>D:\Test\TestFolder\TestFolder1\TestFile04.txt</File> 
</Files> 
<SizeMB>3</SizeMB> 
<BackupLocation>D:\Log backups\File backups</BackupLocation> 
</CONFIGURATION>";

var xdoc = XDocument.Parse(xml);
var configuration = xdoc.Element("CONFIGURATION");
string sizeMB = configuration.Element("SizeMB").Value;
string backupLocation = configuration.Element("BackupLocation").Value;
string[] files = configuration.Element("Files").Elements("File").Select(c => c.Value).ToArray();

Console.WriteLine(sizeMB);
Console.WriteLine(backupLocation);    
Console.WriteLine(string.Join("\r\n", files));

OUTPUT

3
D:\Log backups\File backups
D:\Test\TestFolder\TestFolder1\TestFile.txt
D:\Test\TestFolder\TestFolder1\TestFile01.txt
D:\Test\TestFolder\TestFolder1\TestFile02.txt
D:\Test\TestFolder\TestFolder1\TestFile03.txt
D:\Test\TestFolder\TestFolder1\TestFile04.txt

You already have an array of file locations, like Aaron Anodide recommended you to do. Use this array in a for or foreach loop:

string[] files = configuration.Element("Files").Elements("File").Select(c => c.Value).ToArray();
for (int index=0; index<files.Length; index++)
{
    DoSomeStuffWithFileCLocation(files[i]);
}

or

forach(string file in files)
{
    DoSomeStuffWithFileCLocation(file);
}

It might be a bit more performant to do something like the following:

XDocument doc = XDocument.Load(@"D:\Hello\backupconfig1.xml");
var fileFolders = doc.Root.Element("Files").Elements("File");

Descendants() will return back a collection of all nodes in the document. In the example above it's not a big deal, but if you construct a suitably large document, this may slow things down. Instead, if you know you specifically just want the Files, then navigating to it directly with Element() will be quicker (and arguably more readable).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM