private static void ParseElement(XmlTextReader reader, Container parent, CharacterPositionFinder finder, IXmlFlavor flavor)
        {
            var name    = flavor.GetName(reader);
            var type    = flavor.GetType(reader);
            var content = flavor.GetContent(reader);

            var container = new Container
            {
                Type    = type,
                Name    = name,
                Content = content,
            };

            var isEmpty = reader.IsEmptyElement;

            var startingSpan = GetLocationSpanWithParseAttributes(reader, container, finder, flavor);
            var headerSpan   = GetCharacterSpan(startingSpan, finder);

            if (isEmpty)
            {
                // there is no content, so we have to get away of the footer by just using the '/>' characters as footer
                var headerSpanCorrected = new CharacterSpan(headerSpan.Start, Math.Max(headerSpan.Start, headerSpan.End - 2));
                var footerSpanCorrected = new CharacterSpan(Math.Max(0, headerSpan.End - 1), headerSpan.End);

                container.LocationSpan = startingSpan;
                container.HeaderSpan   = headerSpanCorrected;
                container.FooterSpan   = footerSpanCorrected;
            }
            else
            {
                while (reader.NodeType != XmlNodeType.EndElement)
                {
                    Parse(reader, container, finder, flavor);

                    // we had a side effect (reading further on stream to get the location span), so we have to check whether we found already an element or end element
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        continue;
                    }

                    if (reader.NodeType == XmlNodeType.EndElement)
                    {
                        break;
                    }
                }

                var endingSpan = GetLocationSpan(reader);
                var footerSpan = GetCharacterSpan(endingSpan, finder);

                container.LocationSpan = new LocationSpan(startingSpan.Start, endingSpan.End);
                container.HeaderSpan   = headerSpan;
                container.FooterSpan   = footerSpan;
            }

            // check whether we can use a terminal node instead
            var child = flavor.FinalAdjustAfterParsingComplete(container);

            parent.Children.Add(child);
        }
        private static void ParseTerminalNode(XmlTextReader reader, Container parent, CharacterPositionFinder finder, IXmlFlavor flavor)
        {
            var name    = flavor.GetName(reader);
            var type    = flavor.GetType(reader);
            var content = flavor.GetContent(reader);

            var locationSpan = GetLocationSpan(reader);
            var span         = GetCharacterSpan(locationSpan, finder);

            var child = AddTerminalNode(parent, type, name, content, locationSpan, span);

            flavor.FinalAdjustAfterParsingComplete(child);
        }
        private static void ParseAttribute(XmlTextReader reader, Container parent, CharacterPositionFinder finder, IXmlFlavor flavor)
        {
            var attributeStartPos = new LineInfo(reader.LineNumber, reader.LinePosition);

            var name = flavor.GetName(reader);
            var type = flavor.GetType(reader);

            // important call to be able to read the attribute value
            reader.ReadAttributeValue();

            var content = flavor.GetContent(reader);

            var attributeEndPos = new LineInfo(reader.LineNumber, reader.LinePosition + content.Length);

            var startPos = finder.GetCharacterPosition(attributeStartPos);
            var endPos   = finder.GetCharacterPosition(attributeEndPos);

            var locationSpan = new LocationSpan(attributeStartPos, attributeEndPos);
            var span         = new CharacterSpan(startPos, endPos);

            var child = AddTerminalNode(parent, type, name, content, locationSpan, span);

            flavor.FinalAdjustAfterParsingComplete(child);
        }