Как взорвать строку по выбранным тегам html

Мне нужно взорвать строку, содержащую (недопустимый) HTML, по выбранным тегам - <p>, <ol>, <ul>, <table>, <h1-6> . Если какие-либо теги являются вложенными, строка должна расширяться только по первому тегу.

Вставленный ввод:

  <div id="main">
  <h1 id="heading">Heading h1</h1>
  <p>
  <ol>
    <li>abc</li>
    <li>def</li>
    <li>ghi</li>
  </ol>
  Lorem ipusm lorem ipsum Lorem ipusm lorem ipsum Lorem ipusm lorem ipsum Lorem ipusm.
  </p>
  <p>Test test test test test</p>
  <ul>
    <li>aaa</li>
  </ul>
  </div>

Ожидаемый результат:

$output[0] = '<div id="wrapp"><h1 id="heading">Heading h1</h1>';
$output[1] = '<p><ol><li>abc</li><li>def</li><li>ghi</li></ol>Lorem ipusm lorem ipsum Lorem ipusm lorem ipsum Lorem ipusm lorem ipsum Lorem ipusm.</p>';
$output[2] = '<p>Test test test test test</p>';
$output[3] = '<ul><li>aaa</li></ul></div>';

Я пробовал несколько библиотек DOM, но ни одна не может то, что мне нужно. Самая большая проблема — это разделенный элемент div#main и вложенные теги (недействительный html). Я ценю любые идеи.


person sylar32    schedule 06.07.2014    source источник
comment
Какова цель этого? Что бы это ни было, это можно сделать с помощью DOMDocument. XY Проблема?   -  person Lawrence Cherone    schedule 06.07.2014
comment
Мне нужно разбить длинную строку на более короткие части из-за перевода на разные языки (вся идея немного сложна). Я пробовал, например, библиотеку Ganon, и ее проблема в ‹div›‹p›‹ol›‹/ol ›‹/p›‹/div› часть. Ганон возвращает мне ‹div› -> ‹p› и ‹div› -> ‹ol›, что неправильно — должно быть ‹div› -> ‹p› -> ‹ol› .   -  person sylar32    schedule 06.07.2014


Ответы (1)


Вы можете использовать регулярное выражение, например <(p|h[1-6]|ul|ol|table), с preg_match для найдите позицию вашего открывающего тега. Затем используйте найденное совпадение, чтобы найти закрывающее совпадение. Ваш код будет выглядеть примерно так

$html = "<div id="wrapp"><h1 id="heading">Heading ...";
$output = $match = array();
$regex = '<(p|h[1-6]|ul|ol|table)';
while(preg_match($regex, $html, $match, PREG_OFFSET_CAPTURE)){
    $endTag = '</' . $match[1][0] '>';
    $endPosition = strpos($html, $endTag)
    $output[] = substr($html, 0 , $endPosition);
    $html = substr($html, $endPosition + strlen($endTag));
}

Обратите внимание, что этот код не тестировался.

person neubie4life    schedule 06.07.2014
comment
Спасибо, я исправил несколько ошибок, но в основном все работает так, как мне нужно. Я просто беспокоюсь о его скорости, когда приходит очень большая строка. Это исполняемая версия: $output = $match = array(); $regex = '/‹(p|h[1-6]|ul|ol|table)/'; while(preg_match($regex, $html, $match, PREG_OFFSET_CAPTURE)) { $endTag = '‹/' . $матч[1][0] . '›'; $endPosition = strpos($html, $endTag); $output[] = htmlspecialchars(substr($html, 0, $endPosition + strlen($endTag))); $html = substr($html, $endPosition + strlen($endTag)); } $output[] = htmlspecialchars(substr($html, 0, strlen($html))); print_r ($ вывод); - person sylar32; 06.07.2014