Reputation: 21
I have a problem with xpath. I'm trying to get data from this:
<div class="clan__table">
<div class="clan__headers">
<div class="clan__headerCaption">Rank</div>
<div class="clan__headerCaption">Name</div>
<div class="clan__headerCaption">Level</div>
<div class="clan__headerCaption">League</div>
<div class="clan__headerCaption">Trophies</div>
<div class="clan__headerCaption">Donations</div>
<div class="clan__headerCaption">Role</div>
</div>
<div class="clan__rowContainer">
<div class="clan__row">
#2
</div>
<div class="clan__row">
<a class="ui__blueLink" href='/profile/8C2PQYYL'>Voodoo</a>
</div>
<div class="clan__row">
<span class="clan__playerLevel">11</span>
</div>
<div class="clan__row">
<div class="clan__leagueContainer">
<div class="league__1"></div>
</div>
</div>
<div class="clan__row">
<div class="clan__cup">4000</div>
</div>
<div class="clan__row">96</div>
<div class="clan__row">
Co-Leader
</div>
</div>
....
....
this is my code:
$xpath2 = new DOMXPath($doc2);
$text = "";
$playerlist_ul = $xpath2->query("//div[@class='clan__table']")->item(0);
$playernodes = $playerlist_ul->childNodes;
if (!empty($playernodes))
{
foreach ($playernodes as $node2)
{
if ($node2->hasChildNodes())
{
$playerinfo = new DOMDocument();
libxml_use_internal_errors(true);
$playerinfo->loadHTML($node2->ownerDocument->saveHTML($node2));
$xpath3 = new DOMXPath($playerinfo);
$player['level'] = $xpath3->query("//span[@class='clan__playerLevel']")->item(0)->
textContent;
$player['name'] = $xpath3->query("//a[@class='ui__blueLink']")->item(0)->
textContent;
$player['id'] = $xpath3->query("//a[@class='ui__blueLink']/@href")->item(0)->
textContent;
$player['trophy'] = $xpath3->query("//div[@class='clan__cup']")->item(0)->
textContent;
$player['role'] = $xpath3->query("//div[@class='clan__row']")->item(6)->
textContent;
$player['donate'] = $xpath3->query("//div[@class='clan__row']")->item(5)->
textContent;
$player['clan_position'] = $xpath3->query("//div[@class='clan__row']")->item(0)->
textContent;
$players[] = $player;
}
}
}
Everything almost working but i get error: Trying to get property of non-object in every line with $player['....'] This is result
array (size=49)
0 =>
array (size=6)
'level' => null
'name' => null
'trophy' => null
'role' => null
'donate' => null
'clan_position' => null
1 =>
array (size=6)
'level' => string '11' (length=2)
'name' => string '/profile/8C2PQYYL' (length=17)
'trophy' => string '4056' (length=4)
'role' => string '
Co-Leader
' (length=44)
'donate' => string '192' (length=3)
'clan_position' => string '
#1
' (length=52)
There is something wrong with array[0] So my question is: How to avoid this error?
Upvotes: 0
Views: 612
Reputation: 19492
DOMXpath::query()
will always return a DOMNodeList
instance. You're fetching an node from that list and access its $textContent
property. The error happens if here is no node.
It is easy to solve if you use DOMXpath::evaluate()
. Xpath expression allow for typecasts, but only DOMXpath::evaluate()
supports scalar return values.
So basically you use foreach()
for expressions that return a node list and inside that expressions with typecasts for the details. Here is no need to save a fragment and load it as a separate document, you can provide a context node for the expression.
$document = new DOMDocument();
$document->loadHtml($html);
$xpath = new DOMXpath($document);
$expression = "//div[@class='clan__table']/div[@class='clan__rowContainer']";
foreach ($xpath->evaluate($expression) as $clanNode) {
$result = [
'level' => $xpath->evaluate("string(.//span[@class='clan__playerLevel'])", $clanNode),
'name' => $xpath->evaluate("string(.//a[@class='ui__blueLink'])", $clanNode),
'id' => $xpath->evaluate("string(.//a[@class='ui__blueLink']/@href)", $clanNode),
'trophy' => $xpath->evaluate("string(.//div[@class='clan__cup'])", $clanNode),
'role' => $xpath->evaluate("string(.//div[@class='clan__row'][7])", $clanNode),
'donate' => $xpath->evaluate("string(.//div[@class='clan__row'][6])", $clanNode),
'clan_position' => $xpath->evaluate(
"normalize-space(.//div[@class='clan__row'][1])", $clanNode
)
];
var_dump($result);
}
Output:
array(7) {
["level"]=>
string(2) "11"
["name"]=>
string(6) "Voodoo"
["id"]=>
string(17) "/profile/8C2PQYYL"
["trophy"]=>
string(4) "4000"
["role"]=>
string(46) "
Co-Leader
"
["donate"]=>
string(2) "96"
["clan_position"]=>
string(2) "#2"
}
A little about the Xpath string()
is an explicit typecast. It returns the text content of the first node of the list or an empty string. normalize-space()
includes an implicit typecast, but it remove trims the string and replaces all groups of whitespaces with single spaces. [6]
is the 6th element in the node list.
Upvotes: 1