-1

I need to get hold of all the elements in an XDocument, regardless of name, whose value matches some criterion.

The 'matching a criterion' part isn't the problem - the problem is how to get a collection of all the XElements in an XDocument, in other words to flatten it into a 'list' of XElements, without specifying the element names.

myXDocument.Descendants().Where(el => IsAMatch(el.Value))

only seems to return the first level, but the elements in question are nested a variety of levels deep and have a variety of names over which I have no control (and to be honest, no interest either. I just want to find them).

I could do it recursively, walking the tree and adding every matching element to a list, but it doesn't seem very elegant (and is probably quite slow).

How can do I do this more elegantly?

TIA

haughtonomous
  • 4,602
  • 11
  • 34
  • 52
  • I don't know how else you would accomplish this other than recursion. If you don't know the element names then you can't use XPath, which would be my first suggestion. – Dan Wilson May 03 '18 at 16:18
  • 6
    The `XContainer.Descendants()` method walks the complete XML tree recursively. So there's something in your code causing to process only the first level elements. – dymanoid May 03 '18 at 16:20
  • The recursive method is both the most straightforward and the most elegant solution imo. If you think about it, based on your description, any member of the tree can potentially have a matching element. This means that your solution must be at least O(N), which walking the tree naturally is. – SomeGuy May 03 '18 at 16:21
  • As explained by @dymanoid, [`Descendants()`](https://msdn.microsoft.com/en-us/library/bb360635.aspx) is already recursive so that's not the problem. My guess: you're filtering on the element value, but [`XElement.Value`](https://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.value.aspx) returns the concatenated text contents inside the element belonging to the element itself plus any of its descendants. If you want just the value of the element itself see [How to get XElement's value and not value of all child-nodes?](https://stackoverflow.com/q/4251215/3744182). – dbc May 03 '18 at 17:06
  • But if that's not the issue either we need to see a [mcve] to help you. – dbc May 03 '18 at 17:08
  • What does the method IsAMatch() return? – jdweng May 03 '18 at 17:36
  • IsAmatch() just compares el.Value with a known string (actually a pattern, but that's by the by). – haughtonomous May 04 '18 at 07:47
  • Later: I can see what is happening now - Descendants() is indeed returning all the elements, but nested elements are returned within their parent elements AND in their own right, which I hadn't spotted. IsAMatch(...) needs to constrain itself to the element's immediate value, ignoring the nested (child) elements. – haughtonomous May 04 '18 at 07:57

1 Answers1

0

I can see what is happening now - Descendants() is indeed returning all the elements, but nested elements are returned within their parent elements AND in their own right, which I hadn't spotted. IsAMatch(...) needs to constrain itself to the element's immediate value, ignoring the nested (child) elements.

haughtonomous
  • 4,602
  • 11
  • 34
  • 52