php xpath evaluate duplicate data get only first row

邮差的信 提交于 2019-12-12 04:37:52

问题


This is my PHP code:

<?php

error_reporting(E_ALL);
ini_set("display_errors",1);

ini_set('max_execution_time', 36000); //300 seconds = 5 minutes

$url = 'http://www.sportstats.com/soccer/matches/20170815/';

libxml_use_internal_errors(true); 
$doc = new DOMDocument();
$doc->loadHTMLFile($url);
$xpath = new DOMXpath($doc);


$data = array(

'HomeTeam' => $xpath->evaluate('string(//td[@class="table-home"]/a)'),
'AwayTeam' => $xpath->evaluate('string(//td[contains(@class, "table-away")]/a)'),
'FtScore' => $xpath->evaluate('string(normalize-space(translate(//td[@class="result-neutral"]," " ,"")))'),
'HomeTeamid' => $xpath->evaluate('substring-before(substring-after(substring-after(//td[@class="table-home"]/a/@href, "/soccer/"),"-"),"/")'),
'AwayTeamid' => $xpath->evaluate('substring-before(substring-after(substring-after(//td[@class="table-away"]/a/@href, "/soccer/"),"-"),"/")')

);

foreach ($data as $key) {

echo $data['HomeTeamid'].",";
echo $data['HomeTeam'].",";
echo $data['FtScore'].",";
echo $data['AwayTeam'].",";
echo $data['AwayTeamid']."<br/>";

}

?>

But the script gives duplicate results:

n3QdnjFB,Santos,0-0,Fluminense,EV9L3kU4
n3QdnjFB,Santos,0-0,Fluminense,EV9L3kU4
n3QdnjFB,Santos,0-0,Fluminense,EV9L3kU4
n3QdnjFB,Santos,0-0,Fluminense,EV9L3kU4
n3QdnjFB,Santos,0-0,Fluminense,EV9L3kU4

But I want it's look like...

 HTeamid,Santos,0-0,Fluminense,ATeamid
 HTeamid,Cartagena,1-0,Llaneros,ATeamid
 HTeamid,Cerro Porteno,1-1,Libertad Asuncion,ATeamid
 HTeamid,Operario,2-1,Maranhao,ATeamid
 HTeamid,Emelec,2-0,Fuerza,ATeamid
 ...
 ..
 .

Matches list image I looked at other questions on the site and didn"t find an answer How do i do get all other teams data with echo command (I don't want to do with var_dump). Thanks.


回答1:


Here are two mistakes, you use //td in the location path. This makes the path relative to the document and the string function always return the text content of the first node in the list. You get always the first game.

The typical structure for fetching list data is:

foreach($xpath->evaluate($exprForItems) as $item) {
  $detail = $xpath->evaluate($exprForDetail, $item);
}

A more specific example:

$document = new DOMDocument();
$document->loadHtml($html);
$xpath = new DOMXpath($document);

$expressions = new stdClass();
// this is the expression for items - it returns a node list
$expressions->games = '//div[@id = "LS_todayMatchesContent"]/table/tbody/tr';
// this are detail expressions - they return a string
$expressions->home = 'string(td[@class = "table-home"]/a)';
$expressions->homeId = 'substring-before(substring-after(substring-after(td[@class="table-home"]/a/@href, "/soccer/"),"-"),"/")';
$expressions->away= 'string(td[@class = "table-away"]/a)';

foreach ($xpath->evaluate($expressions->games) as $game) {
  var_dump(
    [
      $xpath->evaluate($expressions->home, $game),
      $xpath->evaluate($expressions->homeId, $game),
      $xpath->evaluate($expressions->away, $game)
    ]
  );
}

Output:

array(3) {
  [0]=>
  string(6) "Santos"
  [1]=>
  string(8) "n3QdnjFB"
  [2]=>
  string(10) "Fluminense"
}
array(3) {
  [0]=>
  string(9) "Cartagena"
  [1]=>
  string(8) "6eofBSjQ"
  [2]=>
  string(8) "Llaneros"
}
//...

So only the detail expressions use the string functions and they always need the item node as the context (second argument). You have to be careful to use the context.




回答2:


Try edit your xpath array like this:

'HomeTeam' => $xpath->query('//td[@class="table-home"]/a'),
'AwayTeam' => $xpath->query('//td[contains(@class, "table-away")]/a'),
'FtScore' => $xpath->query('//td[@class="result-neutral"]'),
...

using query and altering paths.

And then you can echo your results like this:

foreach ($data as $dataKey => $dataValue) {
    foreach ($dataValue as $key => $element) {
        $nodes = $element->childNodes;  
        foreach ($nodes as $node) { 
            $tag = $node->nodeValue;
            echo $dataKey.' - '.$key.' - '.$tag.'<br>';  //$dataKey and $key are just informative
        }
    }
    echo '<br>';
}

For me, it listed:

HomeTeam - 0 - Santos
HomeTeam - 1 - Cartagena
HomeTeam - 2 - Cerro Porteno
HomeTeam - 3 - Operario
HomeTeam - 4 - Boca Juniors
HomeTeam - 5 - Emelec
....
AwayTeam - 0 - Fluminense
AwayTeam - 1 - Llaneros
AwayTeam - 2 - Libertad Asuncion
AwayTeam - 3 - Maranhao
AwayTeam - 4 - Gimnasia y Tiro
AwayTeam - 5 - Fuerza A.
....

Of course, if you want some meaningful print of data, you need it to collect in array....

Hope this is the answer you are looking for :) Have a great day!



来源:https://stackoverflow.com/questions/45712585/php-xpath-evaluate-duplicate-data-get-only-first-row

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!