Linq xml recursive select -
<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>
i want write query fselect tid , again query xml select it's tid suppose condition id equal 1 want out put 2,3,4,7 in condition if put id equal 5 put put 7 how write recursive linq
recursive linq more of party trick you'd want use in production code, here's 1 way it:
xelement nodes = /* load xml */; func<xelement, int, ienumerable<int>> query = null; /* bad code, not use! */ query = (x,id) => x.elements("node") .where (node => (int)node.element("id") == id) // find our node .descendants("tid") // empty in base case .select (tid => (int)tid) .selectmany(tid => query(x,tid) // recurse .concat(new[]{tid}) // keep current tid if node had no tids ) .distinct(); var resultof7423 = query(nodes, 1); var resultof7 = query(nodes, 5); /* end bad code (i hope) */
this baffling , fragile code, , shouldn't use it. instead, create extension method off of xelement
:
public static ienumerable<int> selectrelatedids(this xelement element, int id) { if(element == null) throw new argumentnullexception("element"); return selectrelatedidsiterator(element, id) .where(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 in selectrelatedidsiterator(element, tid)) yield return i; }
this keeps recursion contained , pretty easy understand (at least once head around iterator blocks). it's linq-friendly , potentially composable in way first way not.
Comments
Post a Comment