/// <summary> /// Gets a named entity starting at the currrent /// character ('&') and proceeding until ';'. /// Returns null if the substring does not match /// the expected entity sequence. /// </summary> private static string GetNamedEntity(ITextParser tp) { const string kValidCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; var startPos = tp.Position + 1; var offset = 1; char c; while (true) { c = tp.Peek(offset); if (kValidCharacters.IndexOf(c) == -1) { break; } offset++; } if (c != ';') { return(null); } var length = offset - 1; if (length < 1) { return(null); } return(tp.Substring(startPos, length)); }
/// <summary> /// Skips all characters until the end tag for the given /// <paramref name="tagName"/>. /// </summary> /// <remarks> /// Uses a simple rule: the CData ends at the next /// instance of the end tag. An end that appears in /// the text of the tag--not sure if that can /// happen, but maybe--will be treated as the end. /// </remarks> private void SkipToEndOfScriptCData(string tagName) { var endOffset = tagName.Length + 2; var haveCData = false; while (!tp.EndOfText) { if (tp.Peek() == '<' && tp.Peek(1) == '/' && tp.Peek(endOffset) == '>') { var endTag = tp.Substring(tp.Position + 2, tagName.Length); if (endTag.Equals(tagName, StringComparison.OrdinalIgnoreCase)) { break; } } if (!haveCData) { haveCData = true; xml.Append(kScriptCDataStart); } xml.Append(tp.Peek()); tp.MoveAhead(); } if (haveCData) { xml.Append(kScriptCDataEnd); } return; }
/// <summary> /// Parses the element name from the tag using the given /// <see cref="ITextParser"/> <paramref name="tp"/>. The /// <see cref="ITextParser"/> position should be set to /// the first character of the tag following the "<", /// or following the "</" for end tags. /// Returns true if a syntactically valid name is found. /// </summary> private bool ParseName(ITextParser tp) { const string nameCharacters = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:"; var startPos = tp.Position; var offset = 0; char c; while ((c = tp.Peek(offset)) != TextParser.NullChar) { if (nameCharacters.IndexOf(c) == -1) { break; } offset++; } // Did we get any valid characters? if (offset < 1) { return(false); } // Does the tag name end properly? if (c != '>' && c != '/' && !Char.IsWhiteSpace(c)) { return(false); } if (tp.Peek(offset - 1) == ':') { return(false); } // Our minimal validation has passed... tp.MoveAhead(offset); var length = tp.Position - startPos; Name = tp.Substring(startPos, length).ToLower(); // Force void elements to be self-closing tags. IsSelfClosingTag = IsVoidElement(Name); return(true); }