diff --git a/src/HtmlAgilityPack.Shared/HtmlNode.cs b/src/HtmlAgilityPack.Shared/HtmlNode.cs index 5fb4313..7c7fa04 100644 --- a/src/HtmlAgilityPack.Shared/HtmlNode.cs +++ b/src/HtmlAgilityPack.Shared/HtmlNode.cs @@ -756,10 +756,28 @@ public static bool CanOverlapElement(string name) /// The HTML text. /// The newly created node instance. public static HtmlNode CreateNode(string html) + { + return CreateNode(html, null); + } + + /// + /// Creates an HTML node from a string representing literal HTML. + /// + /// The HTML text. + /// The HTML Document builder. + /// The newly created node instance. + public static HtmlNode CreateNode(string html, Action htmlDocumentBuilder) { // REVIEW: this is *not* optimum... HtmlDocument doc = new HtmlDocument(); + + if (htmlDocumentBuilder != null) + { + htmlDocumentBuilder(doc); + } + doc.LoadHtml(html); + if (!doc.DocumentNode.IsSingleElementNode()) { throw new Exception("Multiple node elments can't be created."); @@ -1447,20 +1465,11 @@ public T GetAttributeValue(string name, T def) { return def; } - - TypeConverter converter = TypeDescriptor.GetConverter(typeof(T)); - try - { - if (converter != null && converter.CanConvertTo(att.Value.GetType())) - { - return (T)converter.ConvertTo(att.Value, typeof(T)); - } - else - { - return (T) (object) att.Value; - } - } + try + { + return (T)att.Value.To(typeof(T)); + } catch { return def; @@ -1659,6 +1668,61 @@ public void RemoveAllIDforNode(HtmlNode node) } } + /// Move a node already associated and append it to this node instead. + /// The child node to move. + public void MoveChild(HtmlNode child) + { + if (child == null) + { + throw new ArgumentNullException($"Oops! the '{nameof(child)}' parameter cannot be null."); + } + + var oldParent = child.ParentNode; + + AppendChild(child); + + if (oldParent != null) + { + oldParent.RemoveChild(child); + } + } + + /// Move a children collection already associated and append it to this node instead. + /// The children collection already associated to move to another node. + public void MoveChildren(HtmlNodeCollection children) + { + if (children == null) + { + throw new ArgumentNullException($"Oops! the '{nameof(children)}' parameter cannot be null."); + } + + var oldParent = children.ParentNode; + + AppendChildren(children); + + if (oldParent != null) + { + oldParent.RemoveChildren(children); + } + } + + /// Removes the children collection for this node. + /// The old children collection to remove. + public void RemoveChildren(HtmlNodeCollection oldChildren) + { + if (oldChildren == null) + { + throw new ArgumentNullException($"Oops! the '{nameof(oldChildren)}' parameter cannot be null."); + } + + var list = oldChildren.ToList(); + + foreach (HtmlNode newChild in list) + { + RemoveChild(newChild); + } + } + /// /// Removes the specified child node. /// diff --git a/src/HtmlAgilityPack.Shared/HtmlNodeCollection.cs b/src/HtmlAgilityPack.Shared/HtmlNodeCollection.cs index 43df9a2..8a04636 100644 --- a/src/HtmlAgilityPack.Shared/HtmlNodeCollection.cs +++ b/src/HtmlAgilityPack.Shared/HtmlNodeCollection.cs @@ -38,6 +38,15 @@ public HtmlNodeCollection(HtmlNode parentnode) #region Properties + /// Gets the parent node associated to the collection. + internal HtmlNode ParentNode + { + get + { + return _parentnode; + } + } + /// /// Gets a given node from the list. /// diff --git a/src/HtmlAgilityPack.Shared/Utilities.cs b/src/HtmlAgilityPack.Shared/Utilities.cs index e3bdec9..e515197 100644 --- a/src/HtmlAgilityPack.Shared/Utilities.cs +++ b/src/HtmlAgilityPack.Shared/Utilities.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; namespace HtmlAgilityPack { @@ -19,5 +20,45 @@ internal static class Utilities return defaultValue; return value; } + +#if !(METRO || NETSTANDARD1_3 || NETSTANDARD1_6) + internal static object To(this Object @this, Type type) + { + if (@this != null) + { + Type targetType = type; + + if (@this.GetType() == targetType) + { + return @this; + } + + TypeConverter converter = TypeDescriptor.GetConverter(@this); + if (converter != null) + { + if (converter.CanConvertTo(targetType)) + { + return converter.ConvertTo(@this, targetType); + } + } + + converter = TypeDescriptor.GetConverter(targetType); + if (converter != null) + { + if (converter.CanConvertFrom(@this.GetType())) + { + return converter.ConvertFrom(@this); + } + } + + if (@this == DBNull.Value) + { + return null; + } + } + + return @this; + } +#endif } } \ No newline at end of file