// Copyright (c) 2015, Yves Goergen, http://unclassified.software/source/easyxml
//
// Copying and distribution of this file, with or without modification, are permitted provided the
// copyright notice and this notice are preserved. This file is offered as-is, without any warranty.
using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
namespace Unclassified.Util
{
///
/// Provides easy read and write access to XML documents through XPath selectors.
///
public class EasyXml
{
#region Private data
///
/// Internal XML document that is acted upon.
///
private XmlDocument xd;
#endregion Private data
#region Constructors
///
/// Initialises a new instance of the EasyXml class and creates a new empty XML document.
///
public EasyXml()
{
xd = new XmlDocument();
}
///
/// Initialises a new instance of the EasyXml class and creates a new XML document from the specified content.
///
/// XML document string.
public EasyXml(string xml)
{
xd = new XmlDocument();
if (!string.IsNullOrWhiteSpace(xml))
{
xd.LoadXml(xml);
}
}
///
/// Initialises a new instance of the EasyXml class with the specified XML document.
///
/// XML document.
public EasyXml(XmlDocument xmlDocument)
{
xd = xmlDocument;
}
#endregion Constructors
#region Public properties
///
/// Gets or sets the current XML document as a formatted string.
///
public string Xml
{
get
{
using (MemoryStream ms = new MemoryStream())
{
XmlWriterSettings xws = new XmlWriterSettings();
xws.Encoding = Encoding.UTF8;
xws.Indent = true;
xws.IndentChars = " ";
XmlWriter xw = XmlWriter.Create(ms, xws);
xd.Save(xw);
// If the BOM is in the stream, skip it for the string output
int start = 0;
int count = (int)ms.Length;
byte[] bom = new byte[3];
ms.Seek(0, SeekOrigin.Begin);
ms.Read(bom, 0, 3);
if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF)
{
// Skip UTF-8 Byte Order Mark (BOM)
start = 3;
count -= start;
}
return Encoding.UTF8.GetString(ms.ToArray(), start, count);
}
}
set
{
xd.LoadXml(value);
}
}
///
/// Gets the current XML document as a formatted string without any declarative markup.
///
public string PlainXml
{
get
{
using (MemoryStream ms = new MemoryStream())
{
XmlWriterSettings xws = new XmlWriterSettings();
xws.Encoding = Encoding.GetEncoding(28605); // ISO-8859-15
xws.Indent = true;
xws.IndentChars = " ";
xws.OmitXmlDeclaration = true;
XmlWriter xw = XmlWriter.Create(ms, xws);
xd.Save(xw);
return Encoding.GetEncoding(28605).GetString(ms.ToArray()); // ISO-8859-15
}
}
}
///
/// Gets the internal XML document for direct access.
///
public XmlDocument XmlDocument
{
get
{
return xd;
}
}
#endregion Public properties
#region Document management methods
///
/// Creates a new document instance and clears all contents.
///
public void Clear()
{
xd = new XmlDocument();
}
///
/// Loads an XML file into this document.
///
/// XML file name.
public void Load(string fileName)
{
xd.Load(fileName);
}
#endregion Document management methods
#region Element read access methods
///
/// Determines whether an element or attribute specified by the XPath selector exists in the document.
///
/// XPath selector to check.
/// true if an element or attribute exists, false otherwise.
public bool Exists(string xPath)
{
return Exists(xd, xPath);
}
///
/// Determines whether an element or attribute specified by the XPath selector exists in the document.
///
/// XML node to start searching at.
/// XPath selector to check.
/// true if an element or attribute exists, false otherwise.
public bool Exists(XmlNode baseNode, string xPath)
{
return baseNode.SelectSingleNode(xPath) != null;
}
///
/// Reads a string value from a node.
///
/// XPath selector for the node.
/// Text contents or attribute value of the selected node.
public string ReadString(string xPath)
{
return ReadStringInternal(xd, xPath, true, null);
}
///
/// Reads a string value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Text contents or attribute value of the selected node.
public string ReadString(string xPath, string defaultValue)
{
return ReadStringInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a string value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Text contents or attribute value of the selected node.
public string ReadString(XmlNode baseNode, string xPath)
{
return ReadStringInternal(baseNode, xPath, true, null);
}
///
/// Reads a string value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Text contents or attribute value of the selected node.
public string ReadString(XmlNode baseNode, string xPath, string defaultValue)
{
return ReadStringInternal(baseNode, xPath, false, defaultValue);
}
///
/// Reads an int value from a node.
///
/// XPath selector for the node.
/// Int value of the selected node.
public int ReadInt(string xPath)
{
return (int)ReadIntInternal(xd, xPath, true, null);
}
///
/// Reads an int value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Int value of the selected node.
public int ReadInt(string xPath, int defaultValue)
{
return (int)ReadIntInternal(xd, xPath, false, defaultValue);
}
///
/// Reads an int value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Int value of the selected node.
public int? ReadInt(string xPath, int? defaultValue)
{
return ReadIntInternal(xd, xPath, false, defaultValue);
}
///
/// Reads an int value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Int value of the selected node.
public int ReadInt(XmlNode baseNode, string xPath)
{
return (int)ReadIntInternal(baseNode, xPath, true, null);
}
///
/// Reads an int value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Int value of the selected node.
public int ReadInt(XmlNode baseNode, string xPath, int defaultValue)
{
return (int)ReadIntInternal(baseNode, xPath, false, defaultValue);
}
///
/// Reads an int value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Int value of the selected node.
public int? ReadInt(XmlNode baseNode, string xPath, int? defaultValue)
{
return ReadIntInternal(baseNode, xPath, false, defaultValue);
}
///
/// Reads a decimal value from a node.
///
/// XPath selector for the node.
/// Decimal value of the selected node.
public decimal ReadDecimal(string xPath)
{
return (decimal)ReadDecimalInternal(xd, xPath, true, null);
}
///
/// Reads a decimal value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Decimal value of the selected node.
public decimal ReadDecimal(string xPath, decimal defaultValue)
{
return (decimal)ReadDecimalInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a decimal value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Decimal value of the selected node.
public decimal? ReadDecimal(string xPath, decimal? defaultValue)
{
return ReadDecimalInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a decimal value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Decimal value of the selected node.
public decimal ReadDecimal(XmlNode baseNode, string xPath)
{
return (decimal)ReadDecimalInternal(baseNode, xPath, true, null);
}
///
/// Reads a decimal value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Decimal value of the selected node.
public decimal ReadDecimal(XmlNode baseNode, string xPath, decimal defaultValue)
{
return (decimal)ReadDecimalInternal(baseNode, xPath, false, defaultValue);
}
///
/// Reads a decimal value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Decimal value of the selected node.
public decimal? ReadDecimal(XmlNode baseNode, string xPath, decimal? defaultValue)
{
return ReadDecimalInternal(baseNode, xPath, false, defaultValue);
}
///
/// Reads a bool value from a node.
///
/// XPath selector for the node.
/// Bool value of the selected node.
public bool ReadBool(string xPath)
{
return (bool)ReadBoolInternal(xd, xPath, true, null);
}
///
/// Reads a bool value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Bool value of the selected node.
public bool ReadBool(string xPath, bool defaultValue)
{
return (bool)ReadBoolInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a bool value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Bool value of the selected node.
public bool? ReadBool(string xPath, bool? defaultValue)
{
return ReadBoolInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a bool value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Bool value of the selected node.
public bool ReadBool(XmlNode baseNode, string xPath)
{
return (bool)ReadBoolInternal(baseNode, xPath, true, null);
}
///
/// Reads a bool value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Bool value of the selected node.
public bool ReadBool(XmlNode baseNode, string xPath, bool defaultValue)
{
return (bool)ReadBoolInternal(baseNode, xPath, false, defaultValue);
}
///
/// Reads a bool value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Bool value of the selected node.
public bool? ReadBool(XmlNode baseNode, string xPath, bool? defaultValue)
{
return ReadBoolInternal(baseNode, xPath, false, defaultValue);
}
///
/// Reads a DateTime value from a node.
///
/// XPath selector for the node.
/// DateTime value of the selected node.
public DateTime ReadDateTime(string xPath)
{
return (DateTime)ReadDateTimeInternal(xd, xPath, true, null);
}
///
/// Reads a DateTime value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// DateTime value of the selected node.
public DateTime ReadDateTime(string xPath, DateTime defaultValue)
{
return (DateTime)ReadDateTimeInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a DateTime value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// DateTime value of the selected node.
public DateTime? ReadDateTime(string xPath, DateTime? defaultValue)
{
return ReadDateTimeInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a DateTime value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// DateTime value of the selected node.
public DateTime ReadDateTime(XmlNode baseNode, string xPath)
{
return (DateTime)ReadDateTimeInternal(baseNode, xPath, true, null);
}
///
/// Reads a DateTime value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// DateTime value of the selected node.
public DateTime ReadDateTime(XmlNode baseNode, string xPath, DateTime defaultValue)
{
return (DateTime)ReadDateTimeInternal(baseNode, xPath, false, defaultValue);
}
///
/// Reads a DateTime value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// DateTime value of the selected node.
public DateTime? ReadDateTime(XmlNode baseNode, string xPath, DateTime? defaultValue)
{
return ReadDateTimeInternal(baseNode, xPath, false, defaultValue);
}
///
/// Reads a TimeSpan value from a node.
///
/// XPath selector for the node.
/// TimeSpan value of the selected node.
public TimeSpan ReadTimeSpan(string xPath)
{
return (TimeSpan)ReadTimeSpanInternal(xd, xPath, true, null);
}
///
/// Reads a TimeSpan value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// TimeSpan value of the selected node.
public TimeSpan ReadTimeSpan(string xPath, TimeSpan defaultValue)
{
return (TimeSpan)ReadTimeSpanInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a TimeSpan value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// TimeSpan value of the selected node.
public TimeSpan? ReadTimeSpan(string xPath, TimeSpan? defaultValue)
{
return ReadTimeSpanInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a TimeSpan value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// TimeSpan value of the selected node.
public TimeSpan ReadTimeSpan(XmlNode baseNode, string xPath)
{
return (TimeSpan)ReadTimeSpanInternal(baseNode, xPath, true, null);
}
///
/// Reads a TimeSpan value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// TimeSpan value of the selected node.
public TimeSpan ReadTimeSpan(XmlNode baseNode, string xPath, TimeSpan defaultValue)
{
return (TimeSpan)ReadTimeSpanInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a TimeSpan value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// TimeSpan value of the selected node.
public TimeSpan? ReadTimeSpan(XmlNode baseNode, string xPath, TimeSpan? defaultValue)
{
return ReadTimeSpanInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a Color value from a node.
///
/// XPath selector for the node.
/// Color value of the selected node.
public Color ReadColor(string xPath)
{
return (Color)ReadColorInternal(xd, xPath, true, null);
}
///
/// Reads a Color value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Color value of the selected node.
public Color ReadColor(string xPath, Color defaultValue)
{
return (Color)ReadColorInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a Color value from a node.
///
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Color value of the selected node.
public Color? ReadColor(string xPath, Color? defaultValue)
{
return ReadColorInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a Color value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Color value of the selected node.
public Color ReadColor(XmlNode baseNode, string xPath)
{
return (Color)ReadColorInternal(baseNode, xPath, true, null);
}
///
/// Reads a Color value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Color value of the selected node.
public Color ReadColor(XmlNode baseNode, string xPath, Color defaultValue)
{
return (Color)ReadColorInternal(xd, xPath, false, defaultValue);
}
///
/// Reads a Color value from a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// Value to be returned if the node does not exist.
/// Color value of the selected node.
public Color? ReadColor(XmlNode baseNode, string xPath, Color? defaultValue)
{
return ReadColorInternal(xd, xPath, false, defaultValue);
}
#endregion Element read access methods
#region Internal element read access methods
private string ReadStringInternal(XmlNode baseNode, string xPath, bool isRequired, string defaultValue)
{
XmlNode node = baseNode.SelectSingleNode(xPath);
XmlElement element = node as XmlElement;
if (element != null)
{
return element.InnerText;
}
XmlAttribute attribute = node as XmlAttribute;
if (attribute != null)
{
return attribute.Value;
}
if (!isRequired)
{
return defaultValue;
}
if (node != null)
{
throw new NotSupportedException("Unsupported node type selected.");
}
else
{
throw new EasyXmlNodeNotFoundException(xPath);
}
}
private int? ReadIntInternal(XmlNode baseNode, string xPath, bool isRequired, int? defaultValue)
{
string s = ReadStringInternal(baseNode, xPath, isRequired, null);
if (string.IsNullOrWhiteSpace(s) && !isRequired)
{
return defaultValue;
}
return int.Parse(s, CultureInfo.InvariantCulture);
}
private decimal? ReadDecimalInternal(XmlNode baseNode, string xPath, bool isRequired, decimal? defaultValue)
{
string s = ReadStringInternal(baseNode, xPath, isRequired, null);
if (string.IsNullOrWhiteSpace(s) && !isRequired)
{
return defaultValue;
}
return decimal.Parse(s, CultureInfo.InvariantCulture);
}
private bool? ReadBoolInternal(XmlNode baseNode, string xPath, bool isRequired, bool? defaultValue)
{
string s = ReadStringInternal(baseNode, xPath, isRequired, null);
if (string.IsNullOrWhiteSpace(s) && !isRequired)
{
return defaultValue;
}
if (!string.IsNullOrWhiteSpace(s))
{
// Word sources:
// http://smwbp.googlecode.com/svn/trunk/release/semediawiki-1.4.2/SemanticMediaWiki/languages/SMW_Messages.php
// http://search.cpan.org/~jmcnamara/Spreadsheet-WriteExcel-2.37/lib/Spreadsheet/WriteExcel/Examples.pm
// http://www.obout.com/t2/KnowledgeBase.aspx?id=308
// https://svn.typo3.org/TYPO3v4/Extensions/cal/tags/cal-1.3.0/controller/locallang.xml
string[] trueWords = new string[] {
"1",
"true", "yes", "on", // en
"wahr", "ja", // de
"verdadero", "si", // es
"tosi", "ei", // fi
"vrai", "oui", // fr
"igaz", // hu
"rétt", // is
"vero", "si", // it
"waar", "ja", // nl
"sant", "ja", // nn, no
"prawda", "tak", // pl
"verdadeiro", "sim", // pt
"истина", "да", // ru
"áno", // sk
"sant", "ja", // sv
"đúng", "có", // vi
"是", // zh-cn, zh-tw
};
string[] falseWords = new string[] {
"0",
"false", "no", "off", // en
"falsch", "nein", // de
"falso", "no", // es
"epätosi", "kyllä", // fi
"faux", "non", // fr
"hamis", // hu
"rangt", // is
"falso", "no", // it
"onwaar", "nee", // nl
"usant", "nei", // nn, no
"fałsz", "nie", // pl
"falso", "nao", "não", // pt
"ложь", "нет", // ru
"nie", // sk
"falskt", "nej", // sv
"sai", "không", // vi
"否", // zh-cn, zh-tw
};
s = s.Trim();
foreach (var word in trueWords)
{
if (s.Equals(word, StringComparison.InvariantCultureIgnoreCase))
return true;
}
foreach (var word in falseWords)
{
if (s.Equals(word, StringComparison.InvariantCultureIgnoreCase))
return false;
}
}
throw new FormatException();
}
private DateTime? ReadDateTimeInternal(XmlNode baseNode, string xPath, bool isRequired, DateTime? defaultValue)
{
string s = ReadStringInternal(baseNode, xPath, isRequired, null);
if (string.IsNullOrWhiteSpace(s) && !isRequired)
{
return defaultValue;
}
return DateTime.Parse(s, CultureInfo.InvariantCulture);
}
private TimeSpan? ReadTimeSpanInternal(XmlNode baseNode, string xPath, bool isRequired, TimeSpan? defaultValue)
{
string s = ReadStringInternal(baseNode, xPath, isRequired, null);
if (string.IsNullOrWhiteSpace(s) && !isRequired)
{
return defaultValue;
}
Match m = Regex.Match(s, "^P((?[0-9]+)D)?(T((?[0-9]+)H)?((?[0-9]+)M)?((?[0-9]+)S)?)?$");
if (m.Success)
{
int days = string.IsNullOrEmpty(m.Groups["D"].Value) ? 0 : int.Parse(m.Groups["D"].Value);
int hours = string.IsNullOrEmpty(m.Groups["H"].Value) ? 0 : int.Parse(m.Groups["H"].Value);
int mins = string.IsNullOrEmpty(m.Groups["M"].Value) ? 0 : int.Parse(m.Groups["M"].Value);
int secs = string.IsNullOrEmpty(m.Groups["S"].Value) ? 0 : int.Parse(m.Groups["S"].Value);
return TimeSpan.FromSeconds(days * 86400 + hours * 3600 + mins * 60 + secs);
}
throw new FormatException();
}
private Color? ReadColorInternal(XmlNode baseNode, string xPath, bool isRequired, Color? defaultValue)
{
string s = ReadStringInternal(baseNode, xPath, isRequired, null);
if (string.IsNullOrWhiteSpace(s) && !isRequired)
{
return defaultValue;
}
Match m = Regex.Match(s, "^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
if (m.Success)
{
int r = int.Parse(m.Groups[1].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
int g = int.Parse(m.Groups[2].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
int b = int.Parse(m.Groups[3].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
return Color.FromArgb(r, g, b);
}
throw new FormatException();
}
#endregion Internal element read access methods
#region Element write access methods
///
/// Creates a node.
///
/// XPath selector for the node.
/// The created or existing node.
public XmlNode Create(string xPath)
{
return Create(xd, xPath, false);
}
///
/// Creates a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// The created or existing node.
public XmlNode Create(XmlNode baseNode, string xPath)
{
return Create(baseNode, xPath, false);
}
///
/// Creates a new node.
///
/// XPath selector for the node.
/// The created node.
public XmlNode CreateNew(string xPath)
{
return Create(xd, xPath, true);
}
///
/// Creates a new node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// The created node.
public XmlNode CreateNew(XmlNode baseNode, string xPath)
{
return Create(baseNode, xPath, true);
}
///
/// Creates a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// true to always create a new node, false to return an existing node.
/// The created or existing node.
public XmlNode Create(XmlNode baseNode, string xPath, bool newNode)
{
// Idea (less strict parsing): xPath.Trim('/').Split('/')
if (!Regex.IsMatch(xPath, "^(/?[-._a-z0-9]+)(/[-._a-z0-9]+)*(/@[-._a-z0-9]+)?$", RegexOptions.IgnoreCase))
{
if (!Regex.IsMatch(xPath, "^@[-._a-z0-9]+$", RegexOptions.IgnoreCase))
{
throw new NotSupportedException("Unsupported XPath expression for creating an XML node.");
}
}
string[] elements = xPath.Split('/');
if (newNode && elements[elements.Length - 1][0] == '@')
{
throw new NotSupportedException("You cannot create a new node with an XPath expression for an XML attribute.");
}
XmlNode node = baseNode;
for (int i = 0; i < elements.Length; i++)
{
string element = elements[i];
if (element.Length == 0) continue;
XmlNode subNode = node.SelectSingleNode(element);
bool skip = newNode && i == elements.Length - 1; // Skip existing to create a new element
if (subNode != null && !skip)
{
node = subNode;
}
else
{
if (element[0] == '@')
{
string attribute = element.Substring(1);
subNode = xd.CreateAttribute(attribute);
node.Attributes.Append((XmlAttribute)subNode);
node = subNode;
}
else
{
subNode = xd.CreateElement(element);
node.AppendChild(subNode);
node = subNode;
}
}
}
return node;
}
///
/// Writes an int value to a node.
///
/// XPath selector for the node.
/// The int value to write.
public void Write(string xPath, int? value)
{
Write(xd, xPath, value);
}
///
/// Writes an int value to a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// The int value to write.
public void Write(XmlNode baseNode, string xPath, int? value)
{
if (value != null)
{
Write(baseNode, xPath, ((int)value).ToString(CultureInfo.InvariantCulture));
}
else
{
Write(baseNode, xPath, "");
}
}
///
/// Writes a decimal value to a node.
///
/// XPath selector for the node.
/// The decimal value to write.
public void Write(string xPath, decimal? value)
{
Write(xd, xPath, value);
}
///
/// Writes a decimal value to a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// The decimal value to write.
public void Write(XmlNode baseNode, string xPath, decimal? value)
{
if (value != null)
{
Write(baseNode, xPath, ((decimal)value).ToString(CultureInfo.InvariantCulture));
}
else
{
Write(baseNode, xPath, "");
}
}
///
/// Writes a bool value to a node.
///
/// XPath selector for the node.
/// The bool value to write.
public void Write(string xPath, bool? value)
{
Write(xd, xPath, value);
}
///
/// Writes a bool value to a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// The bool value to write.
public void Write(XmlNode baseNode, string xPath, bool? value)
{
if (value != null)
{
Write(baseNode, xPath, value == true ? "true" : "false");
}
else
{
Write(baseNode, xPath, "");
}
}
///
/// Writes a DateTime value to a node.
///
/// XPath selector for the node.
/// The DateTime value to write.
public void Write(string xPath, DateTime? value)
{
Write(xd, xPath, value);
}
///
/// Writes a DateTime value to a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// The DateTime value to write.
public void Write(XmlNode baseNode, string xPath, DateTime? value)
{
if (value != null)
{
Write(baseNode, xPath, ((DateTime)value).ToString("s"));
}
else
{
Write(baseNode, xPath, "");
}
}
///
/// Writes a TimeSpan value to a node.
///
/// XPath selector for the node.
/// The TimeSpan value to write.
public void Write(string xPath, TimeSpan? value)
{
Write(xd, xPath, value);
}
///
/// Writes a TimeSpan value to a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// The TimeSpan value to write.
public void Write(XmlNode baseNode, string xPath, TimeSpan? value)
{
if (value != null)
{
TimeSpan t = (TimeSpan)value;
string s = "P";
if (t.Days > 0) s += t.Days + "D";
if (t.Hours > 0 || t.Minutes > 0 || t.Seconds > 0) s += "T";
if (t.Hours > 0) s += t.Hours + "H";
if (t.Minutes > 0) s += t.Minutes + "M";
if (t.Seconds > 0) s += t.Seconds + "S";
if (s == "P") s = "PT0S";
Write(baseNode, xPath, s);
}
else
{
Write(baseNode, xPath, "");
}
}
///
/// Writes a Color value to a node.
///
/// XPath selector for the node.
/// The Color value to write.
public void Write(string xPath, Color? value)
{
Write(xd, xPath, value);
}
///
/// Writes a Color value to a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// The Color value to write.
public void Write(XmlNode baseNode, string xPath, Color? value)
{
if (value != null)
{
Color c = (Color)value;
Write(baseNode, xPath, "#" + c.R.ToString("x2") + c.G.ToString("x2") + c.B.ToString("x2"));
}
else
{
Write(baseNode, xPath, "");
}
}
///
/// Writes a string value to a node.
///
/// XPath selector for the node.
/// The string value to write.
public void Write(string xPath, string value)
{
Write(xd, xPath, value);
}
///
/// Writes a string value to a node.
///
/// Base node for the XPath selector.
/// XPath selector for the node.
/// The string value to write.
public void Write(XmlNode baseNode, string xPath, string value)
{
XmlNode node = baseNode.SelectSingleNode(xPath);
if (node == null)
{
node = Create(baseNode, xPath);
}
XmlElement element = node as XmlElement;
if (element != null)
{
element.InnerText = value;
return;
}
XmlAttribute attribute = node as XmlAttribute;
if (attribute != null)
{
attribute.Value = value;
return;
}
throw new NotSupportedException("Unsupported node type selected.");
}
#endregion Element write access methods
}
///
/// The exception that is thrown when an XML node is not found.
///
public class EasyXmlNodeNotFoundException : Exception
{
///
/// Gets the XPath selector of the node that was not found.
///
public string XPath { get; private set; }
///
/// Initialises a new instance of the EasyXmlNodeNotFoundException class.
///
/// The XPath selector of the node that was not found.
public EasyXmlNodeNotFoundException(string xPath)
{
XPath = xPath;
}
}
}