I've developed code like this:
String resultString = await response.Content.ReadAsStringAsync();
Stream resultStream = await response.Content.ReadAsStreamAsync();
XElement rootElement = XDocument.Load(resultStream).Elements().First();
XElement blobs = rootElement.Element("Blobs");
foreach (var blob in blobs.Elements("Blob"))
{
var t = blob;
}
Now the resultString
and resultStream
come from HttpClient reposnse
. I get the response from an Azure blob REST service (listing), like this:
<EnumerationResults>
<Blobs>
<Blob>
<Name></Name>
<Url></Url>
<Properties></Properties>
</Blob>
<Blob>
<Name></Name>
<Url></Url>
<Properties></Properties>
</Blob>
</Blobs>
</EnumerationResults>
With my code, I've managed to get an IEnumerable<XNode>
from <Blobs>
BUT I can't get to Name
and Url
inside the <Blob>
element. I get all of it as a string in one line. How do I need to change my code to get each <Blob>
and get from it <Name>
and <Url>
?
Well to start with, once you've loaded the document, you can just use the Root
property to get at the root element. You can then get each Blob
element using Descendants
or via multiple calls to Elements
. You can do that outside the foreach
loop though:
var doc = XDocument.Load(resultStream);
var allBlobs = doc.Root.Elements("Blobs").Elements("Blob");
or var doc = XDocument.Load(resultStream); var allBlobs = doc.Root.Descendants("Blob");
Now when you iterate over each blob, you can just get the name element using Element
again, and get the text content of the element by using the explicit string conversion
foreach (var blob in allBlobs)
{
var nameElement = blob.Element("Name");
var nameText = (string) nameElement;
...
}
Obviously that can be done as a single statement - I just wanted to keep them separate for clarity. You can then do the same for the URL. Using the string conversion gives you a null
reference if the element is missing, whereas using the Value
property will give you a NullReferenceException
unless you guard against it. Which is more appropriate depends on your use case.
An alternative approach is to do all the extraction outside your foreach
loop, in a query:
var data = doc.Root.Elements("Blobs").Elements("Blob")
.Select(blob => new {
Name = (string) blob.Element("Name"),
Url = (string) blob.Element("Url");
});
Then:
foreach (var item in data)
{
// Use item.Name and item.Data in here
}