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.HasFlag(HtmlTagFlags.EmbeddedCode))
{
int firstCharPosition = _innerContext.Position;
char firstCharValue;
bool firstCharExist = content.TryGetChar(firstCharPosition, out firstCharValue);
if (firstCharExist && firstCharValue == '<')
{
int secondCharPosition = firstCharPosition + 1;
char secondCharValue;
bool secondCharExist = content.TryGetChar(secondCharPosition, out secondCharValue);
if (secondCharExist)
{
if (secondCharValue.IsAlphaNumeric())
{
// Start tag
isProcessed = ProcessStartTag();
}
else
{
int thirdCharPosition = secondCharPosition + 1;
char thirdCharValue;
bool thirdCharExist = content.TryGetChar(thirdCharPosition, out thirdCharValue);
if (thirdCharExist)
{
switch (secondCharValue)
{
case '/':
if (thirdCharValue.IsAlphaNumeric())
{
isProcessed = ProcessEndTag();
}
break;
case '!':
switch (thirdCharValue)
{
case '-':
int fourthCharPosition = thirdCharPosition + 1;
char fourthCharValue;
bool fourthCharExist = content.TryGetChar(fourthCharPosition, out fourthCharValue);
if (fourthCharExist && fourthCharValue == '-')
{
// Comments
int fifthCharPosition = fourthCharPosition + 1;
char fifthCharValue;
bool fifthCharExist = content.TryGetChar(fifthCharPosition, out fifthCharValue);
if (fifthCharExist)
{
if (fifthCharValue == '[')
{
// 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 '[':
// Remaining conditional comments
// Hidden End If conditional comment (e.g. <![endif]-->)
isProcessed = ProcessHiddenEndIfComment();
if (!isProcessed)
{
// Revealed If conditional comment (e.g. <![if ... ]>)
isProcessed = ProcessRevealedIfComment();
}
if (!isProcessed)
{
// Revealed End If conditional comment (e.g. <![endif]>)
isProcessed = ProcessRevealedEndIfComment();
}
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();
_htmlTagFlagsCache.Clear();
_customHtmlTagFlagsCache.Clear();
_conditionalCommentStack.Clear();
_conditionalCommentOpened = false;
_xmlTagStack.Clear();
_context = null;
_innerContext = null;
}
}
}