У меня есть строка, содержащая также HTML в переменной $html:
'Here is some <a href = "#">text</a> which I do not need to extract but then there are
<figure class = "class-one">
<img src = "/example.jpg" alt = "example alt" class = "some-image-class">
<figcaption>example caption</figcaption>
</figure>
And another one (and many more)
<figure class = "class-one some-other-class">
<img src = "/example2.jpg" alt = "example2 alt">
</figure>'
Я хочу извлечь все элементы <figure> и все, что они содержат, включая их атрибуты и другие html-элементы, и поместить это в массив в PHP, чтобы я получил что-то вроде:
$figures = [
0 => [
"class" => "class-one",
"img" => [
"src" => "/example.jpg",
"alt" => "example alt",
"class" => "some-image-class"
],
"figcaption" => "example caption"
],
1 => [
"class" => "class-one some-other-class",
"img" => [
"src" => "/example2.jpg",
"alt" => "example2 alt",
"class" => null
],
"figcaption" => null
]];
До сих пор я пробовал:
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($html);
libxml_clear_errors();
$figures = array();
foreach ($figures as $figure) {
$figures['class'] = $figure->getAttribute('class');
// here I tried to create the whole array but I can't seem to get the values from the HTML
// also I'm not sure how to get all html-elements within <figure>
}
Вот Демо.
@msg, это просто пример того, что я хочу получить.






$doc = new \DOMDocument();
$doc->loadHTML($html);
$figure = $doc->getElementsByTagName("figure"); // DOMNodeList Object
//Craete array to add all DOMElement value
$figures = array();
$i= 0;
foreach($figure as $item) { // DOMElement Object
$figures[$i]['class']= $item->getAttribute('class');
//DOMElement::getElementsByTagName— Returns html tag
$img = $item->getElementsByTagName('img')[0];
if ($img){
//DOMElement::getAttribute — Returns value of attribute
$figures[$i]['img']['src'] = $img->getAttribute('src');
$figures[$i]['img']['alt'] = $img->getAttribute('alt');
$figures[$i]['img']['class'] = $img->getAttribute('class');
}
//textContent - use to get the text of tag
if ($item->getElementsByTagName('figcaption')[0]){
$figures[$i]['figcaption'] = $item->getElementsByTagName('figcaption')[0]->textContent;
}
$i++;
}
echo "<pre>";
print_r($figures);
echo "</pre>";
Я делаю ошибку для Trying to get property 'textContent' of non-object, потому что нет проверки, существует ли свойство на самом деле.
да, это было предупреждение. Я добавил условие для проверки объекта.
Вот код, который должен привести вас туда, где вы хотите быть. Я добавил комментарии, где я чувствовал, что они будут полезны:
<?php
$htmlString = 'Here is some <a href = "#">text</a> which I do not need to extract but then there are <figure class = "class-one"><img src = "/example.jpg" alt = "example alt" class = "some-image-class"><figcaption>example caption</figcaption></figure>And another one (and many more)<figure class = "class-one some-other-class"><img src = "/example2.jpg" alt = "example2 alt"></figure>';
//Create a new DOM document
$dom = new DOMDocument;
//Parse the HTML.
@$dom->loadHTML($htmlString);
//Create new XP
$xp = new DOMXpath($dom);
//Create empty figures array that will hold all of our parsed HTML data
$figures = array();
//Get all <figure> elements
$figureElements = $xp->query('//figure');
//Create number variable to keep track of our $figures array index
$figureCount = 0;
//Loop through each <figure> element
foreach ($figureElements as $figureElement) {
$figures[$figureCount]["class"] = trim($figureElement->getAttribute('class'));
$figures[$figureCount]["img"]["src"] = $xp->query('//img', $figureElement)->item($figureCount)->getAttribute('src');
$figures[$figureCount]["img"]["alt"] = $xp->query('//img', $figureElement)->item($figureCount)->getAttribute('alt');
//Check that an img class exists, otherwise set the value to null. If we don't do this PHP will throw a NOTICE.
if (boolval($xp->evaluate('//img', $figureElement)->item($figureCount))) {
$figures[$figureCount]["img"]["class"] = $xp->query('//img', $figureElement)->item($figureCount)->getAttribute('class');
} else {
$figures[$figureCount]["img"]["class"] = null;
}
//Check that a <figcaption> element exists, otherwise set the value to null
if (boolval($xp->evaluate('//figcaption', $figureElement)->item($figureCount))) {
$figures[$figureCount]["figcaption"] = $xp->query('//figcaption', $figureElement)->item($figureCount)->nodeValue;
} else {
$figures[$figureCount]["figcaption"] = null;
}
//Increment our $figureCount so that we know we can create a new array index.
$figureCount++;
}
print_r($figures);
?>
Эти комментарии действительно очень полезны. У меня есть еще один вопрос об этом решении: есть ли преимущество в использовании DOMXpath вместо использования только DOMDocument для получения всех значений?
Рад помочь! Да, я использую Xpath, чтобы легко ориентироваться на HTML-элементы, которые я хочу разобрать, а также проверять, действительно ли существуют дочерние элементы и атрибуты, используя оценку Xpath.
Вы перезаписываете переменную
$figuresперед циклом.