C# Linq to XML 获取父对象和子对象

问题描述 投票:0回答:1

我正在尝试读取 XML 文件,然后将值填充到 C# 类(父对象和子对象)中。为了简洁起见,我省略了很多代码。我正在尝试通过 Linq to XML 来完成此任务。

我创建了以下类,它将作为父类,还将托管子字符串对象列表:

public class Field
{
    public string Name { get; set; } = string.Empty;
    public List<string> Options { get; set; } = new();
    public FieldType Type { get; set; } = 0;
}

因此,一个字段可以包含以下 2 项中的 1 项:

  1. 它可以有一个空的字符串选项列表
  2. 或者它可以有一个字符串选项列表

XML 以一种有趣的方式完成,我无法更改它,我只需读入它并填充类和字符串对象(如果有),然后将此列表返回到前端以进行进一步处理。

简化形式的 XML 文件:

<FieldProperties>
    <FieldName>Question 1</FieldName>
    <FieldType>1</FieldType>
</FieldProperties>
<FieldProperties>
    <FieldName>Dietaries</FieldName>
    <FieldType>9</FieldType>
</FieldProperties>
<FieldProperties>
    <FieldName>Question 2</FieldName>
    <FieldType>1</FieldType>
</FieldProperties>
<FieldProperties>
    <FieldName>Transport</FieldName>
    <FieldType>9</FieldType>
</FieldProperties>
<FieldOptions>
    <FieldName>Dietaries</FieldName>
    <Option>Dietary option 1</Option>
</FieldOptions>
<FieldOptions>
    <FieldName>Dietaries</FieldName>
    <Option>Dietary option 2</Option>
</FieldOptions>
<FieldOptions>
    <FieldName>Dietaries</FieldName>
    <Option>Dietary option 3</Option>
</FieldOptions>
<FieldOptions>
    <FieldName>Transport</FieldName>
    <Option>Transport option 1</Option>
</FieldOptions>
<FieldOptions>
    <FieldName>Transport</FieldName>
    <Option>Transport option 2</Option>
</FieldOptions>

字段类由

FieldProperties
标签表示。要确定某个字段是否有选项,您需要检查它的
FieldType
是否为 9。如果
FieldType
为 9,那么您必须去寻找
FieldOptions
,它链接到
FieldName
标签
FieldProperties
标签。

我不知道如何编写这样的查询。我目前所拥有的是循环遍历所有

FieldProperties
,然后填充字段属性。但我不知道如何检查字段类型是否为 9,如果是 9,则去获取
FieldOptions
子对象列表,然后填充选项属性。

这是我目前拥有的:

XDocument xDocument = XDocument.Parse(xmlFields);
XNamespace xNamespace = "http://tempuri.org/FieldDefinition.xsd";
List<Field> fields =
    xDocument.Descendants(xNamespace + "FieldProperties")
        .Select(fieldProperties => new Field
        {
            Name = (string)fieldProperties.Element(xNamespace + "FieldName")!.Value,
            Type = (FieldType)Int32.Parse(fieldProperties.Element(xNamespace + "FieldType")!.Value)
        }).ToList();

return fields;
c# linq linq-to-xml
1个回答
0
投票
var fields = xDocument.Root
                      .Elements(xNamespace + "FieldProperties")
                      .Select(fp => new Field {
                          Name = (string)fp.Element(xNamespace + "FieldName"),
                          Type = (FieldType)int.Parse(fp.Element(xNamespace + "FieldType")!.Value)
                      })
                      .GroupJoin(
                          xDocument.Root.Elements(xNamespace + "FieldOptions"),
                          f => f.Name,
                          fo => (string)fo.Element(xNamespace + "FieldName"),
                          (f, fo) => new { Field = f, Options = fo })
                      .SelectMany(x => 
                          x.Field.Type == FieldType.Options
                              ? x.Options.Select(o => new { x.Field, Option = (string)o.Element(xNamespace + "Option")! }) 
                              : new { x.Field })
                      .GroupBy(x => x.Field)
                      .Select(g => 
                      {
                          var field = g.Key;
                          if (field.Type == FieldType.Options)
                          {
                              field.Options = g.Select(x => x.Option).ToList();
                          }
                          return field;
                      })
                      .ToList();

1.GroupJoin 将字段与其对应的选项匹配

2.SelectMany 展平为 {Field, Option} 对的流

3.GroupBy Field 来合并选项

© www.soinside.com 2019 - 2024. All rights reserved.