Linq查询仅从表的第一行中选择值 [英] Linq query selects values from first row only in table

查看:58
本文介绍了Linq查询仅从表的第一行中选择值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Linq将网站表解析为列表.

I am trying to parse website table to List using Linq.

这是源代码:

<div id="users_table" class="security_slick_container slickgrid_300610 ui-widget" style="overflow: hidden; outline: 0px; position: relative;">
    <div tabindex="0" hidefocus="" style="position:fixed;width:0;height:0;top:0;left:0;outline:0;"></div>
    <div class="slick-header ui-state-default" style="overflow:hidden;position:relative;">
        <div class="slick-header-columns" style="left: -1000px; width: 2132px;" unselectable="on">
            <div class="ui-state-default slick-header-column slick-header-sortable slick-header-column-sorted" id="slickgrid_300610userName" title="" style="width: 94px;"><span class="slick-column-name"><strong>Username:</strong></span><span class="slick-sort-indicator slick-sort-indicator-asc"></span>
                <div class="slick-resizable-handle"></div>
            </div>
            <div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610firstName" title="" style="width: 89px;"><span class="slick-column-name"><strong>Firstname:</strong></span><span class="slick-sort-indicator"></span>
                <div class="slick-resizable-handle"></div>
            </div>
            <div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610lastName" title="" style="width: 109px;"><span class="slick-column-name"><strong>Lastname:</strong></span><span class="slick-sort-indicator"></span>
                <div class="slick-resizable-handle"></div>
            </div>
            <div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610type" title="" style="width: 124px;"><span class="slick-column-name"><strong>Type:</strong></span><span class="slick-sort-indicator"></span>
                <div class="slick-resizable-handle"></div>
            </div>
            <div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610crew" title="" style="width: 109px;"><span class="slick-column-name"><strong>Crew:</strong></span><span class="slick-sort-indicator"></span>
                <div class="slick-resizable-handle"></div>
            </div>
            <div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610jobTitle" title="" style="width: 109px;"><span class="slick-column-name"><strong>Job title:</strong></span><span class="slick-sort-indicator"></span>
                <div class="slick-resizable-handle"></div>
            </div>
            <div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610defaultPriceClass" title="" style="width: 124px;"><span class="slick-column-name"><strong>Defaultprice class:</strong></span><span class="slick-sort-indicator"></span>
                <div class="slick-resizable-handle"></div>
            </div>
            <div class="ui-state-default slick-header-column" id="slickgrid_300610description" title="" style="width: 129px;"><span class="slick-column-name"><strong>Description:</strong></span>
                <div class="slick-resizable-handle"></div>
            </div>
            <div class="ui-state-default slick-header-column" id="slickgrid_300610language" title="" style="width: 39px;"><span class="slick-column-name"><strong>Language:</strong></span>
                <div class="slick-resizable-handle"></div>
            </div>
        </div>
    </div>
    <div class="slick-headerrow ui-state-default" style="overflow: hidden; position: relative; display: none;">
        <div class="slick-headerrow-columns" style="width: 1115px;"></div>
        <div style="display: block; height: 1px; position: absolute; top: 0px; left: 0px; width: 1132px;"></div>
    </div>
    <div class="slick-top-panel-scroller ui-state-default" style="overflow: hidden; position: relative; display: none;">
        <div class="slick-top-panel" style="width:10000px"></div>
    </div>
    <div class="slick-viewport" style="width: 100%; overflow: auto; outline: 0px; position: relative; height: 567px;">
        <div class="grid-canvas" style="height: 16550px; width: 1115px;">
            <div class="ui-widget-content slick-row even" style="top:0px">
                <div class="slick-cell l0 r0">john.smith</div>
                <div class="slick-cell l1 r1">John</div>
                <div class="slick-cell l2 r2">Smith</div>
                <div class="slick-cell l3 r3">Contractor</div>
                <div class="slick-cell l4 r4">Microsoft</div>
                <div class="slick-cell l5 r5">Sales manager</div>
                <div class="slick-cell l6 r6">A</div>
                <div class="slick-cell l7 r7"></div>
                <div class="slick-cell l8 r8">en</div>
            </div>
            <div class="ui-widget-content slick-row odd" style="top:25px">
                <div class="slick-cell l0 r0">robert.geits</div>
                <div class="slick-cell l1 r1">Robert</div>
                <div class="slick-cell l2 r2">Geits</div>
                <div class="slick-cell l3 r3">Staff</div>
                <div class="slick-cell l4 r4">Google</div>
                <div class="slick-cell l5 r5">Project manager</div>
                <div class="slick-cell l6 r6">B</div>
                <div class="slick-cell l7 r7"></div>
                <div class="slick-cell l8 r8">de</div>
            </div>
            <div class="ui-widget-content slick-row even" style="top:50px">
                <div class="slick-cell l0 r0">amir.rooney</div>
                <div class="slick-cell l1 r1">Amir</div>
                <div class="slick-cell l2 r2">Rooney</div>
                <div class="slick-cell l3 r3">Staff</div>
                <div class="slick-cell l4 r4">Microsoft</div>
                <div class="slick-cell l5 r5">Sales manager</div>
                <div class="slick-cell l6 r6">A</div>
                <div class="slick-cell l7 r7"></div>
                <div class="slick-cell l8 r8">en</div>
            </div>
        </div>
    </div>
    <div tabindex="0" hidefocus="" style="position:fixed;width:0;height:0;top:0;left:0;outline:0;"></div>
