public IDocumentFragment ExtractContent() { var fragment = _start.Node.Owner !.CreateDocumentFragment(); if (!_start.Equals(_end)) { var newBoundary = _start; var originalStart = _start; var originalEnd = _end; if (originalStart.Node == originalEnd.Node && _start.Node is ICharacterData) { var text = (ICharacterData)originalStart.Node; var strt = originalStart.Offset; var span = originalEnd.Offset - originalStart.Offset; var clone = (ICharacterData)text.Clone(); clone.Data = text.Substring(strt, span); fragment.AppendChild(clone); text.Replace(strt, span, String.Empty); } else { var commonAncestor = originalStart.Node; while (!commonAncestor.IsInclusiveAncestorOf(originalEnd.Node)) { commonAncestor = commonAncestor.Parent !; } var firstPartiallyContainedChild = !originalStart.Node.IsInclusiveAncestorOf(originalEnd.Node) ? commonAncestor.GetNodes <INode>(predicate: IsPartiallyContained).FirstOrDefault() : null; var lastPartiallyContainedchild = !originalEnd.Node.IsInclusiveAncestorOf(originalStart.Node) ? commonAncestor.GetNodes <INode>(predicate: IsPartiallyContained).LastOrDefault() : null; var containedChildren = commonAncestor.GetNodes <INode>(predicate: Intersects).ToList(); if (containedChildren.OfType <IDocumentType>().Any()) { throw new DomException(DomError.HierarchyRequest); } if (!originalStart.Node.IsInclusiveAncestorOf(originalEnd.Node)) { var referenceNode = originalStart.Node; while (referenceNode.Parent != null && !referenceNode.IsInclusiveAncestorOf(originalEnd.Node)) { referenceNode = referenceNode.Parent; } newBoundary = new Boundary(referenceNode, referenceNode.Parent !.ChildNodes.Index(referenceNode) + 1); } if (firstPartiallyContainedChild is ICharacterData) { var text = (ICharacterData)originalStart.Node; var strt = originalStart.Offset; var span = text.Length - originalStart.Offset; var clone = (ICharacterData)text.Clone(); clone.Data = text.Substring(strt, span); fragment.AppendChild(clone); text.Replace(strt, span, String.Empty); } else if (firstPartiallyContainedChild != null) { var clone = firstPartiallyContainedChild.Clone(); fragment.AppendChild(clone); var subrange = new Range(originalStart, new Boundary(firstPartiallyContainedChild, firstPartiallyContainedChild.ChildNodes.Length)); var subfragment = subrange.ExtractContent(); fragment.AppendChild(subfragment); } foreach (var child in containedChildren) { fragment.AppendChild(child); } if (lastPartiallyContainedchild is ICharacterData) { var text = (ICharacterData)originalEnd.Node; var clone = (ICharacterData)text.Clone(); clone.Data = text.Substring(0, originalEnd.Offset); fragment.AppendChild(clone); text.Replace(0, originalEnd.Offset, String.Empty); } else if (lastPartiallyContainedchild != null) { var clone = lastPartiallyContainedchild.Clone(); fragment.AppendChild(clone); var subrange = new Range(new Boundary(lastPartiallyContainedchild, 0), originalEnd); var subfragment = subrange.ExtractContent(); fragment.AppendChild(subfragment); } _start = newBoundary; _end = newBoundary; } } return(fragment); }
public void Insert(INode node) { if (node is null) { throw new ArgumentNullException(nameof(node)); } var snode = _start.Node; var type = snode.NodeType; var istext = type == NodeType.Text; if (type == NodeType.ProcessingInstruction || type == NodeType.Comment || (istext && snode.Parent is null)) { throw new DomException(DomError.HierarchyRequest); } var referenceNode = istext ? snode : _start.ChildAtOffset; var parent = referenceNode is null ? snode : referenceNode.Parent; parent !.EnsurePreInsertionValidity(node, referenceNode); if (istext) { referenceNode = ((IText)snode).Split(_start.Offset); parent = referenceNode.Parent; } if (node == referenceNode) { referenceNode = referenceNode.NextSibling; } node.Parent?.RemoveChild(node); var newOffset = referenceNode is null ? parent !.ChildNodes.Length : parent !.ChildNodes.Index(referenceNode); newOffset += node.NodeType == NodeType.DocumentFragment ? node.ChildNodes.Length : 1; parent.PreInsert(node, referenceNode); if (_start.Equals(_end)) { _end = new Boundary(parent, newOffset); } }
public void ClearContent() { if (!_start.Equals(_end)) { var newBoundary = new Boundary(); var originalStart = _start; var originalEnd = _end; if (originalEnd.Node == originalStart.Node && originalStart.Node is ICharacterData) { var strt = originalStart.Offset; var text = (ICharacterData)originalStart.Node; var span = originalEnd.Offset - originalStart.Offset; text.Replace(strt, span, String.Empty); } else { var nodesToRemove = Nodes.Where(m => !Intersects(m.Parent !)).ToArray(); if (!originalStart.Node.IsInclusiveAncestorOf(originalEnd.Node)) { var referenceNode = originalStart.Node; while (referenceNode.Parent != null && referenceNode.Parent.IsInclusiveAncestorOf(originalEnd.Node)) { referenceNode = referenceNode.Parent; } newBoundary = new Boundary(referenceNode.Parent !, referenceNode.Parent !.ChildNodes.Index(referenceNode) + 1); } else { newBoundary = originalStart; } if (originalStart.Node is ICharacterData) { var strt = originalStart.Offset; var text = (ICharacterData)originalStart.Node; var span = originalEnd.Offset - originalStart.Offset; text.Replace(strt, span, String.Empty); } foreach (var node in nodesToRemove) { node.Parent !.RemoveChild(node); } if (originalEnd.Node is ICharacterData) { var strt = 0; var text = (ICharacterData)originalEnd.Node; var span = originalEnd.Offset; text.Replace(strt, span, String.Empty); } _start = newBoundary; _end = newBoundary; } } }