views:

299

answers:

1

Given the following XML 'template':

<Request module="CRM" call="list_service_features" id="{ID}">
  <block name="auth">
     <a name="username" format="text">{USERNAME}</a>
     <a name="password" format="password">{PASSWORD}</a>
     <a name="client-id" format="counting">{CLIENT-ID}</a>
  </block>
  <a name="service-id" format="counting">{SERVICE-ID}</a>
</Request>

Using XDocument, what's the best way to set the values in curly braces. I got so far but got stuck on the best way to select each of the three <a /> nodes inside the <block/> element. This is just a small fragment of XML, others may have up to 20 <a name="..."></a> elements.

Thanks
Kevin

ps: the way the XML is constructed wasn't my creation, it's what we have to sent to our supplier's 'web service'...before anyone has a laugh at the format="counting" attribute :)

@David - cheers for the response, appreciated. I was kinda hoping it'd be a bit more elegant, kinda along the lines of:

List<XElement> e = doc.Descendants("a").ToList();
e.Where(x => x.Attributes("name") == "username").Single().Value = "abc";
e.Where(x => x.Attributes("name") == "password").Single().Value = "abc";

Clearly the code above doesn't work but I thought there would be an elegant one liner for each of the <a> tags

+1  A: 

Does this do it for you? Good old Descendants property.

string xmlInput = ...;
XDocument myDoc = XDocument.Parse(xmlInput);
//
List<XElement> someElements = myDoc.Descendants("a").ToList();
someElements.ForEach(x => x.Value = "Foo");
//
Console.WriteLine(myDoc);

Hmm, I see you have an attribute in there. Can do that too:

string xmlInput = //...
XDocument myDoc = XDocument.Parse(xmlInput);
//
List<XText> someText =
  myDoc.Descendants()
  .Nodes()
  .OfType<XText>()
  .Where(x => x.Value.StartsWith("{") && x.Value.EndsWith("}"))
  .ToList();
//
List<XAttribute> someAttributes =
  myDoc.Descendants()
  .Attributes()
  .Where(x => x.Value.StartsWith("{") && x.Value.EndsWith("}"))
  .ToList();
//
someText.ForEach(x => x.Value = "Foo");
someAttributes.ForEach(x => x.Value = "Bar");
//
Console.WriteLine(myDoc);

Ah, now with what you're expecting, I will make it work:

List<XElement> e = myDoc.Descendants("a").ToList();
e.Where(x => x.Attribute("name").Value == "username").Single().Value = "abc";
e.Where(x => x.Attribute("name").Value == "password").Single().Value = "abc";
David B
Yep that's what I'm looking for. I arrived at something similar but more clunky: e.Attributes("name").Where(a => a.Value == "username").Single().Parent.Value = "abcdef"; Much appreciated!
Kev
Nothing clunky there. Looks good.
David B