Разбор h2 и следующего тега в PHP - PullRequest
1 голос
/ 02 октября 2019

Мне нужно создать массив из следующей строки.

$body = '<h2>Heading one</h2>
         <p>Lorem ipsum dolor</p>

         <h2>Heading two</h2>
         <ul>
           <li>list item one.</li>
           <li>List item two.</li>
         </ul>

         <h2>Heading three</h2>
         <table class="table">
           <tbody>
             <tr>
               <td>Table data one</td>
               <td>Description of table data one</td>
             </tr>
             <tr>
               <td>Table data two</td>
               <td>Description of table data two</td>
             </tr>
           </tbody>
         </table>';

Я могу использовать тег h2 в качестве первого индекса для получения значения 'question'.

<code>$dom = new \DOMDocument();
$dom->loadHTML($body);
$xPath = new \DOMXpath($dom);

$question_answer = [];
$tags = $dom->getElementsByTagName('h2');
foreach ($tags as $tag) {
  $next_element = $xPath->query('./following-sibling::p', $tag);
  $question_answer[] = [
    'question' => $tag->nodeValue,
    'answer' =>  $next_element->item(0)->nodeValue,
  ];
}

echo '<pre>';
print_r($question_answer);
echo '
';

Включение предложения @ Kevin, которое отлично работает для тега p и дает следующий результат:

Array
(
    [0] => Array
        (
            [question] => Heading one
            [answer] => Lorem ipsum dolor
        )

    [1] => Array
        (
            [question] => Heading two
            [answer] => 
        )

    [2] => Array
        (
            [question] => Heading three
            [answer] => 
        )

)

Теперь мне просто нужно решить answer, когда следующий тег будетнеупорядоченный список или таблица. Для таблиц меня интересуют только теги td.

Ответы [ 2 ]

1 голос
/ 02 октября 2019

Поскольку вы выполняете итерацию для каждого тега h2, используйте following-sibling::p относительно текущего тега.

foreach ($tags as $tag) {
    $next_element = $xPath->query('./following-sibling::p', $tag);
    if ($next_element->length <= 0) continue; //skip it if p not found
    $question_answer[] = [
        'question' => $tag->nodeValue,
        'answer' => $next_element->item(0)->nodeValue,
    ];
}
0 голосов
/ 03 октября 2019

Мы сейчас исключаем разметку таблицы, потому что она, вероятно, не подходит в этом случае использования. Вот содержание:

$body = '<h2>Heading one</h2>
       <p>Lorem ipsum dolor</p>

       <h2>Heading two</h2>
       <ul>
         <li>List item one.</li>
         <li>List item two.</li>
       </ul>';

Вот код решения:

<code>$dom = new \DOMDocument();
$dom->loadHTML($body);
$xPath = new \DOMXpath($dom);

$question_answer = [];
$tags = $dom->getElementsByTagName('h2');
foreach ($tags as $tag) {
  $possible_answer = $xPath->query('./following-sibling::p | ./following-sibling::ul', $tag);

  if ($possible_answer->length <= 0) {
    continue;
  }

  if ($possible_answer->item(0)->tagName === 'p') {
    $answer = $possible_answer->item(0)->nodeValue;
    $question_answer[] = [
      'question' => $tag->nodeValue,
      'answer' => $answer,
    ];
  }

  elseif ($possible_answer->item(0)->tagName === 'ul') {
    $li_dom = [];
    foreach ($possible_answer->item(0)->getElementsByTagName('li') as $li) {
      $li_dom[] = $li->nodeValue;
    }
    $li_dom = implode(" ", $li_dom);

      $question_answer[] = [
        'question' => $tag->nodeValue,
        'answer' => $li_dom,
      ];
    }
  }

echo '<pre>';
print_r($question_answer);
echo '
';

Вот вывод:

Array
(
    [0] => Array
        (
            [question] => Heading one
            [answer] => Lorem ipsum dolor
        )

    [1] => Array
        (
            [question] => Heading two
            [answer] => List item one. List item two.
        )

)
...