This is some XML I need to be able to read. I need to get the QualitySetting values for each Feature assigned to some variables:
<?xml version="1.0" encoding="UTF-8" ?>
<GraphicsConfig>
<FX>
<Off>
<LocalisationName>$QUALITY_OFF;</LocalisationName>
<Item>
<Feature>LightCones</Feature>
<QualitySetting>0</QualitySetting>
</Item>
<Item>
<Feature>LensFlares</Feature>
<QualitySetting>0</QualitySetting>
</Item>
<Item>
<Feature>Debris</Feature>
<QualitySetting>0</QualitySetting>
</Item>
<Item>
<Feature>ParticleEffects</Feature>
<QualitySetting>0</QualitySetting>
</Item>
<Item>
<Feature>Trails</Feature>
<QualitySetting>0</QualitySetting>
</Item>
<Item>
<Feature>Beams</Feature>
<QualitySetting>0</QualitySetting>
</Item>
<Item>
<Feature>Fog</Feature>
<QualitySetting>0</QualitySetting>
</Item>
</Off>
</FX>
</GraphicsConfig>
I am using XMLReader and I usually use something like:
Dim guiSettings = XElement.Load(_localAppDataFilePath & "\Frontier Developments\Elite Dangerous\Options\Graphics\GraphicsConfigurationOverride.xml")
target = guiSettings.Element("GUIColour").Elements("Default").[Single]()
r = target.Element("MatrixRed").Value
Open to doing this other ways, and if there is no easy way to do this, I am perfectly happy to just locate the <Feature>
element with the appropriate name and then simply just read the very next node, but thought I'd ask as I always want to improve my XML editing knowledge.
The code below uses a combination of XmlReader and XML Linq. I've posted this solution a lot of times. My preference in this case is not to use XmlReader instead use XML Linq to put results into a dictionary and posted that code as well. For huge XML files it is always best to use XmlReader to avoid out of memory error.
I posted solution in both c# and vb.net
Imports System.Xml
Imports System.Xml.Linq
Module Module1
Const FILENAME As String = "c:\temp\test.xml"
Sub Main()
Dim reader As XmlReader = XmlReader.Create(FILENAME)
Dim items As List(Of Item) = New List(Of Item)()
While (Not reader.EOF)
If reader.Name <> "item" Then
reader.ReadToFollowing("Item")
End If
If Not reader.EOF Then
Dim xItem As XElement = XElement.ReadFrom(reader)
Dim item As Item = New Item()
item.feature = xItem.Element("Feature")
item.setting = xItem.Element("QualitySetting")
items.Add(item)
End If
End While
'using a dictionary
Dim doc As XDocument = XDocument.Load(FILENAME)
Dim dict As Dictionary(Of String, String) = doc.Descendants("Item") _
.GroupBy(Function(x) x.Element("Feature").ToString(), Function(y) y.Element("QualitySetting").ToString()) _
.ToDictionary(Function(x) x.Key, Function(y) y.FirstOrDefault())
End Sub
End Module
Public Class Item
Public feature As String
Public setting As String
End Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
List<Item> items = new List<Item>();
while (!reader.EOF)
{
if(reader.Name != "item")
{
reader.ReadToFollowing("Item");
}
if (!reader.EOF)
{
XElement xItem = (XElement)XElement.ReadFrom(reader);
Item item = new Item() {
feature = (string)xItem.Element("Feature"),
setting = (string)xItem.Element("QualitySetting")
};
items.Add(item);
}
}
//using a dictionary
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, string> dict = doc.Descendants("Item")
.GroupBy(x => (string)x.Element("Feature"), y => (string)y.Element("QualitySetting"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
public class Item
{
public string feature { get; set; }
public string setting { get; set; }
}
}