C#使用xdocument将多个元素添加到列表中

时间:2017-07-06 18:32:13

标签: c# xml linq linq-to-xml xdoc

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <fileUploadSpecification>
    <DirectoryPath>C:\watchFolder</DirectoryPath>
    <Region>us-west-2</Region>
    <UploadBucket>configurationtestbucket</UploadBucket>
    <FileType>
      <type>*.txt</type>
      <type>*.OpticomCfg</type>
    </FileType>
  </fileUploadSpecification>
  <fileUploadSpecification>
    <DirectoryPath>C:\watchFolder</DirectoryPath>
    <Region>us-west-2</Region>
    <UploadBucket>loguploadbucket</UploadBucket>
    <FileType>
      <type>*.Xml</type>
      <type>*.Json</type>
    </FileType>
  </fileUploadSpecification>
</root>

这是我需要解析的XML文件,我想获取fileUploadSpecification的每个实例,以便我可以将每组细节放入一个列表中,我认为某些类型的for循环是合适的,我循环通过添加第一组上传详细信息,然后循环并添加第二组。这是我目前拥有的,但它永远不会到达第二个fileUploadSpecification元素,它只是再次返回相同的元素。 我们的想法是为每组fileUploadSpecification元素创建一个新的SettingsData,无论它是如上所示的两个,还是10。

public interface ISettingsEngine
{

    IEnumerable<SettingsData> GetSettings();
}

public class SettingsEngine : ISettingsEngine
{

    public IEnumerable<SettingsData> GetSettings()
    {
        List<SettingsData> dataList = new List<SettingsData>();
        try
        {

            var xDoc = XDocument.Load("File1.xml");

            var instancesToParse = xDoc.Root.Elements().Count();

            var fileCount = xDoc.Root.Elements("FileType").Count();


            for (int x = 0; x < instancesToParse; x++)
            {
                var newSettingsData = new SettingsData();

                newSettingsData.UploadBucket = xDoc.Root.Element("fileUploadSpecification").Element("UploadBucket").Value;
                newSettingsData.Region = xDoc.Root.Element("fileUploadSpecification").Element("Region").Value;
                newSettingsData.DirectoryPath = xDoc.Root.Element("fileUploadSpecification").Element("DirectoryPath").Value;
                var query = xDoc.Root.Descendants("FileType").Elements("type");

                foreach (XElement e in query)
                {
                    newSettingsData.FileType.Add(e.Value);
                }
dataList.Add(newSettingsData);

            }

            return dataList;
        }
        catch(Exception)
        {
            return dataList;
        }
    }
}

public class SettingsData
{

    public List<string> FileType { get; set; }
    public string DirectoryPath { get; set; }
    public string Region { get; set; }
    public string UploadBucket { get; set; }

    public SettingsData()
    {
        FileType = new List<string>();
    }
}

2 个答案:

答案 0 :(得分:1)

var dataList = (from fus in xDoc.Root.Elements("fileUploadSpecification")
             select new SettingsData
             {
                 UploadBucket = fus.Element("UploadBucket").Value,
                 Region = fus.Element("Region").Value,
                 DirectoryPath = fus.Element("DirectoryPath").Value,
                 FileType = fus.Element("FileType")
                               .Elements("type").Select(f =>f.Value).ToList()
             }).ToList();

答案 1 :(得分:0)

每次循环时,您都会再次查找第一个fileUploadSpecification元素。您在一些地方已经使用了Elements()方法。这就是你想要的那个。当你在一个集合上循环时,总是在C#中优先于foreach而不是for。它更快(代码,而不是在运行时),并且更不容易出错。

foreach (var uploadSpec in xDoc.Root.Elements("fileUploadSpecification"))
{
    var newSettingsData = new SettingsData();

    newSettingsData.UploadBucket = uploadSpec.Element("UploadBucket").Value;
    newSettingsData.Region = uploadSpec.Element("Region").Value;
    newSettingsData.DirectoryPath = uploadSpec.Element("DirectoryPath").Value;

    var types = uploadSpec.Descendants("FileType").Elements("type").Select(e => e.Value);

    foreach (var type in types)
    {
        newSettingsData.FileType.Add(type);
    }

    //  Or if newSettingsData.FileType is List<String>...
    //newSettingsData.FileType.AddRange(types);

    dataList.Add(newSettingsData);
}

James Curran的答案在功能上是相同的,但它的形式更好。