Reputation: 71
I am new to XML. I need to parse this XML and read the values from the -Field- element and -name- attribute.
I need values from accountID, deviceID, odometerKM
Here is the XML:
<GTSResponse command="dbget" result="success">
<Record table="EventDataView" partial="true">
<Field name="accountID" primaryKey="true" alternateKeys="adtkey,driverkey">
<![CDATA[salesdemo]]>
</Field>
<Field name="deviceID" primaryKey="true" alternateKeys="adtkey">
<![CDATA[bubba_polaris]]>
</Field>
<Field name="timestamp" primaryKey="true" alternateKeys="adtkey,driverkey">1605919705</Field>
<Field name="statusCode" primaryKey="true">0xF010</Field>
<Field name="latitude">0.0</Field>
<Field name="longitude">0.0</Field>
<Field name="odometerKM">0.2566422</Field>
<Field name="odometerOffsetKM">0.0</Field>
</Record>
<Record table="EventDataView" partial="true">
<Field name="accountID" primaryKey="true" alternateKeys="adtkey,driverkey">
<![CDATA[salesdemo]]>
</Field>
<Field name="deviceID" primaryKey="true" alternateKeys="adtkey">
<![CDATA[bubba_polaris]]>
</Field>
<Field name="timestamp" primaryKey="true" alternateKeys="adtkey,driverkey">1605919705</Field>
<Field name="statusCode" primaryKey="true">0xF010</Field>
<Field name="latitude">0.0</Field>
<Field name="longitude">0.0</Field>
<Field name="odometerKM">0.23445323</Field>
<Field name="odometerOffsetKM">0.0</Field>
</Record>
</GTSResponse>
Here is the code I have tried:
XDocument doc = XDocument.Parse(receivedResponse);
Dictionary<string, string> dataDictionary = new Dictionary<string, string>();
foreach (XElement element in doc.Descendants().Where(p => p.HasElements == false))
{
int keyInt = 0;
string keyName = element.Name.LocalName;
while (dataDictionary.ContainsKey(keyName))
{
keyName = element.Name.Namespace.ToString();
keyName = element.Name.LocalName + "_" + keyInt++;
}
dataDictionary.Add(keyName, element.Value);
}
foreach (var x in dataDictionary)
{
Console.WriteLine("keyName: " + x.Key + " value: " + x.Value);
}
When I run this, it loops through all of the -Field- elements but it does not use the -name-. I need to see the -name- so I know what value I have. I will be updating my database and need to loop through and update fields accordingly by name.
Upvotes: 1
Views: 3027
Reputation: 117175
There's a Record
element that you didn't navigate through.
Try this:
var values =
doc
.Root
.Elements("Record")
.SelectMany((x, n) => x.Elements("Field").Select(y => new { field = y, index = n }))
.ToDictionary(
x => $"{(string)x.field.Attribute("name")}_{x.index}",
x => (string)x.field);
I get this from your sample data:
I think you're better off with this:
Dictionary<int, Dictionary<string, string>> values =
doc
.Root
.Elements("Record")
.Select((x, n) => (x, n))
.ToDictionary(
y => y.n,
y => y.x
.Elements("Field")
.ToDictionary(
z => (string)z.Attribute("name"),
z => (string)z));
Then you get:
Upvotes: 1
Reputation: 34433
Try following :
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
string receivedResponse = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(receivedResponse);
Dictionary<string, Dictionary<string, List<Field>>> dataDictionary = doc.Descendants("Record")
.GroupBy(x => (string)x.Attribute("table"), y => y)
.ToDictionary(x => x.Key, y => y.Elements("Field")
.GroupBy(a => (string)a.Attribute("name"), b => new Field(b))
.ToDictionary(a => a.Key, b => b.ToList()));
}
}
public class Field
{
public string name { get; set; }
public Boolean? primaryKey { get; set; }
public string alternateKeys { get; set; }
public string text { get; set; }
public Field(XElement field)
{
name = (string)field.Attribute("Field");
primaryKey = (field.Attribute("primaryKey") == null) ? null : (Boolean?)field.Attribute("primaryKey");
alternateKeys = (field.Attribute("alternateKeys") == null) ? null : (string)field.Attribute("alternateKeys");
text = (string)field;
}
}
}
Upvotes: 0