Major upgrade
This commit is contained in:
237
Source/Program/Common/Lib/XmlDocumentWrapper.cs
Normal file
237
Source/Program/Common/Lib/XmlDocumentWrapper.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// UNCLASSIFIED
|
||||
/*-------------------------------------------------------------------------
|
||||
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||
COMPANY.
|
||||
|
||||
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||
GOVERNMENT.
|
||||
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace ProgramLib
|
||||
{
|
||||
/// <summary>
|
||||
/// A XML Wrapper class to create/modify XML files
|
||||
/// </summary>
|
||||
internal class XmlDocumentWrapper
|
||||
{
|
||||
public enum AddNodePosition
|
||||
{
|
||||
First,
|
||||
Last
|
||||
}
|
||||
|
||||
private XmlDocument _xmlDoc = null;
|
||||
private string _xmlFilePath = String.Empty;
|
||||
private object _syncObj = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="xmlFilePath">XML file path</param>
|
||||
/// <param name="rootNodeName">name of the root node.</param>
|
||||
public XmlDocumentWrapper(string xmlFilePath, string rootNodeName = "root")
|
||||
{
|
||||
_xmlFilePath = xmlFilePath;
|
||||
CreateXmlDocument(rootNodeName);
|
||||
|
||||
_xmlDoc = new XmlDocument();
|
||||
_xmlDoc.Load(xmlFilePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create XML document if it doesn't exist
|
||||
/// </summary>
|
||||
private void CreateXmlDocument(string rootNodeName)
|
||||
{
|
||||
if (!File.Exists(_xmlFilePath))
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
XmlElement root = doc.CreateElement(rootNodeName);
|
||||
doc.AppendChild(root);
|
||||
|
||||
using (TextWriter sw = new StreamWriter(_xmlFilePath, false, Encoding.UTF8))
|
||||
{
|
||||
doc.Save(sw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save XML document to file
|
||||
/// </summary>
|
||||
public void SaveToFile()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
using (TextWriter sw = new StreamWriter(_xmlFilePath, false, Encoding.UTF8))
|
||||
{
|
||||
_xmlDoc.Save(sw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a node defined by {path}
|
||||
/// </summary>
|
||||
/// <param name="path">example: /root/node1/node2</param>
|
||||
/// <param name="attributesDict">a dictionary of [name,value] pairs</param>
|
||||
/// <param name="innerText">text of the node</param>
|
||||
public void AddNode(string path, Dictionary<string, string> attributesDict = null, string innerText = null, AddNodePosition addNodePosition = AddNodePosition.Last)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
XmlElement elem = (XmlElement)MakeXPath(_xmlDoc, path, addNodePosition);
|
||||
|
||||
if (!String.IsNullOrEmpty(innerText))
|
||||
elem.InnerText = innerText;
|
||||
|
||||
if (attributesDict != null)
|
||||
{
|
||||
List<XmlAttribute> attributes = new List<XmlAttribute>();
|
||||
|
||||
foreach (KeyValuePair<string, string> item in attributesDict)
|
||||
{
|
||||
XmlAttribute attr = _xmlDoc.CreateAttribute(item.Key);
|
||||
attr.Value = item.Value;
|
||||
|
||||
attributes.Add(attr);
|
||||
}
|
||||
|
||||
SetAttrSafe(elem, attributes.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a node
|
||||
/// </summary>
|
||||
public void RemoveNode(XmlNode node)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
node.ParentNode.RemoveChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change attributes and/or inner text of an existing node
|
||||
/// </summary>
|
||||
public void ChangeNode(XmlNode node, Dictionary<string, string> attributesDict = null, string innerText = null)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(innerText))
|
||||
node.InnerText = innerText;
|
||||
|
||||
if (attributesDict != null)
|
||||
{
|
||||
List<XmlAttribute> attributes = new List<XmlAttribute>();
|
||||
|
||||
foreach (KeyValuePair<string, string> item in attributesDict)
|
||||
{
|
||||
XmlAttribute attr = _xmlDoc.CreateAttribute(item.Key);
|
||||
attr.Value = item.Value;
|
||||
|
||||
attributes.Add(attr);
|
||||
}
|
||||
|
||||
SetAttrSafe(node, attributes.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the first node in {path}
|
||||
/// Useful for iterating through the sibling nodes to find the node with a specific attribute so we can modify the node
|
||||
/// </summary>
|
||||
/// <param name="path">example: /root/node1/node2</param>
|
||||
public XmlNode GetNode(string path)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
return _xmlDoc.SelectSingleNode(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all the nodes matching the path
|
||||
/// Useful for iterating through the matched nodes
|
||||
/// </summary>
|
||||
/// <param name="path">example: /root/node1/node2</param>
|
||||
public XmlNodeList GetNodes(string path)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
return _xmlDoc.SelectNodes(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set attribute
|
||||
/// </summary>
|
||||
private void SetAttrSafe(XmlNode node, XmlAttribute[] attrList)
|
||||
{
|
||||
foreach (var attr in attrList)
|
||||
{
|
||||
if (node.Attributes[attr.Name] != null)
|
||||
{
|
||||
node.Attributes[attr.Name].Value = attr.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
node.Attributes.Append(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a node using {xpath}
|
||||
/// </summary>
|
||||
/// <param name="xpath">example: /root/node1/node2</param>
|
||||
private XmlNode MakeXPath(XmlDocument doc, string xpath, AddNodePosition addNodePosition)
|
||||
{
|
||||
return MakeXPath(doc, doc as XmlNode, xpath, addNodePosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterate through each node in {xpath} and create them
|
||||
/// </summary>
|
||||
private XmlNode MakeXPath(XmlDocument doc, XmlNode parent, string xpath, AddNodePosition addNodePosition)
|
||||
{
|
||||
// grab the next node name in the xpath; or return parent if empty
|
||||
string[] partsOfXPath = xpath.Trim('/').Split('/');
|
||||
string nextNodeInXPath = partsOfXPath.First();
|
||||
if (string.IsNullOrEmpty(nextNodeInXPath))
|
||||
return parent;
|
||||
|
||||
// get or create the node from the name
|
||||
XmlNode node = parent.SelectSingleNode(nextNodeInXPath);
|
||||
if (partsOfXPath.Length == 1)
|
||||
{
|
||||
if (addNodePosition == AddNodePosition.Last)
|
||||
node = parent.AppendChild(doc.CreateElement(nextNodeInXPath));
|
||||
else
|
||||
node = parent.PrependChild(doc.CreateElement(nextNodeInXPath));
|
||||
}
|
||||
|
||||
// rejoin the remainder of the array as an xpath expression and recurse
|
||||
string rest = String.Join("/", partsOfXPath.Skip(1).ToArray());
|
||||
return MakeXPath(doc, node, rest, addNodePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user