/// <summary> /// 指定したノードのフォーマット済みHtmlを返す /// </summary> /// <param name="element"></param> /// <returns></returns> public virtual string Format(HtmlElement element) { if (element == null) { throw new ArgumentNullException("element"); } StringBuilder sb = new StringBuilder(); bool format = false; // 開始タグ sb.Append("<").Append(element.Name); // 属性を付加 foreach (HtmlAttribute attr in element.Attributes) { sb.Append(" ").Append(attr.Html); } if (element.Nodes.Count > 0) { sb.Append(">"); indent++; // 子ノードのHtmlを生成 foreach (HtmlNode child in element.Nodes) { if (child is HtmlText) { HtmlText text = (HtmlText)child; sb.Append(text.Content); format = false; } else { HtmlElement childElem = (HtmlElement)child; if (childElem.IsTerminated) { format = true; } if (format) { sb.Append(newline); InsertSpace(sb, indent); } string html = Format(childElem); sb.Append(html); format = true; } } --indent; if (format) { sb.Append(newline); InsertSpace(sb, indent); } sb.Append("</").Append(element.Name).Append(">"); } else { if (element.IsEmptyElementTag) { sb.Append("/>"); } else if (element.IsTerminated) { sb.Append("></").Append(element.Name).Append(">"); } else { sb.Append(">"); } } return(sb.ToString()); }
/// <summary> /// Htmlを解析してノードコレクションを生成 /// </summary> /// <param name="html"></param> /// <returns></returns> public HtmlNodeCollection Parse(string html) { if (html == null) { throw new ArgumentNullException("html"); } // 改行文字などを削除 html = RemoveWhiteSpace(html); HtmlNodeCollection root = new HtmlNodeCollection(null); int index = 0; while (index < html.Length) { // コメントは無視する if (is_match(html, index, "<!--")) { index += 4; // コメントが終わるまでindexを進める while (index < html.Length) { if (is_match(html, index, "-->")) { index += 3; break; } index++; } } // 閉じるタグの場合 else if (is_match(html, index, "</")) { index += 2; // 空白読み飛ばし SkipWhiteSpace(html, ref index); // タグ名を取得 Match m = rexTagName.Match(html, index); if (m.Success) { // 同じ名前の開始タグを取得 int nodeidx = BackFindOpenElement(root, m.Value); if (nodeidx != -1) { NodesDown(root, nodeidx + 1, (HtmlElement)root[nodeidx]); } else { // throw new HtmlException(); } index += m.Length; } // 終了タグが来るまでスキップ SkipChars(html, ref index, "<>".ToCharArray()); if (is_match(html, index, ">")) { index++; } } // 開始タグの場合 else if (is_match(html, index, "<")) { index += 1; // 空白読み飛ばし SkipWhiteSpace(html, ref index); // タグ名を取得 Match m = rexTagName.Match(html, index); if (m.Success) { HtmlElement e = new HtmlElement(m.Value.ToLower()); root.Add(e); index = m.Index + m.Length; // 空白読み飛ばし SkipWhiteSpace(html, ref index); // 属性の読み込み if (not_match(html, index, "/>") && not_match(html, index, ">")) { ParseAttributes(html, ref index, e.Attributes); } // 1つで完結するタグの処理 if (is_match(html, index, "/>")) { e.IsEmptyElementTag = true; index += 2; } // 終了タグの場合 else if (is_match(html, index, ">")) { index++; } } } // テキスト処理 else { // 開始タグを検索し、そこまでをテキストとする int next = html.IndexOf("<", index); HtmlText text; if (next == -1) { text = new HtmlText(html.Substring(index)); index = html.Length; } else { text = new HtmlText(html.Substring(index, next - index)); index = next; } root.Add(text); } } return(root); }