регулярное выражение для выбора между <anchor1> и <anchor2>, игнорируя весь текст внутри любого <> - PullRequest
0 голосов
/ 20 ноября 2011

У меня есть следующие два типа текста:

Введите один:

<div class="meta-name">Corporate Officers</div>
<div class="meta-data"><table border="0" cellspacing="0" cellpadding="0" width="171">
<col width="171"></col>
<tbody>
<tr height="19">
<td width="171" height="19">Officer One</td>
</tr>
</tbody>
</table> 
</div>
</div>

Введите два:

<div class="meta-name">Corporate Officers</div>
<div class="meta-data">Officer Two</div>
</div>
<pre>

Я использую php с preg_match_all. Мне нужно одно выражение, которое вернет Офицера Один и Офицера Два из вышеперечисленного. Я использую Corporate Officer < /div> в качестве первого якоря и < /div> в качестве второго, но я не могу найти Кейта Денниса во всем этом скандале.

Как вернуть текст между anchor1 и anchor2, игнорируя весь текст внутри скобок <> между?

Я видел эти темы, но не смог заставить их решения работать на меня: RegEx: извлекать все до тех пор, пока X не окажется между двумя скобками

все, но все между [и]

Ответы [ 3 ]

1 голос
/ 20 ноября 2011

С SimpleXML :

$xml = new SimpleXMLElement('<div>
    <div class="meta-name">
        Corporate Officers
    </div>
    <div class="meta-data">
        <table border="0" cellspacing="0" cellpadding="0" width="171">
            <col width="171" />
            <tbody>
                <tr height="19">
                    <td width="171" height="19">
                        Officer One
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
');

$results = array();
foreach($xml->children() as $node) {
    if($node->getName() == 'div') {
        $attributes = $node->attributes();
        $classes = explode(' ', $attributes['class']);
        if(in_array('meta-name', $classes) || in_array('meta-data', $classes)) {
            $results[] = getText($node);
        }
    }
}

function getText($node) {
    $text = trim(sprintf('%s', $node));
    if(strlen($text) !== 0) {
        return $text;
    }

    foreach($node->children() as $child) {
        if($text = getText($child)) {
            return $text;
        }
    }

    return null;
}

var_dump($results);

Как правило, никогда не используйте Regex для разбора HTML.

0 голосов
/ 20 ноября 2011

Попробуйте это регулярное выражение:

'~<div\b[^>]*>Corporate\s+Officers</div>\s*<div\b[^>]*>(?:<(?!/?div\b)[^>]*>|\s+)*\K[^<]+~'

Это основано на предположении, что в HTML нет другого текстового содержимого между открывающими тегами <div> и именами, которые вы ищете.Первая часть не требует пояснений:

<div\b[^>]*>Corporate\s+Officers</div>\s*<div\b[^>]*>

Я предполагаю, что текст «Корпоративные сотрудники» достаточен для определения начальной точки, но при необходимости вы можете повторно вставить атрибуты class.После этого

(?:<(?!/?div\b)[^>]*>|\s+)*

... потребляет любое количество тегов, отличных от тегов <div> или </div>, а также любые промежуточные пробелы.Затем \K приходит и говорит забудьте все это, реальный матч начинается здесь .[^<]+ потребляет все до начала следующего тега, и это все, что вы видите в результатах матча.Как будто все до \K было действительно позитивным взглядом, но без всех ограничений.

Вот демо .

0 голосов
/ 20 ноября 2011

Около 80% вопросов регулярных выражений - это xml / html / xhtml.И около 75% ответов состоит в том, чтобы не использовать регулярное выражение.Зачем?Потому что, хотя может показаться, что он работает для вашего примера, он будет хрупким и может сломаться при небольшом изменении ввода.

Пожалуйста, взгляните на этот прекрасный инструмент .Если вы не можете его использовать, вернитесь, и мы предоставим вам помощь.

...