Xml Patterns
XLinq
private static Dictionary<string, string> ReadWithXLinq(string path)
{
XNamespace ns = "randomURI"; //define the namespace
var doc = XElement.Load(path); //don't need an XDocument
//Xname = "randomURI"+"data" or "(randomURI)data"
var dict = from data in doc.Elements(ns + "data")
select new {
Name = data.Attribute("name").Value ,
//casting does not throw NullReference
Value = (string)data.Element(ns+"value")
};
return dict.ToDictionary(d => d.Name, d => d.Value );
}
private static void SaveWithXLinq(Dictionary<string, string> dict, string path)
{
XNamespace ns = "randomURI"; //define the namespace
var doc = new XElement(ns + "root",
from d in dict
select new XElement(ns + "data",
new XAttribute("name", d.Key),
new XElement(ns + "value", d.Value)
));
doc.Save(path);
}
XmlDocument
private static Dictionary<string, string> ReadWithDocument(string path)
{
Dictionary<string, string> dict = new Dictionary<string, string>();
XmlDocument doc = new XmlDocument();
doc.Load(path);
//document has a default namespace <root xmlns="randomURI">
XmlNamespaceManager nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace("b", "randomURI"); //prefix all elements
XmlNodeList dataList = doc.SelectNodes("/b:root/b:data", nsm);
foreach (XmlElement data in dataList)
{
string name = data.GetAttribute("name");
XmlElement value = data.SelectSingleNode("b:value", nsm) as XmlElement;
if (value != null)
{
string val = value.InnerText;
dict.Add(name, val);
}
}
return dict;
}
private static void SaveWithDocument(Dictionary<string, string> dict, string path)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml("<root xmlns=\"randomURI\"/>"); //we have to load the namespace in
//doc.DocumentElement.Prefix = "b"; //if rqd
//document has a default namespace <root xmlns="randomURI">
string nsURI = "randomURI";
foreach (KeyValuePair<string, string> kvp in dict)
{
XmlElement data = doc.CreateElement("data", nsURI); //factory
doc.DocumentElement.AppendChild(data);
data.SetAttribute("name", kvp.Key);
XmlElement value = doc.CreateElement("value", nsURI);
data.AppendChild(value);
value.InnerText = kvp.Value;
}
doc.Save(path);
}
XmlReader/Writer
private static Dictionary<string, string> ReadWithReader(string path)
{
Dictionary<string, string> dict = new Dictionary<string, string>();
XmlReaderSettings settings = new XmlReaderSettings();
NameTable nt = new NameTable();
object dataNT = nt.Add("data"); //optimize comparisons with NT objects instead of string
settings.NameTable = nt;
using (XmlReader rdr = XmlReader.Create(path, settings))
{
while (rdr.Read())
{
if (rdr.NodeType == XmlNodeType.Element && rdr.LocalName.Equals(dataNT)) //NamteTable object
{ //you could jump to the next sibling (skipping childnodes) with ReadToNextSibling
string name = rdr.GetAttribute("name");
if (rdr.ReadToDescendant("value"))
{
string val = rdr.ReadElementContentAsString();
dict.Add(name, val);
}
}
}
}
return dict;
}
private static void SaveWithWriter(Dictionary<string, string> dict, string path)
{
string nsURI = "randomURI";
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
using (XmlWriter writer = XmlWriter.Create(path, settings))
{
writer.WriteStartDocument(); //xml declaration
writer.WriteStartElement("root", nsURI); //automatically add xmlns without prefix
//writer.WriteAttributeString("xmlns", "x", null, "randomURI2"); how to add a prefix namespace
foreach (KeyValuePair<string, string> kvp in dict)
{
writer.WriteStartElement("data", nsURI);
writer.WriteAttributeString("name", "", kvp.Key);
//writer.WriteAttributeString("x", "nspaced", "randomURI2", "value"); //adding the prefx
writer.WriteStartElement("value", nsURI);
writer.WriteValue(kvp.Value);
writer.WriteEndElement();
writer.WriteEndElement();
}
writer.WriteEndElement();
}
}
XPathDocument
private static Dictionary<string, string> ReadWithXPath(string path)
{
Dictionary<string, string> dict = new Dictionary<string, string>();
XPathDocument doc = new XPathDocument(path); //Load
XPathNavigator nav = doc.CreateNavigator();
//for the namespace we reference the navigator
XmlNamespaceManager nsm = new XmlNamespaceManager(nav.NameTable);
nsm.AddNamespace("b", "randomURI"); //prefix all elements
XPathNodeIterator iter = nav.Select("b:root/b:data", nsm); //SelectNodes
XPathExpression findValue = nav.Compile("b:value"); //optimize
findValue.SetContext(nsm);
while (iter.MoveNext())
{
XPathNavigator dataNav = iter.Current;
string name = dataNav.GetAttribute("name", ""); //namespace is rqd
XPathNavigator value = dataNav.SelectSingleNode(findValue);
//you can also XmlReader rdr = dataNav.ReadSubtree();
if (value != null)
dict.Add(name, value.Value);
}
return dict;
}
private static void SaveWithXPath(Dictionary<string, string> dict, string path)
{
string nsURI = "randomURI";
XmlDocument doc = new XmlDocument(); //need a document as XPathDocument is readonly
doc.LoadXml("<root xmlns=\"randomURI\"/>"); //we have to load the namespace in
XPathNavigator nav = doc.CreateNavigator(); //the navigator has CanEdit= true
nav.MoveToRoot();
nav.MoveToFirstChild(); //=/document element
foreach (KeyValuePair<string, string> kvp in dict)
{
XmlWriter writer = nav.AppendChild(); //use a writer
writer.WriteStartElement("data", nsURI);
writer.WriteAttributeString("name", kvp.Key);
writer.WriteStartElement("value", nsURI);
writer.WriteValue(kvp.Value);
writer.WriteEndElement();
writer.Close();
System.Diagnostics.Debug.WriteLine(nav.OuterXml);
}
doc.Save(path);
}