简体   繁体   English

在C#中使用LINQ解析XML

[英]Parsing XML with LINQ in C#

I am trying to do a mapping between C# and XML with LINQ. 我正在尝试使用LINQ在C#和XML之间进行映射。 Currently, I have a class defined in C# that looks like this: 当前,我有一个用C#定义的类,如下所示:

Item.cs Item.cs

public class Item
{
  public string DepartmentName { get; set; }
  public Dictionary<string, string> DepartmentNames { get; set; }

  public string Name { get; set; }
  public Dictionary<string, string> Names { get; set; }
}

My XML file looks like this: 我的XML文件如下所示:

departments.xml departments.xml

<Departments>
  <Department Name="Sports" Title="Sports Department" Path="/sports" en-us="Sports" de-de="Sport">
    <Item Name="Football" en-us="Football" de-de="Fußball" es-mx="" />
    <Item Name="TennisBall" en-us="Tennis Ball" de-de="Tennisball" />
  </Department>

  <Department Name="Automotive" Title="Automotive Department" Path="/autos" en-us="Automotive" de-de="kraftfahrtechnisch">
    <Item Name="Oil" en-us="Oil" de-de="Öl" />
    <Item Name="Tires" en-us="Tires" de-de="Bereifung" es-mx="Ruedas" />
  </Department>
</Departments>

Basically, I have some values I want to load into a definite properties. 基本上,我有一些要加载到确定属性中的值。 Then, I have a list of attributes I know ("en-us", "de-de", "es-mx") that I want to load into Dictionaries. 然后,我有一个我想加载到字典中的属性列表(“ zh-cn”,“ de-de”,“ es-mx”)。 Currently, I have the following: 目前,我有以下内容:

var items = XDocument.Parse(File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"App_Data\Items.xml")))
  .Element("Departments")
  .Elements("Department")
  .Elements("Item")
  .Select(e => new Item
  {
    DepartmentName = ?,
    DepartmentNames = ?,
    Name = e.Attribute("Name").Value,
    Names = ?
  }).ToList();

I'm not sure how to load the properties from a) The parent elements b) Load the Dictionary object. 我不确定如何从a)父元素b)加载Dictionary对象加载属性。 Is this even possible with LINQ? LINQ甚至有可能吗? Essentially, I'm trying to flatten out my data structure in-memory. 本质上,我试图在内存中整理数据结构。

In cases like this, where you need to access properties of outer elements in nested loops, I find the Linq from / select syntax to be more comfortable. 在这种情况下,需要在嵌套循环中访问外部元素的属性,我发现from / select语法中的Linq更加舒适。 Thus: 从而:

        var doc = XDocument.Load(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "InputData.xml"));
        var query = from department in doc.Element("Departments").Elements("Department")
                    from item in department.Elements("Item")
                    select new Item
                    {
                        DepartmentName = department.Attribute("Name").Value,
                        DepartmentNames = department.Attributes().Where(a => a.Name != "Name").ToDictionary(a => a.Name.LocalName, a => a.Value),
                        Name = item.Attribute("Name").Value,
                        Names = item.Attributes().Where(a => a.Name != "Name").ToDictionary(a => a.Name.LocalName, a => a.Value),
                    };
        var items = query.ToList();

Here I am assuming you want every attribute placed in the dictionary other than the Name attribute, which has its own property. 在这里,我假设您希望将字典中除Name属性(其具有自己的属性)之外的每个属性都放置在字典中。

Update 更新

If you have a known list of attributes to put in the dictionary, you can do: 如果您有待放入字典的已知属性列表,则可以执行以下操作:

        var attributes = new HashSet<string>(new[] { "en-us", "de-de", "es-mx" }); // Possibly initialized in a static constructor.

        var query = from department in doc.Element("Departments").Elements("Department")
                    from item in department.Elements("Item")
                    select new Item
                    {
                        DepartmentName = department.Attribute("Name").Value,
                        DepartmentNames = department.Attributes().Where(a => attributes.Contains(a.Name.LocalName)).ToDictionary(a => a.Name.LocalName, a => a.Value),
                        Name = item.Attribute("Name").Value,
                        Names = item.Attributes().Where(a => attributes.Contains(a.Name.LocalName)).ToDictionary(a => a.Name.LocalName, a => a.Value),
                    };
        var items = query.ToList();

I think that the code below is what you want. 我认为下面的代码是您想要的。 I tested here and it worked, but I'm not sure if this is what you intent. 我在这里进行了测试,它确实有效,但是我不确定这是否是您的意图。 I'm just filling the dictionaries with all values of languages. 我只是用所有语言值填充字典。

            var items = XDocument.Parse(
            File.ReadAllText(
            Path.Combine(
                Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 
                "InputData.xml")))
                      .Element("Departments")
                      .Elements("Department")
                      .Select(
                      d => d.Elements("Item").Select(e => new Item
                      {
                        DepartmentName = d.Attribute("Name").Value,
                        DepartmentNames = new Dictionary<string,string>()
                        {
                            { "en-us", d.Attribute("en-us").Value },
                            { "de-de", d.Attribute("de-de").Value}
                        },
                        Name = e.Attribute("Name").Value,
                        Names = new Dictionary<string,string>()
                        {
                            { "en-us", e.Attribute("en-us").Value},
                            { "de-de", e.Attribute("de-de").Value}
                        }
                      })).ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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