1

我的 XML 文件包含类似于以下内容的结构:

<root>
    <Manager name="1">
        <Manager name="2">
            <Employee name="3">
        </Manager>
        <Manager name="abe">
        </Manager>
        <Employee name="4">
        <Employee name="5">
    </Manager>
</root>

XML 提供一个树视图,并且根据用户在树视图中单击的位置,我要么想检索单击的员工(这很容易,因为我可以使用treeview.SelectedNode),或者如果单击是在根节点上,或者一个经理节点,经理下的第一个员工。

IE

  • 单击root应显示详细信息Employee 4(第一个 Employee 记录在Manager 1直接下root)。
  • 点击Manager 1也应该显示Employee 4
  • 单击Manager 2应显示Employee 3.
  • 单击Manager Abe不会产生任何结果。
  • Employee 5仅在直接点击该员工时显示。

也有可能Manager 1在他手下没有任何直接雇员。在这种情况下,单击 root 应该会在第一个有员工的经理下产生第一个 Employee。因此,如果我们假设Employee 4并且Employee 5不在Manager 1,单击 root 将产生Employee 3

我尝试使用,和, 的一些不同变体Element,但有点卡住了。ElementsDescendantDescendants

我想我可以为每个单独的组合(即 和 )编写场景rootClickedmanagerClickedemployeeClicked是我最初所做的,但我正在寻找一些希望更容易维护的东西,代码方面。

我非常希望使用 root.Element("Employee") 会有所帮助,但这会引发Could not find an implementation of the query pattern for source type 'System.Xml.Linq.XEelement'. 'select' not found错误。

任何人都可以为我提供解决我的问题所需的一点点推动吗?

4

2 回答 2

4

使用 XPath

ClickedNode.XPathEvaluate
    ("self::Employee | self::Manager/Employee[1] | self::root/Manager[1]/Employee[1]")

更新

回答已编辑的问题:

使用

 ClickedNode[self::Employee]
|
 ClickedNode[not(self::Employee)]/descendant-or-self::Manager[Employee][1]/Employee[1]

这选择

一个。单击的节点,如果它是“员工”

或者:

湾。单击节点的第一个子Employee节点的第一个子节点,即管理器并有一个子节点Employee

并且,如果 ClickedNode 是XElement(或XNode),则执行以下操作:

  ClickedNode.XPathEvaluate
        (self::*[self::Employee]
      | self::node()[not(self::Employee)]
                       /descendant-or-self::Manager[Employee][1]/Employee[1]
        )

最后,这是一个完整的 C# 代码

一个名为的静态类TestLinqXpath

using System.Xml.Linq;
using System.Xml.XPath;

namespace TestLinqXpath
{
    public  static class TestLinqXpath
    {
        public static XElement SelectNearestDescendantEmployee(XElement clicked)
        {
            string Expr =
@"(self::*[self::Employee]
 | self::node()[not(self::Employee)]
           /descendant-or-self::Manager[Employee][1]/Employee[1]
   )";
            XElement result = clicked.XPathSelectElement(Expr);

            return result;
        }
    }
}

和广泛的测试

using System;
using System.Xml.Linq;
using System.Xml.XPath;

namespace TestLINQ_Xml
{
    class Program
    {
        static void Main(string[] args)
        {
            Test();
        }

        static void Test()
        {
            string xml = 
@"<root>
    <Manager name='1'>
        <Manager name='2'>
            <Employee name='3'/>
        </Manager>
        <Manager name='abe'>
        </Manager>
        <Employee name='4'/>
        <Employee name='5'/>
    </Manager>
</root>";
            XElement top = XElement.Parse(xml);

            XElement cliked1 = top;
            XElement res1 = TestLinqXpath.TestLinqXpath.SelectNearestDescendantEmployee(cliked1);
            Console.WriteLine(res1.ToString());

            XElement cliked2 = top.XPathSelectElement("Manager[@name='1']");
            XElement res2 = TestLinqXpath.TestLinqXpath.SelectNearestDescendantEmployee(cliked2);
            Console.WriteLine(res2.ToString());

            XElement cliked3 = top.XPathSelectElement(".//Manager[@name='2']");
            XElement res3 = TestLinqXpath.TestLinqXpath.SelectNearestDescendantEmployee(cliked3);
            Console.WriteLine(res3.ToString());

            XElement cliked4 = top.XPathSelectElement(".//Manager[@name='abe']");
            XElement res4 = TestLinqXpath.TestLinqXpath.SelectNearestDescendantEmployee(cliked4);
            Console.WriteLine((res4 != null) ? res4.ToString() : "null");

            XElement cliked5 = top.XPathSelectElement(".//Employee[@name='5']");
            XElement res5 = TestLinqXpath.TestLinqXpath.SelectNearestDescendantEmployee(cliked5);
            Console.WriteLine(res5.ToString());
        }
    }
}

运行此测试时,会产生所需的正确结果:

<Employee name="4" />
<Employee name="4" />
<Employee name="3" />
null
<Employee name="5" />
于 2012-10-21T22:03:14.560 回答
1

这个linq2xml应该做

doc.Descendants("Manager").Where(n=>n.Attribute("name").Value=="yourManagerID")
.Select(
x=>x.Elements("Employee").Count()!=0 
?
x.Elements("Employee").First().Attribute("name").Value
:
x.Elements("Manager").First().Element("Employee").Atrribute("name").Value
);
于 2012-10-21T20:05:14.840 回答