Могу ли я получить результат вложенных классов domxpath в массив со значением keys =>? - PullRequest
0 голосов
/ 19 сентября 2019

Я получаю некоторые данные с веб-страницы для клиентов, и это отлично работает, он получает все данные в отдельных строках, разбивая \ n на новые строки, которые я затем сопоставляю с конкретными данными массива, чтобы заполнить поля формы.Точно так же для каждого необходимого значения:

$lines = explode("\n", $html);
$data['vraagprijs']         = preg_replace("/[^0-9]/", "", $lines[5]);

Однако данные, которые мне нужны, могут быть в строке 10 сегодня, но вполне могут быть строкой 11 завтра.Поэтому я хотел бы получить значения в именованных массивах.Пример HTML-кода в URL выглядит следующим образом:

<div class="item_list">             
<span class="item first status">
    <span class="itemName">Status</span>                        
    <span class="itemValue">Sold</span>
</span>
<span class="item price">
    <span class="itemName">Vraagprijs</span>
    <span class="itemValue">389.000</span>
</span>
<span class="item condition">
    <span class="itemName">Aanvaarding</span>
    <span class="itemValue">In overleg</span>
</span>
...
</div>

Это моя функциональная модель:

$tagName3   = 'div';
$attrName3  = 'class';
$attrValue3 = 'item_list';
$html       = getShortTags($tagName3, $attrName3, $attrValue3, $url); 

function getShortTags($tagName, $attrName, $attrValue, $url = "", $exclAttrValue = 'itemTitle') {

    $dom = $this->getDom($url);

    $html                 = '';
    $domxpath             = new \DOMXPath($dom);
    $newDom               = new \DOMDocument;
    $newDom->formatOutput = true;

    $filtered = $domxpath->query(" //" . $tagName . "[@" . $attrName . "='" . $attrValue . "']/descendant::text()[not(parent::span/@" . $attrName . "='" . $exclAttrValue . "')] ");
    $i        = 0;
    while ($myItem   = $filtered->item($i++)) {
        $node   = $newDom->importNode($myItem, true);
        $newDom->appendChild($node); 
    }
    $html = $newDom->saveHTML();
    return $html;
}

Что я получаю?

Status\nSold\nVraagprijs\n389.000\nIn overleg\n....

Требуемый вывод что-то вроде:

$html = array("Status" => "Sold", "Vraagprijs" => "389.000", "Aanvaarding" => "In overleg", ...)

Есть ли способ «циклически проходить» по itemList и получать каждое itemName и itemValue в ассоциативный массив?

1 Ответ

0 голосов
/ 19 сентября 2019

Если вы довольны тем, что делает метод getShortTags() (или если он используется в другом месте, и его так сложно настроить), то вы можете обработать возвращаемое значение.

Этот код сначала использует explode() для разделениявывод за строкой использует array_map() и trim() для удаления любых пробелов и т. д., а затем передает результат через array_filter() для удаления пустых строк.Это оставит данные в парах, поэтому проще всего использовать array_chunk() для извлечения пар, а затем foreach() для пар с первым в качестве ключа и вторым в качестве значения ...

$html = getShortTags($tagName3, $attrName3, $attrValue3, $url);
$lines = array_filter(array_map("trim", explode(PHP_EOL, $html)));
$pairs = array_chunk($lines, 2);
$output = [];
foreach ( $pairs as $pair ) {
    $output[$pair[0]] = $pair[1];
}
print_r($output);

с примером данных дает ..

Array
(
    [Status] => Sold
    [Vraagprijs] => 389.000
    [Aanvaarding] => In overleg
)

Чтобы использовать это непосредственно в документе и без каких-либо предположений (хотя, если у вас нет имени для нескольких значений, то не знаете, чтовы в конечном итоге).Это просто выглядит специально для базового элемента, а затем зацикливается на элементах <span>.Каждый раз внутри этого он будет искать атрибуты класса itemName и itemValue и получать значение из этих ...

$output = [];
$filtered = $domxpath->query("//div[@class='item_list']/span");
foreach ( $filtered as $myItem )  {
    $name= $domxpath->evaluate("string(descendant::span[@class='itemName'])", $myItem);
    $value= $domxpath->evaluate("string(descendant::span[@class='itemValue'])", $myItem);
    $output[$name] = $value;
}
print_r($output);
...