Reputation: 173
I need some help with some LINQ to XML. I've the below XML;
<GcctTestData>
<TestDriveRequest Record="1">
<element name="Time Zone">(GMT+05:30)</element>
<element name="Requested Dealer">Concorde</element>
<element name="Model Year">1999</element>
<element name="Make">Tata</element>
<element name="Model/Vehicle Line">Indica</element>
</TestDriveRequest>
<TestDriveRequest Record="2">
<element name="Time Zone">(GMT+05:30)</element>
<element name="Requested Dealer">Kun"</element>
<element name="Model Year">2020"</element>
<element name="Make">BMW"</element>
<element name="Model/Vehicle Line">3-series</element>
</TestDriveRequest>
<TestDriveRequest Record="3">
<element name="Time Zone">(GMT+05:30)</element>
<element name="Requested Dealer">KUN Hyundai</element>
<element name="Model Year">2001</element>
<element name="Make">Hyundai</element>
<element name="Model/Vehicle Line">Verna</element>
</TestDriveRequest>
</GcctTestData>
I tried it like below:
IEnumerable<XElement> xElements =
from element in root.Elements("TestDriveRequest")
where element.Attribute("Record").Value == "1"
select element;
foreach (XElement el in xElements.Descendants().Where(p => !p.HasElements))
{
int keyInt = 0;
string keyName = el.Attribute("name").Value;
while (keyValuePairs.ContainsKey(keyName))
{
keyName = $"{el.Attribute("name").Value}_{keyInt++}";
}
keyValuePairs.Add(keyName, el.Value);
}
I'll have to get the element name attribute value of the element for that parent which have the record value 1
but the linq query is not fetching it...
After implementing the suggestion of @anu-viswan I face the below problem
Upvotes: 2
Views: 1499
Reputation: 18163
You need to use root.Descendants
instead of root.Elements
.
For example,
IEnumerable<XElement> xElements = from element in root.Descendants("TestDriveRequest")
where element.Attribute("Record").Value == "1"
select element;
XContainer.Elements
Returns a filtered collection of the child elements of this element or document, in document order. Only elements that have a matching XName are included in the collection.
XContainer.Descendants
Returns a filtered collection of the descendant elements for this document or element, in document order. Only elements that have a matching XName are included in the collection Output
Complete Code
IEnumerable<XElement> xElements = from element in root.Descendants("TestDriveRequest")
where element.Attribute("Record").Value == "1"
select element;
foreach (XElement el in xElements.Descendants().Where(p => !p.HasElements))
{
int keyInt = 0;
string keyName = el.Attribute("name").Value;
while (keyValuePairs.ContainsKey(keyName))
{
keyName = $"{el.Attribute("name").Value}_{keyInt++}";
}
keyValuePairs.Add(keyName, el.Value);
}
Sample Output
Upvotes: 2
Reputation: 34421
This is how I would create the dictionary :
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace AscendingSequences
{
class AscendingSequences
{
const string FILENAME = @"c:\temp\test.xml";
public static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Dictionary<int, Dictionary<string, string>> dict = doc.Descendants("TestDriveRequest")
.GroupBy(x => (int)x.Attribute("Record"), y => y.Elements("element")
.GroupBy(a => (string)a.Attribute("name"), b => (string)b)
.ToDictionary(a => a.Key, b => b.FirstOrDefault()))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
Upvotes: 0