private static void AddPreserveFormat( [NotNull] this XElement parentNode, [NotNull] XElement newElement, [CanBeNull] XElement insertAfterElement) { Code.NotNull(parentNode, nameof(parentNode)); Code.NotNull(newElement, nameof(newElement)); Code.AssertState(parentNode.Document != null, "The parent node should be attached to document."); Code.AssertState(newElement.Document == null, "The new node should not be attached to document."); // The node after that we'll insert new one var insertNode = insertAfterElement ?? parentNode.Nodes().LastOrDefault(n => !(n is XText)); // Find indentation text for item and for closing parent node (lazily) var closeTagIndentText = Lazy.Create( () => parentNode.ScanUp().FirstIndentNodeOrDefault()?.Value ?? NewLineChars); var indentText = insertNode?.NodesBeforeSelf().FirstIndentNodeOrDefault()?.Value ?? (closeTagIndentText.Value + IndentChars); var indentNode = new XText(indentText); if (insertNode != null) { // There's element or comment in parent: add indent and new node after it insertNode.AddAfterSelf(indentNode); indentNode.AddAfterSelf(newElement); } else { // Parent has no elements: search new line indent for closing parent node var closeTagIndentNode = parentNode.Nodes().FirstIndentNodeOrDefault(); if (closeTagIndentNode != null) { // There is indent for closing parent node: insert before it closeTagIndentNode.AddBeforeSelf(indentNode); indentNode.AddAfterSelf(newElement); } else { // Add indent, new node and indent for closing parent node parentNode.Add(indentNode); indentNode.AddAfterSelf(newElement); newElement.AddAfterSelf(new XText(closeTagIndentText.Value)); } } }
public static void AddAfterSelfIndented(this XNode self, XElement addedElement) { string selfIndent; if (TryGetElementIndent(self, out selfIndent)) { IndentDescendantNodes(addedElement, selfIndent); var newLineAndIndent = new XText("\n" + selfIndent); self.AddAfterSelf(newLineAndIndent); newLineAndIndent.AddAfterSelf(addedElement); } else { // Ignore indent self.AddAfterSelf(addedElement); } }