protected static string ResolveInnerText(AbstractSavannahXmlNode node, string spaceText)
        {
            var text      = node.InnerText.UnifiedBreakLine();
            var lines     = text.Split('\n');
            var converted = string.Join("\n", lines.Select(x => $"{spaceText}{x}"));

            return(converted);
        }
        /// <summary>
        /// Generate a string in XML format with child elements from a node.
        /// </summary>
        /// <param name="node">Target node.</param>
        /// <param name="space">Indent space size</param>
        /// <returns>String in XML format.</returns>
        protected static string ToString(AbstractSavannahXmlNode node, int indentSize, int space = 0)
        {
            var spaceText = MakeSpace(space);

            var sb = new StringBuilder();

            if (node is SavannahTagNode tagNode)
            {
                var attr = tagNode.Attributes.ToAttributesText(" ");
                attr = string.IsNullOrEmpty(attr) ? attr : $" {attr}";

                if (tagNode.ChildNodes.Any())
                {
                    sb.Append($"{spaceText}<{tagNode.TagName}{attr}>\n");
                    space += indentSize;
                    foreach (var childNode in tagNode.ChildNodes)
                    {
                        sb.Append($"{ToString(childNode, indentSize, space)}\n");
                    }

                    sb.Append($"{spaceText}</{tagNode.TagName}>");
                }
                else
                {
                    sb.Append($"{spaceText}<{tagNode.TagName}{attr} />");
                }
            }
            else if (node is SavannahTextNode)
            {
                sb.Append(ResolveInnerText(node, spaceText));
            }
            else if (node is SavannahCdataNode)
            {
                sb.Append($"{spaceText}<![CDATA[\n");
                sb.Append(ResolveInnerText(node, MakeSpace(space)));
                sb.Append($"\n{spaceText}]]>");
            }
            else
            {
                sb.Append($"{spaceText}<!--\n");
                sb.Append(ResolveInnerText(node, MakeSpace(space + indentSize)));
                sb.Append($"\n{spaceText}-->");
            }


            return(sb.ToString());
        }
        protected static string GenerateOutterXml(AbstractSavannahXmlNode node, int indentSize)
        {
            if (node.Parent == null)
            {
                return(string.Empty);
            }

            if (node.Parent is SavannahTagNode parentTagNode)
            {
                var indent   = MakeSpace(indentSize);
                var str      = node.ToString();
                var innerXml = string.Join("", node.ToString().Split('\n').Select(item => $"{indent}{item}\n"));
                var attr     = parentTagNode.Attributes.ToAttributesText(" ");
                return($"<{node.Parent.TagName}{attr}>\n{innerXml}</{node.Parent.TagName}>");
            }

            return(string.Empty);
        }