/Utilities/Xml/XmlNode.cs
# · C# · 1728 lines · 970 code · 156 blank · 602 comment · 73 complexity · 94db6e76e327e360636061ae7e6678ca MD5 · raw file
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.IO;
- using System.Text;
- using System.Xml.Linq;
- using Delta.Utilities.Helpers;
- using NUnit.Framework;
-
- namespace Delta.Utilities.Xml
- {
- /// <summary>
- /// Our own XmlNode format which provides only required information and
- /// offers a couple of useful functions. The main idea is avoiding that the
- /// user handle complicated xml functions, instead giving a very simple
- /// class which wraps the properties and function we think are important
- /// and is presented in a very easy way to use.
- /// </summary>
- public class XmlNode
- {
- #region GetNamespaceName (Static)
- /// <summary>
- /// Helper method to construct NamespaceName from given
- /// namespaceName and nodeName.
- /// </summary>
- /// <param name="namespaceName">Namespace name</param>
- /// <param name="nodeName">Node name</param>
- /// <returns>Namespace name</returns>
- public static string GetNamespaceName(string namespaceName,
- string nodeName)
- {
- return GetNamespaceName(XNamespace.Get(namespaceName), nodeName);
- }
-
- /// <summary>
- /// Helper method to construct NamespaceName from given
- /// namespace and nodeName.
- /// </summary>
- /// <param name="xNamespace">Namespace</param>
- /// <param name="nodeName">Node name</param>
- /// <returns>Namespace name</returns>
- public static string GetNamespaceName(XNamespace xNamespace,
- string nodeName)
- {
- return (xNamespace + nodeName).ToString();
- }
- #endregion
-
- #region FromFile (Static)
- /// <summary>
- /// Loads the XML file under the given path and returns the root node or
- /// 'null' if the loading fails. AutoSetNamespaceOnChildren is set to
- /// false.
- /// </summary>
- /// <param name="xmlFilePath">Xml file path</param>
- /// <returns>the root node or 'null' if the loading fails</returns>
- public static XmlNode FromFile(string xmlFilePath)
- {
- string error;
- return FromFile(xmlFilePath, false, out error);
- }
-
- /// <summary>
- /// Loads the XML file under the given path and returns the root node or
- /// 'null' if the loading fails.
- /// </summary>
- /// <param name="xmlFilePath">Xml file path</param>
- /// <param name="autoSetNamespaceOnChildren">Flag if the namespace should
- /// be set to the children automatically.</param>
- /// <returns>the root node or 'null' if the loading fails</returns>
- public static XmlNode FromFile(string xmlFilePath,
- bool autoSetNamespaceOnChildren, out string error)
- {
- try
- {
- XDocument xDoc = XDocument.Load(FileHelper.Open(
- xmlFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
- var node = new XmlNode(xDoc.Root, autoSetNamespaceOnChildren);
- error = "";
-
- return node;
- }
- catch (Exception ex)
- {
- error = "XmlNode.FromFile: Couldn't load XML file '" +
- xmlFilePath + "' because:\n" + ex.Message;
- Log.Warning(error);
-
- return null;
- }
- }
- #endregion
-
- #region FromSnippet (Static)
- /// <summary>
- /// Loads and Xml node from an Xml snippet.
- /// </summary>
- /// <param name="xmlAsText">Xml as text</param>
- /// <returns>Xml node</returns>
- public static XmlNode FromSnippet(string xmlAsText)
- {
- string error;
- return FromSnippet(xmlAsText, out error);
- }
-
- /// <summary>
- /// Loads and Xml node from an Xml snippet.
- /// </summary>
- /// <param name="xmlAsText">Xml as text</param>
- /// <param name="error">Error string if anything has gone wrong</param>
- /// <returns>Filled XmlNode from xmlAsText</returns>
- public static XmlNode FromSnippet(string xmlAsText, out string error)
- {
- if (String.IsNullOrEmpty(xmlAsText))
- {
- error =
- "The given XML snippet is empty, unable to return anything " +
- "useful (will return empty node with the name '-InvalidXml-').";
- Log.Warning("XmlNode LoadSnippet failed: " + error);
- return new XmlNode("-InvalidXml-");
- }
-
- // Safety-check that we don't start with "trash" like new-line at the
- // beginning what XLinq don't like
- int cutOffIndex = xmlAsText.IndexOf('<');
- // if xml source doesn't start with '<' then we have "trash"
- if (cutOffIndex > 0)
- {
- xmlAsText = xmlAsText.Substring(cutOffIndex);
- }
-
- // Just using the "Parse()" function from .NET
- // http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.parse.aspx
- XDocument xDocument = XDocument.Parse(xmlAsText);
-
- if (xDocument == null ||
- xDocument.Root == null)
- {
- error =
- "The given text snippet '" + xmlAsText + "' is not valid XML" +
- " (will return empty node with the name '-InvalidXml-').";
- Log.Warning("XmlNode LoadSnippet failed: " + error);
- return new XmlNode("-InvalidXml-");
- }
-
- // Everything is ok
- error = "";
-
- return new XmlNode(xDocument.Root);
- }
- #endregion
-
- #region FromMemoryStream (Static)
- /// <summary>
- /// Helper method to load xml data from a memory stream, which must contain
- /// the same data as a saved xml file (see the Save() method). To load
- /// snippet strings use the FromSnippet method instead.
- /// </summary>
- /// <param name="xmlData">Xml data in a memory stream</param>
- /// <returns>Loaded XmlNode</returns>
- public static XmlNode FromMemoryStream(MemoryStream xmlData)
- {
- xmlData.Seek(0, SeekOrigin.Begin);
- XDocument xDoc = XDocument.Load(xmlData);
- return new XmlNode(xDoc.Root, false);
- }
- #endregion
-
- #region Name (Public)
- /// <summary>
- /// Name of the xml root node.
- /// </summary>
- public string Name
- {
- get
- {
- return xNodeRoot.Name.LocalName;
- }
- }
- #endregion
-
- #region Value (Public)
- /// <summary>
- /// Value of the xml root node
- /// </summary>
- public string Value
- {
- get
- {
- return xNodeRoot.Value;
- }
- set
- {
- xNodeRoot.SetValue(value == null
- ? ""
- : value);
- }
- }
- #endregion
-
- #region Parent (Public)
- /// <summary>
- /// Returns the parent node of this node or 'null' if there is no parent
- /// (anymore).
- /// </summary>
- public XmlNode Parent
- {
- get;
- private set;
- }
- #endregion
-
- #region Children (Public)
- /// <summary>
- /// Returns children nodes from current parent.
- /// </summary>
- public XmlNode[] Children
- {
- get;
- private set;
- }
- #endregion
-
- #region FilePath (Public)
- /// <summary>
- /// The (absolute) file path from where the xml was loaded (is 'None' if
- /// the XML was created dynamically).
- /// </summary>
- public string FilePath
- {
- get
- {
- return xNodeRoot.Document.BaseUri;
- }
- }
- #endregion
-
- #region WillChildInheritNamespace (Public)
- /// <summary>
- /// If disabled (by default all XmlNodes have this disabled):
- /// You have to manually set the namespace on every child node you add,
- /// else it will be empty namespace.
- ///
- /// If enabled:
- /// Added children will automatically use the same namespace as parent node
- ///
- /// You may set the namespace this way:
- ///
- /// XmlNode projectNode =
- /// new XmlNode(
- /// XmlNode.GetNamespaceName(
- /// CsprojXml.Namespace + CsprojXml.ProjectKeyword),
- /// true);
- ///
- /// or
- ///
- /// node.AddChild(XmlNode.GetNamespaceName("some namespace", "Tag Name"))
- /// </summary>
- public bool WillChildInheritNamespace
- {
- get;
- set;
- }
- #endregion
-
- #region Private
-
- #region xNodeRoot (Private)
- /// <summary>
- /// Main element that contain all the info related with the xml node.
- /// Be aware that from this variable we get all the information from
- /// the xml file we are working with.
- /// </summary>
- private readonly XElement xNodeRoot;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// We only allow to create a XmlNode internally and we rely on
- /// XmlHelper to create it when necessary. As expected, to start off
- /// we assign a root node that contains everything we need.
- /// </summary>
- /// <param name="setNodeRoot">represents the root node</param>
- internal XmlNode(XElement setNodeRoot)
- : this(setNodeRoot, null)
- {
- }
-
- /// <summary>
- /// We only allow to create a XmlNode internally and we rely on
- /// XmlHelper to create it when necessary. As expected, to start off
- /// we assign a root node that contains everything we need.
- /// </summary>
- /// <param name="setNodeRoot">represents the root node</param>
- /// <param name="autoSetNamespaceOnChildren">Flag if the namespace should
- /// be set to the children automatically.</param>
- internal XmlNode(XElement setNodeRoot, bool autoSetNamespaceOnChildren)
- : this(setNodeRoot, null, autoSetNamespaceOnChildren)
- {
- }
-
- /// <summary>
- /// We only allow to create a XmlNode internally and we rely on
- /// XmlHelper to create it when necessary. As expected, to start off
- /// we assign a root node that contains everything we need.
- /// </summary>
- /// <param name="setNodeRoot">represents the root node</param>
- /// <param name="setParent">the parent node</param>
- internal XmlNode(XElement setNodeRoot, XmlNode setParent)
- : this(setNodeRoot, setParent, false)
- {
- }
-
- /// <summary>
- /// We only allow to create a XmlNode internally and we rely on
- /// XmlHelper to create it when necessary. As expected, to start off
- /// we assign a root node that contains everything we need.
- /// </summary>
- /// <param name="setNodeRoot">represents the root node</param>
- /// <param name="setParent">the parent node</param>
- /// <param name="autoSetNamespaceOnChildren">Flag if the namespace should
- /// be set to the children automatically.</param>
- internal XmlNode(XElement setNodeRoot, XmlNode setParent,
- bool autoSetNamespaceOnChildren)
- {
- WillChildInheritNamespace = autoSetNamespaceOnChildren;
-
- // Check that we got a valid root node.
- if (setNodeRoot == null)
- {
- throw new ArgumentNullException("setNodeRoot");
- }
-
- xNodeRoot = setNodeRoot;
-
- // We need to read the immediate children once and assign it to the
- // corresponding property for caching
- var descendants = new List<XElement>(xNodeRoot.Elements());
- var childList = new List<XmlNode>();
- for (int i = 0; i < descendants.Count; i++)
- {
- childList.Add(new XmlNode(descendants[i], this,
- autoSetNamespaceOnChildren));
- }
- Children = childList.ToArray();
-
- // and "link" to the parent node if there is one
- Parent = setParent;
- }
-
- /// <summary>
- /// Creates an XML root node with the given name, but no children yet.
- /// When createWithXmlHeader is true an Xml declaration is added at top!
- /// </summary>
- /// <param name="createWithXmlHeader">Create with xml header</param>
- /// <param name="setNamespace">Set namespace</param>
- /// <param name="setRootName">Set root node name</param>
- public XmlNode(string setNamespace, string setRootName,
- bool createWithXmlHeader)
- : this(GetNamespaceName(setNamespace, setRootName),
- createWithXmlHeader)
- {
- }
-
- /// <summary>
- /// Creates an XML root node with the given name, but no children yet.
- /// When createWithXmlHeader is true an Xml declaration is added at top!
- /// </summary>
- /// <param name="createWithXmlHeader">create with xml header</param>
- /// <param name="setNamespace">set namespace</param>
- /// <param name="setRootName">set root name</param>
- public XmlNode(XNamespace setNamespace, string setRootName,
- bool createWithXmlHeader)
- : this(GetNamespaceName(setNamespace, setRootName),
- createWithXmlHeader)
- {
- }
-
- /// <summary>
- /// Creates an XML root node with the given name, but no children yet.
- /// When createWithXmlHeader is true an Xml declaration is added at top!
- /// </summary>
- /// <param name="createWithXmlHeader">create with xml heater</param>
- /// <param name="setRootName">set root name</param>
- public XmlNode(string setRootName, bool createWithXmlHeader)
- {
- if (String.IsNullOrEmpty(setRootName))
- {
- Log.Warning("The XmlNode you want to create has no name.");
- setRootName = "<Empty>";
- }
-
- // Always make sure that we don't have white spaces in the name..
- setRootName = setRootName.Replace(" ", "");
- // Create then the native XML root node
- xNodeRoot = new XElement(setRootName);
- // and the belonging XML document
- if (createWithXmlHeader)
- {
- var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
- xNodeRoot);
- }
- else
- {
- var xDoc = new XDocument();
- xDoc.Add(xNodeRoot);
- }
- // Finally just "say" that we don't have any children (empty array)
- Children = new XmlNode[0];
- }
-
- /// <summary>
- /// Create xml node root node with the given name (no xml header)
- /// </summary>
- /// <param name="setRootName">set root name</param>
- public XmlNode(string setRootName)
- : this(setRootName, false)
- {
- }
- #endregion
-
- #region AddChild (Public)
- /// <summary>
- /// Adds a new child with given name and returns it to be filled.
- /// If ChildWillInheritNamespace is true, it will inherit the namespace of
- /// this node (Namespace part in given name will be ignored).
- /// </summary>
- /// <param name="name">Name for the new child</param>
- /// <returns>The newly added child as an XmlNode</returns>
- public XmlNode AddChild(string name)
- {
- name = ConstructName(name);
- var xElement = new XElement(name);
- var node = new XmlNode(xElement, WillChildInheritNamespace);
- node.Parent = this;
- var childs = new List<XmlNode>(Children);
- childs.Add(node);
- xNodeRoot.Add(xElement);
- Children = childs.ToArray();
- return node;
- }
-
- /// <summary>
- /// Adds a new child with given name and returns it to be filled.
- /// If ChildWillInheritNamespace is true, it will inherit the namespace of
- /// this node (Namespace part in given name will be ignored).
- /// </summary>
- /// <param name="name">Name</param>
- /// <param name="value">Value</param>
- /// <returns>The newly added child as an XmlNode</returns>
- public XmlNode AddChild(string name, string value)
- {
- name = ConstructName(name);
- var xElement = new XElement(name);
- var node = new XmlNode(xElement, WillChildInheritNamespace);
- node.Parent = this;
- node.Value = value;
- xElement.Value = value;
-
- xNodeRoot.Add(xElement);
- var childs = new List<XmlNode>(Children);
- childs.Add(node);
- Children = childs.ToArray();
-
- return node;
- }
-
- /// <summary>
- /// Add child from XmlNode. Note: This will create a copy of the XmlNode
- /// to make sure we do not modify the original XmlNode that could come
- /// from another tree or document.
- /// </summary>
- /// <param name="childNode">Child node we want to add</param>
- public XmlNode AddChild(XmlNode childNode)
- {
- string newName = ConstructName(childNode.Name);
- var xElement = new XElement(newName);
- var node = new XmlNode(xElement, WillChildInheritNamespace);
- node.Parent = this;
- xNodeRoot.Add(xElement);
- var childs = new List<XmlNode>(Children);
- childs.Add(node);
- Children = childs.ToArray();
-
- // Copy the value and all attributes, and also all children recursively
- node.Value = childNode.Value;
- Dictionary<string, string> attributes = childNode.GetAllAttributes();
- foreach (KeyValuePair<string, string> attributePair in attributes)
- {
- node.AddAttribute(attributePair.Key, attributePair.Value);
- }
- foreach (XmlNode copyChild in childNode.Children)
- {
- node.AddChild(copyChild);
- }
-
- return node;
- }
- #endregion
-
- #region AddAttribute (Public)
- /// <summary>
- /// Add attribute
- /// </summary>
- /// <param name="name">name</param>
- /// <param name="value">value</param>
- public void AddAttribute(string name, string value)
- {
- xNodeRoot.SetAttributeValue(name, value);
- }
-
- /// <summary>
- /// Add attribute
- /// </summary>
- public void AddAttribute(string attributeNamespace, string name,
- string value)
- {
- xNodeRoot.SetAttributeValue(XName.Get(name, attributeNamespace), value);
- }
- #endregion
-
- #region GetValueAs (Public)
- /// <summary>
- /// Get value as any supported datatype that is passed to this generic
- /// method. Uses StringHelper.FromInvariantString to convert.
- /// </summary>
- /// <param name="defaultValue">Default value</param>
- /// <returns>Value string converted to type T</returns>
- public T GetValueAs<T>(T defaultValue)
- {
- return Value.FromInvariantString(defaultValue,
- "The value '" + Value + "' of XmlNode '" + Name + "' couldn't be " +
- "converted to type '" + typeof(T) + "'.");
- }
- #endregion
-
- #region GetAttribute (Public)
- /// <summary>
- /// Look for the value of an attribute (specified as parameter) in the
- /// root node. It returns the first attribute which matches with the
- /// given parameters. If desired we can do an depth search in the child
- /// nodes. It is optional due to performance costs (it has to be carefully
- /// used). By default the search is NOT done recursively.
- /// </summary>
- /// <param name="name">Attribute name to search</param>
- /// <param name="searchRecursively">
- /// Allow search recursively in the child nodes (defaults to false).
- /// </param>
- /// <returns>
- /// If found the attribute value, otherwise an empty string.
- /// </returns>
- public string GetAttribute(string name, bool searchRecursively = false)
- {
- // Check that we got a valid root node.
- if (xNodeRoot == null)
- {
- throw new NullReferenceException(
- "Need valid rootNode for GetAttribute.");
- }
-
- // Do we have to search internally?
- if (searchRecursively)
- {
- // Use an appropriate auxiliary function which attempts to look
- // for the required attribute.
- XAttribute attribute = FindFirstDescendantAttribute(
- xNodeRoot.DescendantsAndSelf(), name);
-
- // If the search was a success, just send back the value.
- return
- attribute != null
- ? attribute.Value
- : "";
- }
-
- // Get the first attribute which matches with the specified name
- var attributes =
- new List<XAttribute>(xNodeRoot.Attributes());
- for (int i = 0; i < attributes.Count; i++)
- {
- if (attributes[i].Name.LocalName == name)
- {
- return attributes[i].Value;
- }
- }
- return "";
- }
- #endregion
-
- #region GetAllAttributes (Public)
- /// <summary>
- /// Get all attributes, use this method if you want better performance
- /// than calling GetAttribute or GetAttributeAs, which both do a lot of
- /// checking, support recursion (which is slow) and will do all the
- /// conversion for you (again slow). This is the fastest way to get to
- /// attribute values, but you will have to convert types yourself.
- /// </summary>
- /// <returns>
- /// Dictionary with all attributes and values as strings.
- /// </returns>
- public Dictionary<string, string> GetAllAttributes()
- {
- var result = new Dictionary<string, string>(
- StringComparer.InvariantCultureIgnoreCase);
- // Get the first attribute which matches with the specified name
- foreach (XAttribute attribute in xNodeRoot.Attributes())
- {
- result.Add(attribute.Name.LocalName, attribute.Value);
- }
- return result;
- }
- #endregion
-
- #region GetAttributeAs (Public)
- /// <summary>
- /// Get attribute as any supported datatype that is passed to this generic
- /// method. Note: This currently throws warnings if an attribute is missing
- /// or has no value (empty string), use GetAttribute instead of you don't
- /// want all this extra checking and warnings (this method is slow).
- /// Uses StringHelper.FromInvariantString to convert.
- /// </summary>
- /// <param name="name">Attribute name to search for</param>
- /// <param name="defaultValue">
- /// Default value if the attribute was not found.
- /// </param>
- /// <param name="extraWarningTextIfAnythingGoesWrong">
- /// Extra warning in case anything goes wrong to really help the user to
- /// identify the problem with a related message (e.g. font content name).
- /// By default empty string (""), which means no errors will be reported.
- /// </param>
- /// <returns>
- /// Filled T value or defaultValue if attribute was not found or type
- /// conversion is not supported (a log warning will also be outputted).
- /// </returns>
- public T GetAttributeAs<T>(string name, T defaultValue,
- string extraWarningTextIfAnythingGoesWrong = "")
- {
- return GetAttribute(name).FromInvariantString(defaultValue,
- extraWarningTextIfAnythingGoesWrong);
- }
- #endregion
-
- #region GetChild (Public)
- /// <summary>
- /// Look for a node with the name specified as parameter. It returns the
- /// first node which matchs with the given parameter.
- /// Note: The search is recursively.
- /// </summary>
- /// <param name="childName">Node name to search</param>
- /// <returns>Node</returns>
- public XmlNode GetChild(string childName)
- {
- return GetChild(childName, true);
- }
-
- /// <summary>
- /// Look for a node with the name specified as parameter. It returns the
- /// first node which matchs with the given parameter.
- /// </summary>
- /// <param name="childName">Node name to search</param>
- /// <param name="searchRecursively">
- /// Allow search recursively in the child nodes?
- /// </param>
- public XmlNode GetChild(string childName, bool searchRecursively)
- {
- // Just iterate over all (directly) childs
- for (int index = 0; index < Children.Length; index++)
- {
- // At first directly look for the first one where the name matches
- XmlNode child = Children[index];
- if (StringHelper.Compare(child.Name, childName))
- {
- return child;
- }
-
- // And if doesn't match then just look (recursively) at his childs
- if (searchRecursively)
- {
- XmlNode childOfChild = child.GetChild(childName);
- if (childOfChild != null)
- {
- return childOfChild;
- }
- }
- }
-
- // If we don't have find one, then there isn't one...
- return null;
- }
-
- /// <summary>
- /// Look for a node with the name specified as parameter and which
- /// contains a particular attribute. This function is thought for when
- /// we have several nodes with the same name to allow the user to
- /// get one with a concrete attribute. It returns the first node which
- /// matchs with the attribute name and value.
- /// Note: The search is recursively.
- /// </summary>
- /// <param name="attributeName">Attribute to search</param>
- /// <param name="attributeValue">Attribute value to search</param>
- /// <returns>Found child node or null if nothing was found</returns>
- public XmlNode GetChild(string attributeName, string attributeValue)
- {
- return GetChild(null, attributeName, attributeValue);
- }
-
- /// <summary>
- /// Look for a node with the name specified as parameter and which
- /// contains a particular attribute. This function is thought for when
- /// we have several nodes with the same name to allow the user to
- /// get one with a concrete attribute. It returns the first node which
- /// matchs with the attribute name and value.
- /// Note: The search is recursively.
- /// </summary>
- /// <param name="childName">
- /// Node name to search, can be null for all kind of Xml child nodes.
- /// </param>
- /// <param name="attributeName">Attribute to search</param>
- /// <param name="attributeValue">Attribute value to search</param>
- /// <returns>Found child node or null if nothing was found</returns>
- public XmlNode GetChild(string childName, string attributeName,
- string attributeValue)
- {
- // If there is no node name given, then we iterate over all child nodes...
- bool skipNameCheck = String.IsNullOrEmpty(childName);
-
- // Just iterate over all children
- for (int num = 0; num < Children.Length; num++)
- {
- // At first directly look for the first one where the name matches
- XmlNode child = Children[num];
- if ((skipNameCheck ||
- StringHelper.Compare(child.Name, childName)) &&
- StringHelper.Compare(child.GetAttribute(attributeName),
- attributeValue))
- {
- return child;
- } // if
-
- // And if doesn't match then just look (recursively) at his children
- XmlNode childOfChild = child.GetChild(childName, attributeName,
- attributeValue);
- if (childOfChild != null)
- {
- return childOfChild;
- } // if
- } // for
-
- // If we don't have find one, then there isn't one...
- return null;
- }
-
- /// <summary>
- /// Look for a node with the name specified as parameter and which
- /// contains two particular attributes. This function is thought for when
- /// we have several nodes with the same name to allow the user to
- /// get one with a concrete attribute. It returns the first node which
- /// matches the attribute names and values.
- /// Note: The search is recursively.
- /// </summary>
- /// <param name="childName">
- /// Node name to search, can be null for all kind of Xml child nodes.
- /// </param>
- /// <param name="attribute1Name">First attribute to search</param>
- /// <param name="attribute1Value">First attribute value to search</param>
- /// <param name="attribute2Name">Second attribute to search</param>
- /// <param name="attribute2Value">Second attribute value to search</param>
- /// <returns>Found child node or null if nothing was found</returns>
- public XmlNode GetChild(string childName, string attribute1Name,
- string attribute1Value, string attribute2Name, string attribute2Value)
- {
- // If there is no node name given, then we iterate over all child nodes.
- bool skipNameCheck = String.IsNullOrEmpty(childName);
-
- // Just iterate over all childs
- for (int i = 0; i < Children.Length; i++)
- {
- // At first directly look for the first one where the name matches
- XmlNode child = Children[i];
- if ((skipNameCheck ||
- StringHelper.Compare(child.Name, childName)) &&
- StringHelper.Compare(child.GetAttribute(attribute1Name),
- attribute1Value) &&
- StringHelper.Compare(child.GetAttribute(attribute2Name),
- attribute2Value))
- {
- return child;
- }
-
- // And if doesn't match then just look (recursively) at his children
- XmlNode childOfChild = child.GetChild(childName, attribute1Name,
- attribute1Value, attribute2Name, attribute2Value);
- if (childOfChild != null)
- {
- return childOfChild;
- }
- }
-
- // If we don't have find one, then there isn't one.
- return null;
- }
-
- /// <summary>
- /// Look for a node with the name specified as parameter and which
- /// contains two particular attributes. This function is thought for when
- /// we have several nodes with the same name to allow the user to
- /// get one with a concrete attribute. It returns the first node which
- /// matches all the attribute names and values.
- /// Note: The search is recursively.
- /// </summary>
- /// <param name="childName">
- /// Node name to search, can be null for all kind of Xml child nodes.
- /// </param>
- /// <param name="attribute1Name">First attribute to search</param>
- /// <param name="attribute1Value">First attribute value to search</param>
- /// <param name="attribute2Name">Second attribute to search</param>
- /// <param name="attribute2Value">Second attribute value to search</param>
- /// <param name="attribute3Name">Third attribute to search</param>
- /// <param name="attribute3Value">Third attribute value to search</param>
- /// <returns>Found child node or null if nothing was found</returns>
- public XmlNode GetChild(string childName, string attribute1Name,
- string attribute1Value, string attribute2Name, string attribute2Value,
- string attribute3Name, string attribute3Value)
- {
- // If there is no node name given, then we iterate over all child nodes.
- bool skipNameCheck = String.IsNullOrEmpty(childName);
-
- // Just iterate over all childs
- for (int i = 0; i < Children.Length; i++)
- {
- // At first directly look for the first one where the name matches
- XmlNode child = Children[i];
- if ((skipNameCheck ||
- StringHelper.Compare(child.Name, childName)) &&
- StringHelper.Compare(child.GetAttribute(attribute1Name),
- attribute1Value) &&
- StringHelper.Compare(child.GetAttribute(attribute2Name),
- attribute2Value) &&
- StringHelper.Compare(child.GetAttribute(attribute3Name),
- attribute3Value))
- {
- return child;
- }
-
- // And if doesn't match then just look (recursively) at his children
- XmlNode childOfChild = child.GetChild(childName,
- attribute1Name, attribute1Value,
- attribute2Name, attribute2Value,
- attribute3Name, attribute3Value);
- if (childOfChild != null)
- {
- return childOfChild;
- }
- }
-
- // If we don't have find one, then there isn't one.
- return null;
- }
- #endregion
-
- #region GetChildCount (Public)
- /// <summary>
- /// Gets the number of child that match with the given name.
- /// </summary>
- /// <param name="childName">Child name</param>
- /// <returns>number</returns>
- public int GetChildCount(string childName)
- {
- int foundCount = 0;
-
- for (int i = 0; i < Children.Length; i++)
- {
- // Check this case-insensitive
- if (StringHelper.Compare(Children[i].Name, childName))
- {
- foundCount++;
- }
- }
-
- return foundCount;
- }
- #endregion
-
- #region GetTotalNodeCount
- /// <summary>
- /// Helper method to get the total count of nodes inclusive all child
- /// nodes.
- /// </summary>
- /// <returns>Number of nodes, always at least one (this node)</returns>
- public int GetTotalNodeCount()
- {
- int ret = 1;
- for (int index = 0; index < Children.Length; index++)
- {
- ret += Children[index].GetTotalNodeCount();
- }
- return ret;
- }
- #endregion
-
- #region GetLastChild (Public)
- /// <summary>
- /// Gets last child that matches with the given name.
- /// Note: The search is recursively.
- /// </summary>
- /// <param name="childName">Child name</param>
- public XmlNode GetLastChild(string childName)
- {
- // Just iterate over all (directly) childs
- for (int i = Children.Length - 1; i >= 0; i--)
- {
- // At first directly look for the first one where the name matches
- XmlNode child = Children[i];
- // Check this case-insensitive
- if (StringHelper.Compare(child.Name, childName))
- {
- return child;
- }
-
- // and if doesn't match then just look (recursively) at his childs
- else
- {
- XmlNode childOfChild = child.GetLastChild(childName);
- if (childOfChild != null)
- {
- return childOfChild;
- }
- }
- }
-
- // If we don't have find one, then there isn't one...
- return null;
- }
-
- /// <summary>
- /// Gets last child that matches with the given attribute name and value.
- /// Note: The search is recursively.
- /// </summary>
- /// <param name="attributeName">Attribute name</param>
- /// <param name="attributeValue">Attribute value</param>
- /// <returns>XmlNode of the last child or null if not found.</returns>
- public XmlNode GetLastChild(string attributeName, string attributeValue)
- {
- return GetLastChild(null, attributeName, attributeValue);
- }
-
- /// <summary>
- /// Gets last child that matches with the given name.
- /// Note: The search is recursively.
- /// </summary>
- /// <param name="childName">Node name to search</param>
- /// <param name="attributeName">Attribute to search</param>
- /// <param name="attributeValue">Attribute value to search</param>
- /// <returns>XmlNode of the last child or null if not found.</returns>
- public XmlNode GetLastChild(string childName, string attributeName,
- string attributeValue)
- {
- // If there is no node name given, then we iterate over all child nodes...
- bool skipNameCheck = String.IsNullOrEmpty(childName);
-
- // Just iterate over all childs
- for (int i = Children.Length - 1; i >= 0; i--)
- {
- // At first directly look for the first one where the name matches
- XmlNode child = Children[i];
- // Check this case-insensitive
- if ((skipNameCheck ||
- StringHelper.Compare(child.Name, childName)) &&
- child.GetAttribute(attributeName) == attributeValue)
- {
- return child;
- }
-
- // And if doesn't match then just look (recursively) at his childs
- XmlNode childOfChild = child.GetLastChild(childName, attributeName,
- attributeValue);
- if (childOfChild != null)
- {
- return childOfChild;
- }
- }
-
- // If we don't have find one, then there isn't one...
- return null;
- }
- #endregion
-
- #region GetAllChildren (Public)
- /// <summary>
- /// Look for all nodes with the name specified as parameter and returns
- /// them in an array (non recursive implementation yet).
- /// <para />
- /// <b>Note:</b> Will always return a valid array, in worst case just an
- /// empty one.
- /// </summary>
- /// <param name="childName"></param>
- /// <returns>
- /// Array of XmlNodes from all the children of this node.
- /// </returns>
- public XmlNode[] GetAllChildren(string childName)
- {
- // first see how many children with this name exist
- int count = GetChildCount(childName);
-
- // create array and set nodes
- var foundNodes = new XmlNode[count];
-
- for (int index = 0, j = 0; index < Children.Length; index++)
- {
- if (Children[index].Name == childName)
- {
- foundNodes[j++] = Children[index];
- }
- }
-
- return foundNodes;
- }
- #endregion
-
- #region RemoveChild (Public)
- /// <summary>
- /// Remove child node from this xml node. Basically just does a Children
- /// remove, but since Children is an array it is not that easy. Note:
- /// This will not check recursively, only a direct children is removed.
- /// </summary>
- /// <param name="childNodeToRemove">Child XmlNode we want to remove</param>
- /// <returns>True if a child node was removed, false otherwise</returns>
- public bool RemoveChild(XmlNode childNodeToRemove)
- {
- for (int childNum = 0; childNum < Children.Length; childNum++)
- {
- if (Children[childNum] == childNodeToRemove)
- {
- // Remove this children entry (only here we need to modify the
- // Children array, if nothing was found there is no reason to change)
- childNodeToRemove.xNodeRoot.Remove();
- var newChildren = new List<XmlNode>();
- foreach (XmlNode child in Children)
- {
- if (child != childNodeToRemove)
- {
- newChildren.Add(child);
- }
- }
- Children = newChildren.ToArray();
- // Found children and removed it!
- return true;
- }
- }
-
- // No children to remove was found
- return false;
- }
- #endregion
-
- #region RemoveChildRecursively (Public)
- /// <summary>
- /// Remove xml child node recursively and return if we found and removed
- /// the given child node.
- /// </summary>
- /// <param name="childNodeToRemove">Child XmlNode we want to remove</param>
- /// <returns>True if a child node was removed, false otherwise</returns>
- public bool RemoveChildRecursively(XmlNode childNodeToRemove)
- {
- if (RemoveChild(childNodeToRemove))
- {
- return true;
- }
-
- // Child not found here, try children, but only if they have children too
- foreach (XmlNode child in Children)
- {
- if (child.Children.Length > 0)
- {
- bool removedChild = child.RemoveChildRecursively(childNodeToRemove);
- if (removedChild)
- {
- return true;
- }
- }
- }
-
- // Not found, then nothing was removed
- return false;
- }
- #endregion
-
- #region RemoveAllChildren (Public)
- /// <summary>
- /// Removes all children with given childName. (Not recursively)
- /// </summary>
- /// <param name="childName">child name</param>
- /// <returns>Number of removed children</returns>
- public int RemoveAllChildren(string childName)
- {
- int removedChildren = 0;
- int childCount = Children.Length;
- var survivingChildren = new List<XmlNode>();
- for (int index = 0; index < childCount; index++)
- {
- if (Children[index].Name != childName)
- {
- survivingChildren.Add(Children[index]);
- }
- else
- {
- Children[index].xNodeRoot.Remove();
- removedChildren++;
- }
- }
- Children = survivingChildren.ToArray();
- return removedChildren;
- }
- #endregion
-
- #region RemoveAllAttributes (Public)
- /// <summary>
- /// Removes all attributes of this node (Not recursively).
- /// </summary>
- /// <returns>Number of removed attributes</returns>
- public void RemoveAllAttributes()
- {
- xNodeRoot.RemoveAttributes();
- }
- #endregion
-
- #region Remove (Public)
- /// <summary>
- /// Remove this child node from its parent. Useful to unlink stuff.
- /// </summary>
- public void Remove()
- {
- if (Parent != null)
- {
- Parent.RemoveChild(this);
- }
- }
- #endregion
-
- #region GetWholeDocumentXmlText (Public)
- /// <summary>
- /// Get the whole xml document as formatted xml text.
- /// </summary>
- public string GetWholeDocumentXmlText()
- {
- return xNodeRoot.Document.ToString();
- }
- #endregion
-
- #region GetThisNodeXmlText (Public)
- /// <summary>
- /// Returns the xml text from this node and its children. Use
- /// GetWholeDocumentXmlText to get the xml of the whole file or use
- /// the Name property and GetAttributes for just this node without the
- /// children (this will still return all the children and if we are at
- /// the document level, this returns the same as GetWholeDocumentXmlText.
- /// </summary>
- public string GetThisNodeXmlText()
- {
- return xNodeRoot.ToString();
- }
- #endregion
-
- #region Save (Public)
- /// <summary>
- /// Save whole xml file (does not matter from which xml node we call this).
- /// In case saving is not possible this method will output a warning in
- /// the log and return false, but does not throw an exception.
- /// </summary>
- /// <param name="filePath">Where to save the ContentMetaData.xml</param>
- /// <returns>
- /// True if saving the file was successful, false (and a log warning)
- /// otherwise.
- /// </returns>
- public bool Save(string filePath)
- {
- try
- {
- using (FileStream stream = FileHelper.Open(
- filePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
- {
- if (stream == null)
- {
- return false;
- }
-
- var fileWriter = new StreamWriter(stream, Encoding.UTF8);
- xNodeRoot.Document.Save(fileWriter);
- fileWriter.Flush();
- }
-
- return true;
- }
- catch (Exception ex)
- {
- Log.Warning("Failed to save '" + filePath + "': " + ex);
- return false;
- }
- }
-
- /// <summary>
- /// Save whole xml file (does not matter from which xml node we call this)
- /// into a memory stream, which contains the same data as if we would have
- /// saved this to a file with the other Save overload. Can be loaded again
- /// with FromMemoryStream.
- /// </summary>
- /// <returns>
- /// The newly created memory stream containing the saved UTF8 encoded xml.
- /// </returns>
- public MemoryStream Save()
- {
- try
- {
- var xmlStream = new MemoryStream();
- var fileWriter = new StreamWriter(xmlStream,
- Encoding.UTF8);
- xNodeRoot.Document.Save(fileWriter);
- // And return the result
- return xmlStream;
- }
- catch (Exception ex)
- {
- Log.Warning("Failed to save xml to memory stream: " + ex);
- return new MemoryStream();
- }
- }
- #endregion
-
- #region ToString (Public)
- /// <summary>
- /// To string, will return a limited string with max. 200 characters to
- /// get an overview what this XmlNode is about. Use GetXmlText to grab
- /// the full xml text.
- /// </summary>
- public override string ToString()
- {
- return "XmlNode=" + Name + ": " +
- GetThisNodeXmlText().MaxStringLength(200,
- StringHelper.CutModes.EndWithDots);
- }
- #endregion
-
- #region Methods (Private)
-
- #region ConstructName
- /// <summary>
- /// if WillChildInheritNamespace is true, it applies the parent
- /// namespace to given name, ignoring any given namespace.
- /// </summary>
- /// <param name="name">name</param>
- /// <returns>Namespace name if this child inherits it, otherwise name
- /// </returns>
- private string ConstructName(string name)
- {
- if (WillChildInheritNamespace)
- {
- //Enforce parent namespace
- name = GetNamespaceName(xNodeRoot.Name.Namespace,
- XName.Get(name).LocalName);
- }
- return name;
- }
- #endregion
-
- #region FindFirstDescendantAttribute
- /// <summary>
- /// Find the first descendant attribute in a list of Elements. It
- /// searchs in depth through the descendant nodes, searching for a
- /// coincidence with the name. The first match stops inmediatly the
- /// depth-search and returns the attribute.
- /// </summary>
- /// <param name="Elements">Elements to proceed with the search</param>
- /// <param name="name">Name of the searched attribute</param>
- /// <returns>null</returns>
- private XAttribute FindFirstDescendantAttribute(
- IEnumerable<XElement> Elements, string name)
- {
- // Iterates through all the list
- foreach (XElement element in Elements)
- {
- // It is possible that each element node contains more than one
- // attribute
- // Get the first attribute which matchs with the specified name
- var attributes =
- new List<XAttribute>(element.Attributes());
- for (int i = 0; i < attributes.Count; i++)
- {
- // As specified in the description, it is always returned the
- // first match in the attribute list.
- if (attributes[i].Name.LocalName == name)
- {
- return attributes[i];
- }
- }
-
- // If it isn't found then call recursively the function until the
- // success or end of branch.
- XAttribute attr =
- FindFirstDescendantAttribute(element.Descendants(), name);
- if (attr != null)
- {
- return attr;
- }
- }
- return null;
- }
- #endregion
-
- #endregion
-
- /// <summary>
- /// Tests
- /// </summary>
- internal class XmlNodeTests
- {
- #region Helpers
-
- #region TestXmlDocumentPath
- private const string TestXmlDocumentPath =
- @"C:\Windows\System32\icsxml\ipcfg.xml";
- #endregion
-
- #region TestXmlText
- private const string TestXmlText =
- @"
- <Root xmlns='urn:schemas-upnp-org:service-1-0' testAttribute='test'>
- <Customers CustomerID='ANTON' Age='31'>
- <CompanyName>Antonio Moreno Taquería</CompanyName>
- <ContactName>Antonio Moreno</ContactName>
- <ContactTitle>Owner</ContactTitle>
- <Dead>true</Dead>
- <Phone>(5) 555-3932</Phone>
- <FullAddress>
- <Address>Mataderos 2312</Address>
- <City>México D.F.</City>
- <PostalCode>05023</PostalCode>
- <Country>Mexico</Country>
- </FullAddress>
- <TestGetXmlAttribute TestingID='ANTON' />
- </Customers>
- <Customers CustomerID='ALFKI'>
- <CompanyName>Alfreds Futterkiste</CompanyName>
- <ContactName>Maria Anders</ContactName>
- <ContactTitle>Sales Representative</ContactTitle>
- <Phone>030-0074321</Phone>
- <Fax>030-0076545</Fax>
- <FullAddress>
- <Address>Obere Str. 57</Address>
- <City>Berlin</City>
- <PostalCode>12209</PostalCode>
- <Country>Germany</Country>
- </FullAddress>
- </Customers>
- </Root>";
- #endregion
-
- #region testRootNode
- /// <summary>
- /// Test root node
- /// </summary>
- private static XmlNode testRootNode;
- #endregion
-
- #region TestXml
- /// <summary>
- /// Test xml
- /// </summary>
- public static XmlNode TestXml
- {
- get
- {
- //while (unitTestData.XmlData == null)
- //{
- // // Just wait for data
- // System.Threading.Thread.Sleep(0);
- //}
- //return unitTestData.XmlData as DeltaXmlNode;
- if (testRootNode == null)
- {
- /*obs, creating a file is baaaaaaad and slow and poluting!
- FileHelper.CreateTextFile("Customers.xml", TestXmlText);
- testRootNode = XmlHelper.LoadFile("Customers.xml");
- */
- testRootNode = XmlNode.FromSnippet(TestXmlText);
- }
- return testRootNode;
- }
- }
- #endregion
-
- #region FromSnippet
- public static void FromSnippet()
- {
- XmlNode xml = XmlNode.FromSnippet(TestXmlText);
- Assert.Equal("Root", xml.Name);
- // And convert it again with help of GetXmlText
- xml = XmlNode.FromSnippet(xml.GetWholeDocumentXmlText());
- Assert.Equal("Root", xml.Name);
- }
- #endregion
-
- #endregion
-
- #region CreateXmlNode (Static)
- /// <summary>
- /// Create xml node. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void CreateXmlNode()
- {
- // We only need to load a xml file sample and check that the
- // properties are the expected one.
- XmlNode rootNode = TestXml;
- Assert.NotNull(rootNode);
- Assert.Equal("Root", rootNode.Name);
- }
- #endregion
-
- #region FromFile (Static)
- /// <summary>
- /// Load file. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void FromFile()
- {
- Assert.NotNull(XmlNode.FromFile(TestXmlDocumentPath));
- }
- #endregion
-
- #region RemoveAllChildren (Static)
- /// <summary>
- /// Remove all children
- /// </summary>
- [Test]
- public static void RemoveAllChildren()
- {
- // First load a xml file
- XmlNode rootNode = TestXml;
-
- // Retrieve first contactName, and make sure it has the right value
- Assert.Equal("Antonio Moreno", rootNode.GetChild("ContactName").Value);
-
- // Retrieve first Customers node, and remove all ContactName nodes
- XmlNode customerNode = rootNode.GetChild("Customers");
- customerNode.RemoveAllChildren("ContactName");
-
- // Now check first contactName again
- Assert.Equal("Maria Anders", rootNode.GetChild("ContactName").Value);
-
- // Check the result, the first customer Antonio should not have
- // a ContactName anymore.
- Log.Test("Resulting xml=" + rootNode.GetThisNodeXmlText());
- }
- #endregion
-
- #region RemoveChild (Static)
- /// <summary>
- /// Test the RemoveChild functionality
- /// </summary>
- [Test]
- public static void RemoveChild()
- {
- XmlNode rootNode = XmlNode.FromSnippet("<BlaBla><Blub /></BlaBla>");
- Log.Test("Initial xml=" + rootNode.GetThisNodeXmlText());
- Assert.Equal(1, rootNode.Children.Length);
- rootNode.RemoveChild(rootNode.Children[0]);
- Assert.Equal(0, rootNode.Children.Length);
- Log.Test("Resulting xml=" + rootNode.GetThisNodeXmlText());
-
- // Does it also work when we add something with a string?
- rootNode.AddChild("Blub");
- Log.Test("Added blub xml=" + rootNode.GetThisNodeXmlText());
- //rootNode.RemoveChild(rootNode.Children[0]);
- rootNode.Children[0].Remove();
- Log.Test("Removed blub again xml=" + rootNode.GetThisNodeXmlText());
- // Next check if the same works when constructing XmlNodes
- XmlNode newNode = XmlNode.FromSnippet("<HiThere />");
- rootNode.AddChild(newNode);
- Log.Test("Added HiThere XmlNode=" + rootNode.GetThisNodeXmlText());
- rootNode.Children[0].Remove();
- Log.Test("Final xml=" + rootNode.GetThisNodeXmlText());
- }
- #endregion
-
- #region GetXmlAttribute (Static)
- /// <summary>
- /// Get xml attribute.
- /// </summary>
- [Test]
- public static void GetXmlAttribute()
- {
- // First load a xml file
- XmlNode rootNode = TestXml;
- Assert.NotNull(rootNode);
-
- // Lets get an attribute with and without child search. The first test
- // is expected to get a empty string since there aren't any matches.
- string attribute = rootNode.GetAttribute("TestingID", false);
- Assert.Equal("", attribute);
- // The second test is expected to get any result.
- attribute = rootNode.GetAttribute("TestingID", true);
- Assert.Equal("ANTON", attribute);
- }
- #endregion
-
- #region ReplaceAttribute (Static)
- /// <summary>
- /// Replace attribute.
- /// </summary>
- [Test]
- public static void ReplaceAttribute()
- {
- // First load a xml file
- XmlNode rootNode = TestXml;
- Assert.NotNull(rootNode);
-
- // Lets get an attribute
- string attribute = rootNode.GetAttribute("testAttribute");
- Assert.Equal("test", attribute);
- // And change it
- rootNode.AddAttribute("testAttribute", "new");
- attribute = rootNode.GetAttribute("testAttribute");
- Assert.Equal("new", attribute);
-
- // Finally check output!
- //seems to work fine: Log.Test(rootNode.GetWholeDocumentXmlText());
- }
- #endregion
-
- #region GetChildNode (Static)
- /// <summary>
- /// Get child node. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void GetChildNode()
- {
- // First load a xml file
- XmlNode rootNode = TestXml;
-
- // We will look for an child node and check its attribute in order to
- // confirm that the search is working correctly. The first test is
- // expected to get the first node which matches with the Customers tag.
- XmlNode childNode1 = rootNode.GetChild("Customers");
- Assert.NotNull(childNode1);
- Assert.Equal("Customers", childNode1.Name);
- Assert.Equal("ANTON", childNode1.GetAttribute("CustomerID"));
-
- // The second test looks for an concrete node...
- XmlNode childNode2 = rootNode.GetChild("Customers",
- "CustomerID", "ALFKI");
- Assert.NotNull(childNode2);
- Assert.Equal("Customers", childNode2.Name);
- Assert.Equal("ALFKI", childNode2.GetAttribute("CustomerID"));
- }
- #endregion
-
- #region Parent (Static)
- /// <summary>
- /// Parent. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void Parent()
- {
- Assert.NotNull(TestXml);
- Assert.Null(TestXml.Parent);
-
- Assert.NotEqual(0, TestXml.Children.Length);
-
- XmlNode childOne = TestXml.Children[0];
- Assert.NotNull(childOne);
- Assert.NotNull(childOne.Parent);
- Assert.Equal("Root", childOne.Parent.Name);
-
- Assert.Equal(7, childOne.Children.Length);
-
- XmlNode childChildSix = childOne.Children[5];
- Assert.NotNull(childChildSix);
- Assert.NotNull(childChildSix.Parent);
- Assert.Equal("Customers", childChildSix.Parent.Name);
-
- Assert.Equal(4, childChildSix.Children.Length);
-
- XmlNode childChildChildOne = childChildSix.Children[0];
- Assert.NotNull(childChildChildOne);
- Assert.NotNull(childChildChildOne.Parent);
- Assert.Equal("FullAddress", childChildChildOne.Parent.Name);
- }
- #endregion
-
- #region Childs (Static)
- /// <summary>
- /// Get children. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void Childs()
- {
- // First load a xml file
- XmlNode rootNode = TestXml;
-
- // The first test is expected to get the first node which matches
- // with an concrete Customers tag.
- XmlNode childNode = rootNode.GetChild("Customers",
- "CustomerID", "ANTON");
- Assert.NotNull(childNode);
-
- // Now we can check if the property is working correctly by looking
- // at the number of elements
- Assert.Equal(7, childNode.Children.Length);
- Assert.Equal("CompanyName", childNode.Children[0].Name);
- Assert.Equal("ContactName", childNode.Children[1].Name);
- Assert.Equal("ContactTitle", childNode.Children[2].Name);
- Assert.Equal("Dead", childNode.Children[3].Name);
- Assert.Equal("Phone", childNode.Children[4].Name);
- Assert.Equal("FullAddress", childNode.Children[5].Name);
- }
- #endregion
-
- #region GetValueAs (Static)
- /// <summary>
- /// Get xml Value. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void GetValueAs()
- {
- // First load a xml file
- XmlNode rootNode = TestXml;
- Assert.NotNull(rootNode);
-
- // Lets test the integer conversion function to get the value in the
- // specified format.
- XmlNode node = rootNode.GetChild("Customers", "CustomerID", "ANTON");
- Assert.Equal(5023, node.GetChild("PostalCode").GetValueAs(100));
- // We try to access a field which doesn't have the expected type
- //this produces a warning, we don't want that:
- //Assert.Equal(100, node.GetChild("ContactTitle").GetValueAs(100));
-
- // Lets test the double conversion function to get the value in the
- // specified format.
- Assert.Equal(5023.0, node.GetChild("FullAddress").
- GetChild("PostalCode").GetValueAs(125.5));
- // We try to access a field which doesn't have the expected type
- //Assert.Equal(100.0,
- // node.GetChild("ContactTitle").GetValueAs(100.0));
-
- // Lets test the float conversion function to get the value in the
- // specified format.
- Assert.Equal(5023.0f, node.GetChild("FullAddress").
- GetChild("PostalCode").GetValueAs(125.5f));
- // We try to access a field which doesn't have the expected type
- //Assert.Equal(100.0f,
- // node.GetChild("ContactTitle").GetValueAs(100.0f));
-
- // Lets test the boolean conversion function to get the value in the
- // specified format.
- Assert.True(node.GetChild("Dead").GetValueAs(false));
- // We try to access a field which doesn't have the expected type
- //Assert.False(node.GetChild("ContactTitle").GetValueAs(false));
- }
- #endregion
-
- #region GetAttributeAs (Static)
- /// <summary>
- /// Get attribute. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void GetAttributeAs()
- {
- XmlNode antonNode = TestXml.GetChild("Customers", "CustomerID",
- "ANTON");
-
- Assert.NotNull(antonNode);
- Assert.Equal(31, antonNode.GetAttributeAs("Age", 0));
-
- Assert.NotNull(antonNode);
- Assert.Equal(31, antonNode.GetAttributeAs("Age", 0.0));
-
- Assert.NotNull(antonNode);
- Assert.Equal(31, antonNode.GetAttributeAs("Age", 0.0f));
- }
- #endregion
-
- #region WillChildInheritNamespace (Static)
- /// <summary>
- /// Get namespace name
- /// </summary>
- [Test]
- public static void WillChildInheritNamespace()
- {
- XmlNode rootNode = TestXml;
-
- //Retrieve NamespaceName of rootNode
- string namespaceName = rootNode.xNodeRoot.Name.NamespaceName;
- string testNamespaceName = "testNamespace";
- string emptyNamespaceName = "";
-
- //Enable WillChildInheritNamespace
- rootNode.WillChildInheritNamespace = true;
-
- //Add child, inherit namespace
- XmlNode childNode = rootNode.AddChild("TestNode1");
- Assert.Equal(childNode.xNodeRoot.Name.NamespaceName,
- namespaceName);
- Assert.True(childNode.WillChildInheritNamespace);
-
- //Disable WillChildInheritNamespace
- rootNode.WillChildInheritNamespace = false;
-
- //Add child with different namespace
- XmlNode childNodeNS = rootNode.AddChild(
- GetNamespaceName(testNamespaceName, "TestNode2"));
- Assert.Equal(childNodeNS.xNodeRoot.Name.NamespaceName,
- testNamespaceName);
- Assert.False(childNodeNS.WillChildInheritNamespace);
-
- //Add child with empty namespace
- childNodeNS = rootNode.AddChild(
- GetNamespaceName(emptyNamespaceName, "TestNode3"));
- Assert.Equal(childNodeNS.xNodeRoot.Name.NamespaceName,
- emptyNamespaceName);
- Assert.False(childNodeNS.WillChildInheritNamespace);
- }
- #endregion
- }
- }
- }