Joel Joel - 1 month ago 15
C# Question

select all xml nodes which contain a certain attribute

I have to select all nodes which contain an attribute with a certain name.

This is my current, not working approach.

public List<string> RetrieveValuesForAttribute(string attributeName)
{
var list = new List<string>();

string xpath = "//*[@Name='" + attributeName + "']";
XmlNodeList xmlNodeList = document.SelectNodes(xpath);

foreach (XmlNode xmlNode in xmlNodeList)
{
list.Add(xmlNode.Attributes[attributeName].InnerText);
}

return list;
}


I try to select all nodes which contain the attribute with the name given in the method parameter
attributeName
and add the value the variable
list
.

Example:

This method call:

List<string> result = RetrieveValuesForAttribute("itemSelectedHandler");


Should return an list which contains the string "OnSelectedRelatedContactChanged"

This is the xml file:

<GroupBoxWrapper id="gbRelatedContacts" text="Related Contacts">
<TabIndex>0</TabIndex>
<TabStop>false</TabStop>
<PanelWrapper id="pnlRelatedContactsView" width="1350">
<TabIndex>0</TabIndex>
<TabStop>false</TabStop>
<ListViewWrapper id="lvRelatedContacts" itemSelectedHandler="OnSelectedRelatedContactChanged" itemDoubleClickHandler="OnRelatedContactDoubleClick">
<TabIndex>0</TabIndex>
<TabStop>true</TabStop>
<ListViewColumns>
<Column title="Name" mapNode="Contact\Name" />
<Column title="Lastname" mapNode="Contact\Lastname" />
</ListViewColumns>
</ListViewWrapper>
</PanelWrapper>
</GroupBoxWrapper>


Further questions:
Would it be better to solve this with LINQ?

Solution 1: thank you, ywm

public List<string> RetrieveValuesForAttribute(string attributeName)
{
var list = new List<string>();

string xpath = @"//*[@" + attributeName + "]";
XmlNodeList xmlNodeList = document.SelectNodes(xpath);

foreach (XmlNode xmlNode in xmlNodeList)
{
list.Add(xmlNode.Attributes[attributeName].InnerText);
}

return list;
}


Solution 2: thank you, Jon Skeet

public List<string> RetrieveValuesForAttribute(string attributeName)
{
//document is an XDocument
return document.Descendants()
.Attributes(attributeName)
.Select(x => x.Value)
.ToList();
}


The LINQ to XML Solution looks far more elegant to me.

Answer Source

If you could use LINQ to XML for this, it would be utterly trivial:

// Note that there's an implicit conversion from string to XName,
// but this would let you specify a namespaced version if you want.
public List<string> RetrieveValuesForAttribute(XName attributeName)
{
    // Assume document is an XDocument
    return document.Descendants()
                   .Attributes(attributeName)
                   .Select(x => x.Value)
                   .ToList();
}