2010-10-19 2 views
0

У меня есть некоторые HTML, который выглядит следующим образом:Извлечение из каждого первого TD в таблице

<tr class="row-even"> 
    <td align="center">abcde</td> 
    <td align="center"><a href="deluserconfirm.html?user=abcde"><img src="../images/delete_x.gif" alt="Delete User" border="none" /></a></td> 
</tr> 
<tr class="row-odd"> 
    <td align="center">efgh</td> 
    <td align="center"><a href="deluserconfirm.html?user=efgh"><img src="../images/delete_x.gif" alt="Delete User" border="none" /></a></td> 
</tr> 
<tr class="row-even"> 
    <td align="center">ijkl</td> 
    <td align="center"><a href="deluserconfirm.html?user=ijkl"><img src="../images/delete_x.gif" alt="Delete User" border="none" /></a></td> 
</tr> 

И мне нужно, чтобы получить значения, abcde, efgh и ijkl

Это регулярное выражение, которое я использую в настоящее время:

preg_match_all('/(<tr class="row-even">|<tr class="row-odd">)<td align="center">(.*)<\/td><\/tr>/xs', $html, $matches); 

Да, я не очень хорош в них. Как и в большинстве моих попыток регулярного выражения, это не работает. Может ли кто-нибудь сказать мне, почему?

Кроме того, я знаю о парсерах html/xml, но для этого потребуется значительный пересмотр кода. Так вот на потом. На данный момент нам нужно придерживаться регулярного выражения.

EDIT: Чтобы уточнить, мне нужно значение между первым <td align="center"></td> тегом либо после <tr class="row-even"> или <tr class="row-odd">

+0

Я не так хорош с регулярным выражением, но может быть, вы не заметили, что вам не хватает части для разрыва строки между ' JohnoBoy

+0

, пожалуйста, сообщите нам, что вы хотите сделать точно? Какова функция этого? – klox

+0

@JohnoBoy: Как я могу ввести строки? @klox: Мне нужны значения между первым тегом – HyderA

ответ

2
~<tr class="row-(even|odd)">\s*<td align="center">(.*?)</td>~m 

Обратите внимание на m модификатора и использование \s*.

Кроме того, вы можете сделать первую группу без захвата с помощью ?:. Т.е., (?:even|odd), как вы, вероятно, не заинтересованы в атрибуте class :)

+0

Наконец-то! Кто-то не спорит с regex v/s html parsers! Я попробовал, и он отлично работает. Просто некоторые разъяснения, пожалуйста, я попробовал \ s раньше, и это не сработало с *. Почему это необходимо? Кроме того, что делают персонажи? – HyderA

+0

В PHP вы можете использовать любой символ, чтобы отметить начало и конец вашего регулярного выражения. Он выбрал '' 'для удобства. «*» - квантификатор. Вы используете его, чтобы сказать, что вы хотите от 0 до бесконечности определенного класса. '\ s' в вашем случае, что означает пробельные символы. –

+0

@gAMBOOKa Что @Alin Purcaru сказал :) '~' выбирается, так как он не используется нигде в моем шаблоне. Вы часто видите '/', используемый в качестве разделителя, но это заставило бы меня избежать этого '\ /' в ''. Что касается '\ s': он будет соответствовать пробелу, вкладке или разрыву строки (ноль-ко-многим). – jensgram

0

Это просто быстрое и грязное регулярное выражение, чтобы удовлетворить ваши потребности. Его можно легко очистить и оптимизировать, но это начало.

<tr[^>]+>[^\n]*\n    #Match the opening <tr> tag 
    \s*<td[^>]+>([^<]+)[^\n]+\n #Group the wanted data 
    [^\n]+\n      #Match next line 
</tr>       #Match closing tag 

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

deluserconfirm.html\?user=([^"]+) 
0

Это то, что я придумал

<td align="center">([^<]+)</td> 

я объясню. Одна из проблем заключается в том, что между тегами может быть либо текст, который вы ищете, либо тег. В регулярном выражении [^ <] + говорит, чтобы соответствовать одному или нескольким символам, которые не символ <. Это здорово, потому что это означает, что не будет соответствовать, и группа будет соответствовать только до тех пор, пока тег не будет найден.

+0

Только что заметил, что в моем ответе мои якорные метки были удалены. – mellowsoon

2

Попробуйте это:

preg_match_all('/(?:<tr class="row-even">|<tr class="row-odd">).<td align="center">(.*?)<\/td>/s', $html, $matches); 

Внесены изменений:

  • Вы не учитываемые для новой строки между тегами
  • Вам не нужны й модификатором, как это будет отбросить пробел в регулярном выражении.
  • Сделать подходящим нежирным, используя .*? вместо .*.

Working link

+0

Спасибо, что указали мои точные ошибки. Помогает мне учиться! – HyderA

0

Отказ от ответственности: Использование регулярных выражений для разбора HTML опасно.

Чтобы получить innerhtml первого TD в каждом TR, используйте регулярное выражение:

/<tr[^>]*>\s*<td[^>]>(.+?)<\/td>/si 
2

На самом деле, вам не нужно слишком большие изменения в вашем коде. Извлечение текстовых узлов всегда одинаково с DOM и XPath. Все, что делает изменения, это XPath, поэтому вы можете обернуть DOM-код в функцию, которая заменяет ваш preg_match_all. Это будет всего лишь небольшое изменение, например.

include_once "dom.php"; 
$matches = dom_match_all('//tr/td[1]', $html); 

где dom.php содержит только:

// dom.php 
function dom_match_all($query, $html, array $matches = array()) { 
    $dom = new DOMDocument; 
    libxml_use_internal_errors(TRUE); 
    $dom->loadHTML($html); 
    libxml_clear_errors(); 
    $xPath = new DOMXPath($dom); 
    foreach($xPath->query($query) as $node) { 
     $matches[] = $node->nodeValue; 
    } 
    return $matches; 
} 

и вернется

Array 
(
    [0] => abcde 
    [1] => efgh 
    [2] => ijkl 
) 

Но если вы хотите Regex, использовать Regex. Я просто даю идеи.

+0

Я ценю ваши усилия, и это действительный ответ, за исключением того, что в моем случае это намного сложнее. Я планирую использовать библиотеку simplehtmldom, которую я нашел довольно гладкой. Это приложение по всем практическим причинам, искатель. Таким образом, на протяжении всей заявки существует множество регулярных выражений. Простое включение новой библиотеки - это усилие, потому что нет класса интеграции центральной библиотеки. У меня будет несколько копий кода на всей кодовой базе, если я повторно использую текущую архитектуру. Но я вижу вашу точку зрения, и я уверен, что это поможет кому-то найти подобное решение. – HyderA

+0

@gAMBOOKa без проблем. Вы также можете быть заинтересованы в [Лучшие методы анализа HTML] (http://stackoverflow.com/questions/3577641/best-methods-to-parse-html/3577662#3577662). ИМО там лучше библиотеки, чем SimpleHTMLDom. – Gordon

Смежные вопросы