c# - LINQ to XML - 具有父级属性的自定义对象列表

标签 c# linq linq-to-xml

事实证明,今晚 LINQ 的学习曲线太陡峭了,所以我再次来这里寻求帮助。提前致以深深的谢意。

这是我当前的代码;

_myList = (
from listLv2 in
    _documentRoot.Descendants("Level1").Descendants("Level2")
where
    (string)listLv2.Attribute("id") == "12345"

let attrib_Colour = listLv2.Attribute("Colour")
let attrib_ID = listLv2.Attribute("id")

//select listLv2.Descendants("Level3") <---- not working
select new MyObj
{
let attrib_ChildID = ???..Attribute("id")

ParentColour = attrib_Colour.Value, 
ParentID = attrib_ID.Value, // in this case 12345
ChildID = attrib_ChildID
}).ToList<MyObj>();

这就是我想要实现的目标;

  1. 创建 MyObjs 列表。我在 MyObjs 中转换 Level3 元素。
  2. 我只想要 ID 为 12345 的 Level2 元素中的 Level3 元素
  3. 我想在每个子 Level3 元素中使用 Level2(id=12345) 元素中的一些属性

XML结构如下;

<root>
  <Level1>
<Level2 id="12345" colour="Red">
  <Level3 id="0001" />
  <Level3 id="0002" />
  <Level3 id="0003" />
</Level2>
<Level2 id="45678" colour="Blue">
  <Level3 id="0004" />
  <Level3 id="0005" />
  <Level3 id="0006" />
</Level2>
</Level1>
</root>

列表中的对象应该是这样的;

MyObj.ParentID = 12345
MyObj.ParentColour = "Red"
MyObj.ID = 0001

MyObj.ParentID = 12345
MyObj.ParentColour = "Red"
MyObj.ID = 0002

MyObj.ParentID = 12345
MyObj.ParentColour = "Red"
MyObj.ID = 0003

来自和哪里正在工作。它选择 1 个元素,即 Level2[id=12345]。好的。 Level2 属性正在运行。

这是我无法解决的问题;

  • 如何访问每个子 Level3 元素,以便我可以将其转换为 MyObj
  • 如何创建 Level3 属性(使用“let”)。我想使用 Let 以便我可以检查 null 等

再次感谢

最佳答案

您应该使用 SelectMany 为您的 level2 元素获取 level3 项目。等效查询语法为 from listLv3 in listLv2.Descendants("Level3") :

from listLv2 in _documentRoot.Descendants("Level1").Descendants("Level2")
let attrib_ID = (string)listLv2.Attribute("id")
let attrib_Colour = (string)listLv2.Attribute("colour") // note: lowercase!
where attrib_ID == "12345"
from listLv3 in listLv2.Descendants("Level3")
select new MyObj
{
  ParentColour = attrib_Colour, 
  ParentID = attrib_ID, 
  ChildID = (string)listLv3.Attribute("id")
}

更新:为什么我在解决方案中提到了 SelectMany?因为上面的代码(如果我们忘记使用 let 关键字引入的新范围变量)将被编译为以下方法语法查询:

_documentRoot
    .Descendants("Level1")
    .Descendants("Level2")
    .Where(listLv2 => (string)listLv2.Attribute("id") == "12345")
    .SelectMany(listLv2 => listLv2.Descendants("Level3")) // flattening query
    .Select(listLv3 => new MyObj {
        ParentColour = (string)listLv3.Parent.Attribute("colour"),
        ParentID = "12345", // equal to id you are searching for
        ChildID = (string)listLv3.Attribute("id")
    });

这里的关键点是通过从每个匹配的 level2 元素中选择所有 level3 后代到单个序列来扁平化查询。

顺便说一句,还请考虑 XPath 解决方案:

from listLv3 in root.XPathSelectElements("Level1/Level2[@id='12345']/Level3")
select new MyObj
{
   ParentColour = (string)listLv3.Parent.Attribute("colour"), 
   ParentID = "12345", 
   ChildID = (string)listLv3.Attribute("id")
}

关于c# - LINQ to XML - 具有父级属性的自定义对象列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18872927/

相关文章:

c# - 如何使用 LINQ 对列表的列表进行分组(例如 : List<List<int>>)

c# - dotMemory快照导致wpf崩溃

c# - XmlTextReader - 它是否锁定文件?

c# - 为什么对外部数据源的更改没有反射(reflect)出来,而对内部数据源却显示出来了?

.net - Linq to Xml:异常-名称中不能包含''字符,十六进制值0x20

c# - 如何在C#的字符串中放入静态html?

linq - 如何在 LINQ 中设置自动增量 value=true

c# - 如何在 .NET 枚举中搜索正确的方法

.net - 在 LINQ 查询中获取当前枚举器(迭代器?)。就像 for 循环中的当前索引一样

c# - linq to xml检查 key 是否存在?