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); }