My intention is to iterate through my lovely dictionary (both key and value are strings) and create an xml file from it.
I get the error on the last line (saving the xml).
"InvalidOperationException was unhandled Token EndDocument in state Document would result in an invalid XML document."
Looking through this using breakpoints it would seem that at reaching the end of this, only the initial bit (outside the for each loop) has been done..
I'm half asking what silly mistake I've made, I'm partly asking if there's a more eloquent way of doing this.
Sorry if I've missed anything, let me know if i have, will add.
XDocument xData = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"));
foreach (KeyValuePair<string, string> kvp in inputDictionary)
{
xData.Element(valuesName).Add(
new XElement(valuesName,
new XAttribute("key", kvp.Key),
new XAttribute("value", kvp.Value)));
}
xData.Save("C:\\xData.xml");
Currently you're adding multiple elements directly to the document - so you'd end up with either no root elements (if the dictionary is empty) or potentially multiple root elements (if there's more than one entry in the dictionary). You want a root element, and then your dictionary elements under that. Additionally, you're trying to find an element called valuesName
without ever adding anything, so you'll actually get a NullReferenceException
if there are any dictionary entries.
Fortunately, it's even easier than you've made it, because you can just use LINQ to transform your dictionary into a sequence of elements and put that in the doc.
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("root",
inputDictionary.Select(kvp => new XElement(valuesName,
new XAttribute("key", kvp.Key),
new XAttribute("value", kvp.Value)))));
doc.Save(@"c:\data.xml");
Complete sample app:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
class Test
{
static void Main()
{
XName valuesName = "entry";
var dictionary = new Dictionary<string, string>
{
{ "A", "B" },
{ "Foo", "Bar" }
};
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("root",
dictionary.Select(kvp => new XElement(valuesName,
new XAttribute("key", kvp.Key),
new XAttribute("value", kvp.Value)))));
doc.Save("test.xml");
}
}
Output (order of entries is not guaranteed):
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root>
<entry key="A" value="B" />
<entry key="Foo" value="Bar" />
</root>
An alternative breakdown for this would be:
var elements = inputDictionary.Select(kvp => new XElement(valuesName,
new XAttribute("key", kvp.Key),
new XAttribute("value", kvp.Value)));
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("root", elements));
You may find this simpler to read.
See more on this question at Stackoverflow