PHP: найти строку с помощью preg_match_all

Я дал это:

<tr class="tth3">
  <td>aaa - bbbbb</td>
  <td>6:10 </td>
  <td >bla</td>
</tr>
<tr class="tth3">
  <td>cccc - xxxx</td>
  <td>6:10 </td>
  <td>blabla</td>
</tr>

и я буду искать это регулярное выражение: preg_match_all('/<tr class="tth3">.*?xxx.*?<\/[\s]*tr>/s', ...) И мой результат должен быть только вторым <tr>..</tr>, но я не знаю, как это правильно использовать, так может ли кто-нибудь мне помочь ??


person user1480467    schedule 25.06.2012    source источник
comment
Добро пожаловать в Stack Overflow! Пожалуйста, воздержитесь от синтаксического анализа HTML с помощью RegEx, поскольку он будет сводит вас с ума. Вместо этого используйте анализатор HTML.   -  person Madara's Ghost    schedule 25.06.2012


Ответы (2)


Используя лучшее решение с DOM:

<?php

/**
 * Got this function from the manual's comments
 *
 * @param DOMNode $el
 *
 * @return mixed
 */
function innerHTML(DOMNode $el) {
    $doc = new DOMDocument();
    $doc->appendChild($doc->importNode($el, TRUE));
    $html = trim($doc->saveHTML());
    $tag = $el->nodeName;
    return preg_replace('@^<' . $tag . '[^>]*>|</' . $tag . '>$@', '', $html);
}


$html = <<<HTML
<tr class="tth3">
  <td>aaa - bbbbb</td>
  <td>6:10 </td>
  <td >bla</td>
</tr>
<tr class="tth3">
  <td>cccc - xxxx</td>
  <td>6:10 </td>
  <td>blabla</td>
</tr>
HTML;

$document = new DOMDocument();
$document->loadHTML($html);

$tr_list = $document->getElementsByTagName("tr");

foreach ($tr_list as $tr) {
    /** @var $tr DOMElement */
    $td_list = $tr->getElementsByTagName("td");
    foreach ($td_list as $td) {
        if (preg_match("/xxxx/", $td->textContent)) {
            //This is our TR!!
            echo innerHTML($tr);
            break(2); //Exit both loops
        }
    }
}
person Madara's Ghost    schedule 25.06.2012
comment
THX, но это не решает мою проблему! Я только хотел, чтобы эти внутренние tr совпадали с xxx !! - person user1480467; 25.06.2012
comment
@ user1480467: Вы этого не сказали, вы сказали, что хотите второй tr. Я отредактирую свой код для компенсации. - person Madara's Ghost; 25.06.2012
comment
Извините ... Это мое выражение: / ‹tr class = tth3›. *? Xxx. *? ‹\ / [\ S] * tr› / s, а внутри xxx :) - person user1480467; 25.06.2012

Я не думаю, что помещать класс \s в скобки необходимо, и он может даже интерпретироваться как нечто иное, чем класс пространства. Однако я не уверен на 100%.

[\s]

В любом случае использование:

$num_matches = preg_match_all( '/<tr class="tth3">.*?xxx.*?<\/\s*tr>/s', $subject, $matches );

  1. $num_matches содержит количество совпавших строк
  2. $matches содержит массив фактических совпадающих строк
person efesar    schedule 25.06.2012