PHP Xpath:按类名获取节点值

时间:2016-01-08 20:43:40

标签: php xpath

我正在使用xpath从一段HTML代码中提取数据,而且我已经能够提取大部分数据,除了一件。

HTML的结构如下,但可能只有一个或两个或全部三个,所以我需要能够通过类名来定位它。

LiveAPI.getMatch(match.getId());

此代码已使用xpath查询检索,然后使用以下PHP代码段从xpath查询的结果中提取更多数据。

<li>
    <a href="http://www.website.com">Product URL</a>
</li>
<li>
    <ul>
        <li class="itemone">1</li>
        <li class="itemtwo">2</li>
        <li class="itemthree">3</li>
    </ul>
</li>

问题是$rawData = $xpath->query('//div[@id=\'products\']/ul/li[contains(@class, \'product\')]'); foreach($rawData as $data) { $productRaw = $data->getElementsByTagName('li'); $productTitle = $productRaw[0]->getElementsByTagName('a')[0]->nodeValue; $productRefCode = $productRaw[0]->getElementsByTagName('span')[0]->nodeValue; $productPrice = $productRaw[1]->getElementsByTagName('li'); } ,上面一行是拉出下面的节点列表。

$productPrice

我希望在上面的节点列表中找到类名为DOMNodeList Object ( [length] => 3 ) 的任何内容,我在itemtwo上使用$xpath->query并尝试了$productRaw[1]但没有运气,我已经尝试了下面的两个片段而没有运气。

getElementsByClassName

这两个代码段都会显示错误$productPrice = $productRaw[1]->getElementsByTagName('li')->getElementsByClassName('itemtwo'); ... $productPrice = $productRaw[1]->query('//li[contains(@class, \'itemtwo\')]'); Fatal error: Call to undefined method DOMNodeList::getElementsByClassName()

3 个答案:

答案 0 :(得分:1)

使用DOMXPath::query,将XPath字符串作为第一个参数并将DOMNode作为第二个参数,以相对于某些DOMNode上下文执行XPath,例如:

foreach($rawData as $data) {
    $productRaw = $data->getElementsByTagName('li');
    .....
    $productPrice = $xpath->query('.//li[contains(@class, "itemtwo")]', $productRaw->item(1));
}

还要在XPath表达式的开头使用.来明确告诉表达式是否与当前上下文节点相关。

答案 1 :(得分:0)

这样的东西?

public static void drawLine(Tile t1, Tile t2) {
    int dx = t2.x_index - t1.x_index;
    int dy = t2.y_index - t1.y_index;
    double error = 0;
    double d_error = Math.abs((double) dy / dx); // dx =/= 0, therefore no vertical lines

    // when d_error is greater than 1, the bug occurs

    int y = t1.y_index;
    if (d_error <= 1) { // if related acute angle is < 45 degrees
        if (dx < 0) { // line drawn towards left side of screen
            for (int x=t1.x_index; x>=t2.x_index; x--) {
                Board.tiles[x][y].setColour(Color.red);
                error += d_error;
                while (error >= 0.5) {
                    Board.tiles[x][y].setColour(Color.red);
                    y += dy > 0 ? +1 : -1;// this is where I think the error occurs. In the 
                                          // wiki for the algorithm, this should be some 
                                          // function sign(T) which "decides whether t is 
                                          // positive or negative". I wasn't really sure 
                                          // what this meant, so I just assumed it returned 
                                          // -1 if it was negative and +1 if it was positive. 
                                          // Also it's the only place where y is edited
                                          // that seems to be where the error is occurring. 
                    error -= 1.0;
                }
            }
        } else if (dx > 0) { // line drawn towards right side of screen
            for (int x=t1.x_index; x<=t2.x_index; x++) {
                Board.tiles[x][y].setColour(Color.red);
                error += d_error;
                while (error >= 0.5) {
                    Board.tiles[x][y].setColour(Color.red);
                    y += dy > 0 ? +1 : -1;
                    error -= 1.0;
                }
            }
        }

    // update: switched x and y values when d_error is greater than 1.

    } else { // if related acute angle is > 45 degrees
        dx = t2.y_index - t1.y_index; // switch x and y values
        dy = t2.x_index - t1.x_index;

        d_error = Math.abs((double) dy / dx); // recalculate d_error
        y = t1.x_index;
        if (dx < 0) { // line drawn towards left side of screen
            for (int x=t1.y_index; x>=t2.y_index; x--) {
                Board.tiles[x][y].setColour(Color.red);
                error += d_error;
                while (error >= 0.5) {
                    Board.tiles[x][y].setColour(Color.red);
                    y += dy > 0 ? +1 : -1;
                    error -= 1.0;
                }
            }
        } else if (dx > 0) { // line drawn towards right side of screen
            for (int x=t1.y_index; x<=t2.y_index; x++) {
                Board.tiles[x][y].setColour(Color.red);
                error += d_error;
                while (error >= 0.5) {
                    Board.tiles[x][y].setColour(Color.red);
                    y += dy > 0 ? +1 : -1;
                    error -= 1.0;
                }
            }
        }
    }
}

答案 2 :(得分:0)

har07的回答是在正确的轨道上,但它只返回了长度设置为3的节点列表,就像我已经收到的现有代码一样。

原始代码:

$productPrice = $productRaw[1]->getElementsByTagName('li');

har07的建议:

$productPrice = $xpath->query('.//li[contains(@class, "itemtwo")]', $productRaw->item(1));

解决方案,返回元素类名称等于itemtwo的节点值:

$productPrice = $xpath->query('.//li[contains(@class, \'itemtwo\')]', $productRaw[1])->item(1)->nodeValue;