Search code examples
phpxpathdomdocument

Loop through elements and parse them whith DOMDocument() in PHP


I've a list of item like this:

<div class="list">
    <div class="ui_checkbox type hidden" data-categories="57 48 ">
        <input id="attraction_type_119" type="checkbox" value="119"
        <label for="attraction_type_119">Aquariums</label>
    </div>
    <div class="ui_checkbox type " data-categories="47 ">
        <input id="attraction_type_120" type="checkbox" value="120"
        <label for="attraction_type_120">Arènes et stades</label>
    </div>
</div>

How can I loop through them with DOMDocument to get details like:

  • data-categories
  • input value
  • label text

This is what I tried:

$dom = new DOMDocument();
$dom->loadHTML($html);
$xp = new DOMXpath($dom);
$elements = $dom->getElementsByTagName('div');
$data = array();
foreach($elements as $node){
    foreach($node->childNodes as $child) {
        $data['data_categorie'] = $child->item(0)->getAttribute('data_categories');
        $data['input_value'] = $child->item(0)->getAttribute('input_value');
        $data['label_text'] = $child->item(0)->getAttribute('label_text');
    }
}

But it doesn't work.

What I'm missing here please ?

Thanks.


Solution

  • Setting multiple values in the loop like this $data['data_categorie'] = using the same key for the array $data = array(); will overwrite the values on every iteration.

    As you have multiple items, you could create a temporary array $temp = []; to store the values and add the array to the $data array after storing all the values for the current iteration.

    As you are already using DOMXpath, you could get the div with class="list" using an expression like //div[@class="list"]/div and loop the childNodes checking for nodeName input and get that value plus the value of the next sibling which is the value of the label

    $data = array();
    $xp = new DOMXpath($dom);
    $items = $xp->query('//div[@class="list"]/div');
    foreach($items as $item) {
        $temp["data_categorie"] = $item->getAttribute("data-categories");
        foreach ($item->childNodes as $child) {
            if ($child->nodeName === "input") {
                $temp["input_value"] = $child->getAttribute("value");
                $temp["label_text"] = $child->nextSibling->nodeValue;
            }
        }
        $data[] = $temp;
    }
    
    print_r($data);
    

    Output

    Array
    (
        [0] => Array
            (
                [data_categorie] => 57 48 
                [input_value] => 119
                [label_text] => Aquariums
    
            )
    
        [1] => Array
            (
                [data_categorie] => 47 
                [input_value] => 120
                [label_text] => Arènes et stades
    
            )
    
    )
    

    Php demo