2014-09-12 7 views
0

Для перевода веб-сайта мне нужно найти текст, который находится между html-тегами.PHP - текст между тегами

Мой первый подход состоял в том, чтобы использовать регулярное выражение, но оно недостаточно гибкое. Ближайшее, что я был в состоянии получить с регулярным выражением было: http://regex101.com/r/qB6xU5/1

но терпеть неудачу только в последнем тесте соответствие р тегов в одном матче вместо двух

Я считаю, используя библиотеку дома синтаксического анализа, но WASN (в очень маленьком поиске), чтобы найти тот, который может удовлетворить мои потребности.

Не говоря уже о том, что html может быть с ошибками и яркими шаблонами шаблонов.

Вот некоторые примеры случаев, и результаты, которые должны пройти:

  • <div>test</div> =>test
  • <div><br />test</div> =><br />test
  • <div>te<br />st</div> =>te<br />st
  • <div>test<br /></div> =>test<br />
  • <div><span>my</span>test</div> =><span>my</span>test
  • <div>test<span>my</span></div> =>test<span>my</span>
  • <div>test<span>my</span>test</div> =>test<span>my</span>test
  • <div><span>my</span>test<span>my</span></div> =><span>my</span>test<span>my</span>

В небольшом слове он может быть перефразировать как это: Найти содержание HTML-тегов, содержащих по меньшей мере один строка, которая не заключена в некоторые теги.

+6

Вы пробовали HTML-парсер? – deceze

+2

Анализ HTML с регулярным выражением не сработает - это слишком сложно. Вот тонна большой информации об использовании парсеров: http://stackoverflow.com/questions/3577641/how-do-you-parse-and-process-html-xml-in-php/3577662#3577662 –

+0

** Дон ' t используйте регулярные выражения для анализа HTML. Используйте подходящий модуль синтаксического анализа HTML. ** Вы не можете надежно проанализировать HTML с регулярными выражениями, и вы столкнетесь с печалью и разочарованием в будущем. Как только HTML изменится с ваших ожиданий, ваш код будет сломан. См. Http://htmlparsing.com/php или [этот поток SO] (http://stackoverflow.com/questions/3577641/how-do-you-parse-and-process-html-xml-in-php) для примеры правильного анализа HTML с PHP-модулями, которые уже были написаны, протестированы и отлажены. –

ответ

1

Не используйте регулярное выражение. Используйте парсер HTML!

Вот пример с PHP Simple HTML DOM Parser, но вы можете сделать это с тем, что вы предпочитаете:

$html = str_get_html('<div>test<br /></div>'); 
$div = $html->first_child(); // Here's the div 
$result = ""; 
for($children = $div->first_child; $children; $children = $children->next_sibling()) { 
    $result += $children; 
} 
echo $result; // => "test<br />" 
+0

Как я могу проверить, является ли родной брат текстом или элементом? – Cyrbil

+0

@cyrbil Вы можете проверить [здесь] (http://simplehtmldom.sourceforge.net/manual_api.htm) ссылку. Для достижения того, что вы хотите, вы можете сделать что-то вроде: '$ subling." "== $ sibling-> plaintext' – ProGM

+0

Хорошо, документация simpleDomParser немного устарела ... Но мне удается пройти. Кроме того, у него нет возможности проверять текст, который мне удастся сделать, перейдя рекурсивно в dom и наблюдая, содержит ли элемент кусок текста не между тегами. Чтобы проверить, что я удаляю все теги с помощью регулярного выражения (так как я также хочу удалить содержимое тега, strip_tags недостаточно), тогда проверьте, не осталось ли у меня какого-либо текста. – Cyrbil

0

Для записи здесь полный код. Некоторое регулярное выражение может не понадобиться в некоторых случаях. Но мне все они нужны;)

<?php 
include("simple_php_dom.php"); 

// load html content to parse 
$html_str = file_get_contents("myfile.tpl"); 
$html = str_get_html($html_str); 

// extract strings 
parse($html, $results); 
var_dump($results); // simply display 

/** 
* Parse html element and find every text not between tags 
* @param $elem DOM element to parse 
* @param $results array 
*/ 
function parse($elem, &$results) { 
    // walk though every nodes 
    foreach($elem->childNodes() as $child) { 
     // get sub children 
     $children = $child->childNodes(); 

     // get inner content 
     $content = $child->innertext; 

     // remove starting and ending self closing elements or smarty tags 
     $content = preg_replace('/(^(\s*<[^>]*?\/\s*>)+)|((<[^>]*?\/\s*>\s*)+$)/s', '', $content); 
     $content = preg_replace('/(^(\s*{[^}]*?})+)|((\{[^}]*?\}\s*)+$)/s', '', $content); 
     $content = trim($content); 

     // remove all elements and smarty tags 
     $text = preg_replace('/<(\w+)[^>]*>.*<\s*\/\1\s*>/', '', $content); // remove elements 
     $text = preg_replace('/<\/?.*?\/?>/', '', $text); // remove self closing elements 
     $text = preg_replace('/\{.*?\}/', '', $text); // remove smarty tags 
     $text = preg_replace('/[^\w]/', '', $text); // remove non alphanum characters 
     $text = trim($text); 

     // no children, we are at a leaf and it's probably a text 
     if(empty($children)) { 
      // check if not empty string and exclude comments styles and scripts 
      if(!empty($text) && in_array($child->tag, array("comment","style","script")) === false) { 
       // add to results 
       $results[] = $content; 
      } 
     } 
     // if we are on a branch but in contain text not inside tags 
     elseif(!empty($text)) { 
      // add to results 
      $results[] = $content; 
     } else { 
      // recursive call with sub element 
      parse($child, $results); 
     } 
    } 
} 
Смежные вопросы