У чисто теоретичному сенсі неможливо регулярні вирази розбирати XML. Вони визначені таким чином, що не дозволяють їм пам’ятати жодного попереднього стану, тим самим перешкоджаючи правильному зіставленню довільної теги, і вони не можуть проникнути до довільної глибини вкладення, оскільки введення потрібно вбудовувати в регулярний вираз.
Однак сучасні аналізатори регулярних виразів будуються для їх корисності для розробника, а не для прихильності до точного визначення. Таким чином, у нас є такі речі, як зворотні посилання та рекурсії, які використовують знання попередніх станів. Використовуючи їх, надзвичайно просто створити регулярний вираз, який може досліджувати, перевіряти чи аналізувати XML.
Розглянемо, наприклад,
(?:
<!\-\-[\S\s]*?\-\->
|
<([\w\-\.]+)[^>]*?
(?:
\/>
|
>
(?:
[^<]
|
(?R)
)*
<\/\1>
)
)
Це знайде наступний правильно сформований тег XML або коментар, і він знайде його лише у тому випадку, якщо весь вміст буде правильно сформований. (Цей вираз був протестований за допомогою Notepad ++, який використовує бібліотеку регулярних виразів Boost C ++, яка приблизно наближає PCRE.)
Ось як це працює:
- Перший шматок відповідає коментарю. Потрібно, щоб це було першим, щоб воно розглядало будь-який коментований код, який інакше може спричинити зависання.
- Якщо це не відповідає, він буде шукати початок тегу. Зауважте, що він використовує дужки для збору імені.
- Цей тег буде або закінчуватися а
/>
, таким чином, завершуючи тег, або закінчується а >
, у цьому випадку він буде продовжуватися, вивчаючи вміст тегу.
- Він буде продовжувати синтаксичний аналіз до тих пір, поки не досягне
<
точки a , після чого він повториться до початку виразу, що дозволить йому обробляти або коментар, або новий тег.
- Він буде продовжуватися через цикл, поки не надійде або в кінці тексту, або в той,
<
який не може розібрати. Якщо не збігатися, це, звичайно, призведе до того, що процес розпочнеться. В іншому випадку, <
імовірно, це початок завершального тегу для цієї ітерації. Використовуючи зворотну посилання всередині закриваючого тегу <\/\1>
, він буде відповідати тегу відкриття для поточної ітерації (глибини). Є лише одна група захоплення, тому ця відповідність - справа проста. Це робить його незалежним від назв використовуваних тегів, хоча ви можете змінити групу захоплення, щоб захоплювати лише певні теги, якщо це потрібно.
- У цей момент він або вийде з поточної рекурсії, до наступного рівня, або закінчиться матчем.
Цей приклад вирішує проблеми, що стосуються пробілу чи виявлення відповідного вмісту за допомогою використання символьних груп, які просто заперечують <
або >
, або у випадку коментарів, використовуючи [\S\s]
, що відповідатиме будь-чому, включаючи повернення перевезення та нові рядки, навіть в однорядковій режим, продовжуючи, поки не досягне a
-->
. Отже, він просто ставиться до всього як до дійсного, поки не досягне чогось значимого.
Для більшості цілей такий регулярний вираз не особливо корисний. Він підтвердить, що XML правильно сформований, але це все, що це буде дійсно, і він не враховує властивості (хоча це було б легким доповненням). Це просто так, оскільки він не залишає справжніх проблем, таких як ця, а також визначення імен тегів. Пристосування його для реального використання зробить його набагато більше звіром. Взагалі справжній аналізатор XML був би набагато вищим. Цей, мабуть, найкраще підходить для навчання того, як працює рекурсія.
Короткий виклад історії: використовуйте аналізатор XML для справжньої роботи, і використовуйте це, якщо ви хочете пограти з регулярними виразами.