Query an XDocument for elements by name at any depth
Solution 1
Descendants should work absolutely fine. Here's an example:
using System;
using System.Xml.Linq;
class Test
{
static void Main()
{
string xml = @"
<root>
<child id='1'/>
<child id='2'>
<grandchild id='3' />
<grandchild id='4' />
</child>
</root>";
XDocument doc = XDocument.Parse(xml);
foreach (XElement element in doc.Descendants("grandchild"))
{
Console.WriteLine(element);
}
}
}
Results:
<grandchild id="3" />
<grandchild id="4" />
Solution 2
An example indicating the namespace:
String TheDocumentContent =
@"
<TheNamespace:root xmlns:TheNamespace = 'http://www.w3.org/2001/XMLSchema' >
<TheNamespace:GrandParent>
<TheNamespace:Parent>
<TheNamespace:Child theName = 'Fred' />
<TheNamespace:Child theName = 'Gabi' />
<TheNamespace:Child theName = 'George'/>
<TheNamespace:Child theName = 'Grace' />
<TheNamespace:Child theName = 'Sam' />
</TheNamespace:Parent>
</TheNamespace:GrandParent>
</TheNamespace:root>
";
XDocument TheDocument = XDocument.Parse( TheDocumentContent );
//Example 1:
var TheElements1 =
from
AnyElement
in
TheDocument.Descendants( "{http://www.w3.org/2001/XMLSchema}Child" )
select
AnyElement;
ResultsTxt.AppendText( TheElements1.Count().ToString() );
//Example 2:
var TheElements2 =
from
AnyElement
in
TheDocument.Descendants( "{http://www.w3.org/2001/XMLSchema}Child" )
where
AnyElement.Attribute( "theName" ).Value.StartsWith( "G" )
select
AnyElement;
foreach ( XElement CurrentElement in TheElements2 )
{
ResultsTxt.AppendText( "\r\n" + CurrentElement.Attribute( "theName" ).Value );
}
Solution 3
You can do it this way:
xml.Descendants().Where(p => p.Name.LocalName == "Name of the node to find")
where xml
is a XDocument
.
Be aware that the property Name
returns an object that has a LocalName
and a Namespace
. That's why you have to use Name.LocalName
if you want to compare by name.
Solution 4
Descendants will do exactly what you need, but be sure that you have included a namespace name together with element's name. If you omit it, you will probably get an empty list.
Solution 5
There are two ways to accomplish this,
- LINQ to XML
- XPath
The following are samples of using these approaches,
List<XElement> result = doc.Root.Element("emails").Elements("emailAddress").ToList();
If you use XPath, you need to do some manipulation with the IEnumerable:
IEnumerable<XElement> mails = ((IEnumerable)doc.XPathEvaluate("/emails/emailAddress")).Cast<XElement>();
Note that
var res = doc.XPathEvaluate("/emails/emailAddress");
results either a null pointer, or no results.
Related videos on Youtube
g.mark11
Updated on December 17, 2020Comments
-
g.mark11 over 3 years
I need a success message to pop-up when a user hits the
Submit
button. I tried to make a javascript file to solve the task, but something should be wrong because it does nothing.The Button(HTML):
<button name="submit" type="submit" class="btn btn-primary btn-xl" id="sendMessageButton" action="form.js">Küldés</button>
Javascript file:
$("#sendMessageButton").click(function(){ Swal.fire( 'Good job!', 'You clicked the button!', 'success' ); });
Console Error:
Uncaught ReferenceError: Swal is not defined at HTMLButtonElement.<anonymous> (form.js:2) at HTMLButtonElement.dispatch (jquery.min.js:2) at HTMLButtonElement.y.handle (jquery.min.js:2)
-
Rambarun Komaljeet almost 5 yearsdo you get any errors in the browser js console ?
-
g.mark11 almost 5 yearsUncaught ReferenceError: Swal is not defined at HTMLButtonElement.<anonymous> (form.js:2) at HTMLButtonElement.dispatch (jquery.min.js:2) at HTMLButtonElement.y.handle (jquery.min.js:2)
-
DaWe over 3 years"Küldés" - magyarok mindenhol 😃
-
-
EoRaptor013 over 13 yearsBut, what if my source xml doesn't have a namespace? I suppose I can add one in code (have to look into that), but why is that necessary? In any event, root.Descendants("myTagName") doesn't find elements buried three or four levels deep in my code.
-
SoftwareSavant about 12 yearsDon't want to be mean here, but your example does not show grandchildren. emailAddress is a child of emails. I am wondering if there is a way to use Descendants without using namespaces?
-
pfeds over 11 yearsHow would you tackle this if an element name was duplicated within an xml document? For example: If the xml contained a collection of <Cars> with sub elements of <Part>, and also a collection of <Planes> with sub elements of <Part>, and you want a list of Parts for Cars only.
-
Jon Skeet over 11 years@pfeds: Then I'd use
doc.Descendants("Cars").Descendants("Part")
(or possibly.Elements("Part")
if they were only direct children. -
Tahir Hassan about 11 yearsjust to mention that
XPathEvaluate
is in theSystem.Xml.XPath
namespace. -
The Dag almost 11 yearsXPathEvaluate should do the trick, but your query only takes nodes at a particular depth (one). If you wanted to select all elements named "email" regardless of where in a document they occur, you'd use the path "//email". Obviously such paths are more expensive, since the entire tree must be walked whatever the name is, but it can be quite convenient - provided you know what you're doing.
-
Kim over 10 yearsThanks! We're using datacontract serialization. This creates a header like <MyClassEntries xmlns:i="w3.org/2001/XMLSchema-instance" xmlns="schemas.datacontract.org/2004/07/DataLayer.MyClass"> and I was stumped why I wasn't getting any descendants. I needed to add the {schemas.datacontract.org/2004/07/DataLayer.MyClass} prefix.
-
EvilDr over 8 yearsSix years on and still a fantastic example. In fact, this is still far more helpful than the MSDN explanation :-)
-
Dror Harari over 8 yearsAnd it is still an evil example, Dr., since if there are no "Cars", the above code would result in an NPE. Maybe the .? from the new C# will finally make it valid
-
DareDude over 7 years@DrorHarari Nope, no exception is thrown: Try out
var foo = new XDocument().Descendants("Bar").Descendants("Baz");
BecauseDescendants
returns an emptyIEnumerable<XElement>
and notnull
. -
Eugene Maksimov over 6 yearsI'm trying to get all EmbeddedResource node from c# project file, and this is only way that works. XDocument document = XDocument.Load(csprojPath); IEnumerable<XElement> embeddedResourceElements = document.Descendants( "EmbeddedResource"); Is not works and I don't understand why.
-
g.mark11 almost 5 yearsNo I haven't, this was the problem. Thank you :)
-
Maher Nabil over 2 yearsafter hours of searching and experimenting, this is the only answer that helped. Man can't thank you enough. Kudos for adding the namespace into the Descendants.