PHP Xpath尝试获取非对象

时间:2017-07-06 17:55:54

标签: php xml xpath

我遇到xpath问题。我试图从中获取数据:

<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>
....
....

这是我的代码:

$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;
        }
    }
}

一切几乎正常但我得到错误:尝试使用$ player [&#39; ....&#39;]获取每行中非对象的属性 这是结果

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) 

数组[0]有问题 所以我的问题是:如何避免这个错误?

1 个答案:

答案 0 :(得分:1)

DOMXpath::query()将始终返回DOMNodeList个实例。您从该列表中获取节点并访问其$textContent属性。如果此处没有节点,则会发生错误。

如果您使用DOMXpath::evaluate(),则很容易解决。 Xpath表达式允许类型转换,但只有DOMXpath::evaluate()支持标量返回值。

所以基本上你使用foreach()表达式返回节点列表,并在表达式中使用类型转换来获取详细信息。这里不需要保存片段并将其作为单独的文档加载,您可以为表达式提供上下文节点。

$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);
}

输出:

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"
}

关于Xpath string()的一点点是一个明确的类型转换。它返回列表的第一个节点的文本内容或空字符串。 normalize-space()包含一个隐式类型转换,但是删除修剪字符串并用单个空格替换所有空白组。 [6]是节点列表中的第6个元素。