internal static void AddFromSelectNode(this List<KeyValuePair<string, string>> list, HtmlNode node) { string value = ""; foreach (HtmlNode option in node.ChildNodes) { if (option.Attributes.ContainsKey("selected")) { value = option.Attributes["value"]; break; } } list.Add(Create(node.Attributes["name"], value)); }
internal static void AddFromInputNode(this List<KeyValuePair<string, string>> list, HtmlNode node) { if (!node.Attributes.ContainsKey("type")) { list.AddParameter(node); return; } var type = node.Attributes["type"]; if (!"radio".EqualsIgnoreCase(type) && !"checkbox".EqualsIgnoreCase(type)) { list.AddParameter(node); return; } if (node.Attributes.ContainsKey("checked")) { list.AddParameter(node); return; } }
static private void AddParameter(this List<KeyValuePair<string, string>> List, HtmlNode node) { if (!node.Attributes.ContainsKey("value")) { List.Add(Create(node.Attributes["name"], "")); return; } List.Add(Create(node.Attributes["name"], node.Attributes["value"].Replace(' ', '+'))); }
/// <summary> /// 指定された位置にノードを挿入する /// </summary> /// <param name="index"></param> /// <param name="htmlNode"></param> public void Insert(int index,HtmlNode htmlNode) { _nodeList.Insert(index, htmlNode); }
/// <summary> /// ノードを追加する /// </summary> /// <param name="htmlNode"></param> public void Add(HtmlNode htmlNode) { _nodeList.Add(htmlNode); }
//属性を解析する private void ParseAttribute(HtmlNode node) { while (true) { bool isName = true; //名前=値形式の属性か否か falseの場合、名前=値形式 char delimitter = ' '; //値を区切るデリミタ ' 'を入れているのはコンパイルを通すため bool valueStarted = false; //現在位置が値の中に入っているか bool delimitterUsed = false; //デリミタが使用されているか StringBuilder name = new StringBuilder(); StringBuilder value = new StringBuilder(); while (!MoveNext()) { //=が見つかった場合 if (Current == '=') { isName = false; break; } else if (Current == '>') { if (name.ToString().Trim().Length != 0) { node.Attributes.Add(name.ToString(), null); } return; } //スペースが見つかった場合 else if (Current == ' ' || Current == '/') { //次の文字が=以外の場合(A=B形式の属性で無い場合) if (!EofAt(1) && CharAt(1) != '=') { if (name.ToString().Trim().Length != 0) { node.Attributes.Add(name.ToString(), null); } break; } continue; } // =、またはスペース以外の場合 else { name.Append(Current); } } if (isName) continue; while (!MoveNext()) { //現在位置が値の中に入っていない場合 if (!valueStarted) { if (Current == ' ') { continue; } else if (Current == '\'' || Current == '"') { delimitter = Current; delimitterUsed = true; valueStarted = true; //value.Append(Current); } else { value.Append(Current); valueStarted = true; } } //現在位置が値の中に入っている場合 else { if (delimitterUsed) { if (Current == delimitter) { //value.Append(Current); if (name.Length != 0 && value.Length != 0) { node.Attributes.Add(name.ToString(), value.ToString()); } break; } else { value.Append(Current); } } else { if (Current == ' ' || Current == '/' || Current == '>') { if (name.Length != 0 && value.Length != 0) { node.Attributes.Add(name.ToString(), value.ToString()); } if (Current == '>') { return; } else if (Current == '/') { node.NodeType = NodeType.SelfComplete; break; } else { break; } } else { value.Append(Current); } } } } } }
//タグを解析し、タグの終端まで移動する private HtmlNode ParseTag() { HtmlNode node = null; bool isEndTag = false; //終了タグか否かを判定する if (!EofAt(1)) { if (CharAt(1) == '/') { isEndTag = true; if (MoveNext()) return null; } } //タグ名を取得する StringBuilder tagName = new StringBuilder(); //タグ名の終了位置まで移動する while (!MoveNext()) { if (Current == ' ' || Current == '/' || Current == '>') { break; } tagName.Append(Current); } if (tagName.Length != 0) { node = new HtmlNode(_ignoreCase); node.TagName = tagName.ToString(); if (isEndTag) { node.NodeType = NodeType.EndTag; } else { node.NodeType = NodeType.Tag; } if (Current == '/') { node.NodeType = NodeType.SelfComplete; } } else { return null; } //属性が有る場合 if (!isEndTag && Current != '/' && Current != '>') { if (node != null) { if (!tagName.ToString().Equals("!DOCTYPE", StringComparison.OrdinalIgnoreCase)) { //属性を解析する ParseAttribute(node); } } } //タグの終端まで移動 while(Current != '>') { if (MoveNext()) return null; } return node; }
/// <summary> /// HTMLの階層を構築する /// </summary> private void BuildHierarchy(List<HtmlNode> nodeList, HtmlNode node) { //Console.WriteLine("\r\nBuildHierarchy:{0}-{1}", node != null ? node.TagName : "doc", nodeList.Count); int addedText = 0; HtmlNodeList parentList = new HtmlNodeList(); while (true) { //Console.WriteLine("{0} begin loop:{1}",node != null ? node.TagName : "doc",nodeList.Count); HtmlNode startNode = null; HtmlNode endNode = null; List<HtmlNode> childList = new List<HtmlNode>(); int startTagPos = -1; int endTagPos = -1; int endTagCount = 0; String endTagName = null; //リストの後方から最初にある終了タグを探す for (int i = nodeList.Count - 1; i >= 0; i--) { //終了タグがまだ見つかっていない場合 if (endTagPos == -1) { if (nodeList[i].NodeType == NodeType.EndTag) { endTagPos = i; endTagName = nodeList[i].TagName; endNode = nodeList[i]; //Console.WriteLine("{0} endTagName:{1}", node != null ? node.TagName : "doc", endTagName); } else { if (addedText <= nodeList.Count - 1 - i) { parentList.Insert(0, nodeList[i]); addedText++; } } } //終了タグが見つかっている場合 else { //同一タグ名の終了タグが見つかった場合 if (nodeList[i].NodeType == NodeType.EndTag && nodeList[i].TagName.Equals(endTagName, StringComparison.OrdinalIgnoreCase)) { //終了タグを発見してから同一タグの終了タグが見つかった場合、カウントアップする endTagCount++; } //開始タグが見つかった場合 else if (nodeList[i].NodeType == NodeType.Tag && nodeList[i].TagName.Equals(endTagName, StringComparison.OrdinalIgnoreCase)) { //カウンターが1以上の場合、他の終了タグに対応する開始タグを表す if (endTagCount <= 0) { startTagPos = i; startNode = nodeList[i]; //開始タグと終了タグの間を切りとり、子供のノードに渡す for (int x = startTagPos + 1; x < endTagPos; x++) { nodeList[x].ParentNode = startNode; childList.Add(nodeList[x]); //Console.WriteLine("{0}-{1}-{2} childlist:{3} - {4}", startTagPos, endTagPos, node != null ? node.TagName : "doc", nodeList[x].NodeType,nodeList[x].NodeType == NodeType.Text ? nodeList[x].Text : nodeList[x].TagName); } //開始タグ、終了タグを含む、間のタグを親のリストから削除する nodeList.Remove(startNode); nodeList.Remove(endNode); foreach (HtmlNode childNode in childList) { nodeList.Remove(childNode); } startNode.ParentNode = node; BuildHierarchy(childList, startNode); break; } else { endTagCount--; } } } } if (endTagPos != -1) { if (startTagPos == -1) { //throw new Exception("開始タグがない"); nodeList.Remove(endNode); parentList.Insert(0, endNode); } else { //先頭に追加 parentList.Insert(0, startNode); } } else { break; } } node.ChildNodes = parentList; //Console.WriteLine("終了:BuildHierarchy:{0}-{1}\r\n", node != null ? node.TagName : "doc", nodeList.Count); }