0

I am creating a configuration file editor, and am currently implementing features for updating existing data. I would like to be able to update all attributes within the file which have a specific attribute, such as updating a user name.

My XML file represents users in the following manner:

<user user="user1" ... />
<user user="user2" ... />

My present attempt looks like this:

 xdoc.Descendants().Where(a => a.Attribute("user").Value == UserEditInput).FirstOrDefault().SetAttributeValue("user", NewUser);

where UserEditInput is the name of the current user name and NewUser is the new replacement value.

This throws a NullReferenceException. There are a number of "user" XAttributes in the form shown above with a value equal to that of UserEditInput. This leads me to believe I am not referencing the desired data in the correct manner, not modifying the attributes correctly, or both.

Thank you in advance for any assistance.

ocuenca
  • 38,548
  • 11
  • 89
  • 102
Tim B
  • 23
  • 6

1 Answers1

1

Currently you're trying to fetch the value for the user attribute of every element in the document - including the root element, for example.

Two options here, which I'd probably use both of:

  • Specify that you only want user elements, using xdoc.Descendants("user")
  • Use a cast of XAttribute to string instead of the Value property; that way if there's no such attribute, the cast will return null as well

Additionally, if you don't find the matching element, you're using FirstOrDefault so you'll get a value of null - but you try to set the attribute value anyway. Don't do that.

So, putting it all together - and taking a short cut by using the overload of FirstOrDefault with a predicate:

var element = xdoc.Descendants("user")
                  .FirstOrDefault(a => (string) a.Attribute("user") == UserEditInput);

if (element != null)
{
    element.SetAttributeValue("user", NewUser);
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks for the quick response. The above code works well for editing the user names within a specific section. How would I adapt the code to amend all attributes with the value of UserEditInput throughout the file? Using my previous (and only) idea of xdoc.Descendants() doesn't work. – Tim B Apr 27 '16 at 21:35
  • You can get a list of `element`s (`Where(a => (string) a.Attribute("user") == UserEditInput)`) instead get only the first (`FirstOrDefault(a => (string) a.Attribute("user") == UserEditInput)`) and iterate in it, updating each element with `SetAttributeValue` method ( `foreach(var element in query){ element.SetAttributeValue("user", NewUser);}`) – Uilque Messias Apr 27 '16 at 21:42
  • @TimB: You'd use a `foreach` loop, basically. But that's a different question, and should be asked in a different post, after research and trying things. – Jon Skeet Apr 27 '16 at 21:45
  • I have accepted the answer given as it answered the question actually posed (rather than what I was meaning to ask! The fault was mine). Thank you all for your assistance. – Tim B May 02 '16 at 00:28