List <HtmlAttribute> GetAttributes(ref bool isSingle) { List <HtmlAttribute> attributes = new List <HtmlAttribute> (); TextTokenizer.MoveNext(); while (true) { if (IsEnd(ref isSingle)) { break; } switch (TextTokenizer.Current.Type) { case HtmlTokenType.String: HtmlAttribute attribute = new HtmlAttribute(TextTokenizer.Current); attributes.Add(attribute); TextTokenizer.MoveNext(); if (IsEnd(ref isSingle)) { return(attributes); } switch (TextTokenizer.Current.Type) { case HtmlTokenType.EqualSign: TextTokenizer.MoveNext(); switch (TextTokenizer.Current.Type) { case HtmlTokenType.String: attribute.Values = new List <string> (); string value = HtmlAPI.Unescape(TextTokenizer.Current.String); if (HtmlAPI.Equals(attribute.Name, HtmlKeyword.Class)) { attribute.Values.AddRange(HtmlAPI.Split(value)); } else { attribute.Values.Add(value); } TextTokenizer.MoveNext(); continue; } throw new HtmlTextReaderException <HtmlTokenType> (TextTokenizer, "属性值"); case HtmlTokenType.String: continue; default: throw new HtmlTextReaderException <HtmlTokenType> (TextTokenizer, HtmlKeyword.EqualSign, HtmlKeyword.SingleTag, HtmlKeyword.RightAngleBracket); } default: throw new HtmlTextReaderException <HtmlTokenType> (TextTokenizer, "属性名", HtmlKeyword.SingleTag, HtmlKeyword.RightAngleBracket); } } return(attributes); }
bool ReadNode(HtmlElement parentElement, out HtmlNode node, string endElementLocalName = null) { if (MoveNext()) { switch (Current.Type) { case HtmlTagType.Define: node = new HtmlDocumentType(Current.Attributes, parentElement); return(true); case HtmlTagType.Single: node = new HtmlElement(Current.Name, Current.Attributes, parentElement); return(true); case HtmlTagType.Start: { HtmlElement element = new HtmlElement(Current.Name, Current.Attributes, parentElement); node = element; if (HtmlAPI.IsContentTag(element.LocalName)) { TextTokenizer.SkipIgnoreCharacters(); string text = TextTokenizer.ReadTo($"</{element.LocalName}>").TrimEnd(); if (text.Length > 0) { node.ChildNodes.Add(new HtmlText(text, element)); } return(true); } Tags.Add(element.LocalName); HtmlNode lastNode = null; while (ReadNode(element, out HtmlNode childNode, element.LocalName)) { if (childNode is null) { continue; } if (lastNode != null) { lastNode.NextSibling = childNode; childNode.PreviousSibling = lastNode; } node.ChildNodes.Add(childNode); lastNode = childNode; } return(true); } case HtmlTagType.End: if (endElementLocalName != null && !HtmlAPI.Equals(Current.Name, endElementLocalName)) { if (Tags.Contains(Current.Name)) { Buffer.Push(Current); } else { node = null; return(true); } } if (Tags.Count > 0) { Tags.RemoveAt(Tags.Count - 1); } break; case HtmlTagType.Text: node = new HtmlText(HtmlAPI.Unescape(Current.Content), parentElement); return(true); case HtmlTagType.Comment: node = new HtmlComment(Current.Content, parentElement); return(true); default: throw new NotImplementedException(Current.Type.ToString()); } } node = null; return(false); }