我如何在这里读取完整的XML元素?

本文关键字:XML 元素 在这里 读取 | 更新日期: 2023-09-27 18:16:36

我有一个包含许多Unit的XML文件:

<Unit Name="Length">
<Prefix Char="c"
          IsSelected="false"
          Factor="1"/>
<Prefix Char="d"
          IsSelected="true"
          Factor="104"/>
</Unit>

我想读取整个对象:

public static Dictionary<string, Unit> Units { get; set; } 
public class Prefix
{
    public Func<double, double> fnc = null;            
    public Prefix(string c, double f, bool i, bool ifix = false,string fn = null)
    {
        Char = c;
        Factor = f;
        IsFixed = ifix;
        Unit.funcs.TryGetValue(fn, out fnc);
    }
     public bool IsSelected { get; set; }
     public bool IsFixed { get; set; }
     public double Factor { get; set; }
     public string Char { get; set; }
}
public Unit() { }
public Unit(string n, List<Prefix> p)
{
    _name = n;
    Prefixes = p;
}
 private List<Prefix> _prefixes;
 public List<Prefix> Prefixes
 {
     get { return _prefixes; }
     set { _prefixes = value;  }
 }
 private string _name;
 public string Name
 { 
    get { return _name; }
    set { _name = value; }
 }
  ....
 }

我现在有了这个:

 Form.Units = (data.Descendants("Unit").Select(x => new Unit
                     (
                        x.Attribute("Name").Value,
                        (List<Prefix>) x.Descendants("Prefix").Select(p => new Prefix(
                            p.Attribute("Char").Value,
                            Convert.ToDouble(p.Attribute("Factor").Value),
                            p.Attribute("IsSelected").Value == "true",
                            p.Attribute("IsFixed").Value == "true",
                            p.Attribute("Func").Value)
                         )
                      )
                    )
               ).ToDictionary(x => x.Name, x => x);
并得到以下错误:

"无法强制转换类型的对象'WhereSelectEnumerableIterator 2[System.Xml.Linq.XElement,DD.Prefix]' to type 'System.Collections.Generic.List 1[DD.Prefix]'。"

显然(List<Prefix>)有问题

那么查询必须是什么呢?如何获取列表中的内容?

.

我如何在这里读取完整的XML元素?

我将以以下方式表示此代码:因为它避免了将这些类型约束为可枚举表达式的形参构造函数。例如,避免在你计划用于查询的类型上使用参数构造函数。

我正在放置在Decendents中使用的类型作为XmlElement类型…但我肯定这是不准确的…只需将其替换为正确的类型即可。

另外,这段代码没有考虑到Unit.funcs.TryGetValue(fn, out fnc); ..并且它假定在Prefix类型上有一个属性名称Func。您可以在分配/设置期间执行null检查。

data.Descendants("Unit")
                .Select<XmlElement, Unit>(x => new Unit() 
                { 
                    Name = x.Attribute("Name").Value,
                    Prefixes = x.Descendants("Prefix").Select<XmlElement, Prefix>(p => new Prefix() 
                    {
                        Char = p.Attribute("Char").Value,
                        Factor = Convert.ToDouble(p.Attribute("Factor").Value),
                        IsSelectd = p.Attribute("IsSelected").Value == "true",
                        IsFixed = p.Attribute("IsFixed").Value == "true",
                        Func = p.Attribute("Func").Value
                    }).ToList()
                })
                .Select<Unit, KeyValuePair<string, Unit>>(unit => new KeyValuePair<string, Unit>() 
                {
                    Key = x.Name,
                    Value = x 
                })
                .ToList()
                .ForEach( kvp => {
                    Form.Units.Add(kvp.Key, kvp.Value);
                });

它不是一个列表,而是一个查询,所以你不能把它强制转换为列表,但你可以调用ToList对它进行枚举,并返回一个列表:

 Form.Units = (data.Descendants("Unit").Select(x => new Unit
                 (
                    x.Attribute("Name").Value,
                    //(List<Prefix>) no casting needed
                    x.Descendants("Prefix").Select(p => new Prefix(
                        p.Attribute("Char").Value,
                        Convert.ToDouble(p.Attribute("Factor").Value),
                        p.Attribute("IsSelected").Value == "true",
                        p.Attribute("IsFixed").Value == "true",
                        p.Attribute("Func").Value)
                     ).ToList() // you had an IEnumerable<Prefix> now this is a List<Prefix>
                  )
                )
           ).ToDictionary(x => x.Name, x => x);

为了扩展我的评论,这里有几件事。首先,您可以在.Select上使用.ToList()扩展方法将IEnumerable<T>集合转换为List<T>集合。

其次,如果查询中缺少任何属性或元素,您将获得空引用异常。您可以通过显式转换为string(然后在需要时转换结果)来安全地处理这个问题。

更新后的查询如下所示:

Form.Units = (data.Descendants("Unit").Select(x => new Unit
    ((string)x.Attribute("Name"),
     x.Descendants("Prefix").Select(p => new Prefix(
         (string)p.Attribute("Char"),
         Convert.ToDouble((string)p.Attribute("Factor")),
         (string)p.Attribute("IsSelected") == "true",
         (string)p.Attribute("IsFixed") == "true",
         (string)p.Attribute("Func")).ToList()
      )
    )
)
).ToDictionary(x => x.Name, x => x);

请注意,当使用(string)时,您不需要.Value(因为.Value已经是string)。