Несколько совпадений в группе регулярных выражений?

Мне нужно сопоставить все «теги» (например,% thisIsATag%), которые встречаются в атрибутах XML. (Примечание: я гарантированно получу действительный XML, поэтому нет необходимости использовать полный обход DOM). Мое регулярное выражение работает, кроме случаев, когда естьдва теги в одном атрибуте, возвращается только последний.

Другими словами, это регулярное выражение должно найти tag1, tag2, ..., tag6. Тем не менее, он пропускает tag2 и tag5.

Вот забавный маленький тестовый комплект для вас (PHP):

<?php

$xml = <<<XML
<data>
 <slideshow width="625" height="250">

  <screen delay="%tag1%">
   <text x="30%" y="50%" animatefromx="800">
    <line fontsize="32" fontstyle="bold" text="Screen One!%tag2% %tag3%"/>
   </text>
  </screen>

  <screen delay='%tag4%'>
   <text x="30%" y="50%" animatefromx="800">
    <line fontsize='32' fontstyle='bold' text='Screen 2!%tag5%%tag6%'/>
   </text>
  </screen>

  <screen>
   <text x="30%" y="50%" animatefromx="800">
    <line fontsize="32" fontstyle="bold"  text="Screen Tres!"/>
   </text>
  </screen>

  <screen>
   <text x="30%" y="50%" animatefromx="800">
    <line fontsize="32" fontstyle="bold"  text="Screen FOURRRR!"/>
   </text>
  </screen>

 </slideshow>
</data>
XML;

$matches = null;
preg_match_all('#<[^>]+("([^%>"]*%([^%>"]+)%[^%>"]*)+"|\'([^%>\']*%([^%>\']+)%[^%>\']*)+\')[^>]*>#i', $xml, $matches);

print_r($matches);
?>

Спасибо! :)

Ответы на вопрос(2)

Это:

(%[a-zA-Z0-9]+%)

недостаточно? В вашем примере теги не появляются нигде вне значений атрибутов - не так ли?

 rinogo22 авг. 2009 г., 17:53
+1 хаха! Забавно, как иногда мы пропускаем простейшие решения ... :) Я полагаю, это будет работать в большинстве случаев. Единственное, что меня нервирует, это то, что XMLделает усложняется, и возможно, что подобный тегу текст мог бы также появиться в теле элемента ... Но, опять же, это, вероятно, достаточное решение на данный момент. Спасибо !:)
Решение Вопроса

что вы пытаетесь сделать, это восстановить промежуточные записи из групп, которые совпадают более одного раза за соответствие регулярному выражению. Насколько я знаю, только .NET и Perl 6 предоставляют такую возможность. Вам придется выполнить работу в два этапа: сопоставить значение атрибута с одним или несколькими%tag% последовательности в нем, а затем разбить отдельные последовательности.

Вам не важно, с каким XML-тегом или атрибутом связаны значения, поэтому вы можете использовать это, несколько более простое регулярное выражение, чтобы найти значения с%tag% последовательности в них:

'#"([^"%<>]*+%[^%"]++%[^"]*+)"|\'([^\'%<>]*+%[^%\']++%[^\']*+)\'#'

РЕДАКТИРОВАТЬ: Это регулярное выражение захватывает значение атрибута в группе 1 или группе 2, в зависимости от того, в каких кавычках он использовал. Вот еще одна версия, которая объединяет альтернативы, поэтому всегда может сохранить значение в группе 2:

'#(["\'])((?:(?![%<>]|\1).)*+%(?:(?!%|\1).)++%(?:(?!\1).)*+)\1#'
 rinogo22 авг. 2009 г., 17:57
В то время как другие решения намного проще и все еще решают ту же самую существенную проблему, это решает загадку в основе моего вопроса. Главное, что в PHP (и в большинстве языков) я не могу «восстановить промежуточные записи». Кажется, имеет смысл! Хорошо знать. :)
 Alan Moore22 авг. 2009 г., 18:44
Другие ответы также предполагают%tag% имена могут состоять только из буквенно-цифровых или "словесных" символов, и что%ThingsThatLookLikeTags% всегда будут тегами, независимо от того, где они появляются. Мой только соответствует им в кавычках - что предполагаетOни всегда будут значения атрибута. Но я мог бы расширить его, чтобы он соответствовал строкам только внутри (XML) тегов.

Ваш ответ на вопрос