XmlNode
XmlNode represents a single node in the XML representation
of a Test or TestResult. It replaces System.Xml.XmlNode and
provides a minimal set of methods for operating on the XML
in a platform-independent manner.
using System;
using System.IO;
using System.Xml;
namespace NUnit.Framework.Interfaces
{
public class XmlNode
{
private class NodeFilter
{
private string nodeName;
private string propName;
private string propValue;
public NodeFilter(string xpath)
{
nodeName = xpath;
int num = xpath.IndexOf('[');
if (num >= 0) {
if (!xpath.EndsWith("]"))
throw new ArgumentException("Invalid property expression", "xpath");
nodeName = xpath.Substring(0, num);
string text = xpath.Substring(num + 1, xpath.Length - num - 2);
int num2 = text.IndexOf('=');
if (num2 < 0 || text[0] != '@')
throw new ArgumentException("Invalid property expression", "xpath");
propName = text.Substring(1, num2 - 1).Trim();
propValue = text.Substring(num2 + 1).Trim(' ', '"', '\'');
}
}
public bool Pass(XmlNode node)
{
if (node.Name != nodeName)
return false;
if (propName == null)
return true;
return node.Attributes[propName] == propValue;
}
}
private string name;
private AttributeDictionary attributes;
private NodeList childNodes;
private string textContent;
public string Name => name;
public string TextContent {
get {
return textContent;
}
set {
textContent = value;
}
}
public string EscapedTextContent => Escape(textContent);
public AttributeDictionary Attributes => attributes;
public NodeList ChildNodes => childNodes;
public XmlNode FirstChild {
get {
if (ChildNodes.Count <= 0)
return null;
return ChildNodes[0];
}
}
public string OuterXml {
get {
StringWriter stringWriter = new StringWriter();
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.ConformanceLevel = ConformanceLevel.Fragment;
using (XmlWriter writer = XmlWriter.Create(stringWriter, xmlWriterSettings))
WriteTo(writer);
return stringWriter.ToString();
}
}
public XmlNode(string name)
{
this.name = name;
attributes = new AttributeDictionary();
childNodes = new NodeList();
}
public static XmlNode CreateTopLevelElement(string name)
{
return new XmlNode(name);
}
public XmlNode AddElement(string name)
{
XmlNode xmlNode = new XmlNode(name);
ChildNodes.Add(xmlNode);
return xmlNode;
}
public void AddAttribute(string name, string value)
{
Attributes.Add(name, value);
}
public XmlNode FindDescendant(string xpath)
{
NodeList nodeList = FindDescendants(xpath);
if (nodeList.Count <= 0)
return null;
return nodeList[0];
}
public NodeList FindDescendants(string xpath)
{
NodeList nodeList = new NodeList();
nodeList.Add(this);
return ApplySelection(nodeList, xpath);
}
public void WriteTo(XmlWriter writer)
{
writer.WriteStartElement(Name);
foreach (string key in Attributes.Keys) {
writer.WriteAttributeString(key, Attributes[key]);
}
if (TextContent != null)
writer.WriteString(TextContent);
foreach (XmlNode childNode in ChildNodes) {
childNode.WriteTo(writer);
}
writer.WriteEndElement();
}
private static NodeList ApplySelection(NodeList nodeList, string xpath)
{
Guard.ArgumentNotNullOrEmpty(xpath, "xpath");
if (xpath[0] == '/')
throw new ArgumentException("XPath expressions starting with '/' are not supported", "xpath");
if (xpath.IndexOf("//") >= 0)
throw new ArgumentException("XPath expressions with '//' are not supported", "xpath");
string xpath2 = xpath;
string text = null;
int num = xpath.IndexOf('/');
if (num >= 0) {
xpath2 = xpath.Substring(0, num);
text = xpath.Substring(num + 1);
}
NodeList nodeList2 = new NodeList();
NodeFilter nodeFilter = new NodeFilter(xpath2);
foreach (XmlNode node in nodeList) {
foreach (XmlNode childNode in node.ChildNodes) {
if (nodeFilter.Pass(childNode))
nodeList2.Add(childNode);
}
}
if (text == null)
return nodeList2;
return ApplySelection(nodeList2, text);
}
private static string Escape(string original)
{
return original.Replace("&", "&").Replace("\"", """).Replace("'", "'")
.Replace("<", "<")
.Replace(">", ">");
}
}
}