140

Suppose I have a XmlNode and I want to get the value of an attribute named "Name". How can I do that?

XmlTextReader reader = new XmlTextReader(path);

XmlDocument doc = new XmlDocument();
XmlNode node = doc.ReadNode(reader);

foreach (XmlNode chldNode in node.ChildNodes)
{
     **//Read the attribute Name**
     if (chldNode.Name == Employee)
     {                    
         if (chldNode.HasChildNodes)
         {
             foreach (XmlNode item in node.ChildNodes)
             { 

             }
         }
      }
}

XML Document:

<Root>
    <Employee Name ="TestName">
    <Childs/>
</Root>

9 Answers 9

243

Try this:

string employeeName = chldNode.Attributes["Name"].Value;

Edit: As pointed out in the comments, this will throw an exception if the attribute doesn't exist. The safe way is:

var attribute = node.Attributes["Name"];
if (attribute != null){
    string employeeName = attribute.Value;
    // Process the value here
}
5
  • 38
    Be careful with this approach. I think if the attribute is not present, then accessing the Value member will cause a Null Reference Exception. Commented Oct 21, 2009 at 14:06
  • 3
    if(node.Attributes != null) string employeeName = chldNode.Attributes["Name"].Value;
    – Omidoo
    Commented Sep 28, 2012 at 23:03
  • 7
    @Omidoo That approach has the same issue, for example with <a x="1" />, which passes the test. Perhaps something like var attr = node.Attributes["Name"]; if(attr != null) {...} might work. Commented Nov 13, 2012 at 12:00
  • Take a look at my answer below, which circumvents the NullException problem and is, maybe?, safer to use.
    – Marco7757
    Commented May 19, 2016 at 12:03
  • An updated answer could be string employeeName = chldNode.Attributes["Name"]?.Value;
    – jing
    Commented May 11, 2022 at 8:37
46

To expand Konamiman's solution (including all relevant null checks), this is what I've been doing:

if (node.Attributes != null)
{
   var nameAttribute = node.Attributes["Name"];
   if (nameAttribute != null) 
      return nameAttribute.Value;

   throw new InvalidOperationException("Node 'Name' not found.");
}
3
  • 7
    A shorthand way of not getting an error for nulls is node.Attributes?["Name"]?.Value Commented Mar 2, 2017 at 19:51
  • 1
    Also true, though the only thing I'll point out is that while you can do that in one line (making it good for an assignment or something), it's a bit less flexible in terms of controlling when you throw an exception or otherwise handle the case where node has no attributes.
    – Ari Roth
    Commented Mar 3, 2017 at 0:28
  • 1
    Agreed. Anyone who uses the shorthand way should always make sure it won't cause problems downstream. Commented Mar 3, 2017 at 20:13
17

you can loop through all attributes like you do with nodes

foreach (XmlNode item in node.ChildNodes)
{ 
    // node stuff...

    foreach (XmlAttribute att in item.Attributes)
    {
        // attribute stuff
    }
}
1
  • this will be more preferable..:) Commented Feb 27, 2017 at 5:39
7

If you use chldNode as XmlElement instead of XmlNode, you can use

var attributeValue = chldNode.GetAttribute("Name");

The return value will just be an empty string, in case the attribute name does not exist.

So your loop could look like this:

XmlDocument document = new XmlDocument();
var nodes = document.SelectNodes("//Node/N0de/node");

foreach (XmlElement node in nodes)
{
    var attributeValue = node.GetAttribute("Name");
}

This will select all nodes <node> surrounded by <Node><N0de></N0de><Node> tags and subsequently loop through them and read the attribute "Name".

4

if all you need is the names, use xpath instead. No need to do the iteration yourself and check for null.

string xml = @"
<root>
    <Employee name=""an"" />
    <Employee name=""nobyd"" />
    <Employee/>
</root>
";

var doc = new XmlDocument();

//doc.Load(path);
doc.LoadXml(xml);

var names = doc.SelectNodes("//Employee/@name");
1
  • The methods above didn't work for my XML (though I wish they had). This method does! Thanks! Commented Jun 23, 2015 at 21:41
3

Use

item.Attributes["Name"].Value;

to get the value.

1

You can also use this;

string employeeName = chldNode.Attributes().ElementAt(0).Name
1

Yet another solution:

string s = "??"; // or whatever

if (chldNode.Attributes.Cast<XmlAttribute>()
                       .Select(x => x.Value)
                       .Contains(attributeName))   
   s =  xe.Attributes[attributeName].Value;

It also avoids the exception when the expected attribute attributeName actually doesn't exist.

0

Expanding on Konamiman's solution above. I needed to loop through multiple attributes for a node.

Telecom theTelecom = new Telecom();
if (node.HasAttributes)
{
     var nameAttributeList = node.Attributes();
     foreach (XAttribute a in nameAttributeList)
     {
         if ((null != a.Name?.LocalName) && 
               ("use" == a.Name.LocalName))
         {
             theTelecom.use = a.Value;
         }
         if ((null != a.Name?.LocalName) && 
               ("value" == a.Name.LocalName))
         {
             theTelecom.value = a.Value;
         }
     }
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.