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

b1payxdu  于 2023-09-28  发布在  C#
关注(0)|答案(1)|浏览(136)

我尝试读入一个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;
}

所以一个字段可以有两种情况之一:
1.它可以有一个空的字符串选项列表
1.或者它可以有一个字符串选项列表
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,这是链接到FieldProperties标记的FieldName标记。
我不知道如何写这样的查询。我目前所做的是遍历所有的FieldProperties,然后填充字段属性。但是我不知道如何检查字段类型是否为9,如果是9,则获取FieldOptions子对象的列表,然后填充Options属性。
这就是我目前所拥有的:

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;
qvsjd97n

qvsjd97n1#

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.选择Many可将其展平为{Field,Option}对的流
    3.用于合并选项的GroupBy字段

相关问题