【问题标题】:java find table using jsoup and equivalent xpathjava使用jsoup和等效的xpath查找表
【发布时间】:2017-10-23 15:46:55
【问题描述】:

这是 HTML 代码:

<table class="textfont" cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
    <tbody>
        <tr>
            <td class="chl" width="20%">Batch ID</td><td class="ctext">d32654464bdb424396f6a91f2af29ecf</td>
        </tr>
        <tr>
            <td class="chl" width="20%">ALM Server</td>
            <td class="ctext"></td>
        </tr>
        <tr>
            <td class="chl" width="20%">ALM Domain/Project</td>
            <td class="ctext">EBUSINESS/STERLING</td>
        </tr>
        <tr>
            <td class="chl" width="20%">TestSet URL</td>
            <td class="ctext">almtestset://<a href="http://localhost.com">localhost</a></td>
        </tr>
        <tr>
            <td class="chl" width="20%">Tests Executed</td>
            <td class="ctext"><b>6</b></td>
        </tr>
        <tr>
            <td class="chl" width="20%">Start Time</td>
            <td class="ctext">08/31/2017 12:20:46 PM</td>
        </tr>
        <tr>
            <td class="chl" width="20%">Finish Time</td>
            <td class="ctext">08/31/2017 02:31:46 PM</td>
        </tr>
        <tr>
            <td class="chl" width="20%">Total Duration</td>
            <td class="ctext"><b>2h 11m </b></td>
        </tr>
        <tr>
            <td class="chl" width="20%">Test Parameters</td>
            <td class="ctext"><b>{&quot;browser&quot;:&quot;chrome&quot;,&quot;browser-version&quot;:&quot;56&quot;,&quot;language&quot;:&quot;english&quot;,&quot;country&quot;:&quot;US&quot;}</b></td>
        </tr>
        <tr>
            <td class="chl" width="20%">Passed</td>
            <td class="ctext" style="color:#269900"><b>0</b></td>
        </tr>
        <tr>
            <td class="chl" width="20%">Failed</td>
            <td class="ctext" style="color:#990000"><b>6</b></td>
        </tr>
        <tr>
            <td class="chl" width="20%">Not Completed</td>
            <td class="ctext" style="color: ##ff8000;"><b>0</b></td>
        </tr>
        <tr>
            <td class="chl" width="20%">Test Pass %</td>
            <td class="ctext" style="color:#990000;font-size:14px"><b>0.0%</b></td>
        </tr>
    </tbody>

这是获取表格的 xpath:

//td[text() = 'TestSet URL']/ancestor::table[1]

如何使用 jSoup 获取此表?我试过了:

tableElements = doc.select("td:contains('TestSet URL')");

获取子元素,但这不起作用并返回null。我需要找到桌子并将所有孩子放入地图中。任何帮助将不胜感激!

【问题讨论】:

    标签: java html xpath jsoup


    【解决方案1】:

    以下代码会将您的表格解析为地图,此代码有几个假设:

    • 此 xpath //td[text() = 'TestSet URL']/ancestor::table[1] 将在其正文中的任何位置找到包含文本“TestSet URL”的任何表,这似乎有点脆弱,但假设它对您来说足够了 getTable() 中的 JSoup 代码在功能上等同于xpath
    • 下面的代码假定每一行包含两个单元格,第一个是键,第二个是值,因为您想将表格内容解析为地图,这个假设似乎有效
    • 如果不满足上述假设,即如果给定的 HTML 不包含在其正文中嵌入“TestSet URL”的表定义,或者如果该表的任何行中有两个以上的单元格,则下面的代码将引发异常。

    如果这些假设无效,则 getTableparseTable 的内部结构将发生变化,但通用方法仍然有效。

    public void parseTable() {
        Document doc = Jsoup.parse(html);
    
        // declare a holder to contain the 'mapped rows', this is a map based on the assumption that every row represents a discreet key:value pair
        Map<String, String> asMap = new HashMap<>();
        Element table = getTable(doc);
    
        // now walk though the rows creating a map for each one
        Elements rows = table.select("tr");
        for (int i = 0; i < rows.size(); i++) {
            Element row = rows.get(i);
            Elements cols = row.select("td");
    
            // expecting this table to consist of key:value pairs where the first cell is the key and the second cell is the value
            if (cols.size() == 2) {
                asMap.put(cols.get(0).text(), cols.get(1).text());
            } else {
                throw new RuntimeException(String.format("Cannot parse the table row: %s to a key:value pair because it contains %s cells!", row.text(), cols.size()));
            }
        }
        System.out.println(asMap);
    }
    
    private Element getTable(Document doc) {
        Elements tables = doc.select("table");
        for (int i = 0; i < tables.size(); i++) {
            // this xpath //td[text() = 'TestSet URL']/ancestor::table[1] will find the first table which contains the
            // text "TestSet URL" anywhere in its body
            // this crude evaluation is the JSoup equivalent of that xpath
            if (tables.get(i).text().contains("TestSet URL")) {
                return tables.get(i);
            }
        }
        throw new RuntimeException("Cannot find a table element which contains 'TestSet URL'!");
    }
    

    对于您问题中发布的 HTML,上面的代码将输出:

    {Finish Time=08/31/2017 02:31:46 PM, Passed=0, Test Parameters={"browser":"chrome","browser-version":"56","language":"english","country":"US"}, TestSet URL=almtestset://localhost, Failed=6, Test Pass %=0.0%, Not Completed=0, Start Time=08/31/2017 12:20:46 PM, Total Duration=2h 11m, Tests Executed=6, ALM Domain/Project=EBUSINESS/STERLING, Batch ID=d32654464bdb424396f6a91f2af29ecf, ALM Server=}    
    

    【讨论】:

    • 会看看,谢谢!您的假设是正确的,其中只有一个包含“TestSet URL”的表。每个都是键/值对,尽管有些上的值可能是空的。一旦我评估并尝试了您建议的代码,就会更新。
    • 我发现有些表是嵌入到其他表中的,所以只好调整getTable方法,但是效果很好。非常感谢!
    【解决方案2】:

    您必须删除那些引号才能获得包含文本的行;只是

    tableElements = doc.select("td:contains(TestSet URL)");
    

    但请注意,您只选择包含文本“TestSet URL”的 td 元素。要选择整个表,请使用

    Element table = doc.select("table.textfont").first();
    

    这意味着选择具有 class=textfont 的表,并且为了避免选择具有相同类值的多个表,您必须指定选择哪个表,因此:first()。

    获取所有 tr 元素:

        Elements tableRows = doc.select("table.textfont tr");
        for(Element e: tableRows)
        System.out.println(e);
    

    【讨论】:

      猜你喜欢
      • 2014-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多