0
<Nodes>
  <Node>
    <ID>1</ID>
    <TIDS>
      <TID>2</TID>
      <TID>3</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>2</ID>
    <TIDS>
      <TID>4</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>3</ID>
    <TIDS>
      <TID>7</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>4</ID>
    <TIDS>
      <TID>7</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>5</ID>
    <TIDS>
      <TID>7</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>6</ID>
    <TIDS>
      <TID>7</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>7</ID>
  </Node>
</Nodes>

我想编写查询,它将 fselect TID 并再次查询 xml 以选择它的 TID 假设我的 where 条件是 ID 等于 1 然后我想在我的 where 条件中输出 2,3,4,7 如果我输入 ID 等于 5 然后输入7 如何编写递归 linq

4

3 回答 3

1
 var result = xml.Elements()
   // Find element with <ID>1</ID>
   .Where(x => x.Elements().Any(d => d.Name == "ID" && d.Value == "1"))
   // Find element <TIDS>
   .Elements().Where(x => x.Name == "TIDS")
   // Find elements <TID>
   .Elements().Where(x => x.Name == "TID")
   // Select values
   .Select(x => x.Value);

注意,我做了xml这样的变量:

   XElement xml = XElement.Parse (@"<Nodes>
  <Node>
    <ID>1</ID>
    <TIDS>
      <TID>2</TID>
      <TID>3</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>2</ID>
    <TIDS>
      <TID>4</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>3</ID>
    <TIDS>
      <TID>7</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>4</ID>
    <TIDS>
      <TID>7</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>5</ID>
    <TIDS>
      <TID>7</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>6</ID>
    <TIDS>
      <TID>7</TID>
    </TIDS>
  </Node>
  <Node>
    <ID>7</ID>
  </Node>
</Nodes>");
于 2013-07-25T20:23:02.163 回答
0

该函数为您传入的GetTids返回一个列表。初始值传递后,它返回一个列表 ( )。然后运行一个循环,每个值都用于查询 XML 并添加到.TIDsIDIDtidIndexTIDtidList

List<string> TidList()
{
    var xml = XDocument.Load(@"C:\PathToXml\File.xml");

    var tidIndex = GetTids(xml, "1").ToList();
    var tidList = new List<string>(tidIndex);

    foreach (var tid in tidIndex)
        tidList.AddRange(GetTids(xml, tid));

    return tidList;
}

static IEnumerable<string> GetTids (XDocument xml, string id)
{
    return xml.Descendants("Node")
        .Where(x => x.Element("ID").Value == id)
        .Descendants("TID")
        .Select (s => s.Value);
}

这将返回:

在此处输入图像描述

于 2013-07-26T02:06:11.427 回答
0

递归 LINQ 更像是一种聚会技巧,而不是您真正想在生产代码中使用的任何东西,但这是一种方法:

XElement nodes = /* load your xml */;

Func<XElement, int, IEnumerable<int>> query = null;

/* BAD CODE, DO NOT USE! */
query = (x,id) => 
   x.Elements("Node")
     .Where (node => (int)node.Element("ID") == id) // find our node
     .Descendants("TID")      // this will be empty in the base case
     .Select (tid => (int)tid)
     .SelectMany(tid => 
       query(x,tid)           // recurse
       .Concat(new[]{tid})    // keep the current TID if its node had no TIDs
     )
     .Distinct();

var resultOf7423 = query(nodes, 1);
var resultOf7 = query(nodes, 5);
/* END BAD CODE (I HOPE) */

这是令人费解且脆弱的代码,您几乎可以肯定不应该使用它。相反,您可以创建一个扩展方法XElement

public static IEnumerable<int> SelectRelatedIds(this XElement element, int id)
{
    if(element == null) throw new ArgumentNullException("element");
    return SelectRelatedIdsIterator(element, id)
                .Where(i => i != id)
                .Distinct();
}

private static IEnumerable<int> SelectRelatedIdsIterator(XElement element, int id)
{
    yield return id;

    var tids = element.Elements("Node")
                .Where (node => (int)node.Element("ID") == id)
                .Descendants("TID");

    foreach (int tid in tids)
        foreach(var i in  SelectRelatedIdsIterator(element, tid))
            yield return i;
}

这使递归保持包含并且很容易理解(至少在您了解迭代器块时)。它也是 LINQ 友好的,并且可能以第一种方式不是的方式组合。

于 2013-07-26T01:04:46.533 回答