LINQ:如何返回所有子元素?

3

我正在开发一个应用程序,需要从XML文件中显示数据。有一些转换正在进行,但最终结果将显示在树视图中。当用户单击节点时,我希望在列表视图中弹出详细信息。

当没有选择节点时,我基本上使用LINQ来获取我遇到的第一个项目的详细信息。

这是我的XML的简化版本:

<root>
   <parent label="parent1">
      <child label="child1">
         <element1>data</element1>
         <element2>data</element2>
         ...
      </child>
      <child label="child2">
         <element1>data</element1>
         <element2>data</element2>
         ...
      </child>
   </parent>
</root>

以下是用于获取它的代码(在通过XPAthSelectStatement选择已设置为树视图的父节点后):

protected void listsSource_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
    XElement rootElement = XElement.Load(MapPath(TreeSource.DataFile));
    rootElement = rootElement.XPathSelectElement("//parent[@label='parent1']");
    XElement parentElement;

    parentElement = rootElement;

    var query = (from itemElement in parentElement.Descendants("child")
                 select new
                 {
                     varElement1 = itemElement.Element("element1").Value,
                     varElement2 = itemElement.Element("element2").Value,
                     ...
                 }).Take(1);

    e.result = Query;
}

这很有效,我可以从中读取varElement1varElement2的值。但是,当我尝试实现类似的机制来处理用户实际选择节点时,似乎遇到了障碍。
我的方法是使用另一个XPatchSelectStatement来获取实际的节点:
parentElement = rootElement.XPathSelectElement("//child[@label='" + tvwChildren.SelectedNode.Text + "']");

但是我不知道如何构建一个适当的LINQ查询来读取所有嵌套在子节点下的元素。我尝试使用parentElement.Elements(),但这导致了一个错误。我还尝试使用Nodes(),但结果也类似。
我想我可以使用foreach循环来访问节点,但然后我不知道如何将结果放入LINQ查询中,以便我可以返回相同的e.Result = query
我对LINQ相当新,正如你可能已经猜到的那样,所以任何提示都将非常感激。

我实际上成功地弄清楚了,我只需要使用:var query = (from itemElement in parentElement.DescendantsAndSelf("child") - SchmitzIT
4个回答

1

我认为在这种情况下数据绑定更容易。

XDocument doc = XDocument.Load(filePath);
if (doc.Root == null)
{
throw new ApplicationException("invalid data");
}
tvwChildren.Source=doc;

但是如果你想这样做,希望以下内容能够帮到你(虽然不是完全解决方案)

XElement root = XElement.Load("Employees.xml");
TreeNode rootNode = new TreeNode(root.Name.LocalName);
treeView1.Nodes.Add(rootNode);
    foreach(XElement employee in root.Elements())
           {
            TreeNode employeeNode = new TreeNode("Employee ID :" + employee.Attribute("employeeid").Value);
            rootNode.Nodes.Add(employeeNode);
                 if (employee.HasElements)
                 {
                    foreach(XElement employeechild in employee.Descendants())
                     {
                        TreeNode childNode = new TreeNode(employeechild.Value);
                        employeeNode.Nodes.Add(childNode);
                     }
                 }
            }

你可以尝试使用Resharper工具来创建更好的Linq语句。它会显示可能的语句,你可以轻松地将每个for、foreach循环转换为Linq语句。


虽然我不确定你的方法是否适用于我的需求(我已经让树形视图工作了,但现在正在尝试从中读取内容到我的列表视图),但我真的很感谢Resharper的提示。我会去尝试一下 :) - SchmitzIT

1
这是一个查询,将返回指定标签下的子元素(假设该标签下只有一个名为child的子元素):
var childElement = rootNode.Descendants("child")
                           .Single(e=>e.Attribute("label").Value == "child1");

如果您有多个 label="child1" 的子元素,但这些元素位于不同的父元素下,则可以使用相同的方法首先获取父元素,然后获取子元素。
有了上面的内容,您可以使用以下查询获取 child 节点下的所有 element 节点:
var elements = childElement.Descendants().Select(e=>e.Value);

第二个片段似乎完成了我想要的事情。我可以在查询结果中看到这些值。我会尝试一下,看看如何将那里的值加载到varElement1和varElement2变量中。 - SchmitzIT

0

我不太确定我理解你想做什么,但听起来可能是这样:

var data =
    from p in xml.Root.Elements("parent")
    where p.Attribute("label").Value == "parent1"
    from c in p.Elements("child")
    where c.Attribute("label").Value == "child2"
    from d in c.Elements()
    select d.Value;

如果有帮助,请告诉我。


0

使用 这个 XML 库,你可以这样编写 XPath:

XElement child = rootElement.XPathElement(
    "//parent[@label={0}]/child[@label={1}]", "parent1", "child2");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接