Использование Lookahead для сопоставления строки с использованием регулярного выражения - PullRequest
1 голос
/ 09 декабря 2008

Мне нужно сопоставить строку, содержащую html, используя регулярное выражение, чтобы вытащить все вложенные промежутки. Я предполагаю, что есть способ сделать это с помощью регулярного выражения, но все утро безуспешно.

То есть для образца входной строки

<DIV id=c445c9c2-a02e-4cec-b254-c134adfa4192 style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #000000 1px solid; BORDER-LEFT: #000000 1px solid; BORDER-BOTTOM: #000000 1px solid; BACKGROUND-COLOR: #eeeeee">
<SPAN id=b8db8cd1-f600-448f-be26-2aa56ea09a9c>
<SPAN id=304ccd38-8161-4def-a557-1a048c963df4>
<IMG src="http://avis.co.uk/Assets/build/menu.gif">
</SPAN>
</SPAN>
<SPAN id=bc88c866-5370-4c72-990b-06fbe22038d5>
<SPAN id=55b88bbe-15ca-49c9-ad96-cecc6ca7004e>UK<BR></SPAN>
</SPAN>
<SPAN id=52bb62ca-8f0a-42f1-a13b-9b263225ff1d>
<SPAN id=0e1c3eb6-046d-4f07-96c1-d1ac099d5f1c>
<IMG src="http://avis.co.uk/Assets/build/menu.gif">
</SPAN>
</SPAN>
<SPAN id=4c29eef2-cd77-4d33-9828-e442685a25cb>
<SPAN id=0d5a266a-14ae-4a89-9263-9e0ab57f7ad2>Italy</SPAN>
</SPAN>
<SPAN id=f0a72eea-fddd-471e-89e6-56e9b9efbece>
<SPAN id=b7d9ada7-ade0-49fe-aa5f-270237e87c2b>
<IMG src="http://avis.co.uk/Assets/build/menu.gif">
</SPAN>
</SPAN>
<SPAN id=7604df94-34ba-4c89-bf11-125df01731ff>
<SPAN id=330d6429-4f1b-46a2-a485-9001e2c6b8c1>Netherlands</SPAN>
</SPAN>
<SPAN id=a18fb516-451e-4c32-ab31-3e3be29235f6>
<SPAN id=6c70238d-78f9-468f-bb8d-370fff13c909>
<IMG src="http://avis.co.uk/Assets/build/menu.gif">
</SPAN>
</SPAN>
<SPAN id=5a2465eb-b337-4f94-a4f8-6f5001dfbd75>
<SPAN id=47877a9e-a7d5-4f13-a41e-6948f899e385>Malta &amp; Gozo

Я хотел бы получить каждый внешний диапазон и содержащий его диапазон, поэтому в приведенном выше тексте должно быть восемь результатов

Любая помощь с радостью принята

Ответы [ 4 ]

5 голосов
/ 09 декабря 2008

Еще раз используйте анализатор HTML для обхода DOM: регулярные выражения никогда не будут достаточно надежными для этого.

4 голосов
/ 09 декабря 2008

На самом деле это невозможно решить с помощью стандартного регулярного выражения, поскольку они в основном реализуют грамматики типа 3 в иерархии Хомского (автоматы конечного состояния), тогда как вам нужна хотя бы грамматика типа 2 (какой-то стек или рекурсия) для правильного распознавания произвольных вложенных структур.

Однако, если вы ограничите максимально возможный уровень вложенности, то это возможно, но я все еще сомневаюсь, являются ли регулярные выражения лучшим решением.

1 голос
/ 09 декабря 2008

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

@"(?is)<SPAN\b[^>]*>\s*(<SPAN\b[^>]*>.*?</SPAN>)\s*</SPAN>"

Это в основном то же самое, что и регулярное выражение PhiLho, за исключением того, что оно разрешает пробелы между тегами на обоих концах. Мне также пришлось добавить модификатор SingleLine / DOTALL для размещения разделителей строк в сопоставленном тексте. Я не знаю, было ли какое-либо из этих изменений действительно необходимым; примеры данных, которые опубликовал ОП, были в одной строке, но Филиол разбил их (тем самым нарушив свое собственное регулярное выражение).

0 голосов
/ 09 декабря 2008

По сути, я согласен с приведенными выше советами: использование регулярных выражений для синтаксического анализа HTML требует, чтобы когда-нибудь был нарушен код на странных допустимых HTML-конструкциях (не говоря уже о некорректном HTML, который принимают браузеры ...). Поиск и использование хорошего анализатора HTML может быть полезным во многих отношениях ...

Теперь я прагматичен (и не могу устоять перед небольшим вызовом регулярных выражений ...), и иногда я использую RE против сгенерированного машиной HTML (часто это функция экспорта), потому что я знаю, что структура, которую я вижу, вряд ли изменится В отличие от страниц, созданных вручную, где автор может делать опечатки ... Это в основном для быстрого взлома, который я могу адаптировать, если выходные данные когда-либо изменятся.

В вашем случае HTML-код достаточно регулярный, линейный и предсказуемый, поэтому RE довольно прост. Я даю код Java, потому что я не знаю C #, но адаптация должна быть тривиальной.

Pattern p = Pattern.compile("(<SPAN id.*?<SPAN id.*?</SPAN></SPAN>)");
Matcher m = p.matcher(html);
while (m.find())
{
  System.out.println(m.group(1));
}

НТН.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...