/// <summary> /// Parses XML content /// </summary> /// <param name="content">XML content</param> public void Parse(string content) { int contentLength = content.Length; if (contentLength == 0) { return; } lock (_parsingSynchronizer) { _innerContext = new InnerMarkupParsingContext(content); _context = new MarkupParsingContext(_innerContext); int endPosition = contentLength - 1; int previousPosition = -1; try { while (_innerContext.Position <= endPosition) { bool isProcessed = false; if (_innerContext.PeekCurrentChar() == '<') { switch (_innerContext.PeekNextChar()) { case char c when IsTagFirstChar(c): // Start tag isProcessed = ProcessStartTag(); break; case '/': if (IsTagFirstChar(_innerContext.PeekNextChar())) { // End tag isProcessed = ProcessEndTag(); } break; case '!': switch (_innerContext.PeekNextChar()) { case '-': if (_innerContext.PeekNextChar() == '-') { // XML comments isProcessed = ProcessComment(); } break; case '[': // CDATA sections isProcessed = ProcessCdataSection(); break; case 'D': // Doctype declaration isProcessed = ProcessDoctype(); break; } break; case '?': // XML declaration and processing instructions isProcessed = ProcessProcessingInstruction(); break; } } if (!isProcessed) { // Text ProcessText(); } if (_innerContext.Position == previousPosition) { throw new MarkupParsingException( string.Format(Strings.ErrorMessage_MarkupParsingFailed, "XML"), _innerContext.NodeCoordinates, _innerContext.GetSourceFragment()); } previousPosition = _innerContext.Position; } // Check whether there were not closed tags if (_tagStack.Count > 0) { StackedXmlTag stackedTag = _tagStack.Pop(); throw new MarkupParsingException( string.Format(Strings.ErrorMessage_NotClosedTag, stackedTag.Name), stackedTag.Coordinates, SourceCodeNavigator.GetSourceFragment(_innerContext.SourceCode, stackedTag.Coordinates)); } } catch (MarkupParsingException) { throw; } finally { _tagStack.Clear(); _context = null; _innerContext = null; } } }
/// <summary> /// Parses HTML content /// </summary> /// <param name="content">HTML content</param> public void Parse(string content) { int contentLength = content.Length; if (contentLength == 0) { return; } lock (_parsingSynchronizer) { _innerContext = new InnerMarkupParsingContext(content); _context = new MarkupParsingContext(_innerContext); int endPosition = contentLength - 1; int previousPosition = -1; try { while (_innerContext.Position <= endPosition) { bool isProcessed = false; HtmlTag lastStackedTag = _tagStack.LastOrDefault(); // Make sure we're not in a tag, that contains embedded code if (lastStackedTag == null || !lastStackedTag.Flags.IsSet(HtmlTagFlags.EmbeddedCode)) { if (_innerContext.PeekCurrentChar() == '<') { switch (_innerContext.PeekNextChar()) { case char c when c.IsAlphaNumeric(): // Start tag isProcessed = ProcessStartTag(); break; case '/': if (_innerContext.PeekNextChar().IsAlphaNumeric()) { // End tag isProcessed = ProcessEndTag(); } break; case '!': switch (_innerContext.PeekNextChar()) { case '-': if (_innerContext.PeekNextChar() == '-') { // Comments if (_innerContext.PeekNextChar() == '[') { // Revealed validating If conditional comments // (e.g. <!--[if ... ]><!--> or <!--[if ... ]>-->) isProcessed = ProcessRevealedValidatingIfComment(); if (!isProcessed) { // Hidden If conditional comments (e.g. <!--[if ... ]>) isProcessed = ProcessHiddenIfComment(); } } else { // Revealed validating End If conditional comments // (e.g. <!--<![endif]-->) isProcessed = ProcessRevealedValidatingEndIfComment(); } if (!isProcessed) { // HTML comments isProcessed = ProcessComment(); } } break; case '[': switch (_innerContext.PeekNextChar()) { case 'i': case 'I': // Revealed If conditional comment (e.g. <![if ... ]>) isProcessed = ProcessRevealedIfComment(); break; case 'e': case 'E': // Hidden End If conditional comment (e.g. <![endif]-->) isProcessed = ProcessHiddenEndIfComment(); if (!isProcessed) { // Revealed End If conditional comment (e.g. <![endif]>) isProcessed = ProcessRevealedEndIfComment(); } break; case 'C': // CDATA sections isProcessed = ProcessCdataSection(); break; } break; case 'D': case 'd': // Doctype declaration isProcessed = ProcessDoctype(); break; } break; case '?': // XML declaration isProcessed = ProcessXmlDeclaration(); break; } } if (!isProcessed) { // Text ProcessText(); } } else { // Embedded code ProcessEmbeddedCode(); } if (_innerContext.Position == previousPosition) { throw new MarkupParsingException( string.Format(Strings.ErrorMessage_MarkupParsingFailed, "HTML"), _innerContext.NodeCoordinates, _innerContext.GetSourceFragment()); } previousPosition = _innerContext.Position; } // Clean up any remaining tags ParseEndTag(); // Check whether there were not closed conditional comment if (_conditionalCommentStack.Count > 0) { throw new MarkupParsingException( Strings.ErrorMessage_NotClosedConditionalComment, _innerContext.NodeCoordinates, _innerContext.GetSourceFragment()); } } catch (MarkupParsingException) { throw; } finally { _tagStack.Clear(); _tempAttributes.Clear(); _conditionalCommentStack.Clear(); _conditionalCommentOpened = false; _xmlTagStack.Clear(); _context = null; _innerContext = null; } } }