迭代通过xpath求值返回

How is correct wayt to interate all elements return by xpath->evaluate?

i have that structure:

<?
$html = '
<div class="xGh" style="background-image: url(\'name_file0.jpg\');"></div>
<div class="xGh" style="background-image: url(\'name_file1.jpg\');"></div>
<div class="xGh" style="background-image: url(\'name_file2.jpg\');"></div>
<div class="xGh" style="background-image: url(\'name_file3.jpg\');"></div>
';

libxml_use_internal_errors(true);
$dom = new domDocument('1.0', 'utf-8'); 
$dom->loadHTML($html); 
$dom->preserveWhiteSpace = false; 
$xpath = new DOMXPath($dom);

$img = $xpath->evaluate('substring-before(substring-after(//div[@class=\'xGh\']/@style, "background-image: url(\'"), "\')")');    

echo $img;//name_file0.jpg

edit

With that loop in can iterate my object, but not correct result:

<?
$html = '
<div class="xGh" style="background-image: url(\'name_file0.jpg\');"></div>
<div class="xGh" style="background-image: url(\'name_file1.jpg\');"></div>
<div class="xGh" style="background-image: url(\'name_file2.jpg\');"></div>
<div class="xGh" style="background-image: url(\'name_file3.jpg\');"></div>
';

libxml_use_internal_errors(true);
$dom = new domDocument('1.0', 'utf-8'); 
$dom->loadHTML($html); 
$dom->preserveWhiteSpace = false; 
$xpath = new DOMXPath($dom);

$items = $xpath->query('//div[@class="xGh"]');
for($i = 0; $i < $items->length; $i++)
{   $ci = $xpath->evaluate("substring-before(substring-after(//*[@class=\"xGh\"]/@style, \"background-image: url('\"), \"')\")");
echo $ci;
}//name_file0.jpgname_file0.jpgname_file0.jpgname_file0.jpg

The output needed is :

name_file0.jpgname_file1.jpgname_file2.jpgname_file3.jpg

Where is the correct place to put one count iterator in that loop, to give sequence files not the same?

How iterate to return others?

Let's try this:

<?php

$html = '
<div class="xGh" style="background-image: url(\'name_file0.jpg\');"></div>
<div class="xGh" style="background-image: url(\'name_file1.jpg\');"></div>
<div class="xGh" style="background-image: url(\'name_file2.jpg\');"></div>
<div class="xGh" style="background-image: url(\'name_file3.jpg\');"></div>
';

libxml_use_internal_errors(true);
$dom = new DOMDocument('1.0', 'utf-8');
$dom->loadHTML($html);
$dom->preserveWhiteSpace = false;
$xpath = new DOMXPath($dom);

$divs = $xpath->query('//div[@class=\'xGh\']/@style');

/* @var DOMAttr $div */
foreach ($divs as $div) {
    preg_match("/url\('(.*)'\)/", $div->nodeValue, $matches);

    if (!isset($matches[1])) {
        continue;
    }
    $url = $matches[1];

    // name_file0.jpg, ...
    echo $url . "
";
}

substring-after() and substring-before() are Xpath string functions. If the first argument is a location path, they will cast the nodes list result into a string. That means it will return the text content of the first node in the list or an empty string if the list was empty.

The return value of DOMXpath::evaluate() depends on the expression. If the expression is a location path, it will be an node list. If you use string function or operators it might be an scalar. These kind of expression are not supported by DOMXpath::query() however.

Typically you need one location path expression to iterate the nodes and then use DOM node methods/properties and detail expressions using the node as context.

@daniel-o used the DOMNode::$nodeValue and used PCRE in PHP. This is the easier solution here, but it would work with Xpath as well.

$attributes = $xpath->evaluate('//div[@class=\'xGh\']/@style');
/* @var DOMAttr $style */
foreach ($attributes as $style) {
  $url = $xpath->evaluate(
    'substring-before(substring-after(., "background-image: url(\'"), "\')")', 
    $style
  );
  var_dump($url); 
}