void OnEndTagOpen(object sender, HtmlParserOpenTagEventArgs e) { var nameToken = e.NameToken; if (nameToken != null) { ITextProvider text = _parser.Text; Log.AppendFormat("OnEndTagOpen: {0}: @[{1} ... {2}] '{3}'\r\n\tHasNamespace: {4} @[{5} ... {6}]\r\n\tHasName: {7} @[{8} ... {9}]\r\n\r\n", TokenTypeAsString(e.NameToken.TokenType), e.NameToken.Start, e.NameToken.End, text.GetText(e.NameToken), nameToken.HasPrefix().ToString(), nameToken.PrefixRange.Start, nameToken.PrefixRange.End, nameToken.HasName().ToString(), nameToken.NameRange.Start, nameToken.NameRange.End); } else { Log.Append("OnEndTagOpen: null\r\n"); } }
private void OnEndTagOpen(object sender, HtmlParserOpenTagEventArgs e) { // Current element must already be on the stack. It is not null // only when we are processing start tag. Debug.Assert(_currentElementRecord == null); // e.Token contains NameToken describing element prefix:name range. // </ precedes the range immediately. Note that token may contain invalid/empty // range if element name is missing such as in </{ws} or </>. We will ignore // malformed end tags. if (e.NameToken != null && e.NameToken.QualifiedName.Length > 0) { // close at name.start-1 (skip < of the tag, end exclusive) // subtract </ _currentElementRecord = CloseElements(e.NameToken.QualifiedName, e.NameToken.QualifiedName.Start - 2, new string[0]); if (_currentElementRecord != null) { _currentElementRecord.Element.OpenEndTag(e.OpenAngleBracketPosition, e.NameToken, _tree.Text.Length); } else { var dummyElement = new ElementNode(_tree.RootNode, e.OpenAngleBracketPosition, e.NameToken, _tree.Text.Length); _orphanedEndTagRecord = new ElementRecord(dummyElement); _orphanedEndTagRecord.Element.OpenEndTag(e.OpenAngleBracketPosition, e.NameToken, _tree.Text.Length); } } }
private void OnStartTagOpen(object sender, HtmlParserOpenTagEventArgs e) { Debug.Assert(_currentElementRecord == null); // e.NameToken describes element prefix:name range. // < precedes the range immediately. // Artifacts are not allowed in element names. string[] containerNames; // Close any elements on the stack that must be closed either by implicit // closure or by the fact that they are inside the element that is being closed. if (e.NameToken != null && e.NameToken.IsNameWellFormed() && _tree.HtmlClosureProvider.IsImplicitlyClosed(_tree.Text, e.NameToken, out containerNames)) { // close at name.start-1 (skip < of the tag, end exclusive) CloseElements(e.NameToken.QualifiedName, e.NameToken.QualifiedName.Start - 1, containerNames); } // Parent is the element on top of the stack or the root node if stack is empty var parentRecord = _elementStack.Count > 0 ? _elementStack.Peek() : _rootNodeRecord; ElementNode element = new ElementNode(parentRecord.Element, e.OpenAngleBracketPosition, e.NameToken, _tree.Text.Length); parentRecord.Children.Add(element); _currentElementRecord = new ElementRecord(element); }