使用 LINQ 提取列表
Posted
技术标签:
【中文标题】使用 LINQ 提取列表【英文标题】:Using LINQ to extract list 【发布时间】:2021-08-12 06:15:36 【问题描述】:我尝试使用这段代码提取列表。如果我这样做,顶点将始终只解析第一个点并跳过所有剩余的点。 (Vertices.Count == 1)
Lines = xdoc.Descendants("LineEntity")
.Select(line => new LineEntity
Id = (long)line.Element("Id"),
Name = (string)line.Element("Name"),
ConductorMaterial = (string)line.Element("ConductorMaterial"),
IsUnderground = (bool)line.Element("IsUnderground"),
R = (float)line.Element("R"),
FirstEnd = (long)line.Element("FirstEnd"),
SecondEnd = (long)line.Element("SecondEnd"),
LineType = (string)line.Element("LineType"),
ThermalConstantHeat = (long)line.Element("ThermalConstantHeat"),
Vertices = line.Descendants("Vertices")
.Select(p => new Point3D
X = (double)p.Element("Point").Element("X"),
Y = (double)p.Element("Point").Element("Y"),
Z = 1
).ToList()
).ToList();
我要解析的 XML 文件如下所示
【问题讨论】:
你能把xml的图片替换成实际的xml作为文本吗? 出于好奇,为什么 x 和 y 点部分有 .Value 而其他部分没有? 我看到 R 中的 float 你不解析,但你在 X 和 Y 中为 double 解析,为什么?尝试像你为 float 做的投射而不解析和做 .Value,它会工作吗? @Mocas 尝试并编辑了代码,仍然只解析 Point 中的第一个值。 @Marco 几千行 【参考方案1】:你需要从Vertices
得到Point
Vertices = line.Descendants("Vertices")
.Elements("Point")
.Select(p => new Point3D
X = (double)p.Element("X"),
Y = (double)p.Element("Y"),
Z = 1
)
Lines = xdoc.Descendants("LineEntity")
.Select(line => new LineEntity
Id = (long)line.Element("Id"),
Name = (string)line.Element("Name"),
ConductorMaterial = (string)line.Element("ConductorMaterial"),
IsUnderground = (bool)line.Element("IsUnderground"),
R = (float)line.Element("R"),
FirstEnd = (long)line.Element("FirstEnd"),
SecondEnd = (long)line.Element("SecondEnd"),
LineType = (string)line.Element("LineType"),
ThermalConstantHeat = (long)line.Element("ThermalConstantHeat"),
Vertices = line.Descendants("Vertices").Elements("Point")
.Select(p => new Point3D
X = (double)p.Element("X"),
Y = (double)p.Element("Y"),
Z = 1
).ToList()
).ToList();
【讨论】:
【参考方案2】:也许你需要这样的东西,或者沿着这条线 不完全确定它是怎么回事,但你明白了。
Lines = xdoc.Descendants("LineEntity")
.Select(line => new LineEntity
Id = (long)line.Element("Id"),
Name = (string)line.Element("Name"),
ConductorMaterial = (string)line.Element("ConductorMaterial"),
IsUnderground = (bool)line.Element("IsUnderground"),
R = (float)line.Element("R"),
FirstEnd = (long)line.Element("FirstEnd"),
SecondEnd = (long)line.Element("SecondEnd"),
LineType = (string)line.Element("LineType"),
ThermalConstantHeat = (long)line.Element("ThermalConstantHeat"),
Vertices = line.Descendants("Vertices")
.Select(v =>
return v.Descendants("Ponit").Select(p =>
new new Point3D
X = (double).Element("X"),
Y = (double).Element("Y"),
Z = 1
).ToList()
).ToList();
【讨论】:
【参考方案3】:只需反序列化文档,无需手动解析:
[XmlRoot("root")]//here comes name of your top-level xml element, ie root
public class RootDoc
public List<LineEntity> Lines get; set;
public class LineEntity
public int Id get; set;
public string Name get; set;
[XmlArrayItem("Point")]
public List<Point3D> Vertices get; set;
[TestFixture]
public class ParseTests
[Test]
public async Task Repro()
var xdoc = XDocument.Parse(File.ReadAllText("in.xml"));
var serializer = new XmlSerializer(typeof(RootDoc));
var reader = xdoc.CreateReader();
var parsed = (RootDoc)serializer.Deserialize(reader);
reader.Close();
parsed.Lines.ForEach(x=> x.Vertices.ForEach(y=> y.Z = 1)); //setting Z value like in your example.
var lines = parsed.Lines;
示例 xml:
<root>
<Lines>
<LineEntity>
<Id>123</Id>
<Name>nn</Name>
<Vertices>
<Point>
<X>123.123</X>
<Y>234.234</Y>
</Point>
</Vertices>
</LineEntity>
</Lines>
</root>
附言
您的字段没有自定义映射逻辑,因此不要使标准程序过于复杂。
【讨论】:
以上是关于使用 LINQ 提取列表的主要内容,如果未能解决你的问题,请参考以下文章