</div>

什么是执行此类操作的正确Linq查询?我当前的Linq查询出于某种原因仅从表中选择第一行?

What is the right Linq query to perform such an operation? My current Linq query selects only first row from table for some reason?

这是我当前的代码:

var DataHere = from cells in driver.FindElements(By.XPath("//*[@id=\"users_table\"]")) //.FindElements(By.TagName("div"))
               select new
               {
                   Username = cells.FindElement(By.XPath("//div[contains(@class, 'slick-cell l0 r0')]")).Text,
                   Firstname = cells.FindElement(By.XPath("//div[contains(@class, 'slick-cell l1 r1')]")).Text,
                   Lastname = cells.FindElement(By.XPath("//div[contains(@class, 'slick-cell l2 r2')]")).Text,
                   Type = cells.FindElement(By.XPath("//div[contains(@class, 'slick-cell l3 r3')]")).Text,
                   Crew = cells.FindElement(By.XPath("//div[contains(@class, 'slick-cell l4 r4')]")).Text,
                   JobTitle = cells.FindElement(By.XPath("//div[contains(@class, 'slick-cell l5 r5')]")).Text,
                   DefaultPrice = cells.FindElement(By.XPath("//div[contains(@class, 'slick-cell l6 r6')]")).Text,
                   Future = cells.FindElement(By.XPath("//div[contains(@class, 'slick-cell l7 r7')]")).Text,
                   Language = cells.FindElement(By.XPath("//div[contains(@class, 'slick-cell l8 r8')]")).Text,
               };

我正在使用此行检查列表中的值:

I am checking values in List using this line:

DataHere.ToList().ForEach(i => Console.Write("{0}\t", i));

推荐答案

您似乎希望 driver.FindElements(...)返回的每个元素都是< divclass ="ui-widget-content slick-row ..."> 元素.一个简单的CSS选择器应该可以解决问题:

It looks like you expect each element returned by driver.FindElements(...) to be a <div class="ui-widget-content slick-row ..."> element. A simple CSS selector should do the trick:

var rows = driver.FindElements(By.CssSelector("#users_table .slick-viewport .slick-row"));

LINQ语句如下:

var DataHere = from row in driver.FindElements(By.CssSelector("#users_table .slick-viewport .slick-row"))
               select new
               {
                   ...
               };

在每一行中,您需要找到单元格"似乎是< div class ="slick-cell"> .您的xpath都以//开头以查找每个单元格.这些xpath将在全局范围内进行评估-它将搜索 entire 网页.您想将xpath的作用域限定为每一行.代替:

Within each row you need to find "cells" which seem to be <div class="slick-cell">. Your xpaths all begin with // to find each cell. Those xpaths will be evaluated globally — it will search the entire web page. You want to scope the xpaths to each row. Instead of:

rows.FindElement(By.XPath("//div[contains(@class, 'slick-cell l0 r0')]"))

您要在每个xpath前面加上.字符:

You want to prefix each xpath with a . character:

      row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l0 r0')]"))
                                ^
                                |
This becomes relative xpath ----+

.字符表示Selenium将在当前 row 对象中搜索,这是您在本例中想要的.如果不这样做,Selenium将返回整个网页中与XPath表达式匹配的第一个元素.

The . character means Selenium will search within the current row object, which is what you want in this case. If you don't, Selenium returns the very first element in the entire web page that matches the XPath expression.

我还建议创建一个代表每个对象的正确的页面对象模型行:

I would also recommend creating a proper page object model representing each row:

public class UserTableRow
{
    private readonly IWebElement row;

    public string Username => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l0 r0')]")).Text,
    public string Firstname => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l1 r1')]")).Text,
    public string Lastname => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l2 r2')]")).Text,
    public string Type => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l3 r3')]")).Text,
    public string Crew => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l4 r4')]")).Text,
    public string JobTitle => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l5 r5')]")).Text,
    public string DefaultPrice => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l6 r6')]")).Text,
    public string Future => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l7 r7')]")).Text,
    public string Language => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l8 r8')]")).Text,

    public UserTableRow(IWebElement row)
    {
        this.row = row;
    }
}

这将真正清理您的LINQ语句:

This will really clean up your LINQ statement:

var DataHere = from row in driver.FindElements(By.CssSelector("#users_table .slick-viewport .slick-row"))
               select new UserTableRow(row);

这篇关于Linq查询仅从表的第一行中选择值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