php xpath evaluate duplicate data get only first r

2019-09-13 22:47发布

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.

2条回答
狗以群分
2楼-- · 2019-09-13 23:41

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!

查看更多
来,给爷笑一个
3楼-- · 2019-09-13 23:45

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.

查看更多
登录 后发表回答