Reputation: 1579
I have an XML string that looks like the following:
<?xml version="1.0" encoding="utf-8"?>
<Report>
<Version Name="2.0">
<Note>The meaning of life is 42.</Note>
<Note>Hitchiker's Guide to the Galaxy</Note>
</Version>
<Version Name="2.1">
<Note>Football is awesome!</Note>
<Note>Let's go sailing!</Note>
</Version>
</Report>
I'm trying to output the information for each version to my webpage. So far I'm able to get the version number but haven't been able to associate the note with the version number. Here's what I have:
var xml = Client.GetReleaseNotes();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var versions = Client.GetUniqueNames(doc.SelectNodes("//Version"));
versions.Reverse();
Where Client.GetReleaseNotes();
gives me my XML string to parse.
public List<string> GetUniqueNames(XmlNodeList nodes)
{
List<string> list = new List<string>();
foreach (XmlNode node in nodes)
{
var attr = node.Attributes["Name"] ?? node.Attributes["Title"];
string name = attr.InnerText;
if (!list.Contains(name) && name.IndexOf("sample", StringComparison.OrdinalIgnoreCase) == -1)
list.Add(name);
}
list.Sort();
return list;
}
public List<string> GetVersionNotes(XmlNodeList nodes)
{
List<string> list = new List<string>();
foreach (XmlNode node in nodes)
{
list.Add(node.Value);
}
list.Sort();
return list;
}
As you can see below I used a foreach loop to output the version number to the screen.
<section id="release-notes">
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<h2 class="section-heading">Release Notes</h2>
</div>
</div>
<div class="row">
@foreach (string version in versions)
{
<div class="col-md-4">
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="webHeading">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#webPanel" aria-expanded="true" aria-controls="webPanel">
Version @version
</a>
</h4>
</div>
<div id="webPanel" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="webHeading">
<ul class="list-group">
@{
var notes = Client.GetVersionNotes(doc.SelectNodes("//version[@value='" + version + "']/note"));
}
@foreach (string note in notes)
{
<li class="list-group-item">@note</li>
}
</ul>
</div>
</div>
</div>
</div>
}
</div>
</div>
</section>
I then proceeded to use another foreach loop and try and grab the child elements for each version. This way I could have a way to associate the notes with it's version. I read that you could use the SelectNodes method to get child nodes based on a specific criteria like the value of a parent node. That's what prompted me to create the line var notes = Client.GetVersionNotes(doc.SelectNodes("//version[@value='" + version + "']/note"));
However I'm still unable to get the notes. What am I doing wrong? Can someone please point me in the right direction?
Upvotes: 1
Views: 2397
Reputation: 117009
Another option you have is to use LINQ to XML.
Here's how:
var doc = XDocument.Parse(@"<?xml version=""1.0"" encoding=""utf - 8""?>
<Report>
<Version Name = ""2.0"">
<Note>The meaning of life is 42.</Note>
<Note>Hitchiker's Guide to the Galaxy</Note>
</Version>
<Version Name = ""2.1"">
<Note>Football is awesome!</Note>
<Note>Let's go sailing!</Note>
</Version>
</Report>");
var lookup =
doc
.Descendants("Note")
.ToLookup(
x => x.Parent.Attribute("Name").Value,
x => x.Value);
That gives you this lookup:
Then you can do this:
var notes = lookup["2.1"].ToList();
And that gives you:
Upvotes: 1
Reputation: 89285
Notice that element and attribute names in XPath are case-sensitive. Also, you have the wrong attribute name in your XPath (should've been @Name
instead of @value
). Try this way to get the corresponding Note
elements :
doc.SelectNodes("//Version[@Name='" + version + "']/Note")
Upvotes: 2